usp10/tests: A spelling fix in an ok() message.
[wine.git] / dlls / oleaut32 / typelib.c
blob09b669ed3eb280ce24c78f9f42873ac2a0624a14
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 <stdlib.h>
51 #include <string.h>
52 #include <stdarg.h>
53 #include <stdio.h>
54 #include <ctype.h>
56 #define COBJMACROS
57 #define NONAMELESSUNION
59 #include "winerror.h"
60 #include "windef.h"
61 #include "winbase.h"
62 #include "winnls.h"
63 #include "winreg.h"
64 #include "winuser.h"
65 #include "winternl.h"
66 #include "lzexpand.h"
68 #include "objbase.h"
69 #include "typelib.h"
70 #include "wine/debug.h"
71 #include "variant.h"
72 #include "wine/asm.h"
73 #include "wine/heap.h"
74 #include "wine/list.h"
76 WINE_DEFAULT_DEBUG_CHANNEL(ole);
77 WINE_DECLARE_DEBUG_CHANNEL(typelib);
79 typedef struct
81 WORD offset;
82 WORD length;
83 WORD flags;
84 WORD id;
85 WORD handle;
86 WORD usage;
87 } NE_NAMEINFO;
89 typedef struct
91 WORD type_id; /* Type identifier */
92 WORD count; /* Number of resources of this type */
93 DWORD resloader; /* SetResourceHandler() */
95 * Name info array.
97 } NE_TYPEINFO;
99 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
100 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
101 static void TLB_FreeVarDesc(VARDESC*);
103 /****************************************************************************
104 * FromLExxx
106 * Takes p_iVal (which is in little endian) and returns it
107 * in the host machine's byte order.
109 #ifdef WORDS_BIGENDIAN
110 static WORD FromLEWord(WORD p_iVal)
112 return (((p_iVal & 0x00FF) << 8) |
113 ((p_iVal & 0xFF00) >> 8));
117 static DWORD FromLEDWord(DWORD p_iVal)
119 return (((p_iVal & 0x000000FF) << 24) |
120 ((p_iVal & 0x0000FF00) << 8) |
121 ((p_iVal & 0x00FF0000) >> 8) |
122 ((p_iVal & 0xFF000000) >> 24));
124 #else
125 #define FromLEWord(X) (X)
126 #define FromLEDWord(X) (X)
127 #endif
129 #define DISPATCH_HREF_OFFSET 0x01000000
130 #define DISPATCH_HREF_MASK 0xff000000
132 /****************************************************************************
133 * FromLExxx
135 * Fix byte order in any structure if necessary
137 #ifdef WORDS_BIGENDIAN
138 static void FromLEWords(void *p_Val, int p_iSize)
140 WORD *Val = p_Val;
142 p_iSize /= sizeof(WORD);
144 while (p_iSize) {
145 *Val = FromLEWord(*Val);
146 Val++;
147 p_iSize--;
152 static void FromLEDWords(void *p_Val, int p_iSize)
154 DWORD *Val = p_Val;
156 p_iSize /= sizeof(DWORD);
158 while (p_iSize) {
159 *Val = FromLEDWord(*Val);
160 Val++;
161 p_iSize--;
164 #else
165 #define FromLEWords(X,Y) /*nothing*/
166 #define FromLEDWords(X,Y) /*nothing*/
167 #endif
170 * Find a typelib key which matches a requested maj.min version.
172 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
174 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
175 WCHAR buffer[60];
176 char key_name[16];
177 DWORD len, i;
178 INT best_maj = -1, best_min = -1;
179 HKEY hkey;
181 memcpy( buffer, typelibW, sizeof(typelibW) );
182 StringFromGUID2( guid, buffer + lstrlenW(buffer), 40 );
184 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
185 return FALSE;
187 len = sizeof(key_name);
188 i = 0;
189 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
191 INT v_maj, v_min;
193 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
195 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
197 if (*wMaj == 0xffff && *wMin == 0xffff)
199 if (v_maj > best_maj) best_maj = v_maj;
200 if (v_min > best_min) best_min = v_min;
202 else if (*wMaj == v_maj)
204 best_maj = v_maj;
206 if (*wMin == v_min)
208 best_min = v_min;
209 break; /* exact match */
211 if (*wMin != 0xffff && v_min > best_min) best_min = v_min;
214 len = sizeof(key_name);
216 RegCloseKey( hkey );
218 TRACE("found best_maj %d, best_min %d\n", best_maj, best_min);
220 if (*wMaj == 0xffff && *wMin == 0xffff)
222 if (best_maj >= 0 && best_min >= 0)
224 *wMaj = best_maj;
225 *wMin = best_min;
226 return TRUE;
230 if (*wMaj == best_maj && best_min >= 0)
232 *wMin = best_min;
233 return TRUE;
235 return FALSE;
238 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
239 /* buffer must be at least 60 characters long */
240 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
242 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
243 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
245 memcpy( buffer, TypelibW, sizeof(TypelibW) );
246 StringFromGUID2( guid, buffer + lstrlenW(buffer), 40 );
247 swprintf( buffer + lstrlenW(buffer), 20, VersionFormatW, wMaj, wMin );
248 return buffer;
251 /* get the path of an interface key, in the form "Interface\\<guid>" */
252 /* buffer must be at least 50 characters long */
253 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
255 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
257 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
258 StringFromGUID2( guid, buffer + lstrlenW(buffer), 40 );
259 return buffer;
262 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
263 /* buffer must be at least 16 characters long */
264 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
266 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
267 static const WCHAR win16W[] = {'w','i','n','1','6',0};
268 static const WCHAR win32W[] = {'w','i','n','3','2',0};
269 static const WCHAR win64W[] = {'w','i','n','6','4',0};
271 swprintf( buffer, 16, LcidFormatW, lcid );
272 switch(syskind)
274 case SYS_WIN16: lstrcatW( buffer, win16W ); break;
275 case SYS_WIN32: lstrcatW( buffer, win32W ); break;
276 case SYS_WIN64: lstrcatW( buffer, win64W ); break;
277 default:
278 TRACE("Typelib is for unsupported syskind %i\n", syskind);
279 return NULL;
281 return buffer;
284 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
286 struct tlibredirect_data
288 ULONG size;
289 DWORD res;
290 ULONG name_len;
291 ULONG name_offset;
292 LANGID langid;
293 WORD flags;
294 ULONG help_len;
295 ULONG help_offset;
296 WORD major_version;
297 WORD minor_version;
300 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
301 static HRESULT query_typelib_path( REFGUID guid, WORD wMaj, WORD wMin,
302 SYSKIND syskind, LCID lcid, BSTR *path, BOOL redir )
304 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
305 LCID myLCID = lcid;
306 HKEY hkey;
307 WCHAR buffer[60];
308 WCHAR Path[MAX_PATH];
309 LONG res;
311 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
313 if (redir)
315 ACTCTX_SECTION_KEYED_DATA data;
317 data.cbSize = sizeof(data);
318 if (FindActCtxSectionGuid( 0, NULL, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION, guid, &data ))
320 struct tlibredirect_data *tlib = (struct tlibredirect_data*)data.lpData;
321 WCHAR *nameW;
322 DWORD len;
324 if ((wMaj != 0xffff || wMin != 0xffff) && (tlib->major_version != wMaj || tlib->minor_version < wMin))
325 return TYPE_E_LIBNOTREGISTERED;
327 nameW = (WCHAR*)((BYTE*)data.lpSectionBase + tlib->name_offset);
328 len = SearchPathW( NULL, nameW, NULL, ARRAY_SIZE( Path ), Path, NULL );
329 if (!len) return TYPE_E_LIBNOTREGISTERED;
331 TRACE_(typelib)("got path from context %s\n", debugstr_w(Path));
332 *path = SysAllocString( Path );
333 return S_OK;
337 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
338 get_typelib_key( guid, wMaj, wMin, buffer );
340 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
341 if (res == ERROR_FILE_NOT_FOUND)
343 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
344 return TYPE_E_LIBNOTREGISTERED;
346 else if (res != ERROR_SUCCESS)
348 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
349 return TYPE_E_REGISTRYACCESS;
352 while (hr != S_OK)
354 LONG dwPathLen = sizeof(Path);
356 get_lcid_subkey( myLCID, syskind, buffer );
358 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
360 if (!lcid)
361 break;
362 else if (myLCID == lcid)
364 /* try with sub-langid */
365 myLCID = SUBLANGID(lcid);
367 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
369 /* try with system langid */
370 myLCID = 0;
372 else
374 break;
377 else
379 *path = SysAllocString( Path );
380 hr = S_OK;
383 RegCloseKey( hkey );
384 TRACE_(typelib)("-- 0x%08x\n", hr);
385 return hr;
388 /****************************************************************************
389 * QueryPathOfRegTypeLib [OLEAUT32.164]
391 * Gets the path to a registered type library.
393 * PARAMS
394 * guid [I] referenced guid
395 * wMaj [I] major version
396 * wMin [I] minor version
397 * lcid [I] locale id
398 * path [O] path of typelib
400 * RETURNS
401 * Success: S_OK.
402 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
403 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
404 * opened.
406 HRESULT WINAPI QueryPathOfRegTypeLib( REFGUID guid, WORD wMaj, WORD wMin, LCID lcid, LPBSTR path )
408 BOOL redir = TRUE;
409 #ifdef _WIN64
410 HRESULT hres = query_typelib_path( guid, wMaj, wMin, SYS_WIN64, lcid, path, TRUE );
411 if(SUCCEEDED(hres))
412 return hres;
413 redir = FALSE;
414 #endif
415 return query_typelib_path( guid, wMaj, wMin, SYS_WIN32, lcid, path, redir );
418 /******************************************************************************
419 * CreateTypeLib [OLEAUT32.160] creates a typelib
421 * RETURNS
422 * Success: S_OK
423 * Failure: Status
425 HRESULT WINAPI CreateTypeLib(
426 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
428 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
429 return E_FAIL;
432 /******************************************************************************
433 * LoadTypeLib [OLEAUT32.161]
435 * Loads a type library
437 * PARAMS
438 * szFile [I] Name of file to load from.
439 * pptLib [O] Pointer that receives ITypeLib object on success.
441 * RETURNS
442 * Success: S_OK
443 * Failure: Status
445 * SEE
446 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
448 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
450 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
451 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
454 /******************************************************************************
455 * LoadTypeLibEx [OLEAUT32.183]
457 * Loads and optionally registers a type library
459 * RETURNS
460 * Success: S_OK
461 * Failure: Status
463 HRESULT WINAPI LoadTypeLibEx(
464 LPCOLESTR szFile, /* [in] Name of file to load from */
465 REGKIND regkind, /* [in] Specify kind of registration */
466 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
468 WCHAR szPath[MAX_PATH+1];
469 HRESULT res;
471 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
473 if (!szFile || !pptLib)
474 return E_INVALIDARG;
476 *pptLib = NULL;
478 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
480 if (SUCCEEDED(res))
481 switch(regkind)
483 case REGKIND_DEFAULT:
484 /* don't register typelibs supplied with full path. Experimentation confirms the following */
485 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
486 (szFile[0] && (szFile[1] == ':'))) break;
487 /* else fall-through */
489 case REGKIND_REGISTER:
490 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
492 ITypeLib_Release(*pptLib);
493 *pptLib = 0;
495 break;
496 case REGKIND_NONE:
497 break;
500 TRACE(" returns %08x\n",res);
501 return res;
504 /******************************************************************************
505 * LoadRegTypeLib [OLEAUT32.162]
507 * Loads a registered type library.
509 * PARAMS
510 * rguid [I] GUID of the registered type library.
511 * wVerMajor [I] major version.
512 * wVerMinor [I] minor version.
513 * lcid [I] locale ID.
514 * ppTLib [O] pointer that receives an ITypeLib object on success.
516 * RETURNS
517 * Success: S_OK.
518 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
519 * LoadTypeLib.
521 HRESULT WINAPI LoadRegTypeLib(
522 REFGUID rguid,
523 WORD wVerMajor,
524 WORD wVerMinor,
525 LCID lcid,
526 ITypeLib **ppTLib)
528 BSTR bstr=NULL;
529 HRESULT res;
531 *ppTLib = NULL;
533 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
535 if(SUCCEEDED(res))
537 res= LoadTypeLib(bstr, ppTLib);
538 SysFreeString(bstr);
540 if ((wVerMajor!=0xffff || wVerMinor!=0xffff) && *ppTLib)
542 TLIBATTR *attr;
544 res = ITypeLib_GetLibAttr(*ppTLib, &attr);
545 if (res == S_OK)
547 BOOL mismatch = attr->wMajorVerNum != wVerMajor || attr->wMinorVerNum < wVerMinor;
548 ITypeLib_ReleaseTLibAttr(*ppTLib, attr);
550 if (mismatch)
552 ITypeLib_Release(*ppTLib);
553 *ppTLib = NULL;
554 res = TYPE_E_LIBNOTREGISTERED;
560 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
562 return res;
566 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
567 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
568 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
569 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
570 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
571 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
573 static void TLB_register_interface(TLIBATTR *libattr, LPOLESTR name, TYPEATTR *tattr, DWORD flag)
575 WCHAR keyName[60];
576 HKEY key, subKey;
578 static const WCHAR typelib_proxy_clsid[] = {'{','0','0','0','2','0','4','2','4','-',
579 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
580 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
581 static const WCHAR dispatch_proxy_clsid[] = {'{','0','0','0','2','0','4','2','0','-',
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};
585 get_interface_key( &tattr->guid, keyName );
586 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
587 KEY_WRITE | flag, NULL, &key, NULL) == ERROR_SUCCESS)
589 const WCHAR *proxy_clsid;
591 if (tattr->typekind == TKIND_INTERFACE || (tattr->wTypeFlags & TYPEFLAG_FDUAL))
592 proxy_clsid = typelib_proxy_clsid;
593 else
594 proxy_clsid = dispatch_proxy_clsid;
596 if (name)
597 RegSetValueExW(key, NULL, 0, REG_SZ,
598 (BYTE *)name, (lstrlenW(name)+1) * sizeof(OLECHAR));
600 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
601 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS) {
602 RegSetValueExW(subKey, NULL, 0, REG_SZ,
603 (const BYTE *)proxy_clsid, sizeof(typelib_proxy_clsid));
604 RegCloseKey(subKey);
607 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
608 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS) {
609 RegSetValueExW(subKey, NULL, 0, REG_SZ,
610 (const BYTE *)proxy_clsid, sizeof(typelib_proxy_clsid));
611 RegCloseKey(subKey);
614 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
615 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS)
617 WCHAR buffer[40];
618 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
619 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
621 StringFromGUID2(&libattr->guid, buffer, 40);
622 RegSetValueExW(subKey, NULL, 0, REG_SZ,
623 (BYTE *)buffer, (lstrlenW(buffer)+1) * sizeof(WCHAR));
624 swprintf(buffer, ARRAY_SIZE(buffer), fmtver, libattr->wMajorVerNum, libattr->wMinorVerNum);
625 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
626 (BYTE*)buffer, (lstrlenW(buffer)+1) * sizeof(WCHAR));
627 RegCloseKey(subKey);
630 RegCloseKey(key);
634 /******************************************************************************
635 * RegisterTypeLib [OLEAUT32.163]
636 * Adds information about a type library to the System Registry
637 * NOTES
638 * Docs: ITypeLib FAR * ptlib
639 * Docs: OLECHAR FAR* szFullPath
640 * Docs: OLECHAR FAR* szHelpDir
642 * RETURNS
643 * Success: S_OK
644 * Failure: Status
646 HRESULT WINAPI RegisterTypeLib(
647 ITypeLib * ptlib, /* [in] Pointer to the library*/
648 OLECHAR * szFullPath, /* [in] full Path of the library*/
649 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
650 may be NULL*/
652 HRESULT res;
653 TLIBATTR *attr;
654 WCHAR keyName[60];
655 WCHAR tmp[16];
656 HKEY key, subKey;
657 UINT types, tidx;
658 TYPEKIND kind;
659 DWORD disposition;
661 if (ptlib == NULL || szFullPath == NULL)
662 return E_INVALIDARG;
664 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
665 return E_FAIL;
667 #ifndef _WIN64
668 if (attr->syskind == SYS_WIN64) return TYPE_E_BADMODULEKIND;
669 #endif
671 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
673 res = S_OK;
674 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
675 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
677 LPOLESTR doc;
679 /* Set the human-readable name of the typelib */
680 if (FAILED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
681 res = E_FAIL;
682 else if (doc)
684 if (RegSetValueExW(key, NULL, 0, REG_SZ,
685 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
686 res = E_FAIL;
688 SysFreeString(doc);
691 /* Make up the name of the typelib path subkey */
692 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
694 /* Create the typelib path subkey */
695 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
696 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
698 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
699 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
700 res = E_FAIL;
702 RegCloseKey(subKey);
704 else
705 res = E_FAIL;
707 /* Create the flags subkey */
708 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
709 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
711 /* FIXME: is %u correct? */
712 static const WCHAR formatW[] = {'%','u',0};
713 WCHAR buf[20];
714 swprintf(buf, ARRAY_SIZE(buf), formatW, attr->wLibFlags);
715 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
716 (BYTE *)buf, (lstrlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
717 res = E_FAIL;
719 RegCloseKey(subKey);
721 else
722 res = E_FAIL;
724 /* create the helpdir subkey */
725 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
726 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
728 BOOL freeHelpDir = FALSE;
729 OLECHAR* pIndexStr;
731 /* if we created a new key, and helpDir was null, set the helpdir
732 to the directory which contains the typelib. However,
733 if we just opened an existing key, we leave the helpdir alone */
734 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
735 szHelpDir = SysAllocString(szFullPath);
736 pIndexStr = wcsrchr(szHelpDir, '\\');
737 if (pIndexStr) {
738 *pIndexStr = 0;
740 freeHelpDir = TRUE;
743 /* if we have an szHelpDir, set it! */
744 if (szHelpDir != NULL) {
745 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
746 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
747 res = E_FAIL;
751 /* tidy up */
752 if (freeHelpDir) SysFreeString(szHelpDir);
753 RegCloseKey(subKey);
755 } else {
756 res = E_FAIL;
759 RegCloseKey(key);
761 else
762 res = E_FAIL;
764 /* register OLE Automation-compatible interfaces for this typelib */
765 types = ITypeLib_GetTypeInfoCount(ptlib);
766 for (tidx=0; tidx<types; tidx++) {
767 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
768 LPOLESTR name = NULL;
769 ITypeInfo *tinfo = NULL;
771 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
773 switch (kind) {
774 case TKIND_INTERFACE:
775 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
776 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
777 break;
779 case TKIND_DISPATCH:
780 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
781 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
782 break;
784 default:
785 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
786 break;
789 if (tinfo) {
790 TYPEATTR *tattr = NULL;
791 ITypeInfo_GetTypeAttr(tinfo, &tattr);
793 if (tattr) {
794 TRACE_(typelib)("guid=%s, flags=%04x (",
795 debugstr_guid(&tattr->guid),
796 tattr->wTypeFlags);
798 if (TRACE_ON(typelib)) {
799 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
800 XX(FAPPOBJECT);
801 XX(FCANCREATE);
802 XX(FLICENSED);
803 XX(FPREDECLID);
804 XX(FHIDDEN);
805 XX(FCONTROL);
806 XX(FDUAL);
807 XX(FNONEXTENSIBLE);
808 XX(FOLEAUTOMATION);
809 XX(FRESTRICTED);
810 XX(FAGGREGATABLE);
811 XX(FREPLACEABLE);
812 XX(FDISPATCHABLE);
813 XX(FREVERSEBIND);
814 XX(FPROXY);
815 #undef XX
816 MESSAGE("\n");
819 /* Register all dispinterfaces (which includes dual interfaces) and
820 oleautomation interfaces */
821 if ((kind == TKIND_INTERFACE && (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
822 kind == TKIND_DISPATCH)
824 BOOL is_wow64;
825 DWORD opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
827 /* register interface<->typelib coupling */
828 TLB_register_interface(attr, name, tattr, 0);
830 /* register TLBs into the opposite registry view, too */
831 if(opposite == KEY_WOW64_32KEY ||
832 (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64))
833 TLB_register_interface(attr, name, tattr, opposite);
836 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
839 ITypeInfo_Release(tinfo);
842 SysFreeString(name);
846 ITypeLib_ReleaseTLibAttr(ptlib, attr);
848 return res;
851 static void TLB_unregister_interface(GUID *guid, REGSAM flag)
853 WCHAR subKeyName[50];
854 HKEY subKey;
856 /* the path to the type */
857 get_interface_key( guid, subKeyName );
859 /* Delete its bits */
860 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE | flag, &subKey) != ERROR_SUCCESS)
861 return;
863 RegDeleteKeyW(subKey, ProxyStubClsidW);
864 RegDeleteKeyW(subKey, ProxyStubClsid32W);
865 RegDeleteKeyW(subKey, TypeLibW);
866 RegCloseKey(subKey);
867 RegDeleteKeyExW(HKEY_CLASSES_ROOT, subKeyName, flag, 0);
870 /******************************************************************************
871 * UnRegisterTypeLib [OLEAUT32.186]
872 * Removes information about a type library from the System Registry
873 * NOTES
875 * RETURNS
876 * Success: S_OK
877 * Failure: Status
879 HRESULT WINAPI UnRegisterTypeLib(
880 REFGUID libid, /* [in] Guid of the library */
881 WORD wVerMajor, /* [in] major version */
882 WORD wVerMinor, /* [in] minor version */
883 LCID lcid, /* [in] locale id */
884 SYSKIND syskind)
886 BSTR tlibPath = NULL;
887 DWORD tmpLength;
888 WCHAR keyName[60];
889 WCHAR subKeyName[50];
890 int result = S_OK;
891 DWORD i = 0;
892 BOOL deleteOtherStuff;
893 HKEY key = NULL;
894 TYPEATTR* typeAttr = NULL;
895 TYPEKIND kind;
896 ITypeInfo* typeInfo = NULL;
897 ITypeLib* typeLib = NULL;
898 int numTypes;
900 TRACE("(IID: %s)\n",debugstr_guid(libid));
902 /* Create the path to the key */
903 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
905 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
907 TRACE("Unsupported syskind %i\n", syskind);
908 result = E_INVALIDARG;
909 goto end;
912 /* get the path to the typelib on disk */
913 if (query_typelib_path(libid, wVerMajor, wVerMinor, syskind, lcid, &tlibPath, FALSE) != S_OK) {
914 result = E_INVALIDARG;
915 goto end;
918 /* Try and open the key to the type library. */
919 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
920 result = E_INVALIDARG;
921 goto end;
924 /* Try and load the type library */
925 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib) != S_OK) {
926 result = TYPE_E_INVALIDSTATE;
927 goto end;
930 /* remove any types registered with this typelib */
931 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
932 for (i=0; i<numTypes; i++) {
933 /* get the kind of type */
934 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
935 goto enddeleteloop;
938 /* skip non-interfaces, and get type info for the type */
939 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
940 goto enddeleteloop;
942 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
943 goto enddeleteloop;
945 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
946 goto enddeleteloop;
949 if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
950 kind == TKIND_DISPATCH)
952 BOOL is_wow64;
953 REGSAM opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
955 TLB_unregister_interface(&typeAttr->guid, 0);
957 /* unregister TLBs into the opposite registry view, too */
958 if(opposite == KEY_WOW64_32KEY ||
959 (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64)) {
960 TLB_unregister_interface(&typeAttr->guid, opposite);
964 enddeleteloop:
965 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
966 typeAttr = NULL;
967 if (typeInfo) ITypeInfo_Release(typeInfo);
968 typeInfo = NULL;
971 /* Now, delete the type library path subkey */
972 get_lcid_subkey( lcid, syskind, subKeyName );
973 RegDeleteKeyW(key, subKeyName);
974 *wcsrchr( subKeyName, '\\' ) = 0; /* remove last path component */
975 RegDeleteKeyW(key, subKeyName);
977 /* check if there is anything besides the FLAGS/HELPDIR keys.
978 If there is, we don't delete them */
979 tmpLength = ARRAY_SIZE(subKeyName);
980 deleteOtherStuff = TRUE;
981 i = 0;
982 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
983 tmpLength = ARRAY_SIZE(subKeyName);
985 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
986 if (!wcscmp(subKeyName, FLAGSW)) continue;
987 if (!wcscmp(subKeyName, HELPDIRW)) continue;
988 deleteOtherStuff = FALSE;
989 break;
992 /* only delete the other parts of the key if we're absolutely sure */
993 if (deleteOtherStuff) {
994 RegDeleteKeyW(key, FLAGSW);
995 RegDeleteKeyW(key, HELPDIRW);
996 RegCloseKey(key);
997 key = NULL;
999 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
1000 *wcsrchr( keyName, '\\' ) = 0; /* remove last path component */
1001 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
1004 end:
1005 SysFreeString(tlibPath);
1006 if (typeLib) ITypeLib_Release(typeLib);
1007 if (key) RegCloseKey(key);
1008 return result;
1011 /******************************************************************************
1012 * RegisterTypeLibForUser [OLEAUT32.442]
1013 * Adds information about a type library to the user registry
1014 * NOTES
1015 * Docs: ITypeLib FAR * ptlib
1016 * Docs: OLECHAR FAR* szFullPath
1017 * Docs: OLECHAR FAR* szHelpDir
1019 * RETURNS
1020 * Success: S_OK
1021 * Failure: Status
1023 HRESULT WINAPI RegisterTypeLibForUser(
1024 ITypeLib * ptlib, /* [in] Pointer to the library*/
1025 OLECHAR * szFullPath, /* [in] full Path of the library*/
1026 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
1027 may be NULL*/
1029 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib,
1030 debugstr_w(szFullPath), debugstr_w(szHelpDir));
1031 return RegisterTypeLib(ptlib, szFullPath, szHelpDir);
1034 /******************************************************************************
1035 * UnRegisterTypeLibForUser [OLEAUT32.443]
1036 * Removes information about a type library from the user registry
1038 * RETURNS
1039 * Success: S_OK
1040 * Failure: Status
1042 HRESULT WINAPI UnRegisterTypeLibForUser(
1043 REFGUID libid, /* [in] GUID of the library */
1044 WORD wVerMajor, /* [in] major version */
1045 WORD wVerMinor, /* [in] minor version */
1046 LCID lcid, /* [in] locale id */
1047 SYSKIND syskind)
1049 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
1050 debugstr_guid(libid), wVerMajor, wVerMinor, lcid, syskind);
1051 return UnRegisterTypeLib(libid, wVerMajor, wVerMinor, lcid, syskind);
1054 /*======================= ITypeLib implementation =======================*/
1056 typedef struct tagTLBGuid {
1057 GUID guid;
1058 INT hreftype;
1059 UINT offset;
1060 struct list entry;
1061 } TLBGuid;
1063 typedef struct tagTLBCustData
1065 TLBGuid *guid;
1066 VARIANT data;
1067 struct list entry;
1068 } TLBCustData;
1070 /* data structure for import typelibs */
1071 typedef struct tagTLBImpLib
1073 int offset; /* offset in the file (MSFT)
1074 offset in nametable (SLTG)
1075 just used to identify library while reading
1076 data from file */
1077 TLBGuid *guid; /* libid */
1078 BSTR name; /* name */
1080 LCID lcid; /* lcid of imported typelib */
1082 WORD wVersionMajor; /* major version number */
1083 WORD wVersionMinor; /* minor version number */
1085 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
1086 NULL if not yet loaded */
1087 struct list entry;
1088 } TLBImpLib;
1090 typedef struct tagTLBString {
1091 BSTR str;
1092 UINT offset;
1093 struct list entry;
1094 } TLBString;
1096 /* internal ITypeLib data */
1097 typedef struct tagITypeLibImpl
1099 ITypeLib2 ITypeLib2_iface;
1100 ITypeComp ITypeComp_iface;
1101 ICreateTypeLib2 ICreateTypeLib2_iface;
1102 LONG ref;
1103 TLBGuid *guid;
1104 LCID lcid;
1105 SYSKIND syskind;
1106 int ptr_size;
1107 WORD ver_major;
1108 WORD ver_minor;
1109 WORD libflags;
1110 LCID set_lcid;
1112 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1113 * exported to the application as a UNICODE string.
1115 struct list string_list;
1116 struct list name_list;
1117 struct list guid_list;
1119 const TLBString *Name;
1120 const TLBString *DocString;
1121 const TLBString *HelpFile;
1122 const TLBString *HelpStringDll;
1123 DWORD dwHelpContext;
1124 int TypeInfoCount; /* nr of typeinfo's in librarry */
1125 struct tagITypeInfoImpl **typeinfos;
1126 struct list custdata_list;
1127 struct list implib_list;
1128 int ctTypeDesc; /* number of items in type desc array */
1129 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1130 library. Only used while reading MSFT
1131 typelibs */
1132 struct list ref_list; /* list of ref types in this typelib */
1133 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1136 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1137 struct list entry;
1138 WCHAR *path;
1139 INT index;
1140 } ITypeLibImpl;
1142 static const ITypeLib2Vtbl tlbvt;
1143 static const ITypeCompVtbl tlbtcvt;
1144 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl;
1146 static inline ITypeLibImpl *impl_from_ITypeLib2(ITypeLib2 *iface)
1148 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeLib2_iface);
1151 static inline ITypeLibImpl *impl_from_ITypeLib(ITypeLib *iface)
1153 return impl_from_ITypeLib2((ITypeLib2*)iface);
1156 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1158 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeComp_iface);
1161 static inline ITypeLibImpl *impl_from_ICreateTypeLib2( ICreateTypeLib2 *iface )
1163 return CONTAINING_RECORD(iface, ITypeLibImpl, ICreateTypeLib2_iface);
1166 /* ITypeLib methods */
1167 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1168 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1170 /*======================= ITypeInfo implementation =======================*/
1172 /* data for referenced types */
1173 typedef struct tagTLBRefType
1175 INT index; /* Type index for internal ref or for external ref
1176 it the format is SLTG. -2 indicates to
1177 use guid */
1179 TYPEKIND tkind;
1180 TLBGuid *guid; /* guid of the referenced type */
1181 /* if index == TLB_REF_USE_GUID */
1183 HREFTYPE reference; /* The href of this ref */
1184 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1185 TLB_REF_INTERNAL for internal refs
1186 TLB_REF_NOT_FOUND for broken refs */
1188 struct list entry;
1189 } TLBRefType;
1191 #define TLB_REF_USE_GUID -2
1193 #define TLB_REF_INTERNAL (void*)-2
1194 #define TLB_REF_NOT_FOUND (void*)-1
1196 /* internal Parameter data */
1197 typedef struct tagTLBParDesc
1199 const TLBString *Name;
1200 struct list custdata_list;
1201 } TLBParDesc;
1203 /* internal Function data */
1204 typedef struct tagTLBFuncDesc
1206 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1207 const TLBString *Name; /* the name of this function */
1208 TLBParDesc *pParamDesc; /* array with param names and custom data */
1209 int helpcontext;
1210 int HelpStringContext;
1211 const TLBString *HelpString;
1212 const TLBString *Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1213 struct list custdata_list;
1214 } TLBFuncDesc;
1216 /* internal Variable data */
1217 typedef struct tagTLBVarDesc
1219 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1220 VARDESC *vardesc_create; /* additional data needed for storing VARDESC */
1221 const TLBString *Name; /* the name of this variable */
1222 int HelpContext;
1223 int HelpStringContext;
1224 const TLBString *HelpString;
1225 struct list custdata_list;
1226 } TLBVarDesc;
1228 /* internal implemented interface data */
1229 typedef struct tagTLBImplType
1231 HREFTYPE hRef; /* hRef of interface */
1232 int implflags; /* IMPLFLAG_*s */
1233 struct list custdata_list;
1234 } TLBImplType;
1236 /* internal TypeInfo data */
1237 typedef struct tagITypeInfoImpl
1239 ITypeInfo2 ITypeInfo2_iface;
1240 ITypeComp ITypeComp_iface;
1241 ICreateTypeInfo2 ICreateTypeInfo2_iface;
1242 LONG ref;
1243 BOOL not_attached_to_typelib;
1244 BOOL needs_layout;
1246 TLBGuid *guid;
1247 TYPEATTR typeattr;
1248 TYPEDESC *tdescAlias;
1250 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1251 int index; /* index in this typelib; */
1252 HREFTYPE hreftype; /* hreftype for app object binding */
1253 /* type libs seem to store the doc strings in ascii
1254 * so why should we do it in unicode?
1256 const TLBString *Name;
1257 const TLBString *DocString;
1258 const TLBString *DllName;
1259 const TLBString *Schema;
1260 DWORD dwHelpContext;
1261 DWORD dwHelpStringContext;
1263 /* functions */
1264 TLBFuncDesc *funcdescs;
1266 /* variables */
1267 TLBVarDesc *vardescs;
1269 /* Implemented Interfaces */
1270 TLBImplType *impltypes;
1272 struct list *pcustdata_list;
1273 struct list custdata_list;
1274 } ITypeInfoImpl;
1276 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1278 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeComp_iface);
1281 static inline ITypeInfoImpl *impl_from_ITypeInfo2( ITypeInfo2 *iface )
1283 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeInfo2_iface);
1286 static inline ITypeInfoImpl *impl_from_ITypeInfo( ITypeInfo *iface )
1288 return impl_from_ITypeInfo2((ITypeInfo2*)iface);
1291 static inline ITypeInfoImpl *info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2 *iface )
1293 return CONTAINING_RECORD(iface, ITypeInfoImpl, ICreateTypeInfo2_iface);
1296 static const ITypeInfo2Vtbl tinfvt;
1297 static const ITypeCompVtbl tcompvt;
1298 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl;
1300 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1301 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1303 typedef struct tagTLBContext
1305 unsigned int oStart; /* start of TLB in file */
1306 unsigned int pos; /* current pos */
1307 unsigned int length; /* total length */
1308 void *mapping; /* memory mapping */
1309 MSFT_SegDir * pTblDir;
1310 ITypeLibImpl* pLibInfo;
1311 } TLBContext;
1314 static inline BSTR TLB_get_bstr(const TLBString *str)
1316 return str != NULL ? str->str : NULL;
1319 static inline int TLB_str_memcmp(void *left, const TLBString *str, DWORD len)
1321 if(!str)
1322 return 1;
1323 return memcmp(left, str->str, len);
1326 static inline const GUID *TLB_get_guidref(const TLBGuid *guid)
1328 return guid != NULL ? &guid->guid : NULL;
1331 static inline const GUID *TLB_get_guid_null(const TLBGuid *guid)
1333 return guid != NULL ? &guid->guid : &GUID_NULL;
1336 static int get_ptr_size(SYSKIND syskind)
1338 switch(syskind){
1339 case SYS_WIN64:
1340 return 8;
1341 case SYS_WIN32:
1342 case SYS_MAC:
1343 case SYS_WIN16:
1344 return 4;
1346 WARN("Unhandled syskind: 0x%x\n", syskind);
1347 return 4;
1351 debug
1353 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1354 if (pTD->vt & VT_RESERVED)
1355 szVarType += strlen(strcpy(szVarType, "reserved | "));
1356 if (pTD->vt & VT_BYREF)
1357 szVarType += strlen(strcpy(szVarType, "ref to "));
1358 if (pTD->vt & VT_ARRAY)
1359 szVarType += strlen(strcpy(szVarType, "array of "));
1360 if (pTD->vt & VT_VECTOR)
1361 szVarType += strlen(strcpy(szVarType, "vector of "));
1362 switch(pTD->vt & VT_TYPEMASK) {
1363 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1364 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1365 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1366 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1367 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1368 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1369 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1370 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1371 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1372 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1373 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1374 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1375 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1376 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1377 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1378 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1379 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1380 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1381 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1382 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1383 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1384 pTD->u.hreftype); break;
1385 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1386 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1387 case VT_PTR: sprintf(szVarType, "ptr to ");
1388 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1389 break;
1390 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1391 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1392 break;
1393 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1394 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1395 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1396 break;
1398 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1402 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1403 char buf[200];
1404 USHORT flags = edesc->u.paramdesc.wParamFlags;
1405 dump_TypeDesc(&edesc->tdesc,buf);
1406 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1407 MESSAGE("\t\tu.paramdesc.wParamFlags");
1408 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1409 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1410 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1411 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1412 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1413 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1414 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1415 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1416 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1418 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1419 int i;
1420 MESSAGE("memid is %08x\n",funcdesc->memid);
1421 for (i=0;i<funcdesc->cParams;i++) {
1422 MESSAGE("Param %d:\n",i);
1423 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1425 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1426 switch (funcdesc->funckind) {
1427 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1428 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1429 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1430 case FUNC_STATIC: MESSAGE("static");break;
1431 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1432 default: MESSAGE("unknown");break;
1434 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1435 switch (funcdesc->invkind) {
1436 case INVOKE_FUNC: MESSAGE("func");break;
1437 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1438 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1439 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1441 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1442 switch (funcdesc->callconv) {
1443 case CC_CDECL: MESSAGE("cdecl");break;
1444 case CC_PASCAL: MESSAGE("pascal");break;
1445 case CC_STDCALL: MESSAGE("stdcall");break;
1446 case CC_SYSCALL: MESSAGE("syscall");break;
1447 default:break;
1449 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1450 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1451 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1453 MESSAGE("\telemdescFunc (return value type):\n");
1454 dump_ELEMDESC(&funcdesc->elemdescFunc);
1457 static const char * const typekind_desc[] =
1459 "TKIND_ENUM",
1460 "TKIND_RECORD",
1461 "TKIND_MODULE",
1462 "TKIND_INTERFACE",
1463 "TKIND_DISPATCH",
1464 "TKIND_COCLASS",
1465 "TKIND_ALIAS",
1466 "TKIND_UNION",
1467 "TKIND_MAX"
1470 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1472 int i;
1473 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd->Name)), pfd->funcdesc.cParams);
1474 for (i=0;i<pfd->funcdesc.cParams;i++)
1475 MESSAGE("\tparm%d: %s\n",i,debugstr_w(TLB_get_bstr(pfd->pParamDesc[i].Name)));
1478 dump_FUNCDESC(&(pfd->funcdesc));
1480 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd->HelpString)));
1481 if(pfd->Entry == NULL)
1482 MESSAGE("\tentry: (null)\n");
1483 else if(pfd->Entry == (void*)-1)
1484 MESSAGE("\tentry: invalid\n");
1485 else if(IS_INTRESOURCE(pfd->Entry))
1486 MESSAGE("\tentry: %p\n", pfd->Entry);
1487 else
1488 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd->Entry)));
1490 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1492 while (n)
1494 dump_TLBFuncDescOne(pfd);
1495 ++pfd;
1496 --n;
1499 static void dump_TLBVarDesc(const TLBVarDesc * pvd, UINT n)
1501 while (n)
1503 TRACE_(typelib)("%s\n", debugstr_w(TLB_get_bstr(pvd->Name)));
1504 ++pvd;
1505 --n;
1509 static void dump_TLBImpLib(const TLBImpLib *import)
1511 TRACE_(typelib)("%s %s\n", debugstr_guid(TLB_get_guidref(import->guid)),
1512 debugstr_w(import->name));
1513 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1514 import->wVersionMinor, import->lcid, import->offset);
1517 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1519 TLBRefType *ref;
1521 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1523 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1524 if(ref->index == -1)
1525 TRACE_(typelib)("%s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
1526 else
1527 TRACE_(typelib)("type no: %d\n", ref->index);
1529 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1531 TRACE_(typelib)("in lib\n");
1532 dump_TLBImpLib(ref->pImpTLInfo);
1537 static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1539 if(!impl)
1540 return;
1541 while (n) {
1542 TRACE_(typelib)("implementing/inheriting interface hRef = %x implflags %x\n",
1543 impl->hRef, impl->implflags);
1544 ++impl;
1545 --n;
1549 static void dump_DispParms(const DISPPARAMS * pdp)
1551 unsigned int index;
1553 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1555 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1557 TRACE("named args:\n");
1558 for (index = 0; index < pdp->cNamedArgs; index++)
1559 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1562 if (pdp->cArgs && pdp->rgvarg)
1564 TRACE("args:\n");
1565 for (index = 0; index < pdp->cArgs; index++)
1566 TRACE(" [%d] %s\n", index, debugstr_variant(pdp->rgvarg+index));
1570 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1572 TRACE("%p ref=%u\n", pty, pty->ref);
1573 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty->Name)), debugstr_w(TLB_get_bstr(pty->DocString)));
1574 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty->guid)));
1575 TRACE("kind:%s\n", typekind_desc[pty->typeattr.typekind]);
1576 TRACE("fct:%u var:%u impl:%u\n", pty->typeattr.cFuncs, pty->typeattr.cVars, pty->typeattr.cImplTypes);
1577 TRACE("wTypeFlags: 0x%04x\n", pty->typeattr.wTypeFlags);
1578 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1579 if (pty->typeattr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty->DllName)));
1580 if (TRACE_ON(ole))
1581 dump_TLBFuncDesc(pty->funcdescs, pty->typeattr.cFuncs);
1582 dump_TLBVarDesc(pty->vardescs, pty->typeattr.cVars);
1583 dump_TLBImplType(pty->impltypes, pty->typeattr.cImplTypes);
1586 static void dump_VARDESC(const VARDESC *v)
1588 MESSAGE("memid %d\n",v->memid);
1589 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1590 MESSAGE("oInst %d\n",v->u.oInst);
1591 dump_ELEMDESC(&(v->elemdescVar));
1592 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1593 MESSAGE("varkind %d\n",v->varkind);
1596 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1598 /* VT_LPWSTR is largest type that, may appear in type description */
1599 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1600 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1601 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1602 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1603 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1604 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1605 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1606 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1609 static void TLB_abort(void)
1611 DebugBreak();
1614 /* returns the size required for a deep copy of a typedesc into a
1615 * flat buffer */
1616 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1618 SIZE_T size = 0;
1620 if (alloc_initial_space)
1621 size += sizeof(TYPEDESC);
1623 switch (tdesc->vt)
1625 case VT_PTR:
1626 case VT_SAFEARRAY:
1627 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1628 break;
1629 case VT_CARRAY:
1630 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1631 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1632 break;
1634 return size;
1637 /* deep copy a typedesc into a flat buffer */
1638 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1640 if (!dest)
1642 dest = buffer;
1643 buffer = (char *)buffer + sizeof(TYPEDESC);
1646 *dest = *src;
1648 switch (src->vt)
1650 case VT_PTR:
1651 case VT_SAFEARRAY:
1652 dest->u.lptdesc = buffer;
1653 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1654 break;
1655 case VT_CARRAY:
1656 dest->u.lpadesc = buffer;
1657 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1658 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1659 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1660 break;
1662 return buffer;
1665 /* free custom data allocated by MSFT_CustData */
1666 static inline void TLB_FreeCustData(struct list *custdata_list)
1668 TLBCustData *cd, *cdn;
1669 LIST_FOR_EACH_ENTRY_SAFE(cd, cdn, custdata_list, TLBCustData, entry)
1671 list_remove(&cd->entry);
1672 VariantClear(&cd->data);
1673 heap_free(cd);
1677 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1679 DWORD len;
1680 BSTR ret;
1682 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1683 ret = SysAllocStringLen(NULL, len - 1);
1684 if (!ret) return ret;
1685 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1686 return ret;
1689 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(TLBFuncDesc *funcdescs,
1690 UINT n, MEMBERID memid)
1692 while(n){
1693 if(funcdescs->funcdesc.memid == memid)
1694 return funcdescs;
1695 ++funcdescs;
1696 --n;
1698 return NULL;
1701 static inline TLBVarDesc *TLB_get_vardesc_by_memberid(TLBVarDesc *vardescs,
1702 UINT n, MEMBERID memid)
1704 while(n){
1705 if(vardescs->vardesc.memid == memid)
1706 return vardescs;
1707 ++vardescs;
1708 --n;
1710 return NULL;
1713 static inline TLBVarDesc *TLB_get_vardesc_by_name(TLBVarDesc *vardescs,
1714 UINT n, const OLECHAR *name)
1716 while(n){
1717 if(!lstrcmpiW(TLB_get_bstr(vardescs->Name), name))
1718 return vardescs;
1719 ++vardescs;
1720 --n;
1722 return NULL;
1725 static inline TLBCustData *TLB_get_custdata_by_guid(struct list *custdata_list, REFGUID guid)
1727 TLBCustData *cust_data;
1728 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1729 if(IsEqualIID(TLB_get_guid_null(cust_data->guid), guid))
1730 return cust_data;
1731 return NULL;
1734 static inline ITypeInfoImpl *TLB_get_typeinfo_by_name(ITypeInfoImpl **typeinfos,
1735 UINT n, const OLECHAR *name)
1737 while(n){
1738 if(!lstrcmpiW(TLB_get_bstr((*typeinfos)->Name), name))
1739 return *typeinfos;
1740 ++typeinfos;
1741 --n;
1743 return NULL;
1746 static void TLBVarDesc_Constructor(TLBVarDesc *var_desc)
1748 list_init(&var_desc->custdata_list);
1751 static TLBVarDesc *TLBVarDesc_Alloc(UINT n)
1753 TLBVarDesc *ret;
1755 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1756 if(!ret)
1757 return NULL;
1759 while(n){
1760 TLBVarDesc_Constructor(&ret[n-1]);
1761 --n;
1764 return ret;
1767 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1769 TLBParDesc *ret;
1771 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1772 if(!ret)
1773 return NULL;
1775 while(n){
1776 list_init(&ret[n-1].custdata_list);
1777 --n;
1780 return ret;
1783 static void TLBFuncDesc_Constructor(TLBFuncDesc *func_desc)
1785 list_init(&func_desc->custdata_list);
1788 static TLBFuncDesc *TLBFuncDesc_Alloc(UINT n)
1790 TLBFuncDesc *ret;
1792 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1793 if(!ret)
1794 return NULL;
1796 while(n){
1797 TLBFuncDesc_Constructor(&ret[n-1]);
1798 --n;
1801 return ret;
1804 static void TLBImplType_Constructor(TLBImplType *impl)
1806 list_init(&impl->custdata_list);
1809 static TLBImplType *TLBImplType_Alloc(UINT n)
1811 TLBImplType *ret;
1813 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1814 if(!ret)
1815 return NULL;
1817 while(n){
1818 TLBImplType_Constructor(&ret[n-1]);
1819 --n;
1822 return ret;
1825 static TLBGuid *TLB_append_guid(struct list *guid_list,
1826 const GUID *new_guid, HREFTYPE hreftype)
1828 TLBGuid *guid;
1830 LIST_FOR_EACH_ENTRY(guid, guid_list, TLBGuid, entry) {
1831 if (IsEqualGUID(&guid->guid, new_guid))
1832 return guid;
1835 guid = heap_alloc(sizeof(TLBGuid));
1836 if (!guid)
1837 return NULL;
1839 memcpy(&guid->guid, new_guid, sizeof(GUID));
1840 guid->hreftype = hreftype;
1842 list_add_tail(guid_list, &guid->entry);
1844 return guid;
1847 static HRESULT TLB_set_custdata(struct list *custdata_list, TLBGuid *tlbguid, VARIANT *var)
1849 TLBCustData *cust_data;
1851 switch(V_VT(var)){
1852 case VT_I4:
1853 case VT_R4:
1854 case VT_UI4:
1855 case VT_INT:
1856 case VT_UINT:
1857 case VT_HRESULT:
1858 case VT_BSTR:
1859 break;
1860 default:
1861 return DISP_E_BADVARTYPE;
1864 cust_data = TLB_get_custdata_by_guid(custdata_list, TLB_get_guid_null(tlbguid));
1866 if (!cust_data) {
1867 cust_data = heap_alloc(sizeof(TLBCustData));
1868 if (!cust_data)
1869 return E_OUTOFMEMORY;
1871 cust_data->guid = tlbguid;
1872 VariantInit(&cust_data->data);
1874 list_add_tail(custdata_list, &cust_data->entry);
1875 }else
1876 VariantClear(&cust_data->data);
1878 return VariantCopy(&cust_data->data, var);
1881 static TLBString *TLB_append_str(struct list *string_list, BSTR new_str)
1883 TLBString *str;
1885 if(!new_str)
1886 return NULL;
1888 LIST_FOR_EACH_ENTRY(str, string_list, TLBString, entry) {
1889 if (wcscmp(str->str, new_str) == 0)
1890 return str;
1893 str = heap_alloc(sizeof(TLBString));
1894 if (!str)
1895 return NULL;
1897 str->str = SysAllocString(new_str);
1898 if (!str->str) {
1899 heap_free(str);
1900 return NULL;
1903 list_add_tail(string_list, &str->entry);
1905 return str;
1908 static HRESULT TLB_get_size_from_hreftype(ITypeInfoImpl *info, HREFTYPE href,
1909 ULONG *size, WORD *align)
1911 ITypeInfo *other;
1912 TYPEATTR *attr;
1913 HRESULT hr;
1915 hr = ITypeInfo2_GetRefTypeInfo(&info->ITypeInfo2_iface, href, &other);
1916 if(FAILED(hr))
1917 return hr;
1919 hr = ITypeInfo_GetTypeAttr(other, &attr);
1920 if(FAILED(hr)){
1921 ITypeInfo_Release(other);
1922 return hr;
1925 if(size)
1926 *size = attr->cbSizeInstance;
1927 if(align)
1928 *align = attr->cbAlignment;
1930 ITypeInfo_ReleaseTypeAttr(other, attr);
1931 ITypeInfo_Release(other);
1933 return S_OK;
1936 static HRESULT TLB_size_instance(ITypeInfoImpl *info, SYSKIND sys,
1937 TYPEDESC *tdesc, ULONG *size, WORD *align)
1939 ULONG i, sub, ptr_size;
1940 HRESULT hr;
1942 ptr_size = get_ptr_size(sys);
1944 switch(tdesc->vt){
1945 case VT_VOID:
1946 *size = 0;
1947 break;
1948 case VT_I1:
1949 case VT_UI1:
1950 *size = 1;
1951 break;
1952 case VT_I2:
1953 case VT_BOOL:
1954 case VT_UI2:
1955 *size = 2;
1956 break;
1957 case VT_I4:
1958 case VT_R4:
1959 case VT_ERROR:
1960 case VT_UI4:
1961 case VT_INT:
1962 case VT_UINT:
1963 case VT_HRESULT:
1964 *size = 4;
1965 break;
1966 case VT_R8:
1967 case VT_I8:
1968 case VT_UI8:
1969 *size = 8;
1970 break;
1971 case VT_BSTR:
1972 case VT_DISPATCH:
1973 case VT_UNKNOWN:
1974 case VT_PTR:
1975 case VT_SAFEARRAY:
1976 case VT_LPSTR:
1977 case VT_LPWSTR:
1978 *size = ptr_size;
1979 break;
1980 case VT_DATE:
1981 *size = sizeof(DATE);
1982 break;
1983 case VT_VARIANT:
1984 *size = sizeof(VARIANT);
1985 #ifdef _WIN64
1986 if(sys == SYS_WIN32)
1987 *size -= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
1988 #endif
1989 break;
1990 case VT_DECIMAL:
1991 *size = sizeof(DECIMAL);
1992 break;
1993 case VT_CY:
1994 *size = sizeof(CY);
1995 break;
1996 case VT_CARRAY:
1997 *size = 0;
1998 for(i = 0; i < tdesc->u.lpadesc->cDims; ++i)
1999 *size += tdesc->u.lpadesc->rgbounds[i].cElements;
2000 hr = TLB_size_instance(info, sys, &tdesc->u.lpadesc->tdescElem, &sub, align);
2001 if(FAILED(hr))
2002 return hr;
2003 *size *= sub;
2004 return S_OK;
2005 case VT_USERDEFINED:
2006 return TLB_get_size_from_hreftype(info, tdesc->u.hreftype, size, align);
2007 default:
2008 FIXME("Unsized VT: 0x%x\n", tdesc->vt);
2009 return E_FAIL;
2012 if(align){
2013 if(*size < 4)
2014 *align = *size;
2015 else
2016 *align = 4;
2019 return S_OK;
2022 /**********************************************************************
2024 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2027 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
2029 if (where != DO_NOT_SEEK)
2031 where += pcx->oStart;
2032 if (where > pcx->length)
2034 /* FIXME */
2035 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
2036 TLB_abort();
2038 pcx->pos = where;
2042 /* read function */
2043 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
2045 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2046 pcx->pos, count, pcx->oStart, pcx->length, where);
2048 MSFT_Seek(pcx, where);
2049 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
2050 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
2051 pcx->pos += count;
2052 return count;
2055 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
2056 LONG where )
2058 DWORD ret;
2060 ret = MSFT_Read(buffer, count, pcx, where);
2061 FromLEDWords(buffer, ret);
2063 return ret;
2066 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
2067 LONG where )
2069 DWORD ret;
2071 ret = MSFT_Read(buffer, count, pcx, where);
2072 FromLEWords(buffer, ret);
2074 return ret;
2077 static HRESULT MSFT_ReadAllGuids(TLBContext *pcx)
2079 TLBGuid *guid;
2080 MSFT_GuidEntry entry;
2081 int offs = 0;
2083 MSFT_Seek(pcx, pcx->pTblDir->pGuidTab.offset);
2084 while (1) {
2085 if (offs >= pcx->pTblDir->pGuidTab.length)
2086 return S_OK;
2088 MSFT_ReadLEWords(&entry, sizeof(MSFT_GuidEntry), pcx, DO_NOT_SEEK);
2090 guid = heap_alloc(sizeof(TLBGuid));
2092 guid->offset = offs;
2093 guid->guid = entry.guid;
2094 guid->hreftype = entry.hreftype;
2096 list_add_tail(&pcx->pLibInfo->guid_list, &guid->entry);
2098 offs += sizeof(MSFT_GuidEntry);
2102 static TLBGuid *MSFT_ReadGuid( int offset, TLBContext *pcx)
2104 TLBGuid *ret;
2106 LIST_FOR_EACH_ENTRY(ret, &pcx->pLibInfo->guid_list, TLBGuid, entry){
2107 if(ret->offset == offset){
2108 TRACE_(typelib)("%s\n", debugstr_guid(&ret->guid));
2109 return ret;
2113 return NULL;
2116 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
2118 MSFT_NameIntro niName;
2120 if (offset < 0)
2122 ERR_(typelib)("bad offset %d\n", offset);
2123 return -1;
2126 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
2127 pcx->pTblDir->pNametab.offset+offset);
2129 return niName.hreftype;
2132 static HRESULT MSFT_ReadAllNames(TLBContext *pcx)
2134 char *string;
2135 MSFT_NameIntro intro;
2136 INT16 len_piece;
2137 int offs = 0, lengthInChars;
2139 MSFT_Seek(pcx, pcx->pTblDir->pNametab.offset);
2140 while (1) {
2141 TLBString *tlbstr;
2143 if (offs >= pcx->pTblDir->pNametab.length)
2144 return S_OK;
2146 MSFT_ReadLEWords(&intro, sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2147 intro.namelen &= 0xFF;
2148 len_piece = intro.namelen + sizeof(MSFT_NameIntro);
2149 if(len_piece % 4)
2150 len_piece = (len_piece + 4) & ~0x3;
2151 if(len_piece < 8)
2152 len_piece = 8;
2154 string = heap_alloc(len_piece + 1);
2155 MSFT_Read(string, len_piece - sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2156 string[intro.namelen] = '\0';
2158 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2159 string, -1, NULL, 0);
2160 if (!lengthInChars) {
2161 heap_free(string);
2162 return E_UNEXPECTED;
2165 tlbstr = heap_alloc(sizeof(TLBString));
2167 tlbstr->offset = offs;
2168 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2169 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2171 heap_free(string);
2173 list_add_tail(&pcx->pLibInfo->name_list, &tlbstr->entry);
2175 offs += len_piece;
2179 static TLBString *MSFT_ReadName( TLBContext *pcx, int offset)
2181 TLBString *tlbstr;
2183 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->name_list, TLBString, entry) {
2184 if (tlbstr->offset == offset) {
2185 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2186 return tlbstr;
2190 return NULL;
2193 static TLBString *MSFT_ReadString( TLBContext *pcx, int offset)
2195 TLBString *tlbstr;
2197 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->string_list, TLBString, entry) {
2198 if (tlbstr->offset == offset) {
2199 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2200 return tlbstr;
2204 return NULL;
2208 * read a value and fill a VARIANT structure
2210 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
2212 int size;
2214 TRACE_(typelib)("\n");
2216 if(offset <0) { /* data are packed in here */
2217 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
2218 V_I4(pVar) = offset & 0x3ffffff;
2219 return;
2221 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
2222 pcx->pTblDir->pCustData.offset + offset );
2223 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
2224 switch (V_VT(pVar)){
2225 case VT_EMPTY: /* FIXME: is this right? */
2226 case VT_NULL: /* FIXME: is this right? */
2227 case VT_I2 : /* this should not happen */
2228 case VT_I4 :
2229 case VT_R4 :
2230 case VT_ERROR :
2231 case VT_BOOL :
2232 case VT_I1 :
2233 case VT_UI1 :
2234 case VT_UI2 :
2235 case VT_UI4 :
2236 case VT_INT :
2237 case VT_UINT :
2238 case VT_VOID : /* FIXME: is this right? */
2239 case VT_HRESULT :
2240 size=4; break;
2241 case VT_R8 :
2242 case VT_CY :
2243 case VT_DATE :
2244 case VT_I8 :
2245 case VT_UI8 :
2246 case VT_DECIMAL : /* FIXME: is this right? */
2247 case VT_FILETIME :
2248 size=8;break;
2249 /* pointer types with known behaviour */
2250 case VT_BSTR :{
2251 char * ptr;
2252 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
2253 if(size == -1){
2254 V_BSTR(pVar) = NULL;
2255 }else{
2256 ptr = heap_alloc_zero(size);
2257 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);
2258 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
2259 /* FIXME: do we need a AtoW conversion here? */
2260 V_UNION(pVar, bstrVal[size])='\0';
2261 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
2262 heap_free(ptr);
2265 size=-4; break;
2266 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2267 case VT_DISPATCH :
2268 case VT_VARIANT :
2269 case VT_UNKNOWN :
2270 case VT_PTR :
2271 case VT_SAFEARRAY :
2272 case VT_CARRAY :
2273 case VT_USERDEFINED :
2274 case VT_LPSTR :
2275 case VT_LPWSTR :
2276 case VT_BLOB :
2277 case VT_STREAM :
2278 case VT_STORAGE :
2279 case VT_STREAMED_OBJECT :
2280 case VT_STORED_OBJECT :
2281 case VT_BLOB_OBJECT :
2282 case VT_CF :
2283 case VT_CLSID :
2284 default:
2285 size=0;
2286 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2287 V_VT(pVar));
2290 if(size>0) /* (big|small) endian correct? */
2291 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
2292 return;
2295 * create a linked list with custom data
2297 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
2299 MSFT_CDGuid entry;
2300 TLBCustData* pNew;
2301 int count=0;
2303 TRACE_(typelib)("\n");
2305 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
2307 while(offset >=0){
2308 count++;
2309 pNew=heap_alloc_zero(sizeof(TLBCustData));
2310 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
2311 pNew->guid = MSFT_ReadGuid(entry.GuidOffset, pcx);
2312 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
2313 list_add_head(custdata_list, &pNew->entry);
2314 offset = entry.next;
2316 return count;
2319 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd)
2321 if(type <0)
2322 pTd->vt=type & VT_TYPEMASK;
2323 else
2324 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
2326 TRACE_(typelib)("vt type = %X\n", pTd->vt);
2329 static BOOL TLB_is_propgetput(INVOKEKIND invkind)
2331 return (invkind == INVOKE_PROPERTYGET ||
2332 invkind == INVOKE_PROPERTYPUT ||
2333 invkind == INVOKE_PROPERTYPUTREF);
2336 static void
2337 MSFT_DoFuncs(TLBContext* pcx,
2338 ITypeInfoImpl* pTI,
2339 int cFuncs,
2340 int cVars,
2341 int offset,
2342 TLBFuncDesc** pptfd)
2345 * member information is stored in a data structure at offset
2346 * indicated by the memoffset field of the typeinfo structure
2347 * There are several distinctive parts.
2348 * The first part starts with a field that holds the total length
2349 * of this (first) part excluding this field. Then follow the records,
2350 * for each member there is one record.
2352 * The first entry is always the length of the record (including this
2353 * length word).
2354 * The rest of the record depends on the type of the member. If there is
2355 * a field indicating the member type (function, variable, interface, etc)
2356 * I have not found it yet. At this time we depend on the information
2357 * in the type info and the usual order how things are stored.
2359 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2360 * for each member;
2362 * Third is an equal sized array with file offsets to the name entry
2363 * of each member.
2365 * The fourth and last (?) part is an array with offsets to the records
2366 * in the first part of this file segment.
2369 int infolen, nameoffset, reclength, i;
2370 int recoffset = offset + sizeof(INT);
2372 char *recbuf = heap_alloc(0xffff);
2373 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2374 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2376 TRACE_(typelib)("\n");
2378 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2380 *pptfd = TLBFuncDesc_Alloc(cFuncs);
2381 ptfd = *pptfd;
2382 for ( i = 0; i < cFuncs ; i++ )
2384 int optional;
2386 /* name, eventually add to a hash table */
2387 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2388 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2390 /* read the function information record */
2391 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2393 reclength &= 0xffff;
2395 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2397 /* size without argument data */
2398 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2399 if (pFuncRec->FKCCIC & 0x1000)
2400 optional -= pFuncRec->nrargs * sizeof(INT);
2402 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2403 ptfd->helpcontext = pFuncRec->HelpContext;
2405 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2406 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2408 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2410 if (pFuncRec->FKCCIC & 0x2000 )
2412 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2413 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2414 ptfd->Entry = (TLBString*)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2416 else
2417 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2419 else
2420 ptfd->Entry = (TLBString*)-1;
2422 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2423 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2425 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2426 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2428 /* fill the FuncDesc Structure */
2429 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2430 offset + infolen + ( i + 1) * sizeof(INT));
2432 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2433 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2434 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2435 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2436 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2437 ptfd->funcdesc.oVft = (pFuncRec->VtableOffset & ~1) * sizeof(void *) / pTI->pTypeLib->ptr_size;
2438 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2440 /* nameoffset is sometimes -1 on the second half of a propget/propput
2441 * pair of functions */
2442 if ((nameoffset == -1) && (i > 0) &&
2443 TLB_is_propgetput(ptfd_prev->funcdesc.invkind) &&
2444 TLB_is_propgetput(ptfd->funcdesc.invkind))
2445 ptfd->Name = ptfd_prev->Name;
2446 else
2447 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2449 MSFT_GetTdesc(pcx,
2450 pFuncRec->DataType,
2451 &ptfd->funcdesc.elemdescFunc.tdesc);
2453 /* do the parameters/arguments */
2454 if(pFuncRec->nrargs)
2456 int j = 0;
2457 MSFT_ParameterInfo paraminfo;
2459 ptfd->funcdesc.lprgelemdescParam =
2460 heap_alloc_zero(pFuncRec->nrargs * (sizeof(ELEMDESC) + sizeof(PARAMDESCEX)));
2462 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2464 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2465 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2467 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2469 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2471 MSFT_GetTdesc(pcx,
2472 paraminfo.DataType,
2473 &elemdesc->tdesc);
2475 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2477 /* name */
2478 if (paraminfo.oName != -1)
2479 ptfd->pParamDesc[j].Name =
2480 MSFT_ReadName( pcx, paraminfo.oName );
2481 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(TLB_get_bstr(ptfd->pParamDesc[j].Name)));
2483 /* default value */
2484 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2485 (pFuncRec->FKCCIC & 0x1000) )
2487 INT* pInt = (INT *)((char *)pFuncRec +
2488 reclength -
2489 (pFuncRec->nrargs * 4) * sizeof(INT) );
2491 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2493 pParamDesc->pparamdescex = (PARAMDESCEX*)(ptfd->funcdesc.lprgelemdescParam+pFuncRec->nrargs)+j;
2494 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2496 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2497 pInt[j], pcx);
2499 else
2500 elemdesc->u.paramdesc.pparamdescex = NULL;
2502 /* custom info */
2503 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2504 j*sizeof(pFuncRec->oArgCustData[0])) &&
2505 pFuncRec->FKCCIC & 0x80 )
2507 MSFT_CustData(pcx,
2508 pFuncRec->oArgCustData[j],
2509 &ptfd->pParamDesc[j].custdata_list);
2512 /* SEEK value = jump to offset,
2513 * from there jump to the end of record,
2514 * go back by (j-1) arguments
2516 MSFT_ReadLEDWords( &paraminfo ,
2517 sizeof(MSFT_ParameterInfo), pcx,
2518 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2519 * sizeof(MSFT_ParameterInfo)));
2523 /* scode is not used: archaic win16 stuff FIXME: right? */
2524 ptfd->funcdesc.cScodes = 0 ;
2525 ptfd->funcdesc.lprgscode = NULL ;
2527 ptfd_prev = ptfd;
2528 ++ptfd;
2529 recoffset += reclength;
2531 heap_free(recbuf);
2534 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2535 int cVars, int offset, TLBVarDesc ** pptvd)
2537 int infolen, nameoffset, reclength;
2538 char recbuf[256];
2539 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2540 TLBVarDesc *ptvd;
2541 int i;
2542 int recoffset;
2544 TRACE_(typelib)("\n");
2546 ptvd = *pptvd = TLBVarDesc_Alloc(cVars);
2547 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2548 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2549 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2550 recoffset += offset+sizeof(INT);
2551 for(i=0;i<cVars;i++, ++ptvd){
2552 /* name, eventually add to a hash table */
2553 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2554 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2555 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2556 /* read the variable information record */
2557 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2558 reclength &= 0xff;
2559 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2561 /* optional data */
2562 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2563 ptvd->HelpContext = pVarRec->HelpContext;
2565 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2566 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2568 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2569 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2571 /* fill the VarDesc Structure */
2572 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2573 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2574 ptvd->vardesc.varkind = pVarRec->VarKind;
2575 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2576 MSFT_GetTdesc(pcx, pVarRec->DataType,
2577 &ptvd->vardesc.elemdescVar.tdesc);
2578 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2579 if(pVarRec->VarKind == VAR_CONST ){
2580 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2581 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2582 pVarRec->OffsValue, pcx);
2583 } else
2584 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2585 recoffset += reclength;
2589 /* process Implemented Interfaces of a com class */
2590 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2591 int offset)
2593 int i;
2594 MSFT_RefRecord refrec;
2595 TLBImplType *pImpl;
2597 TRACE_(typelib)("\n");
2599 pTI->impltypes = TLBImplType_Alloc(count);
2600 pImpl = pTI->impltypes;
2601 for(i=0;i<count;i++){
2602 if(offset<0) break; /* paranoia */
2603 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2604 pImpl->hRef = refrec.reftype;
2605 pImpl->implflags=refrec.flags;
2606 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2607 offset=refrec.onext;
2608 ++pImpl;
2612 #ifdef _WIN64
2613 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2614 * and some structures, and fix the alignment */
2615 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl *info)
2617 if(info->typeattr.typekind == TKIND_ALIAS){
2618 switch(info->tdescAlias->vt){
2619 case VT_BSTR:
2620 case VT_DISPATCH:
2621 case VT_UNKNOWN:
2622 case VT_PTR:
2623 case VT_SAFEARRAY:
2624 case VT_LPSTR:
2625 case VT_LPWSTR:
2626 info->typeattr.cbSizeInstance = sizeof(void*);
2627 info->typeattr.cbAlignment = sizeof(void*);
2628 break;
2629 case VT_CARRAY:
2630 case VT_USERDEFINED:
2631 TLB_size_instance(info, SYS_WIN64, info->tdescAlias, &info->typeattr.cbSizeInstance, &info->typeattr.cbAlignment);
2632 break;
2633 case VT_VARIANT:
2634 info->typeattr.cbSizeInstance = sizeof(VARIANT);
2635 info->typeattr.cbAlignment = 8;
2636 default:
2637 if(info->typeattr.cbSizeInstance < sizeof(void*))
2638 info->typeattr.cbAlignment = info->typeattr.cbSizeInstance;
2639 else
2640 info->typeattr.cbAlignment = sizeof(void*);
2641 break;
2643 }else if(info->typeattr.typekind == TKIND_INTERFACE ||
2644 info->typeattr.typekind == TKIND_DISPATCH ||
2645 info->typeattr.typekind == TKIND_COCLASS){
2646 info->typeattr.cbSizeInstance = sizeof(void*);
2647 info->typeattr.cbAlignment = sizeof(void*);
2650 #endif
2653 * process a typeinfo record
2655 static ITypeInfoImpl * MSFT_DoTypeInfo(
2656 TLBContext *pcx,
2657 int count,
2658 ITypeLibImpl * pLibInfo)
2660 MSFT_TypeInfoBase tiBase;
2661 ITypeInfoImpl *ptiRet;
2663 TRACE_(typelib)("count=%u\n", count);
2665 ptiRet = ITypeInfoImpl_Constructor();
2666 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2667 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2669 /* this is where we are coming from */
2670 ptiRet->pTypeLib = pLibInfo;
2671 ptiRet->index=count;
2673 ptiRet->guid = MSFT_ReadGuid(tiBase.posguid, pcx);
2674 ptiRet->typeattr.lcid = pLibInfo->set_lcid; /* FIXME: correct? */
2675 ptiRet->typeattr.lpstrSchema = NULL; /* reserved */
2676 ptiRet->typeattr.cbSizeInstance = tiBase.size;
2677 ptiRet->typeattr.typekind = tiBase.typekind & 0xF;
2678 ptiRet->typeattr.cFuncs = LOWORD(tiBase.cElement);
2679 ptiRet->typeattr.cVars = HIWORD(tiBase.cElement);
2680 ptiRet->typeattr.cbAlignment = (tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2681 ptiRet->typeattr.wTypeFlags = tiBase.flags;
2682 ptiRet->typeattr.wMajorVerNum = LOWORD(tiBase.version);
2683 ptiRet->typeattr.wMinorVerNum = HIWORD(tiBase.version);
2684 ptiRet->typeattr.cImplTypes = tiBase.cImplTypes;
2685 ptiRet->typeattr.cbSizeVft = tiBase.cbSizeVft;
2686 if (ptiRet->typeattr.typekind == TKIND_ALIAS) {
2687 TYPEDESC tmp;
2688 MSFT_GetTdesc(pcx, tiBase.datatype1, &tmp);
2689 ptiRet->tdescAlias = heap_alloc(TLB_SizeTypeDesc(&tmp, TRUE));
2690 TLB_CopyTypeDesc(NULL, &tmp, ptiRet->tdescAlias);
2693 /* FIXME: */
2694 /* IDLDESC idldescType; *//* never saw this one != zero */
2696 /* name, eventually add to a hash table */
2697 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2698 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2699 TRACE_(typelib)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet->Name)));
2700 /* help info */
2701 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2702 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2703 ptiRet->dwHelpContext=tiBase.helpcontext;
2705 if (ptiRet->typeattr.typekind == TKIND_MODULE)
2706 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2708 /* note: InfoType's Help file and HelpStringDll come from the containing
2709 * library. Further HelpString and Docstring appear to be the same thing :(
2711 /* functions */
2712 if(ptiRet->typeattr.cFuncs >0 )
2713 MSFT_DoFuncs(pcx, ptiRet, ptiRet->typeattr.cFuncs,
2714 ptiRet->typeattr.cVars,
2715 tiBase.memoffset, &ptiRet->funcdescs);
2716 /* variables */
2717 if(ptiRet->typeattr.cVars >0 )
2718 MSFT_DoVars(pcx, ptiRet, ptiRet->typeattr.cFuncs,
2719 ptiRet->typeattr.cVars,
2720 tiBase.memoffset, &ptiRet->vardescs);
2721 if(ptiRet->typeattr.cImplTypes >0 ) {
2722 switch(ptiRet->typeattr.typekind)
2724 case TKIND_COCLASS:
2725 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->typeattr.cImplTypes,
2726 tiBase.datatype1);
2727 break;
2728 case TKIND_DISPATCH:
2729 /* This is not -1 when the interface is a non-base dual interface or
2730 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2731 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2732 not this interface.
2735 if (tiBase.datatype1 != -1)
2737 ptiRet->impltypes = TLBImplType_Alloc(1);
2738 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2740 break;
2741 default:
2742 ptiRet->impltypes = TLBImplType_Alloc(1);
2743 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2744 break;
2747 MSFT_CustData(pcx, tiBase.oCustData, ptiRet->pcustdata_list);
2749 TRACE_(typelib)("%s guid: %s kind:%s\n",
2750 debugstr_w(TLB_get_bstr(ptiRet->Name)),
2751 debugstr_guid(TLB_get_guidref(ptiRet->guid)),
2752 typekind_desc[ptiRet->typeattr.typekind]);
2753 if (TRACE_ON(typelib))
2754 dump_TypeInfo(ptiRet);
2756 return ptiRet;
2759 static HRESULT MSFT_ReadAllStrings(TLBContext *pcx)
2761 char *string;
2762 INT16 len_str, len_piece;
2763 int offs = 0, lengthInChars;
2765 MSFT_Seek(pcx, pcx->pTblDir->pStringtab.offset);
2766 while (1) {
2767 TLBString *tlbstr;
2769 if (offs >= pcx->pTblDir->pStringtab.length)
2770 return S_OK;
2772 MSFT_ReadLEWords(&len_str, sizeof(INT16), pcx, DO_NOT_SEEK);
2773 len_piece = len_str + sizeof(INT16);
2774 if(len_piece % 4)
2775 len_piece = (len_piece + 4) & ~0x3;
2776 if(len_piece < 8)
2777 len_piece = 8;
2779 string = heap_alloc(len_piece + 1);
2780 MSFT_Read(string, len_piece - sizeof(INT16), pcx, DO_NOT_SEEK);
2781 string[len_str] = '\0';
2783 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2784 string, -1, NULL, 0);
2785 if (!lengthInChars) {
2786 heap_free(string);
2787 return E_UNEXPECTED;
2790 tlbstr = heap_alloc(sizeof(TLBString));
2792 tlbstr->offset = offs;
2793 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2794 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2796 heap_free(string);
2798 list_add_tail(&pcx->pLibInfo->string_list, &tlbstr->entry);
2800 offs += len_piece;
2804 static HRESULT MSFT_ReadAllRefs(TLBContext *pcx)
2806 TLBRefType *ref;
2807 int offs = 0;
2809 MSFT_Seek(pcx, pcx->pTblDir->pImpInfo.offset);
2810 while (offs < pcx->pTblDir->pImpInfo.length) {
2811 MSFT_ImpInfo impinfo;
2812 TLBImpLib *pImpLib;
2814 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx, DO_NOT_SEEK);
2816 ref = heap_alloc_zero(sizeof(TLBRefType));
2817 list_add_tail(&pcx->pLibInfo->ref_list, &ref->entry);
2819 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2820 if(pImpLib->offset==impinfo.oImpFile)
2821 break;
2823 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2824 ref->reference = offs;
2825 ref->pImpTLInfo = pImpLib;
2826 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2827 ref->guid = MSFT_ReadGuid(impinfo.oGuid, pcx);
2828 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
2829 ref->index = TLB_REF_USE_GUID;
2830 } else
2831 ref->index = impinfo.oGuid;
2832 }else{
2833 ERR("Cannot find a reference\n");
2834 ref->reference = -1;
2835 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2838 offs += sizeof(impinfo);
2841 return S_OK;
2844 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2845 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2846 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2847 * tradeoff here.
2849 static struct list tlb_cache = LIST_INIT(tlb_cache);
2850 static CRITICAL_SECTION cache_section;
2851 static CRITICAL_SECTION_DEBUG cache_section_debug =
2853 0, 0, &cache_section,
2854 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2855 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2857 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2860 typedef struct TLB_PEFile
2862 IUnknown IUnknown_iface;
2863 LONG refs;
2864 HMODULE dll;
2865 HRSRC typelib_resource;
2866 HGLOBAL typelib_global;
2867 LPVOID typelib_base;
2868 } TLB_PEFile;
2870 static inline TLB_PEFile *pefile_impl_from_IUnknown(IUnknown *iface)
2872 return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2875 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2877 if (IsEqualIID(riid, &IID_IUnknown))
2879 *ppv = iface;
2880 IUnknown_AddRef(iface);
2881 return S_OK;
2883 *ppv = NULL;
2884 return E_NOINTERFACE;
2887 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2889 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2890 return InterlockedIncrement(&This->refs);
2893 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2895 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2896 ULONG refs = InterlockedDecrement(&This->refs);
2897 if (!refs)
2899 if (This->typelib_global)
2900 FreeResource(This->typelib_global);
2901 if (This->dll)
2902 FreeLibrary(This->dll);
2903 heap_free(This);
2905 return refs;
2908 static const IUnknownVtbl TLB_PEFile_Vtable =
2910 TLB_PEFile_QueryInterface,
2911 TLB_PEFile_AddRef,
2912 TLB_PEFile_Release
2915 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2917 TLB_PEFile *This;
2918 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2920 This = heap_alloc(sizeof(TLB_PEFile));
2921 if (!This)
2922 return E_OUTOFMEMORY;
2924 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
2925 This->refs = 1;
2926 This->dll = NULL;
2927 This->typelib_resource = NULL;
2928 This->typelib_global = NULL;
2929 This->typelib_base = NULL;
2931 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2932 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2934 if (This->dll)
2936 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2937 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2938 if (This->typelib_resource)
2940 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2941 if (This->typelib_global)
2943 This->typelib_base = LockResource(This->typelib_global);
2945 if (This->typelib_base)
2947 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2948 *ppBase = This->typelib_base;
2949 *ppFile = &This->IUnknown_iface;
2950 return S_OK;
2955 TRACE("No TYPELIB resource found\n");
2956 hr = E_FAIL;
2959 TLB_PEFile_Release(&This->IUnknown_iface);
2960 return hr;
2963 typedef struct TLB_NEFile
2965 IUnknown IUnknown_iface;
2966 LONG refs;
2967 LPVOID typelib_base;
2968 } TLB_NEFile;
2970 static inline TLB_NEFile *nefile_impl_from_IUnknown(IUnknown *iface)
2972 return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
2975 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2977 if (IsEqualIID(riid, &IID_IUnknown))
2979 *ppv = iface;
2980 IUnknown_AddRef(iface);
2981 return S_OK;
2983 *ppv = NULL;
2984 return E_NOINTERFACE;
2987 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2989 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2990 return InterlockedIncrement(&This->refs);
2993 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2995 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2996 ULONG refs = InterlockedDecrement(&This->refs);
2997 if (!refs)
2999 heap_free(This->typelib_base);
3000 heap_free(This);
3002 return refs;
3005 static const IUnknownVtbl TLB_NEFile_Vtable =
3007 TLB_NEFile_QueryInterface,
3008 TLB_NEFile_AddRef,
3009 TLB_NEFile_Release
3012 /***********************************************************************
3013 * read_xx_header [internal]
3015 static int read_xx_header( HFILE lzfd )
3017 IMAGE_DOS_HEADER mzh;
3018 char magic[3];
3020 LZSeek( lzfd, 0, SEEK_SET );
3021 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
3022 return 0;
3023 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
3024 return 0;
3026 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3027 if ( 2 != LZRead( lzfd, magic, 2 ) )
3028 return 0;
3030 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3032 if ( magic[0] == 'N' && magic[1] == 'E' )
3033 return IMAGE_OS2_SIGNATURE;
3034 if ( magic[0] == 'P' && magic[1] == 'E' )
3035 return IMAGE_NT_SIGNATURE;
3037 magic[2] = '\0';
3038 WARN("Can't handle %s files.\n", magic );
3039 return 0;
3043 /***********************************************************************
3044 * find_ne_resource [internal]
3046 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
3047 DWORD *resLen, DWORD *resOff )
3049 IMAGE_OS2_HEADER nehd;
3050 NE_TYPEINFO *typeInfo;
3051 NE_NAMEINFO *nameInfo;
3052 DWORD nehdoffset;
3053 LPBYTE resTab;
3054 DWORD resTabSize;
3055 int count;
3057 /* Read in NE header */
3058 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
3059 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return FALSE;
3061 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
3062 if ( !resTabSize )
3064 TRACE("No resources in NE dll\n" );
3065 return FALSE;
3068 /* Read in resource table */
3069 resTab = heap_alloc( resTabSize );
3070 if ( !resTab ) return FALSE;
3072 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
3073 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
3075 heap_free( resTab );
3076 return FALSE;
3079 /* Find resource */
3080 typeInfo = (NE_TYPEINFO *)(resTab + 2);
3082 if (!IS_INTRESOURCE(typeid)) /* named type */
3084 BYTE len = strlen( typeid );
3085 while (typeInfo->type_id)
3087 if (!(typeInfo->type_id & 0x8000))
3089 BYTE *p = resTab + typeInfo->type_id;
3090 if ((*p == len) && !_strnicmp( (char*)p+1, typeid, len )) goto found_type;
3092 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3093 typeInfo->count * sizeof(NE_NAMEINFO));
3096 else /* numeric type id */
3098 WORD id = LOWORD(typeid) | 0x8000;
3099 while (typeInfo->type_id)
3101 if (typeInfo->type_id == id) goto found_type;
3102 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3103 typeInfo->count * sizeof(NE_NAMEINFO));
3106 TRACE("No typeid entry found for %p\n", typeid );
3107 heap_free( resTab );
3108 return FALSE;
3110 found_type:
3111 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
3113 if (!IS_INTRESOURCE(resid)) /* named resource */
3115 BYTE len = strlen( resid );
3116 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3118 BYTE *p = resTab + nameInfo->id;
3119 if (nameInfo->id & 0x8000) continue;
3120 if ((*p == len) && !_strnicmp( (char*)p+1, resid, len )) goto found_name;
3123 else /* numeric resource id */
3125 WORD id = LOWORD(resid) | 0x8000;
3126 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3127 if (nameInfo->id == id) goto found_name;
3129 TRACE("No resid entry found for %p\n", typeid );
3130 heap_free( resTab );
3131 return FALSE;
3133 found_name:
3134 /* Return resource data */
3135 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
3136 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
3138 heap_free( resTab );
3139 return TRUE;
3142 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
3144 HFILE lzfd = -1;
3145 OFSTRUCT ofs;
3146 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
3147 TLB_NEFile *This;
3149 This = heap_alloc(sizeof(TLB_NEFile));
3150 if (!This) return E_OUTOFMEMORY;
3152 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
3153 This->refs = 1;
3154 This->typelib_base = NULL;
3156 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
3157 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
3159 DWORD reslen, offset;
3160 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
3162 This->typelib_base = heap_alloc(reslen);
3163 if( !This->typelib_base )
3164 hr = E_OUTOFMEMORY;
3165 else
3167 LZSeek( lzfd, offset, SEEK_SET );
3168 reslen = LZRead( lzfd, This->typelib_base, reslen );
3169 LZClose( lzfd );
3170 *ppBase = This->typelib_base;
3171 *pdwTLBLength = reslen;
3172 *ppFile = &This->IUnknown_iface;
3173 return S_OK;
3178 if( lzfd >= 0) LZClose( lzfd );
3179 TLB_NEFile_Release(&This->IUnknown_iface);
3180 return hr;
3183 typedef struct TLB_Mapping
3185 IUnknown IUnknown_iface;
3186 LONG refs;
3187 HANDLE file;
3188 HANDLE mapping;
3189 LPVOID typelib_base;
3190 } TLB_Mapping;
3192 static inline TLB_Mapping *mapping_impl_from_IUnknown(IUnknown *iface)
3194 return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
3197 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3199 if (IsEqualIID(riid, &IID_IUnknown))
3201 *ppv = iface;
3202 IUnknown_AddRef(iface);
3203 return S_OK;
3205 *ppv = NULL;
3206 return E_NOINTERFACE;
3209 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
3211 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3212 return InterlockedIncrement(&This->refs);
3215 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
3217 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3218 ULONG refs = InterlockedDecrement(&This->refs);
3219 if (!refs)
3221 if (This->typelib_base)
3222 UnmapViewOfFile(This->typelib_base);
3223 if (This->mapping)
3224 CloseHandle(This->mapping);
3225 if (This->file != INVALID_HANDLE_VALUE)
3226 CloseHandle(This->file);
3227 heap_free(This);
3229 return refs;
3232 static const IUnknownVtbl TLB_Mapping_Vtable =
3234 TLB_Mapping_QueryInterface,
3235 TLB_Mapping_AddRef,
3236 TLB_Mapping_Release
3239 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
3241 TLB_Mapping *This;
3243 This = heap_alloc(sizeof(TLB_Mapping));
3244 if (!This)
3245 return E_OUTOFMEMORY;
3247 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
3248 This->refs = 1;
3249 This->file = INVALID_HANDLE_VALUE;
3250 This->mapping = NULL;
3251 This->typelib_base = NULL;
3253 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3254 if (INVALID_HANDLE_VALUE != This->file)
3256 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
3257 if (This->mapping)
3259 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
3260 if(This->typelib_base)
3262 /* retrieve file size */
3263 *pdwTLBLength = GetFileSize(This->file, NULL);
3264 *ppBase = This->typelib_base;
3265 *ppFile = &This->IUnknown_iface;
3266 return S_OK;
3271 IUnknown_Release(&This->IUnknown_iface);
3272 return TYPE_E_CANTLOADLIBRARY;
3275 /****************************************************************************
3276 * TLB_ReadTypeLib
3278 * find the type of the typelib file and map the typelib resource into
3279 * the memory
3282 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3283 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
3285 ITypeLibImpl *entry;
3286 HRESULT ret;
3287 INT index = 1;
3288 LPWSTR index_str, file = (LPWSTR)pszFileName;
3289 LPVOID pBase = NULL;
3290 DWORD dwTLBLength = 0;
3291 IUnknown *pFile = NULL;
3292 HANDLE h;
3294 *ppTypeLib = NULL;
3296 index_str = wcsrchr(pszFileName, '\\');
3297 if(index_str && *++index_str != '\0')
3299 LPWSTR end_ptr;
3300 LONG idx = wcstol(index_str, &end_ptr, 10);
3301 if(*end_ptr == '\0')
3303 int str_len = index_str - pszFileName - 1;
3304 index = idx;
3305 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
3306 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
3307 file[str_len] = 0;
3311 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
3313 if(wcschr(file, '\\'))
3315 lstrcpyW(pszPath, file);
3317 else
3319 int len = GetSystemDirectoryW(pszPath, cchPath);
3320 pszPath[len] = '\\';
3321 memcpy(pszPath + len + 1, file, (lstrlenW(file) + 1) * sizeof(WCHAR));
3325 if(file != pszFileName) heap_free(file);
3327 h = CreateFileW(pszPath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
3328 if(h != INVALID_HANDLE_VALUE){
3329 FILE_NAME_INFORMATION size_info;
3330 BOOL br;
3332 /* GetFileInformationByHandleEx returns the path of the file without
3333 * WOW64 redirection */
3334 br = GetFileInformationByHandleEx(h, FileNameInfo, &size_info, sizeof(size_info));
3335 if(br || GetLastError() == ERROR_MORE_DATA){
3336 FILE_NAME_INFORMATION *info;
3337 DWORD size = sizeof(*info) + size_info.FileNameLength + sizeof(WCHAR);
3339 info = HeapAlloc(GetProcessHeap(), 0, size);
3341 br = GetFileInformationByHandleEx(h, FileNameInfo, info, size);
3342 if(br){
3343 info->FileName[info->FileNameLength / sizeof(WCHAR)] = 0;
3344 lstrcpynW(pszPath + 2, info->FileName, cchPath - 2);
3347 HeapFree(GetProcessHeap(), 0, info);
3350 CloseHandle(h);
3353 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
3355 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3356 EnterCriticalSection(&cache_section);
3357 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
3359 if (!wcsicmp(entry->path, pszPath) && entry->index == index)
3361 TRACE("cache hit\n");
3362 *ppTypeLib = &entry->ITypeLib2_iface;
3363 ITypeLib2_AddRef(*ppTypeLib);
3364 LeaveCriticalSection(&cache_section);
3365 return S_OK;
3368 LeaveCriticalSection(&cache_section);
3370 /* now actually load and parse the typelib */
3372 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3373 if (ret == TYPE_E_CANTLOADLIBRARY)
3374 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3375 if (ret == TYPE_E_CANTLOADLIBRARY)
3376 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
3377 if (SUCCEEDED(ret))
3379 if (dwTLBLength >= 4)
3381 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
3382 if (dwSignature == MSFT_SIGNATURE)
3383 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
3384 else if (dwSignature == SLTG_SIGNATURE)
3385 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
3386 else
3388 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
3389 ret = TYPE_E_CANTLOADLIBRARY;
3392 else
3393 ret = TYPE_E_CANTLOADLIBRARY;
3394 IUnknown_Release(pFile);
3397 if(*ppTypeLib) {
3398 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
3400 TRACE("adding to cache\n");
3401 impl->path = heap_alloc((lstrlenW(pszPath)+1) * sizeof(WCHAR));
3402 lstrcpyW(impl->path, pszPath);
3403 /* We should really canonicalise the path here. */
3404 impl->index = index;
3406 /* FIXME: check if it has added already in the meantime */
3407 EnterCriticalSection(&cache_section);
3408 list_add_head(&tlb_cache, &impl->entry);
3409 LeaveCriticalSection(&cache_section);
3410 ret = S_OK;
3412 else
3414 if(ret != E_FAIL)
3415 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
3417 ret = TYPE_E_CANTLOADLIBRARY;
3421 return ret;
3424 /*================== ITypeLib(2) Methods ===================================*/
3426 static ITypeLibImpl* TypeLibImpl_Constructor(void)
3428 ITypeLibImpl* pTypeLibImpl;
3430 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
3431 if (!pTypeLibImpl) return NULL;
3433 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3434 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3435 pTypeLibImpl->ICreateTypeLib2_iface.lpVtbl = &CreateTypeLib2Vtbl;
3436 pTypeLibImpl->ref = 1;
3438 list_init(&pTypeLibImpl->implib_list);
3439 list_init(&pTypeLibImpl->custdata_list);
3440 list_init(&pTypeLibImpl->name_list);
3441 list_init(&pTypeLibImpl->string_list);
3442 list_init(&pTypeLibImpl->guid_list);
3443 list_init(&pTypeLibImpl->ref_list);
3444 pTypeLibImpl->dispatch_href = -1;
3446 return pTypeLibImpl;
3449 /****************************************************************************
3450 * ITypeLib2_Constructor_MSFT
3452 * loading an MSFT typelib from an in-memory image
3454 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3456 TLBContext cx;
3457 LONG lPSegDir;
3458 MSFT_Header tlbHeader;
3459 MSFT_SegDir tlbSegDir;
3460 ITypeLibImpl * pTypeLibImpl;
3461 int i;
3463 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3465 pTypeLibImpl = TypeLibImpl_Constructor();
3466 if (!pTypeLibImpl) return NULL;
3468 /* get pointer to beginning of typelib data */
3469 cx.pos = 0;
3470 cx.oStart=0;
3471 cx.mapping = pLib;
3472 cx.pLibInfo = pTypeLibImpl;
3473 cx.length = dwTLBLength;
3475 /* read header */
3476 MSFT_ReadLEDWords(&tlbHeader, sizeof(tlbHeader), &cx, 0);
3477 TRACE_(typelib)("header:\n");
3478 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3479 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3480 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3481 return NULL;
3483 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3485 /* there is a small amount of information here until the next important
3486 * part:
3487 * the segment directory . Try to calculate the amount of data */
3488 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3490 /* now read the segment directory */
3491 TRACE("read segment directory (at %d)\n",lPSegDir);
3492 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3493 cx.pTblDir = &tlbSegDir;
3495 /* just check two entries */
3496 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3498 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3499 heap_free(pTypeLibImpl);
3500 return NULL;
3503 MSFT_ReadAllNames(&cx);
3504 MSFT_ReadAllStrings(&cx);
3505 MSFT_ReadAllGuids(&cx);
3507 /* now fill our internal data */
3508 /* TLIBATTR fields */
3509 pTypeLibImpl->guid = MSFT_ReadGuid(tlbHeader.posguid, &cx);
3511 pTypeLibImpl->syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3512 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3513 pTypeLibImpl->ver_major = LOWORD(tlbHeader.version);
3514 pTypeLibImpl->ver_minor = HIWORD(tlbHeader.version);
3515 pTypeLibImpl->libflags = ((WORD) tlbHeader.flags & 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE;
3517 pTypeLibImpl->set_lcid = tlbHeader.lcid2;
3518 pTypeLibImpl->lcid = tlbHeader.lcid;
3520 /* name, eventually add to a hash table */
3521 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3523 /* help info */
3524 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3525 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3527 if( tlbHeader.varflags & HELPDLLFLAG)
3529 int offset;
3530 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3531 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3534 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3536 /* custom data */
3537 if(tlbHeader.CustomDataOffset >= 0)
3539 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3542 /* fill in type descriptions */
3543 if(tlbSegDir.pTypdescTab.length > 0)
3545 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3546 INT16 td[4];
3547 pTypeLibImpl->ctTypeDesc = cTD;
3548 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3549 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3550 for(i=0; i<cTD; )
3552 /* FIXME: add several sanity checks here */
3553 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3554 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3556 /* FIXME: check safearray */
3557 if(td[3] < 0)
3558 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3559 else
3560 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3562 else if(td[0] == VT_CARRAY)
3564 /* array descr table here */
3565 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3567 else if(td[0] == VT_USERDEFINED)
3569 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3571 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3574 /* second time around to fill the array subscript info */
3575 for(i=0;i<cTD;i++)
3577 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3578 if(tlbSegDir.pArrayDescriptions.offset>0)
3580 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3581 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3583 if(td[1]<0)
3584 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3585 else
3586 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3588 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3590 for(j = 0; j<td[2]; j++)
3592 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3593 sizeof(INT), &cx, DO_NOT_SEEK);
3594 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3595 sizeof(INT), &cx, DO_NOT_SEEK);
3598 else
3600 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3601 ERR("didn't find array description data\n");
3606 /* imported type libs */
3607 if(tlbSegDir.pImpFiles.offset>0)
3609 TLBImpLib *pImpLib;
3610 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3611 UINT16 size;
3613 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3615 char *name;
3617 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3618 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3619 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3621 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3622 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3623 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3624 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3626 size >>= 2;
3627 name = heap_alloc_zero(size+1);
3628 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3629 pImpLib->name = TLB_MultiByteToBSTR(name);
3630 heap_free(name);
3632 pImpLib->guid = MSFT_ReadGuid(oGuid, &cx);
3633 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3635 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3639 MSFT_ReadAllRefs(&cx);
3641 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3643 /* type infos */
3644 if(tlbHeader.nrtypeinfos >= 0 )
3646 ITypeInfoImpl **ppTI;
3648 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3650 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3652 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3654 ++ppTI;
3655 (pTypeLibImpl->TypeInfoCount)++;
3659 #ifdef _WIN64
3660 if(pTypeLibImpl->syskind == SYS_WIN32){
3661 for(i = 0; i < pTypeLibImpl->TypeInfoCount; ++i)
3662 TLB_fix_32on64_typeinfo(pTypeLibImpl->typeinfos[i]);
3664 #endif
3666 TRACE("(%p)\n", pTypeLibImpl);
3667 return &pTypeLibImpl->ITypeLib2_iface;
3671 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3673 char b[3];
3674 int i;
3675 short s;
3677 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3678 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3679 return FALSE;
3682 guid->Data4[0] = s >> 8;
3683 guid->Data4[1] = s & 0xff;
3685 b[2] = '\0';
3686 for(i = 0; i < 6; i++) {
3687 memcpy(b, str + 24 + 2 * i, 2);
3688 guid->Data4[i + 2] = strtol(b, NULL, 16);
3690 return TRUE;
3693 static WORD SLTG_ReadString(const char *ptr, const TLBString **pStr, ITypeLibImpl *lib)
3695 WORD bytelen;
3696 DWORD len;
3697 BSTR tmp_str;
3699 *pStr = NULL;
3700 bytelen = *(const WORD*)ptr;
3701 if(bytelen == 0xffff) return 2;
3703 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3704 tmp_str = SysAllocStringLen(NULL, len);
3705 if (tmp_str) {
3706 MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, tmp_str, len);
3707 *pStr = TLB_append_str(&lib->string_list, tmp_str);
3708 SysFreeString(tmp_str);
3710 return bytelen + 2;
3713 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3715 WORD bytelen;
3717 *str = NULL;
3718 bytelen = *(const WORD*)ptr;
3719 if(bytelen == 0xffff) return 2;
3720 *str = heap_alloc(bytelen + 1);
3721 memcpy(*str, ptr + 2, bytelen);
3722 (*str)[bytelen] = '\0';
3723 return bytelen + 2;
3726 static TLBString *SLTG_ReadName(const char *pNameTable, int offset, ITypeLibImpl *lib)
3728 BSTR tmp_str;
3729 TLBString *tlbstr;
3731 LIST_FOR_EACH_ENTRY(tlbstr, &lib->name_list, TLBString, entry) {
3732 if (tlbstr->offset == offset)
3733 return tlbstr;
3736 tmp_str = TLB_MultiByteToBSTR(pNameTable + offset);
3737 tlbstr = TLB_append_str(&lib->name_list, tmp_str);
3738 SysFreeString(tmp_str);
3740 return tlbstr;
3743 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3745 char *ptr = pLibBlk;
3746 WORD w;
3748 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3749 FIXME("libblk magic = %04x\n", w);
3750 return 0;
3753 ptr += 6;
3754 if((w = *(WORD*)ptr) != 0xffff) {
3755 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3756 ptr += w;
3758 ptr += 2;
3760 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString, pTypeLibImpl);
3762 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile, pTypeLibImpl);
3764 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3765 ptr += 4;
3767 pTypeLibImpl->syskind = *(WORD*)ptr;
3768 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3769 ptr += 2;
3771 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3772 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3773 else
3774 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = 0;
3775 ptr += 2;
3777 ptr += 4; /* skip res12 */
3779 pTypeLibImpl->libflags = *(WORD*)ptr;
3780 ptr += 2;
3782 pTypeLibImpl->ver_major = *(WORD*)ptr;
3783 ptr += 2;
3785 pTypeLibImpl->ver_minor = *(WORD*)ptr;
3786 ptr += 2;
3788 pTypeLibImpl->guid = TLB_append_guid(&pTypeLibImpl->guid_list, (GUID*)ptr, -2);
3789 ptr += sizeof(GUID);
3791 return ptr - (char*)pLibBlk;
3794 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3795 typedef struct
3797 unsigned int num;
3798 HREFTYPE refs[1];
3799 } sltg_ref_lookup_t;
3801 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3802 HREFTYPE *typelib_ref)
3804 if(table && typeinfo_ref < table->num)
3806 *typelib_ref = table->refs[typeinfo_ref];
3807 return S_OK;
3810 ERR_(typelib)("Unable to find reference\n");
3811 *typelib_ref = -1;
3812 return E_FAIL;
3815 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3817 BOOL done = FALSE;
3819 while(!done) {
3820 if((*pType & 0xe00) == 0xe00) {
3821 pTD->vt = VT_PTR;
3822 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3823 pTD = pTD->u.lptdesc;
3825 switch(*pType & 0x3f) {
3826 case VT_PTR:
3827 pTD->vt = VT_PTR;
3828 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3829 pTD = pTD->u.lptdesc;
3830 break;
3832 case VT_USERDEFINED:
3833 pTD->vt = VT_USERDEFINED;
3834 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3835 done = TRUE;
3836 break;
3838 case VT_CARRAY:
3840 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3841 array */
3843 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3845 pTD->vt = VT_CARRAY;
3846 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3847 pTD->u.lpadesc->cDims = pSA->cDims;
3848 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3849 pSA->cDims * sizeof(SAFEARRAYBOUND));
3851 pTD = &pTD->u.lpadesc->tdescElem;
3852 break;
3855 case VT_SAFEARRAY:
3857 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3858 useful? */
3860 pType++;
3861 pTD->vt = VT_SAFEARRAY;
3862 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3863 pTD = pTD->u.lptdesc;
3864 break;
3866 default:
3867 pTD->vt = *pType & 0x3f;
3868 done = TRUE;
3869 break;
3871 pType++;
3873 return pType;
3876 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3877 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3879 /* Handle [in/out] first */
3880 if((*pType & 0xc000) == 0xc000)
3881 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3882 else if(*pType & 0x8000)
3883 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3884 else if(*pType & 0x4000)
3885 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3886 else
3887 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3889 if(*pType & 0x2000)
3890 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3892 if(*pType & 0x80)
3893 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3895 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3899 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3900 char *pNameTable)
3902 unsigned int ref;
3903 char *name;
3904 TLBRefType *ref_type;
3905 sltg_ref_lookup_t *table;
3906 HREFTYPE typelib_ref;
3908 if(pRef->magic != SLTG_REF_MAGIC) {
3909 FIXME("Ref magic = %x\n", pRef->magic);
3910 return NULL;
3912 name = ( (char*)pRef->names + pRef->number);
3914 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3915 table->num = pRef->number >> 3;
3917 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3919 /* We don't want the first href to be 0 */
3920 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3922 for(ref = 0; ref < pRef->number >> 3; ref++) {
3923 char *refname;
3924 unsigned int lib_offs, type_num;
3926 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3928 name += SLTG_ReadStringA(name, &refname);
3929 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3930 FIXME_(typelib)("Can't sscanf ref\n");
3931 if(lib_offs != 0xffff) {
3932 TLBImpLib *import;
3934 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
3935 if(import->offset == lib_offs)
3936 break;
3938 if(&import->entry == &pTL->implib_list) {
3939 char fname[MAX_PATH+1];
3940 int len;
3941 GUID tmpguid;
3943 import = heap_alloc_zero(sizeof(*import));
3944 import->offset = lib_offs;
3945 TLB_GUIDFromString( pNameTable + lib_offs + 4, &tmpguid);
3946 import->guid = TLB_append_guid(&pTL->guid_list, &tmpguid, 2);
3947 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3948 &import->wVersionMajor,
3949 &import->wVersionMinor,
3950 &import->lcid, fname) != 4) {
3951 FIXME_(typelib)("can't sscanf ref %s\n",
3952 pNameTable + lib_offs + 40);
3954 len = strlen(fname);
3955 if(fname[len-1] != '#')
3956 FIXME("fname = %s\n", fname);
3957 fname[len-1] = '\0';
3958 import->name = TLB_MultiByteToBSTR(fname);
3959 list_add_tail(&pTL->implib_list, &import->entry);
3961 ref_type->pImpTLInfo = import;
3963 /* Store a reference to IDispatch */
3964 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid->guid, &IID_StdOle) && type_num == 4)
3965 pTL->dispatch_href = typelib_ref;
3967 } else { /* internal ref */
3968 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3970 ref_type->reference = typelib_ref;
3971 ref_type->index = type_num;
3973 heap_free(refname);
3974 list_add_tail(&pTL->ref_list, &ref_type->entry);
3976 table->refs[ref] = typelib_ref;
3977 typelib_ref += 4;
3979 if((BYTE)*name != SLTG_REF_MAGIC)
3980 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3981 dump_TLBRefType(pTL);
3982 return table;
3985 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3986 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3988 SLTG_ImplInfo *info;
3989 TLBImplType *pImplType;
3990 /* I don't really get this structure, usually it's 0x16 bytes
3991 long, but iuser.tlb contains some that are 0x18 bytes long.
3992 That's ok because we can use the next ptr to jump to the next
3993 one. But how do we know the length of the last one? The WORD
3994 at offs 0x8 might be the clue. For now I'm just assuming that
3995 the last one is the regular 0x16 bytes. */
3997 info = (SLTG_ImplInfo*)pBlk;
3998 while(1){
3999 pTI->typeattr.cImplTypes++;
4000 if(info->next == 0xffff)
4001 break;
4002 info = (SLTG_ImplInfo*)(pBlk + info->next);
4005 info = (SLTG_ImplInfo*)pBlk;
4006 pTI->impltypes = TLBImplType_Alloc(pTI->typeattr.cImplTypes);
4007 pImplType = pTI->impltypes;
4008 while(1) {
4009 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
4010 pImplType->implflags = info->impltypeflags;
4011 ++pImplType;
4013 if(info->next == 0xffff)
4014 break;
4015 if(OneOnly)
4016 FIXME_(typelib)("Interface inheriting more than one interface\n");
4017 info = (SLTG_ImplInfo*)(pBlk + info->next);
4019 info++; /* see comment at top of function */
4020 return (char*)info;
4023 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
4024 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4026 TLBVarDesc *pVarDesc;
4027 const TLBString *prevName = NULL;
4028 SLTG_Variable *pItem;
4029 unsigned short i;
4030 WORD *pType;
4032 pVarDesc = pTI->vardescs = TLBVarDesc_Alloc(cVars);
4034 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
4035 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
4037 pVarDesc->vardesc.memid = pItem->memid;
4039 if (pItem->magic != SLTG_VAR_MAGIC &&
4040 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
4041 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
4042 return;
4045 if (pItem->name == 0xfffe)
4046 pVarDesc->Name = prevName;
4047 else
4048 pVarDesc->Name = SLTG_ReadName(pNameTable, pItem->name, pTI->pTypeLib);
4050 TRACE_(typelib)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc->Name)));
4051 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
4052 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
4054 if(pItem->flags & 0x02)
4055 pType = &pItem->type;
4056 else
4057 pType = (WORD*)(pBlk + pItem->type);
4059 if (pItem->flags & ~0xda)
4060 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
4062 SLTG_DoElem(pType, pBlk,
4063 &pVarDesc->vardesc.elemdescVar, ref_lookup);
4065 if (TRACE_ON(typelib)) {
4066 char buf[300];
4067 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
4068 TRACE_(typelib)("elemdescVar: %s\n", buf);
4071 if (pItem->flags & 0x40) {
4072 TRACE_(typelib)("VAR_DISPATCH\n");
4073 pVarDesc->vardesc.varkind = VAR_DISPATCH;
4075 else if (pItem->flags & 0x10) {
4076 TRACE_(typelib)("VAR_CONST\n");
4077 pVarDesc->vardesc.varkind = VAR_CONST;
4078 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
4079 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
4080 if (pItem->flags & 0x08)
4081 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
4082 else {
4083 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
4085 case VT_LPSTR:
4086 case VT_LPWSTR:
4087 case VT_BSTR:
4089 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
4090 BSTR str;
4091 TRACE_(typelib)("len = %u\n", len);
4092 if (len == 0xffff) {
4093 str = NULL;
4094 } else {
4095 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
4096 str = SysAllocStringLen(NULL, alloc_len);
4097 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
4099 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
4100 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
4101 break;
4103 case VT_I2:
4104 case VT_UI2:
4105 case VT_I4:
4106 case VT_UI4:
4107 case VT_INT:
4108 case VT_UINT:
4109 V_INT(pVarDesc->vardesc.u.lpvarValue) =
4110 *(INT*)(pBlk + pItem->byte_offs);
4111 break;
4112 default:
4113 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
4117 else {
4118 TRACE_(typelib)("VAR_PERINSTANCE\n");
4119 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
4120 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
4123 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
4124 pVarDesc->vardesc.wVarFlags = pItem->varflags;
4126 if (pItem->flags & 0x80)
4127 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
4129 prevName = pVarDesc->Name;
4131 pTI->typeattr.cVars = cVars;
4134 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
4135 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4137 SLTG_Function *pFunc;
4138 unsigned short i;
4139 TLBFuncDesc *pFuncDesc;
4141 pTI->funcdescs = TLBFuncDesc_Alloc(cFuncs);
4143 pFuncDesc = pTI->funcdescs;
4144 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
4145 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
4147 int param;
4148 WORD *pType, *pArg;
4150 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
4151 case SLTG_FUNCTION_MAGIC:
4152 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
4153 break;
4154 case SLTG_DISPATCH_FUNCTION_MAGIC:
4155 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
4156 break;
4157 case SLTG_STATIC_FUNCTION_MAGIC:
4158 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
4159 break;
4160 default:
4161 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
4162 continue;
4164 pFuncDesc->Name = SLTG_ReadName(pNameTable, pFunc->name, pTI->pTypeLib);
4166 pFuncDesc->funcdesc.memid = pFunc->dispid;
4167 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
4168 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
4169 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
4170 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
4171 pFuncDesc->funcdesc.oVft = (pFunc->vtblpos & ~1) * sizeof(void *) / pTI->pTypeLib->ptr_size;
4173 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
4174 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
4176 if(pFunc->retnextopt & 0x80)
4177 pType = &pFunc->rettype;
4178 else
4179 pType = (WORD*)(pBlk + pFunc->rettype);
4181 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
4183 pFuncDesc->funcdesc.lprgelemdescParam =
4184 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
4185 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
4187 pArg = (WORD*)(pBlk + pFunc->arg_off);
4189 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
4190 char *paramName = pNameTable + *pArg;
4191 BOOL HaveOffs;
4192 /* If arg type follows then paramName points to the 2nd
4193 letter of the name, else the next WORD is an offset to
4194 the arg type and paramName points to the first letter.
4195 So let's take one char off paramName and see if we're
4196 pointing at an alpha-numeric char. However if *pArg is
4197 0xffff or 0xfffe then the param has no name, the former
4198 meaning that the next WORD is the type, the latter
4199 meaning that the next WORD is an offset to the type. */
4201 HaveOffs = FALSE;
4202 if(*pArg == 0xffff)
4203 paramName = NULL;
4204 else if(*pArg == 0xfffe) {
4205 paramName = NULL;
4206 HaveOffs = TRUE;
4208 else if(paramName[-1] && !isalnum(paramName[-1]))
4209 HaveOffs = TRUE;
4211 pArg++;
4213 if(HaveOffs) { /* the next word is an offset to type */
4214 pType = (WORD*)(pBlk + *pArg);
4215 SLTG_DoElem(pType, pBlk,
4216 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4217 pArg++;
4218 } else {
4219 if(paramName)
4220 paramName--;
4221 pArg = SLTG_DoElem(pArg, pBlk,
4222 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4225 /* Are we an optional param ? */
4226 if(pFuncDesc->funcdesc.cParams - param <=
4227 pFuncDesc->funcdesc.cParamsOpt)
4228 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
4230 if(paramName) {
4231 pFuncDesc->pParamDesc[param].Name = SLTG_ReadName(pNameTable,
4232 paramName - pNameTable, pTI->pTypeLib);
4233 } else {
4234 pFuncDesc->pParamDesc[param].Name = pFuncDesc->Name;
4238 pTI->typeattr.cFuncs = cFuncs;
4241 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
4242 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4243 SLTG_TypeInfoTail *pTITail)
4245 char *pFirstItem;
4246 sltg_ref_lookup_t *ref_lookup = NULL;
4248 if(pTIHeader->href_table != 0xffffffff) {
4249 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4250 pNameTable);
4253 pFirstItem = pBlk;
4255 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4256 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
4258 heap_free(ref_lookup);
4262 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
4263 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4264 const SLTG_TypeInfoTail *pTITail)
4266 char *pFirstItem;
4267 sltg_ref_lookup_t *ref_lookup = NULL;
4269 if(pTIHeader->href_table != 0xffffffff) {
4270 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4271 pNameTable);
4274 pFirstItem = pBlk;
4276 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4277 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
4280 if (pTITail->funcs_off != 0xffff)
4281 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4283 heap_free(ref_lookup);
4285 if (TRACE_ON(typelib))
4286 dump_TLBFuncDesc(pTI->funcdescs, pTI->typeattr.cFuncs);
4289 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
4290 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4291 const SLTG_TypeInfoTail *pTITail)
4293 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4296 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
4297 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4298 const SLTG_TypeInfoTail *pTITail)
4300 WORD *pType;
4301 sltg_ref_lookup_t *ref_lookup = NULL;
4303 if (pTITail->simple_alias) {
4304 /* if simple alias, no more processing required */
4305 pTI->tdescAlias = heap_alloc_zero(sizeof(TYPEDESC));
4306 pTI->tdescAlias->vt = pTITail->tdescalias_vt;
4307 return;
4310 if(pTIHeader->href_table != 0xffffffff) {
4311 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4312 pNameTable);
4315 /* otherwise it is an offset to a type */
4316 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
4318 pTI->tdescAlias = heap_alloc(sizeof(TYPEDESC));
4319 SLTG_DoType(pType, pBlk, pTI->tdescAlias, ref_lookup);
4321 heap_free(ref_lookup);
4324 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
4325 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4326 const SLTG_TypeInfoTail *pTITail)
4328 sltg_ref_lookup_t *ref_lookup = NULL;
4329 if (pTIHeader->href_table != 0xffffffff)
4330 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4331 pNameTable);
4333 if (pTITail->vars_off != 0xffff)
4334 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4336 if (pTITail->funcs_off != 0xffff)
4337 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4339 if (pTITail->impls_off != 0xffff)
4340 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
4342 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4343 * of dispinterface functions including the IDispatch ones, so
4344 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4345 pTI->typeattr.cbSizeVft = pTI->typeattr.cFuncs * pTI->pTypeLib->ptr_size;
4347 heap_free(ref_lookup);
4348 if (TRACE_ON(typelib))
4349 dump_TLBFuncDesc(pTI->funcdescs, pTI->typeattr.cFuncs);
4352 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
4353 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4354 const SLTG_TypeInfoTail *pTITail)
4356 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4359 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
4360 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4361 const SLTG_TypeInfoTail *pTITail)
4363 sltg_ref_lookup_t *ref_lookup = NULL;
4364 if (pTIHeader->href_table != 0xffffffff)
4365 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4366 pNameTable);
4368 if (pTITail->vars_off != 0xffff)
4369 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4371 if (pTITail->funcs_off != 0xffff)
4372 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4373 heap_free(ref_lookup);
4374 if (TRACE_ON(typelib))
4375 dump_TypeInfo(pTI);
4378 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4379 manageable copy of it into this */
4380 typedef struct {
4381 WORD small_no;
4382 char *index_name;
4383 char *other_name;
4384 WORD res1a;
4385 WORD name_offs;
4386 WORD more_bytes;
4387 char *extra;
4388 WORD res20;
4389 DWORD helpcontext;
4390 WORD res26;
4391 GUID uuid;
4392 } SLTG_InternalOtherTypeInfo;
4394 /****************************************************************************
4395 * ITypeLib2_Constructor_SLTG
4397 * loading a SLTG typelib from an in-memory image
4399 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
4401 ITypeLibImpl *pTypeLibImpl;
4402 SLTG_Header *pHeader;
4403 SLTG_BlkEntry *pBlkEntry;
4404 SLTG_Magic *pMagic;
4405 SLTG_Index *pIndex;
4406 SLTG_Pad9 *pPad9;
4407 LPVOID pBlk, pFirstBlk;
4408 SLTG_LibBlk *pLibBlk;
4409 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
4410 char *pAfterOTIBlks = NULL;
4411 char *pNameTable, *ptr;
4412 int i;
4413 DWORD len, order;
4414 ITypeInfoImpl **ppTypeInfoImpl;
4416 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
4419 pTypeLibImpl = TypeLibImpl_Constructor();
4420 if (!pTypeLibImpl) return NULL;
4422 pHeader = pLib;
4424 TRACE_(typelib)("header:\n");
4425 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
4426 pHeader->nrOfFileBlks );
4427 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
4428 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
4429 pHeader->SLTG_magic);
4430 return NULL;
4433 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4434 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
4436 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4437 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
4439 /* Next we have a magic block */
4440 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
4442 /* Let's see if we're still in sync */
4443 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
4444 sizeof(SLTG_COMPOBJ_MAGIC))) {
4445 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
4446 return NULL;
4448 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
4449 sizeof(SLTG_DIR_MAGIC))) {
4450 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
4451 return NULL;
4454 pIndex = (SLTG_Index*)(pMagic+1);
4456 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
4458 pFirstBlk = pPad9 + 1;
4460 /* We'll set up a ptr to the main library block, which is the last one. */
4462 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1;
4463 pBlkEntry[order].next != 0;
4464 order = pBlkEntry[order].next - 1) {
4465 pBlk = (char*)pBlk + pBlkEntry[order].len;
4467 pLibBlk = pBlk;
4469 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
4471 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4472 interspersed */
4474 len += 0x40;
4476 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4478 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
4481 ptr = (char*)pLibBlk + len;
4483 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4484 WORD w, extra;
4485 len = 0;
4487 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
4489 w = *(WORD*)(ptr + 2);
4490 if(w != 0xffff) {
4491 len += w;
4492 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
4493 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4494 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4496 w = *(WORD*)(ptr + 4 + len);
4497 if(w != 0xffff) {
4498 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4499 len += w;
4500 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4501 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4502 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4504 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4505 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4506 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4507 if(extra) {
4508 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4509 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4510 len += extra;
4512 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4513 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4514 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4515 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4516 len += sizeof(SLTG_OtherTypeInfo);
4517 ptr += len;
4520 pAfterOTIBlks = ptr;
4522 /* Skip this WORD and get the next DWORD */
4523 len = *(DWORD*)(pAfterOTIBlks + 2);
4525 /* Now add this to pLibBLk look at what we're pointing at and
4526 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4527 dust and we should be pointing at the beginning of the name
4528 table */
4530 pNameTable = (char*)pLibBlk + len;
4532 switch(*(WORD*)pNameTable) {
4533 case 0xffff:
4534 break;
4535 case 0x0200:
4536 pNameTable += 0x20;
4537 break;
4538 default:
4539 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4540 break;
4543 pNameTable += 0x216;
4545 pNameTable += 2;
4547 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4549 pTypeLibImpl->Name = SLTG_ReadName(pNameTable, pLibBlk->name, pTypeLibImpl);
4552 /* Hopefully we now have enough ptrs set up to actually read in
4553 some TypeInfos. It's not clear which order to do them in, so
4554 I'll just follow the links along the BlkEntry chain and read
4555 them in the order in which they are in the file */
4557 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4558 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4560 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4561 pBlkEntry[order].next != 0;
4562 order = pBlkEntry[order].next - 1, i++) {
4564 SLTG_TypeInfoHeader *pTIHeader;
4565 SLTG_TypeInfoTail *pTITail;
4566 SLTG_MemberHeader *pMemHeader;
4568 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4569 FIXME_(typelib)("Index strings don't match\n");
4570 heap_free(pOtherTypeInfoBlks);
4571 return NULL;
4574 pTIHeader = pBlk;
4575 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4576 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4577 heap_free(pOtherTypeInfoBlks);
4578 return NULL;
4580 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4581 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4582 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4584 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4585 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4586 (*ppTypeInfoImpl)->index = i;
4587 (*ppTypeInfoImpl)->Name = SLTG_ReadName(pNameTable, pOtherTypeInfoBlks[i].name_offs, pTypeLibImpl);
4588 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4589 (*ppTypeInfoImpl)->guid = TLB_append_guid(&pTypeLibImpl->guid_list, &pOtherTypeInfoBlks[i].uuid, 2);
4590 (*ppTypeInfoImpl)->typeattr.typekind = pTIHeader->typekind;
4591 (*ppTypeInfoImpl)->typeattr.wMajorVerNum = pTIHeader->major_version;
4592 (*ppTypeInfoImpl)->typeattr.wMinorVerNum = pTIHeader->minor_version;
4593 (*ppTypeInfoImpl)->typeattr.wTypeFlags =
4594 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4596 if((*ppTypeInfoImpl)->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
4597 (*ppTypeInfoImpl)->typeattr.typekind = TKIND_DISPATCH;
4599 if((pTIHeader->typeflags1 & 7) != 2)
4600 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4601 if(pTIHeader->typeflags3 != 2)
4602 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4604 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4605 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl)->Name)),
4606 typekind_desc[pTIHeader->typekind],
4607 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl)->guid)),
4608 (*ppTypeInfoImpl)->typeattr.wTypeFlags);
4610 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4612 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4614 (*ppTypeInfoImpl)->typeattr.cbAlignment = pTITail->cbAlignment;
4615 (*ppTypeInfoImpl)->typeattr.cbSizeInstance = pTITail->cbSizeInstance;
4616 (*ppTypeInfoImpl)->typeattr.cbSizeVft = pTITail->cbSizeVft;
4618 switch(pTIHeader->typekind) {
4619 case TKIND_ENUM:
4620 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4621 pTIHeader, pTITail);
4622 break;
4624 case TKIND_RECORD:
4625 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4626 pTIHeader, pTITail);
4627 break;
4629 case TKIND_INTERFACE:
4630 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4631 pTIHeader, pTITail);
4632 break;
4634 case TKIND_COCLASS:
4635 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4636 pTIHeader, pTITail);
4637 break;
4639 case TKIND_ALIAS:
4640 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4641 pTIHeader, pTITail);
4642 break;
4644 case TKIND_DISPATCH:
4645 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4646 pTIHeader, pTITail);
4647 break;
4649 case TKIND_MODULE:
4650 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4651 pTIHeader, pTITail);
4652 break;
4654 default:
4655 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4656 break;
4660 /* could get cFuncs, cVars and cImplTypes from here
4661 but we've already set those */
4662 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4663 X(06);
4664 X(16);
4665 X(18);
4666 X(1a);
4667 X(1e);
4668 X(24);
4669 X(26);
4670 X(2a);
4671 X(2c);
4672 X(2e);
4673 X(30);
4674 X(32);
4675 X(34);
4676 #undef X
4677 ++ppTypeInfoImpl;
4678 pBlk = (char*)pBlk + pBlkEntry[order].len;
4681 if(i != pTypeLibImpl->TypeInfoCount) {
4682 FIXME("Somehow processed %d TypeInfos\n", i);
4683 heap_free(pOtherTypeInfoBlks);
4684 return NULL;
4687 heap_free(pOtherTypeInfoBlks);
4688 return &pTypeLibImpl->ITypeLib2_iface;
4691 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4693 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4695 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4697 if(IsEqualIID(riid, &IID_IUnknown) ||
4698 IsEqualIID(riid,&IID_ITypeLib)||
4699 IsEqualIID(riid,&IID_ITypeLib2))
4701 *ppv = &This->ITypeLib2_iface;
4703 else if(IsEqualIID(riid, &IID_ICreateTypeLib) ||
4704 IsEqualIID(riid, &IID_ICreateTypeLib2))
4706 *ppv = &This->ICreateTypeLib2_iface;
4708 else
4710 *ppv = NULL;
4711 TRACE("-- Interface: E_NOINTERFACE\n");
4712 return E_NOINTERFACE;
4715 IUnknown_AddRef((IUnknown*)*ppv);
4716 return S_OK;
4719 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4721 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4722 ULONG ref = InterlockedIncrement(&This->ref);
4724 TRACE("(%p) ref=%u\n", This, ref);
4726 return ref;
4729 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4731 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4732 ULONG ref = InterlockedDecrement(&This->ref);
4734 TRACE("(%p) ref=%u\n",This, ref);
4736 if (!ref)
4738 TLBImpLib *pImpLib, *pImpLibNext;
4739 TLBRefType *ref_type, *ref_type_next;
4740 TLBString *tlbstr, *tlbstr_next;
4741 TLBGuid *tlbguid, *tlbguid_next;
4742 int i;
4744 /* remove cache entry */
4745 if(This->path)
4747 TRACE("removing from cache list\n");
4748 EnterCriticalSection(&cache_section);
4749 if(This->entry.next)
4750 list_remove(&This->entry);
4751 LeaveCriticalSection(&cache_section);
4752 heap_free(This->path);
4754 TRACE(" destroying ITypeLib(%p)\n",This);
4756 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->string_list, TLBString, entry) {
4757 list_remove(&tlbstr->entry);
4758 SysFreeString(tlbstr->str);
4759 heap_free(tlbstr);
4762 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->name_list, TLBString, entry) {
4763 list_remove(&tlbstr->entry);
4764 SysFreeString(tlbstr->str);
4765 heap_free(tlbstr);
4768 LIST_FOR_EACH_ENTRY_SAFE(tlbguid, tlbguid_next, &This->guid_list, TLBGuid, entry) {
4769 list_remove(&tlbguid->entry);
4770 heap_free(tlbguid);
4773 TLB_FreeCustData(&This->custdata_list);
4775 for (i = 0; i < This->ctTypeDesc; i++)
4776 if (This->pTypeDesc[i].vt == VT_CARRAY)
4777 heap_free(This->pTypeDesc[i].u.lpadesc);
4779 heap_free(This->pTypeDesc);
4781 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4783 if (pImpLib->pImpTypeLib)
4784 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4785 SysFreeString(pImpLib->name);
4787 list_remove(&pImpLib->entry);
4788 heap_free(pImpLib);
4791 LIST_FOR_EACH_ENTRY_SAFE(ref_type, ref_type_next, &This->ref_list, TLBRefType, entry)
4793 list_remove(&ref_type->entry);
4794 heap_free(ref_type);
4797 for (i = 0; i < This->TypeInfoCount; ++i){
4798 heap_free(This->typeinfos[i]->tdescAlias);
4799 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4801 heap_free(This->typeinfos);
4802 heap_free(This);
4803 return 0;
4806 return ref;
4809 /* ITypeLib::GetTypeInfoCount
4811 * Returns the number of type descriptions in the type library
4813 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4815 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4816 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4817 return This->TypeInfoCount;
4820 /* ITypeLib::GetTypeInfo
4822 * retrieves the specified type description in the library.
4824 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4825 ITypeLib2 *iface,
4826 UINT index,
4827 ITypeInfo **ppTInfo)
4829 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4831 TRACE("%p %u %p\n", This, index, ppTInfo);
4833 if(!ppTInfo)
4834 return E_INVALIDARG;
4836 if(index >= This->TypeInfoCount)
4837 return TYPE_E_ELEMENTNOTFOUND;
4839 *ppTInfo = (ITypeInfo *)&This->typeinfos[index]->ITypeInfo2_iface;
4840 ITypeInfo_AddRef(*ppTInfo);
4842 return S_OK;
4846 /* ITypeLibs::GetTypeInfoType
4848 * Retrieves the type of a type description.
4850 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4851 ITypeLib2 *iface,
4852 UINT index,
4853 TYPEKIND *pTKind)
4855 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4857 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4859 if(!pTKind)
4860 return E_INVALIDARG;
4862 if(index >= This->TypeInfoCount)
4863 return TYPE_E_ELEMENTNOTFOUND;
4865 *pTKind = This->typeinfos[index]->typeattr.typekind;
4867 return S_OK;
4870 /* ITypeLib::GetTypeInfoOfGuid
4872 * Retrieves the type description that corresponds to the specified GUID.
4875 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4876 ITypeLib2 *iface,
4877 REFGUID guid,
4878 ITypeInfo **ppTInfo)
4880 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4881 int i;
4883 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4885 for(i = 0; i < This->TypeInfoCount; ++i){
4886 if(IsEqualIID(TLB_get_guid_null(This->typeinfos[i]->guid), guid)){
4887 *ppTInfo = (ITypeInfo *)&This->typeinfos[i]->ITypeInfo2_iface;
4888 ITypeInfo_AddRef(*ppTInfo);
4889 return S_OK;
4893 return TYPE_E_ELEMENTNOTFOUND;
4896 /* ITypeLib::GetLibAttr
4898 * Retrieves the structure that contains the library's attributes.
4901 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4902 ITypeLib2 *iface,
4903 LPTLIBATTR *attr)
4905 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4907 TRACE("(%p, %p)\n", This, attr);
4909 if (!attr) return E_INVALIDARG;
4911 *attr = heap_alloc(sizeof(**attr));
4912 if (!*attr) return E_OUTOFMEMORY;
4914 (*attr)->guid = *TLB_get_guid_null(This->guid);
4915 (*attr)->lcid = This->set_lcid;
4916 (*attr)->syskind = This->syskind;
4917 (*attr)->wMajorVerNum = This->ver_major;
4918 (*attr)->wMinorVerNum = This->ver_minor;
4919 (*attr)->wLibFlags = This->libflags;
4921 return S_OK;
4924 /* ITypeLib::GetTypeComp
4926 * Enables a client compiler to bind to a library's types, variables,
4927 * constants, and global functions.
4930 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4931 ITypeLib2 *iface,
4932 ITypeComp **ppTComp)
4934 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4936 TRACE("(%p)->(%p)\n",This,ppTComp);
4937 *ppTComp = &This->ITypeComp_iface;
4938 ITypeComp_AddRef(*ppTComp);
4940 return S_OK;
4943 /* ITypeLib::GetDocumentation
4945 * Retrieves the library's documentation string, the complete Help file name
4946 * and path, and the context identifier for the library Help topic in the Help
4947 * file.
4949 * On a successful return all non-null BSTR pointers will have been set,
4950 * possibly to NULL.
4952 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4953 ITypeLib2 *iface,
4954 INT index,
4955 BSTR *pBstrName,
4956 BSTR *pBstrDocString,
4957 DWORD *pdwHelpContext,
4958 BSTR *pBstrHelpFile)
4960 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4961 HRESULT result = E_INVALIDARG;
4962 ITypeInfo *pTInfo;
4964 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4965 This, index,
4966 pBstrName, pBstrDocString,
4967 pdwHelpContext, pBstrHelpFile);
4969 if(index<0)
4971 /* documentation for the typelib */
4972 if(pBstrName)
4974 if (This->Name)
4976 if(!(*pBstrName = SysAllocString(TLB_get_bstr(This->Name))))
4977 goto memerr1;
4979 else
4980 *pBstrName = NULL;
4982 if(pBstrDocString)
4984 if (This->DocString)
4986 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->DocString))))
4987 goto memerr2;
4989 else
4990 *pBstrDocString = NULL;
4992 if(pdwHelpContext)
4994 *pdwHelpContext = This->dwHelpContext;
4996 if(pBstrHelpFile)
4998 if (This->HelpFile)
5000 if(!(*pBstrHelpFile = SysAllocString(TLB_get_bstr(This->HelpFile))))
5001 goto memerr3;
5003 else
5004 *pBstrHelpFile = NULL;
5007 result = S_OK;
5009 else
5011 /* for a typeinfo */
5012 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
5014 if(SUCCEEDED(result))
5016 result = ITypeInfo_GetDocumentation(pTInfo,
5017 MEMBERID_NIL,
5018 pBstrName,
5019 pBstrDocString,
5020 pdwHelpContext, pBstrHelpFile);
5022 ITypeInfo_Release(pTInfo);
5025 return result;
5026 memerr3:
5027 if (pBstrDocString) SysFreeString (*pBstrDocString);
5028 memerr2:
5029 if (pBstrName) SysFreeString (*pBstrName);
5030 memerr1:
5031 return STG_E_INSUFFICIENTMEMORY;
5034 /* ITypeLib::IsName
5036 * Indicates whether a passed-in string contains the name of a type or member
5037 * described in the library.
5040 static HRESULT WINAPI ITypeLib2_fnIsName(
5041 ITypeLib2 *iface,
5042 LPOLESTR szNameBuf,
5043 ULONG lHashVal,
5044 BOOL *pfName)
5046 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5047 int tic;
5048 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
5050 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
5051 pfName);
5053 *pfName=TRUE;
5054 for(tic = 0; tic < This->TypeInfoCount; ++tic){
5055 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5056 if(!TLB_str_memcmp(szNameBuf, pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5057 for(fdc = 0; fdc < pTInfo->typeattr.cFuncs; ++fdc) {
5058 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
5059 int pc;
5060 if(!TLB_str_memcmp(szNameBuf, pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5061 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++){
5062 if(!TLB_str_memcmp(szNameBuf, pFInfo->pParamDesc[pc].Name, nNameBufLen))
5063 goto ITypeLib2_fnIsName_exit;
5066 for(vrc = 0; vrc < pTInfo->typeattr.cVars; ++vrc){
5067 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
5068 if(!TLB_str_memcmp(szNameBuf, pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5072 *pfName=FALSE;
5074 ITypeLib2_fnIsName_exit:
5075 TRACE("(%p)slow! search for %s: %sfound!\n", This,
5076 debugstr_w(szNameBuf), *pfName ? "" : "NOT ");
5078 return S_OK;
5081 /* ITypeLib::FindName
5083 * Finds occurrences of a type description in a type library. This may be used
5084 * to quickly verify that a name exists in a type library.
5087 static HRESULT WINAPI ITypeLib2_fnFindName(
5088 ITypeLib2 *iface,
5089 LPOLESTR name,
5090 ULONG hash,
5091 ITypeInfo **ppTInfo,
5092 MEMBERID *memid,
5093 UINT16 *found)
5095 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5096 int tic;
5097 UINT count = 0;
5098 UINT len;
5100 TRACE("(%p)->(%s %u %p %p %p)\n", This, debugstr_w(name), hash, ppTInfo, memid, found);
5102 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
5103 return E_INVALIDARG;
5105 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
5106 for(tic = 0; count < *found && tic < This->TypeInfoCount; ++tic) {
5107 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5108 TLBVarDesc *var;
5109 UINT fdc;
5111 if(!TLB_str_memcmp(name, pTInfo->Name, len)) {
5112 memid[count] = MEMBERID_NIL;
5113 goto ITypeLib2_fnFindName_exit;
5116 for(fdc = 0; fdc < pTInfo->typeattr.cFuncs; ++fdc) {
5117 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
5119 if(!TLB_str_memcmp(name, func->Name, len)) {
5120 memid[count] = func->funcdesc.memid;
5121 goto ITypeLib2_fnFindName_exit;
5125 var = TLB_get_vardesc_by_name(pTInfo->vardescs, pTInfo->typeattr.cVars, name);
5126 if (var) {
5127 memid[count] = var->vardesc.memid;
5128 goto ITypeLib2_fnFindName_exit;
5131 continue;
5132 ITypeLib2_fnFindName_exit:
5133 ITypeInfo2_AddRef(&pTInfo->ITypeInfo2_iface);
5134 ppTInfo[count] = (ITypeInfo *)&pTInfo->ITypeInfo2_iface;
5135 count++;
5137 TRACE("found %d typeinfos\n", count);
5139 *found = count;
5141 return S_OK;
5144 /* ITypeLib::ReleaseTLibAttr
5146 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5149 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
5150 ITypeLib2 *iface,
5151 TLIBATTR *pTLibAttr)
5153 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5154 TRACE("(%p)->(%p)\n", This, pTLibAttr);
5155 heap_free(pTLibAttr);
5158 /* ITypeLib2::GetCustData
5160 * gets the custom data
5162 static HRESULT WINAPI ITypeLib2_fnGetCustData(
5163 ITypeLib2 * iface,
5164 REFGUID guid,
5165 VARIANT *pVarVal)
5167 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5168 TLBCustData *pCData;
5170 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
5172 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
5173 if(!pCData)
5174 return TYPE_E_ELEMENTNOTFOUND;
5176 VariantInit(pVarVal);
5177 VariantCopy(pVarVal, &pCData->data);
5179 return S_OK;
5182 /* ITypeLib2::GetLibStatistics
5184 * Returns statistics about a type library that are required for efficient
5185 * sizing of hash tables.
5188 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
5189 ITypeLib2 * iface,
5190 ULONG *pcUniqueNames,
5191 ULONG *pcchUniqueNames)
5193 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5195 FIXME("(%p): stub!\n", This);
5197 if(pcUniqueNames) *pcUniqueNames=1;
5198 if(pcchUniqueNames) *pcchUniqueNames=1;
5199 return S_OK;
5202 /* ITypeLib2::GetDocumentation2
5204 * Retrieves the library's documentation string, the complete Help file name
5205 * and path, the localization context to use, and the context ID for the
5206 * library Help topic in the Help file.
5209 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
5210 ITypeLib2 * iface,
5211 INT index,
5212 LCID lcid,
5213 BSTR *pbstrHelpString,
5214 DWORD *pdwHelpStringContext,
5215 BSTR *pbstrHelpStringDll)
5217 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5218 HRESULT result;
5219 ITypeInfo *pTInfo;
5221 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
5223 /* the help string should be obtained from the helpstringdll,
5224 * using the _DLLGetDocumentation function, based on the supplied
5225 * lcid. Nice to do sometime...
5227 if(index<0)
5229 /* documentation for the typelib */
5230 if(pbstrHelpString)
5231 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->DocString));
5232 if(pdwHelpStringContext)
5233 *pdwHelpStringContext=This->dwHelpContext;
5234 if(pbstrHelpStringDll)
5235 *pbstrHelpStringDll=SysAllocString(TLB_get_bstr(This->HelpStringDll));
5237 result = S_OK;
5239 else
5241 /* for a typeinfo */
5242 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
5244 if(SUCCEEDED(result))
5246 ITypeInfo2 * pTInfo2;
5247 result = ITypeInfo_QueryInterface(pTInfo,
5248 &IID_ITypeInfo2,
5249 (LPVOID*) &pTInfo2);
5251 if(SUCCEEDED(result))
5253 result = ITypeInfo2_GetDocumentation2(pTInfo2,
5254 MEMBERID_NIL,
5255 lcid,
5256 pbstrHelpString,
5257 pdwHelpStringContext,
5258 pbstrHelpStringDll);
5260 ITypeInfo2_Release(pTInfo2);
5263 ITypeInfo_Release(pTInfo);
5266 return result;
5269 static HRESULT TLB_copy_all_custdata(struct list *custdata_list, CUSTDATA *pCustData)
5271 TLBCustData *pCData;
5272 unsigned int ct;
5273 CUSTDATAITEM *cdi;
5275 ct = list_count(custdata_list);
5277 pCustData->prgCustData = CoTaskMemAlloc(ct * sizeof(CUSTDATAITEM));
5278 if(!pCustData->prgCustData)
5279 return E_OUTOFMEMORY;
5281 pCustData->cCustData = ct;
5283 cdi = pCustData->prgCustData;
5284 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
5285 cdi->guid = *TLB_get_guid_null(pCData->guid);
5286 VariantCopy(&cdi->varValue, &pCData->data);
5287 ++cdi;
5290 return S_OK;
5294 /* ITypeLib2::GetAllCustData
5296 * Gets all custom data items for the library.
5299 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
5300 ITypeLib2 * iface,
5301 CUSTDATA *pCustData)
5303 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5304 TRACE("(%p)->(%p)\n", This, pCustData);
5305 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
5308 static const ITypeLib2Vtbl tlbvt = {
5309 ITypeLib2_fnQueryInterface,
5310 ITypeLib2_fnAddRef,
5311 ITypeLib2_fnRelease,
5312 ITypeLib2_fnGetTypeInfoCount,
5313 ITypeLib2_fnGetTypeInfo,
5314 ITypeLib2_fnGetTypeInfoType,
5315 ITypeLib2_fnGetTypeInfoOfGuid,
5316 ITypeLib2_fnGetLibAttr,
5317 ITypeLib2_fnGetTypeComp,
5318 ITypeLib2_fnGetDocumentation,
5319 ITypeLib2_fnIsName,
5320 ITypeLib2_fnFindName,
5321 ITypeLib2_fnReleaseTLibAttr,
5323 ITypeLib2_fnGetCustData,
5324 ITypeLib2_fnGetLibStatistics,
5325 ITypeLib2_fnGetDocumentation2,
5326 ITypeLib2_fnGetAllCustData
5330 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5332 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5334 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
5337 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
5339 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5341 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
5344 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
5346 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5348 return ITypeLib2_Release(&This->ITypeLib2_iface);
5351 static HRESULT WINAPI ITypeLibComp_fnBind(
5352 ITypeComp * iface,
5353 OLECHAR * szName,
5354 ULONG lHash,
5355 WORD wFlags,
5356 ITypeInfo ** ppTInfo,
5357 DESCKIND * pDescKind,
5358 BINDPTR * pBindPtr)
5360 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5361 BOOL typemismatch = FALSE;
5362 int i;
5364 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5366 *pDescKind = DESCKIND_NONE;
5367 pBindPtr->lptcomp = NULL;
5368 *ppTInfo = NULL;
5370 for(i = 0; i < This->TypeInfoCount; ++i){
5371 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5372 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo->Name)));
5374 /* FIXME: check wFlags here? */
5375 /* FIXME: we should use a hash table to look this info up using lHash
5376 * instead of an O(n) search */
5377 if ((pTypeInfo->typeattr.typekind == TKIND_ENUM) ||
5378 (pTypeInfo->typeattr.typekind == TKIND_MODULE))
5380 if (pTypeInfo->Name && !wcscmp(pTypeInfo->Name->str, szName))
5382 *pDescKind = DESCKIND_TYPECOMP;
5383 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
5384 ITypeComp_AddRef(pBindPtr->lptcomp);
5385 TRACE("module or enum: %s\n", debugstr_w(szName));
5386 return S_OK;
5390 if ((pTypeInfo->typeattr.typekind == TKIND_MODULE) ||
5391 (pTypeInfo->typeattr.typekind == TKIND_ENUM))
5393 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5394 HRESULT hr;
5396 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5397 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
5399 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
5400 return S_OK;
5402 else if (hr == TYPE_E_TYPEMISMATCH)
5403 typemismatch = TRUE;
5406 if ((pTypeInfo->typeattr.typekind == TKIND_COCLASS) &&
5407 (pTypeInfo->typeattr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
5409 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5410 HRESULT hr;
5411 ITypeInfo *subtypeinfo;
5412 BINDPTR subbindptr;
5413 DESCKIND subdesckind;
5415 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
5416 &subtypeinfo, &subdesckind, &subbindptr);
5417 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
5419 TYPEDESC tdesc_appobject;
5420 const VARDESC vardesc_appobject =
5422 -2, /* memid */
5423 NULL, /* lpstrSchema */
5425 0 /* oInst */
5428 /* ELEMDESC */
5430 /* TYPEDESC */
5432 &tdesc_appobject
5434 VT_PTR
5437 0, /* wVarFlags */
5438 VAR_STATIC /* varkind */
5441 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
5442 tdesc_appobject.vt = VT_USERDEFINED;
5444 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
5446 /* cleanup things filled in by Bind call so we can put our
5447 * application object data in there instead */
5448 switch (subdesckind)
5450 case DESCKIND_FUNCDESC:
5451 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
5452 break;
5453 case DESCKIND_VARDESC:
5454 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
5455 break;
5456 default:
5457 break;
5459 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
5461 if (pTypeInfo->hreftype == -1)
5462 FIXME("no hreftype for interface %p\n", pTypeInfo);
5464 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
5465 if (FAILED(hr))
5466 return hr;
5468 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5469 *ppTInfo = (ITypeInfo *)&pTypeInfo->ITypeInfo2_iface;
5470 ITypeInfo_AddRef(*ppTInfo);
5471 return S_OK;
5473 else if (hr == TYPE_E_TYPEMISMATCH)
5474 typemismatch = TRUE;
5478 if (typemismatch)
5480 TRACE("type mismatch %s\n", debugstr_w(szName));
5481 return TYPE_E_TYPEMISMATCH;
5483 else
5485 TRACE("name not found %s\n", debugstr_w(szName));
5486 return S_OK;
5490 static HRESULT WINAPI ITypeLibComp_fnBindType(
5491 ITypeComp * iface,
5492 OLECHAR * szName,
5493 ULONG lHash,
5494 ITypeInfo ** ppTInfo,
5495 ITypeComp ** ppTComp)
5497 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5498 ITypeInfoImpl *info;
5500 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5502 if(!szName || !ppTInfo || !ppTComp)
5503 return E_INVALIDARG;
5505 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, szName);
5506 if(!info){
5507 *ppTInfo = NULL;
5508 *ppTComp = NULL;
5509 return S_OK;
5512 *ppTInfo = (ITypeInfo *)&info->ITypeInfo2_iface;
5513 ITypeInfo_AddRef(*ppTInfo);
5514 *ppTComp = &info->ITypeComp_iface;
5515 ITypeComp_AddRef(*ppTComp);
5517 return S_OK;
5520 static const ITypeCompVtbl tlbtcvt =
5523 ITypeLibComp_fnQueryInterface,
5524 ITypeLibComp_fnAddRef,
5525 ITypeLibComp_fnRelease,
5527 ITypeLibComp_fnBind,
5528 ITypeLibComp_fnBindType
5531 /*================== ITypeInfo(2) Methods ===================================*/
5532 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5534 ITypeInfoImpl *pTypeInfoImpl;
5536 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5537 if (pTypeInfoImpl)
5539 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5540 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5541 pTypeInfoImpl->ICreateTypeInfo2_iface.lpVtbl = &CreateTypeInfo2Vtbl;
5542 pTypeInfoImpl->ref = 0;
5543 pTypeInfoImpl->hreftype = -1;
5544 pTypeInfoImpl->typeattr.memidConstructor = MEMBERID_NIL;
5545 pTypeInfoImpl->typeattr.memidDestructor = MEMBERID_NIL;
5546 pTypeInfoImpl->pcustdata_list = &pTypeInfoImpl->custdata_list;
5547 list_init(pTypeInfoImpl->pcustdata_list);
5549 TRACE("(%p)\n", pTypeInfoImpl);
5550 return pTypeInfoImpl;
5553 /* ITypeInfo::QueryInterface
5555 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5556 ITypeInfo2 *iface,
5557 REFIID riid,
5558 VOID **ppvObject)
5560 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5562 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5564 *ppvObject=NULL;
5565 if(IsEqualIID(riid, &IID_IUnknown) ||
5566 IsEqualIID(riid,&IID_ITypeInfo)||
5567 IsEqualIID(riid,&IID_ITypeInfo2))
5568 *ppvObject = &This->ITypeInfo2_iface;
5569 else if(IsEqualIID(riid, &IID_ICreateTypeInfo) ||
5570 IsEqualIID(riid, &IID_ICreateTypeInfo2))
5571 *ppvObject = &This->ICreateTypeInfo2_iface;
5572 else if(IsEqualIID(riid, &IID_ITypeComp))
5573 *ppvObject = &This->ITypeComp_iface;
5575 if(*ppvObject){
5576 IUnknown_AddRef((IUnknown*)*ppvObject);
5577 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5578 return S_OK;
5580 TRACE("-- Interface: E_NOINTERFACE\n");
5581 return E_NOINTERFACE;
5584 /* ITypeInfo::AddRef
5586 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5588 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5589 ULONG ref = InterlockedIncrement(&This->ref);
5591 TRACE("(%p)->ref is %u\n",This, ref);
5593 if (ref == 1 /* incremented from 0 */)
5594 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5596 return ref;
5599 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5601 UINT i;
5603 TRACE("destroying ITypeInfo(%p)\n",This);
5605 for (i = 0; i < This->typeattr.cFuncs; ++i)
5607 int j;
5608 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5609 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5611 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5612 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5613 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5614 TLB_FreeCustData(&pFInfo->pParamDesc[j].custdata_list);
5616 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5617 heap_free(pFInfo->pParamDesc);
5618 TLB_FreeCustData(&pFInfo->custdata_list);
5620 heap_free(This->funcdescs);
5622 for(i = 0; i < This->typeattr.cVars; ++i)
5624 TLBVarDesc *pVInfo = &This->vardescs[i];
5625 if (pVInfo->vardesc_create) {
5626 TLB_FreeVarDesc(pVInfo->vardesc_create);
5627 } else if (pVInfo->vardesc.varkind == VAR_CONST) {
5628 VariantClear(pVInfo->vardesc.u.lpvarValue);
5629 heap_free(pVInfo->vardesc.u.lpvarValue);
5631 TLB_FreeCustData(&pVInfo->custdata_list);
5633 heap_free(This->vardescs);
5635 if(This->impltypes){
5636 for (i = 0; i < This->typeattr.cImplTypes; ++i){
5637 TLBImplType *pImpl = &This->impltypes[i];
5638 TLB_FreeCustData(&pImpl->custdata_list);
5640 heap_free(This->impltypes);
5643 TLB_FreeCustData(&This->custdata_list);
5645 heap_free(This);
5648 /* ITypeInfo::Release
5650 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5652 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5653 ULONG ref = InterlockedDecrement(&This->ref);
5655 TRACE("(%p)->(%u)\n",This, ref);
5657 if (!ref)
5659 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5660 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5661 if (not_attached_to_typelib)
5662 heap_free(This);
5663 /* otherwise This will be freed when typelib is freed */
5666 return ref;
5669 /* ITypeInfo::GetTypeAttr
5671 * Retrieves a TYPEATTR structure that contains the attributes of the type
5672 * description.
5675 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5676 LPTYPEATTR *ppTypeAttr)
5678 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5679 SIZE_T size;
5681 TRACE("(%p)\n",This);
5683 size = sizeof(**ppTypeAttr);
5684 if (This->typeattr.typekind == TKIND_ALIAS && This->tdescAlias)
5685 size += TLB_SizeTypeDesc(This->tdescAlias, FALSE);
5687 *ppTypeAttr = heap_alloc(size);
5688 if (!*ppTypeAttr)
5689 return E_OUTOFMEMORY;
5691 **ppTypeAttr = This->typeattr;
5692 (*ppTypeAttr)->guid = *TLB_get_guid_null(This->guid);
5694 if (This->tdescAlias)
5695 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias, This->tdescAlias, *ppTypeAttr + 1);
5697 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5698 /* This should include all the inherited funcs */
5699 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / This->pTypeLib->ptr_size;
5700 /* This is always the size of IDispatch's vtbl */
5701 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5702 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5704 return S_OK;
5707 /* ITypeInfo::GetTypeComp
5709 * Retrieves the ITypeComp interface for the type description, which enables a
5710 * client compiler to bind to the type description's members.
5713 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5714 ITypeComp * *ppTComp)
5716 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5718 TRACE("(%p)->(%p)\n", This, ppTComp);
5720 *ppTComp = &This->ITypeComp_iface;
5721 ITypeComp_AddRef(*ppTComp);
5722 return S_OK;
5725 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5727 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5728 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5729 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5730 return size;
5733 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5735 *dest = *src;
5736 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5737 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5739 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5740 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5741 *buffer += sizeof(PARAMDESCEX);
5742 *pparamdescex_dest = *pparamdescex_src;
5743 pparamdescex_dest->cBytes = sizeof(PARAMDESCEX);
5744 VariantInit(&pparamdescex_dest->varDefaultValue);
5745 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5746 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5748 else
5749 dest->u.paramdesc.pparamdescex = NULL;
5750 return S_OK;
5753 static HRESULT TLB_SanitizeBSTR(BSTR str)
5755 UINT len = SysStringLen(str), i;
5756 for (i = 0; i < len; ++i)
5757 if (str[i] > 0x7f)
5758 str[i] = '?';
5759 return S_OK;
5762 static HRESULT TLB_SanitizeVariant(VARIANT *var)
5764 if (V_VT(var) == VT_INT)
5765 return VariantChangeType(var, var, 0, VT_I4);
5766 else if (V_VT(var) == VT_UINT)
5767 return VariantChangeType(var, var, 0, VT_UI4);
5768 else if (V_VT(var) == VT_BSTR)
5769 return TLB_SanitizeBSTR(V_BSTR(var));
5771 return S_OK;
5774 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5776 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5777 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5780 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5782 FUNCDESC *dest;
5783 char *buffer;
5784 SIZE_T size = sizeof(*src);
5785 SHORT i;
5786 HRESULT hr;
5788 size += sizeof(*src->lprgscode) * src->cScodes;
5789 size += TLB_SizeElemDesc(&src->elemdescFunc);
5790 for (i = 0; i < src->cParams; i++)
5792 size += sizeof(ELEMDESC);
5793 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5796 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5797 if (!dest) return E_OUTOFMEMORY;
5799 *dest = *src;
5800 if (dispinterface) /* overwrite funckind */
5801 dest->funckind = FUNC_DISPATCH;
5802 buffer = (char *)(dest + 1);
5804 dest->oVft = dest->oVft & 0xFFFC;
5806 if (dest->cScodes) {
5807 dest->lprgscode = (SCODE *)buffer;
5808 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5809 buffer += sizeof(*src->lprgscode) * src->cScodes;
5810 } else
5811 dest->lprgscode = NULL;
5813 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5814 if (FAILED(hr))
5816 SysFreeString((BSTR)dest);
5817 return hr;
5820 if (dest->cParams) {
5821 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5822 buffer += sizeof(ELEMDESC) * src->cParams;
5823 for (i = 0; i < src->cParams; i++)
5825 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5826 if (FAILED(hr))
5827 break;
5829 if (FAILED(hr))
5831 /* undo the above actions */
5832 for (i = i - 1; i >= 0; i--)
5833 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5834 TLB_FreeElemDesc(&dest->elemdescFunc);
5835 SysFreeString((BSTR)dest);
5836 return hr;
5838 } else
5839 dest->lprgelemdescParam = NULL;
5841 /* special treatment for dispinterfaces: this makes functions appear
5842 * to return their [retval] value when it is really returning an
5843 * HRESULT */
5844 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5846 if (dest->cParams &&
5847 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5849 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5850 if (elemdesc->tdesc.vt != VT_PTR)
5852 ERR("elemdesc should have started with VT_PTR instead of:\n");
5853 if (ERR_ON(ole))
5854 dump_ELEMDESC(elemdesc);
5855 return E_UNEXPECTED;
5858 /* copy last parameter to the return value. we are using a flat
5859 * buffer so there is no danger of leaking memory in
5860 * elemdescFunc */
5861 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5863 /* remove the last parameter */
5864 dest->cParams--;
5866 else
5867 /* otherwise this function is made to appear to have no return
5868 * value */
5869 dest->elemdescFunc.tdesc.vt = VT_VOID;
5873 *dest_ptr = dest;
5874 return S_OK;
5877 static void TLB_FreeVarDesc(VARDESC *var_desc)
5879 TLB_FreeElemDesc(&var_desc->elemdescVar);
5880 if (var_desc->varkind == VAR_CONST)
5881 VariantClear(var_desc->u.lpvarValue);
5882 SysFreeString((BSTR)var_desc);
5885 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5887 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5889 if (index >= This->typeattr.cFuncs)
5890 return TYPE_E_ELEMENTNOTFOUND;
5892 *ppFuncDesc = &This->funcdescs[index].funcdesc;
5893 return S_OK;
5896 /* internal function to make the inherited interfaces' methods appear
5897 * part of the interface */
5898 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5899 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5901 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5902 HRESULT hr;
5903 UINT implemented_funcs = 0;
5905 if (funcs)
5906 *funcs = 0;
5907 else
5908 *hrefoffset = DISPATCH_HREF_OFFSET;
5910 if(This->impltypes)
5912 ITypeInfo *pSubTypeInfo;
5913 UINT sub_funcs;
5915 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5916 if (FAILED(hr))
5917 return hr;
5919 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5920 index,
5921 ppFuncDesc,
5922 &sub_funcs, hrefoffset);
5923 implemented_funcs += sub_funcs;
5924 ITypeInfo_Release(pSubTypeInfo);
5925 if (SUCCEEDED(hr))
5926 return hr;
5927 *hrefoffset += DISPATCH_HREF_OFFSET;
5930 if (funcs)
5931 *funcs = implemented_funcs + This->typeattr.cFuncs;
5932 else
5933 *hrefoffset = 0;
5935 if (index < implemented_funcs)
5936 return E_INVALIDARG;
5937 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5938 ppFuncDesc);
5941 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5943 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5944 while (TRUE)
5946 switch (pTypeDesc->vt)
5948 case VT_USERDEFINED:
5949 pTypeDesc->u.hreftype += hrefoffset;
5950 return;
5951 case VT_PTR:
5952 case VT_SAFEARRAY:
5953 pTypeDesc = pTypeDesc->u.lptdesc;
5954 break;
5955 case VT_CARRAY:
5956 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5957 break;
5958 default:
5959 return;
5964 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5966 SHORT i;
5967 for (i = 0; i < pFuncDesc->cParams; i++)
5968 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5969 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5972 /* ITypeInfo::GetFuncDesc
5974 * Retrieves the FUNCDESC structure that contains information about a
5975 * specified function.
5978 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5979 LPFUNCDESC *ppFuncDesc)
5981 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5982 const FUNCDESC *internal_funcdesc;
5983 HRESULT hr;
5984 UINT hrefoffset = 0;
5986 TRACE("(%p) index %d\n", This, index);
5988 if (!ppFuncDesc)
5989 return E_INVALIDARG;
5991 if (This->needs_layout)
5992 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
5994 if (This->typeattr.typekind == TKIND_DISPATCH)
5995 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5996 &internal_funcdesc, NULL,
5997 &hrefoffset);
5998 else
5999 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
6000 &internal_funcdesc);
6001 if (FAILED(hr))
6003 WARN("description for function %d not found\n", index);
6004 return hr;
6007 hr = TLB_AllocAndInitFuncDesc(
6008 internal_funcdesc,
6009 ppFuncDesc,
6010 This->typeattr.typekind == TKIND_DISPATCH);
6012 if ((This->typeattr.typekind == TKIND_DISPATCH) && hrefoffset)
6013 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
6015 TRACE("-- 0x%08x\n", hr);
6016 return hr;
6019 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
6021 VARDESC *dest;
6022 char *buffer;
6023 SIZE_T size = sizeof(*src);
6024 HRESULT hr;
6026 if (src->lpstrSchema) size += (lstrlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
6027 if (src->varkind == VAR_CONST)
6028 size += sizeof(VARIANT);
6029 size += TLB_SizeElemDesc(&src->elemdescVar);
6031 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
6032 if (!dest) return E_OUTOFMEMORY;
6034 *dest = *src;
6035 buffer = (char *)(dest + 1);
6036 if (src->lpstrSchema)
6038 int len;
6039 dest->lpstrSchema = (LPOLESTR)buffer;
6040 len = lstrlenW(src->lpstrSchema);
6041 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
6042 buffer += (len + 1) * sizeof(WCHAR);
6045 if (src->varkind == VAR_CONST)
6047 HRESULT hr;
6049 dest->u.lpvarValue = (VARIANT *)buffer;
6050 *dest->u.lpvarValue = *src->u.lpvarValue;
6051 buffer += sizeof(VARIANT);
6052 VariantInit(dest->u.lpvarValue);
6053 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
6054 if (FAILED(hr))
6056 SysFreeString((BSTR)dest);
6057 return hr;
6060 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
6061 if (FAILED(hr))
6063 if (src->varkind == VAR_CONST)
6064 VariantClear(dest->u.lpvarValue);
6065 SysFreeString((BSTR)dest);
6066 return hr;
6068 *dest_ptr = dest;
6069 return S_OK;
6072 /* ITypeInfo::GetVarDesc
6074 * Retrieves a VARDESC structure that describes the specified variable.
6077 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
6078 LPVARDESC *ppVarDesc)
6080 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6081 const TLBVarDesc *pVDesc = &This->vardescs[index];
6083 TRACE("(%p) index %d\n", This, index);
6085 if(index >= This->typeattr.cVars)
6086 return TYPE_E_ELEMENTNOTFOUND;
6088 if (This->needs_layout)
6089 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6091 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
6094 /* ITypeInfo_GetNames
6096 * Retrieves the variable with the specified member ID (or the name of the
6097 * property or method and its parameters) that correspond to the specified
6098 * function ID.
6100 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
6101 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
6103 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6104 const TLBFuncDesc *pFDesc;
6105 const TLBVarDesc *pVDesc;
6106 int i;
6107 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
6109 if(!rgBstrNames)
6110 return E_INVALIDARG;
6112 *pcNames = 0;
6114 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->typeattr.cFuncs, memid);
6115 if(pFDesc)
6117 if(!cMaxNames || !pFDesc->Name)
6118 return S_OK;
6120 *rgBstrNames = SysAllocString(TLB_get_bstr(pFDesc->Name));
6121 ++(*pcNames);
6123 for(i = 0; i < pFDesc->funcdesc.cParams; ++i){
6124 if(*pcNames >= cMaxNames || !pFDesc->pParamDesc[i].Name)
6125 return S_OK;
6126 rgBstrNames[*pcNames] = SysAllocString(TLB_get_bstr(pFDesc->pParamDesc[i].Name));
6127 ++(*pcNames);
6129 return S_OK;
6132 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->typeattr.cVars, memid);
6133 if(pVDesc)
6135 *rgBstrNames=SysAllocString(TLB_get_bstr(pVDesc->Name));
6136 *pcNames=1;
6138 else
6140 if(This->impltypes &&
6141 (This->typeattr.typekind == TKIND_INTERFACE || This->typeattr.typekind == TKIND_DISPATCH)) {
6142 /* recursive search */
6143 ITypeInfo *pTInfo;
6144 HRESULT result;
6145 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6146 if(SUCCEEDED(result))
6148 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
6149 ITypeInfo_Release(pTInfo);
6150 return result;
6152 WARN("Could not search inherited interface!\n");
6154 else
6156 WARN("no names found\n");
6158 *pcNames=0;
6159 return TYPE_E_ELEMENTNOTFOUND;
6161 return S_OK;
6165 /* ITypeInfo::GetRefTypeOfImplType
6167 * If a type description describes a COM class, it retrieves the type
6168 * description of the implemented interface types. For an interface,
6169 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6170 * if any exist.
6173 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
6174 ITypeInfo2 *iface,
6175 UINT index,
6176 HREFTYPE *pRefType)
6178 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6179 HRESULT hr = S_OK;
6181 TRACE("(%p) index %d\n", This, index);
6182 if (TRACE_ON(ole)) dump_TypeInfo(This);
6184 if(index==(UINT)-1)
6186 /* only valid on dual interfaces;
6187 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6190 if (This->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
6192 *pRefType = -2;
6194 else
6196 hr = TYPE_E_ELEMENTNOTFOUND;
6199 else if(index == 0 && This->typeattr.typekind == TKIND_DISPATCH)
6201 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6202 *pRefType = This->pTypeLib->dispatch_href;
6204 else
6206 if(index >= This->typeattr.cImplTypes)
6207 hr = TYPE_E_ELEMENTNOTFOUND;
6208 else{
6209 *pRefType = This->impltypes[index].hRef;
6210 if (This->typeattr.typekind == TKIND_INTERFACE)
6211 *pRefType |= 0x2;
6215 if(TRACE_ON(ole))
6217 if(SUCCEEDED(hr))
6218 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
6219 else
6220 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
6223 return hr;
6226 /* ITypeInfo::GetImplTypeFlags
6228 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6229 * or base interface in a type description.
6231 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
6232 UINT index, INT *pImplTypeFlags)
6234 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6236 TRACE("(%p) index %d\n", This, index);
6238 if(!pImplTypeFlags)
6239 return E_INVALIDARG;
6241 if(This->typeattr.typekind == TKIND_DISPATCH && index == 0){
6242 *pImplTypeFlags = 0;
6243 return S_OK;
6246 if(index >= This->typeattr.cImplTypes)
6247 return TYPE_E_ELEMENTNOTFOUND;
6249 *pImplTypeFlags = This->impltypes[index].implflags;
6251 return S_OK;
6254 /* GetIDsOfNames
6255 * Maps between member names and member IDs, and parameter names and
6256 * parameter IDs.
6258 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
6259 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
6261 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6262 const TLBVarDesc *pVDesc;
6263 HRESULT ret=S_OK;
6264 UINT i, fdc;
6266 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
6267 cNames);
6269 /* init out parameters in case of failure */
6270 for (i = 0; i < cNames; i++)
6271 pMemId[i] = MEMBERID_NIL;
6273 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc) {
6274 int j;
6275 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
6276 if(!lstrcmpiW(*rgszNames, TLB_get_bstr(pFDesc->Name))) {
6277 if(cNames) *pMemId=pFDesc->funcdesc.memid;
6278 for(i=1; i < cNames; i++){
6279 for(j=0; j<pFDesc->funcdesc.cParams; j++)
6280 if(!lstrcmpiW(rgszNames[i],TLB_get_bstr(pFDesc->pParamDesc[j].Name)))
6281 break;
6282 if( j<pFDesc->funcdesc.cParams)
6283 pMemId[i]=j;
6284 else
6285 ret=DISP_E_UNKNOWNNAME;
6287 TRACE("-- 0x%08x\n", ret);
6288 return ret;
6291 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->typeattr.cVars, *rgszNames);
6292 if(pVDesc){
6293 if(cNames)
6294 *pMemId = pVDesc->vardesc.memid;
6295 return ret;
6297 /* not found, see if it can be found in an inherited interface */
6298 if(This->impltypes) {
6299 /* recursive search */
6300 ITypeInfo *pTInfo;
6301 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6302 if(SUCCEEDED(ret)){
6303 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
6304 ITypeInfo_Release(pTInfo);
6305 return ret;
6307 WARN("Could not search inherited interface!\n");
6308 } else
6309 WARN("no names found\n");
6310 return DISP_E_UNKNOWNNAME;
6314 #ifdef __i386__
6316 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6317 extern double call_double_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6318 __ASM_GLOBAL_FUNC( call_method,
6319 "pushl %ebp\n\t"
6320 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6321 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6322 "movl %esp,%ebp\n\t"
6323 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6324 "pushl %esi\n\t"
6325 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6326 "pushl %edi\n\t"
6327 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6328 "movl 12(%ebp),%edx\n\t"
6329 "movl %esp,%edi\n\t"
6330 "shll $2,%edx\n\t"
6331 "jz 1f\n\t"
6332 "subl %edx,%edi\n\t"
6333 "andl $~15,%edi\n\t"
6334 "movl %edi,%esp\n\t"
6335 "movl 12(%ebp),%ecx\n\t"
6336 "movl 16(%ebp),%esi\n\t"
6337 "cld\n\t"
6338 "rep; movsl\n"
6339 "1:\tcall *8(%ebp)\n\t"
6340 "subl %esp,%edi\n\t"
6341 "movl 20(%ebp),%ecx\n\t"
6342 "movl %edi,(%ecx)\n\t"
6343 "leal -8(%ebp),%esp\n\t"
6344 "popl %edi\n\t"
6345 __ASM_CFI(".cfi_same_value %edi\n\t")
6346 "popl %esi\n\t"
6347 __ASM_CFI(".cfi_same_value %esi\n\t")
6348 "popl %ebp\n\t"
6349 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6350 __ASM_CFI(".cfi_same_value %ebp\n\t")
6351 "ret" )
6352 __ASM_GLOBAL_FUNC( call_double_method,
6353 "jmp " __ASM_NAME("call_method") )
6355 #elif defined(__x86_64__)
6357 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
6358 extern double CDECL call_double_method( void *func, int nb_args, const DWORD_PTR *args );
6359 __ASM_GLOBAL_FUNC( call_method,
6360 "pushq %rbp\n\t"
6361 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6362 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6363 "movq %rsp,%rbp\n\t"
6364 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6365 "pushq %rsi\n\t"
6366 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6367 "pushq %rdi\n\t"
6368 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6369 "movq %rcx,%rax\n\t"
6370 "movq $4,%rcx\n\t"
6371 "cmp %rcx,%rdx\n\t"
6372 "cmovgq %rdx,%rcx\n\t"
6373 "leaq 0(,%rcx,8),%rdx\n\t"
6374 "subq %rdx,%rsp\n\t"
6375 "andq $~15,%rsp\n\t"
6376 "movq %rsp,%rdi\n\t"
6377 "movq %r8,%rsi\n\t"
6378 "rep; movsq\n\t"
6379 "movq 0(%rsp),%rcx\n\t"
6380 "movq 8(%rsp),%rdx\n\t"
6381 "movq 16(%rsp),%r8\n\t"
6382 "movq 24(%rsp),%r9\n\t"
6383 "movq 0(%rsp),%xmm0\n\t"
6384 "movq 8(%rsp),%xmm1\n\t"
6385 "movq 16(%rsp),%xmm2\n\t"
6386 "movq 24(%rsp),%xmm3\n\t"
6387 "callq *%rax\n\t"
6388 "leaq -16(%rbp),%rsp\n\t"
6389 "popq %rdi\n\t"
6390 __ASM_CFI(".cfi_same_value %rdi\n\t")
6391 "popq %rsi\n\t"
6392 __ASM_CFI(".cfi_same_value %rsi\n\t")
6393 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6394 "popq %rbp\n\t"
6395 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6396 __ASM_CFI(".cfi_same_value %rbp\n\t")
6397 "ret")
6398 __ASM_GLOBAL_FUNC( call_double_method,
6399 "jmp " __ASM_NAME("call_method") )
6401 #elif defined(__arm__)
6403 extern LONGLONG CDECL call_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6404 extern float CDECL call_float_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6405 extern double CDECL call_double_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6406 __ASM_GLOBAL_FUNC( call_method,
6407 /* r0 = *func
6408 * r1 = nb_stk_args
6409 * r2 = *stk_args (pointer to 'nb_stk_args' DWORD values to push on stack)
6410 * 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)
6413 "push {fp, lr}\n\t" /* Save frame pointer and return address (stack still aligned to 8 bytes) */
6414 "mov fp, sp\n\t" /* Save stack pointer as our frame for cleaning the stack on return */
6416 "lsls r1, r1, #2\n\t" /* r1 = nb_stk_args * sizeof(DWORD) */
6417 "beq 1f\n\t" /* Skip allocation if no stack args */
6418 "add r2, r2, r1\n" /* Calculate ending address of incoming stack data */
6419 "2:\tldr ip, [r2, #-4]!\n\t" /* Get next value */
6420 "str ip, [sp, #-4]!\n\t" /* Push it on the stack */
6421 "subs r1, r1, #4\n\t" /* Decrement count */
6422 "bgt 2b\n\t" /* Loop till done */
6424 "1:\n\t"
6425 #ifndef __SOFTFP__
6426 "vldm r3!, {s0-s15}\n\t" /* Load the s0-s15/d0-d7 arguments */
6427 #endif
6428 "mov ip, r0\n\t" /* Save the function call address to ip before we nuke r0 with arguments to pass */
6429 "ldm r3, {r0-r3}\n\t" /* Load the r0-r3 arguments */
6431 "blx ip\n\t" /* Call the target function */
6433 "mov sp, fp\n\t" /* Clean the stack using fp */
6434 "pop {fp, pc}\n\t" /* Restore fp and return */
6436 __ASM_GLOBAL_FUNC( call_float_method,
6437 "b " __ASM_NAME("call_method") )
6438 __ASM_GLOBAL_FUNC( call_double_method,
6439 "b " __ASM_NAME("call_method") )
6441 #endif /* __arm__ */
6443 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6445 HRESULT hr = S_OK;
6446 ITypeInfo *tinfo2 = NULL;
6447 TYPEATTR *tattr = NULL;
6449 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6450 if (hr)
6452 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6453 "hr = 0x%08x\n",
6454 tdesc->u.hreftype, hr);
6455 return hr;
6457 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6458 if (hr)
6460 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
6461 ITypeInfo_Release(tinfo2);
6462 return hr;
6465 switch (tattr->typekind)
6467 case TKIND_ENUM:
6468 *vt |= VT_I4;
6469 break;
6471 case TKIND_ALIAS:
6472 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
6473 break;
6475 case TKIND_INTERFACE:
6476 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
6477 *vt |= VT_DISPATCH;
6478 else
6479 *vt |= VT_UNKNOWN;
6480 break;
6482 case TKIND_DISPATCH:
6483 *vt |= VT_DISPATCH;
6484 break;
6486 case TKIND_COCLASS:
6487 *vt |= VT_DISPATCH;
6488 break;
6490 case TKIND_RECORD:
6491 FIXME("TKIND_RECORD unhandled.\n");
6492 hr = E_NOTIMPL;
6493 break;
6495 case TKIND_UNION:
6496 FIXME("TKIND_UNION unhandled.\n");
6497 hr = E_NOTIMPL;
6498 break;
6500 default:
6501 FIXME("TKIND %d unhandled.\n",tattr->typekind);
6502 hr = E_NOTIMPL;
6503 break;
6505 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6506 ITypeInfo_Release(tinfo2);
6507 return hr;
6510 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6512 HRESULT hr = S_OK;
6514 /* enforce only one level of pointer indirection */
6515 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
6517 tdesc = tdesc->u.lptdesc;
6519 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6520 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6521 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6522 if ((tdesc->vt == VT_USERDEFINED) ||
6523 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
6525 VARTYPE vt_userdefined = 0;
6526 const TYPEDESC *tdesc_userdefined = tdesc;
6527 if (tdesc->vt == VT_PTR)
6529 vt_userdefined = VT_BYREF;
6530 tdesc_userdefined = tdesc->u.lptdesc;
6532 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
6533 if ((hr == S_OK) &&
6534 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
6535 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
6537 *vt |= vt_userdefined;
6538 return S_OK;
6541 *vt = VT_BYREF;
6544 switch (tdesc->vt)
6546 case VT_HRESULT:
6547 *vt |= VT_ERROR;
6548 break;
6549 case VT_USERDEFINED:
6550 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
6551 break;
6552 case VT_VOID:
6553 case VT_CARRAY:
6554 case VT_PTR:
6555 case VT_LPSTR:
6556 case VT_LPWSTR:
6557 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
6558 hr = DISP_E_BADVARTYPE;
6559 break;
6560 case VT_SAFEARRAY:
6561 *vt |= VT_ARRAY;
6562 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
6563 break;
6564 case VT_INT:
6565 *vt |= VT_I4;
6566 break;
6567 case VT_UINT:
6568 *vt |= VT_UI4;
6569 break;
6570 default:
6571 *vt |= tdesc->vt;
6572 break;
6574 return hr;
6577 static HRESULT get_iface_guid(ITypeInfo *tinfo, HREFTYPE href, GUID *guid)
6579 ITypeInfo *tinfo2;
6580 TYPEATTR *tattr;
6581 HRESULT hres;
6582 int flags, i;
6584 hres = ITypeInfo_GetRefTypeInfo(tinfo, href, &tinfo2);
6585 if(FAILED(hres))
6586 return hres;
6588 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6589 if(FAILED(hres)) {
6590 ITypeInfo_Release(tinfo2);
6591 return hres;
6594 switch(tattr->typekind) {
6595 case TKIND_ALIAS:
6596 hres = get_iface_guid(tinfo2, tattr->tdescAlias.u.hreftype, guid);
6597 break;
6599 case TKIND_INTERFACE:
6600 case TKIND_DISPATCH:
6601 *guid = tattr->guid;
6602 break;
6604 case TKIND_COCLASS:
6605 for (i = 0; i < tattr->cImplTypes; i++)
6607 ITypeInfo_GetImplTypeFlags(tinfo2, i, &flags);
6608 if (flags & IMPLTYPEFLAG_FDEFAULT)
6609 break;
6612 if (i == tattr->cImplTypes)
6613 i = 0;
6615 hres = ITypeInfo_GetRefTypeOfImplType(tinfo2, i, &href);
6616 if (SUCCEEDED(hres))
6617 hres = get_iface_guid(tinfo2, href, guid);
6618 break;
6620 default:
6621 ERR("Unexpected typekind %d\n", tattr->typekind);
6622 hres = E_UNEXPECTED;
6625 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6626 ITypeInfo_Release(tinfo2);
6627 return hres;
6630 /***********************************************************************
6631 * DispCallFunc (OLEAUT32.@)
6633 * Invokes a function of the specified calling convention, passing the
6634 * specified arguments and returns the result.
6636 * PARAMS
6637 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6638 * oVft [I] The offset in the vtable. See notes.
6639 * cc [I] Calling convention of the function to call.
6640 * vtReturn [I] The return type of the function.
6641 * cActuals [I] Number of parameters.
6642 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6643 * prgpvarg [I] The arguments to pass.
6644 * pvargResult [O] The return value of the function. Can be NULL.
6646 * RETURNS
6647 * Success: S_OK.
6648 * Failure: HRESULT code.
6650 * NOTES
6651 * The HRESULT return value of this function is not affected by the return
6652 * value of the user supplied function, which is returned in pvargResult.
6654 * If pvInstance is NULL then a non-object function is to be called and oVft
6655 * is the address of the function to call.
6657 * The cc parameter can be one of the following values:
6658 *|CC_FASTCALL
6659 *|CC_CDECL
6660 *|CC_PASCAL
6661 *|CC_STDCALL
6662 *|CC_FPFASTCALL
6663 *|CC_SYSCALL
6664 *|CC_MPWCDECL
6665 *|CC_MPWPASCAL
6668 HRESULT WINAPI
6669 DispCallFunc(
6670 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
6671 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
6673 #ifdef __i386__
6674 int argspos = 0, stack_offset;
6675 void *func;
6676 UINT i;
6677 DWORD *args;
6679 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6680 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6681 pvargResult, V_VT(pvargResult));
6683 if (cc != CC_STDCALL && cc != CC_CDECL)
6685 FIXME("unsupported calling convention %d\n",cc);
6686 return E_INVALIDARG;
6689 /* maximum size for an argument is sizeof(VARIANT) */
6690 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6692 if (pvInstance)
6694 const FARPROC *vtable = *(FARPROC **)pvInstance;
6695 func = vtable[oVft/sizeof(void *)];
6696 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6698 else func = (void *)oVft;
6700 switch (vtReturn)
6702 case VT_DECIMAL:
6703 case VT_VARIANT:
6704 args[argspos++] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6705 break;
6706 case VT_HRESULT:
6707 WARN("invalid return type %u\n", vtReturn);
6708 heap_free( args );
6709 return E_INVALIDARG;
6710 default:
6711 break;
6714 for (i = 0; i < cActuals; i++)
6716 VARIANT *arg = prgpvarg[i];
6718 switch (prgvt[i])
6720 case VT_EMPTY:
6721 break;
6722 case VT_I8:
6723 case VT_UI8:
6724 case VT_R8:
6725 case VT_DATE:
6726 case VT_CY:
6727 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6728 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6729 break;
6730 case VT_DECIMAL:
6731 case VT_VARIANT:
6732 memcpy( &args[argspos], arg, sizeof(*arg) );
6733 argspos += sizeof(*arg) / sizeof(DWORD);
6734 break;
6735 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6736 args[argspos++] = V_BOOL(arg);
6737 break;
6738 default:
6739 args[argspos++] = V_UI4(arg);
6740 break;
6742 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6745 switch (vtReturn)
6747 case VT_EMPTY:
6748 case VT_DECIMAL:
6749 case VT_VARIANT:
6750 call_method( func, argspos, args, &stack_offset );
6751 break;
6752 case VT_R4:
6753 V_R4(pvargResult) = call_double_method( func, argspos, args, &stack_offset );
6754 break;
6755 case VT_R8:
6756 case VT_DATE:
6757 V_R8(pvargResult) = call_double_method( func, argspos, args, &stack_offset );
6758 break;
6759 case VT_I8:
6760 case VT_UI8:
6761 case VT_CY:
6762 V_UI8(pvargResult) = call_method( func, argspos, args, &stack_offset );
6763 break;
6764 default:
6765 V_UI4(pvargResult) = call_method( func, argspos, args, &stack_offset );
6766 break;
6768 heap_free( args );
6769 if (stack_offset && cc == CC_STDCALL)
6771 WARN( "stack pointer off by %d\n", stack_offset );
6772 return DISP_E_BADCALLEE;
6774 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6775 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6776 return S_OK;
6778 #elif defined(__x86_64__)
6779 int argspos = 0;
6780 UINT i;
6781 DWORD_PTR *args;
6782 void *func;
6784 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6785 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6786 pvargResult, V_VT(pvargResult));
6788 if (cc != CC_STDCALL && cc != CC_CDECL)
6790 FIXME("unsupported calling convention %d\n",cc);
6791 return E_INVALIDARG;
6794 /* maximum size for an argument is sizeof(DWORD_PTR) */
6795 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6797 if (pvInstance)
6799 const FARPROC *vtable = *(FARPROC **)pvInstance;
6800 func = vtable[oVft/sizeof(void *)];
6801 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6803 else func = (void *)oVft;
6805 switch (vtReturn)
6807 case VT_DECIMAL:
6808 case VT_VARIANT:
6809 args[argspos++] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6810 break;
6811 case VT_HRESULT:
6812 WARN("invalid return type %u\n", vtReturn);
6813 heap_free( args );
6814 return E_INVALIDARG;
6815 default:
6816 break;
6819 for (i = 0; i < cActuals; i++)
6821 VARIANT *arg = prgpvarg[i];
6823 switch (prgvt[i])
6825 case VT_DECIMAL:
6826 case VT_VARIANT:
6827 args[argspos++] = (ULONG_PTR)arg;
6828 break;
6829 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6830 args[argspos++] = V_BOOL(arg);
6831 break;
6832 default:
6833 args[argspos++] = V_UI8(arg);
6834 break;
6836 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6839 switch (vtReturn)
6841 case VT_R4:
6842 V_R4(pvargResult) = call_double_method( func, argspos, args );
6843 break;
6844 case VT_R8:
6845 case VT_DATE:
6846 V_R8(pvargResult) = call_double_method( func, argspos, args );
6847 break;
6848 case VT_DECIMAL:
6849 case VT_VARIANT:
6850 call_method( func, argspos, args );
6851 break;
6852 default:
6853 V_UI8(pvargResult) = call_method( func, argspos, args );
6854 break;
6856 heap_free( args );
6857 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6858 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6859 return S_OK;
6861 #elif defined(__arm__)
6862 int argspos;
6863 void *func;
6864 UINT i;
6865 DWORD *args;
6866 struct {
6867 #ifndef __SOFTFP__
6868 union {
6869 float s[16];
6870 double d[8];
6871 } sd;
6872 #endif
6873 DWORD r[4];
6874 } regs;
6875 int rcount; /* 32-bit register index count */
6876 #ifndef __SOFTFP__
6877 int scount = 0; /* single-precision float register index count */
6878 int dcount = 0; /* double-precision float register index count */
6879 #endif
6881 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6882 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6884 if (cc != CC_STDCALL && cc != CC_CDECL)
6886 FIXME("unsupported calling convention %d\n",cc);
6887 return E_INVALIDARG;
6890 argspos = 0;
6891 rcount = 0;
6893 if (pvInstance)
6895 const FARPROC *vtable = *(FARPROC **)pvInstance;
6896 func = vtable[oVft/sizeof(void *)];
6897 regs.r[rcount++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6899 else func = (void *)oVft;
6901 /* Determine if we need to pass a pointer for the return value as arg 0. If so, do that */
6902 /* first as it will need to be in the 'r' registers: */
6903 switch (vtReturn)
6905 case VT_DECIMAL:
6906 case VT_VARIANT:
6907 regs.r[rcount++] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6908 break;
6909 case VT_HRESULT:
6910 WARN("invalid return type %u\n", vtReturn);
6911 return E_INVALIDARG;
6912 default: /* And all others are in 'r', 's', or 'd' registers or have no return value */
6913 break;
6916 /* maximum size for an argument is sizeof(VARIANT). Also allow for return pointer and stack alignment. */
6917 args = heap_alloc( sizeof(VARIANT) * cActuals + sizeof(DWORD) * 4 );
6919 for (i = 0; i < cActuals; i++)
6921 VARIANT *arg = prgpvarg[i];
6922 DWORD *pdwarg = (DWORD *)(arg); /* a reinterpret_cast of the variant, used for copying structures when they are split between registers and stack */
6923 int ntemp; /* Used for counting words split between registers and stack */
6925 switch (prgvt[i])
6927 case VT_EMPTY:
6928 break;
6929 case VT_R8: /* these must be 8-byte aligned, and put in 'd' regs or stack, as they are double-floats */
6930 case VT_DATE:
6931 #ifndef __SOFTFP__
6932 dcount = max( (scount + 1) / 2, dcount );
6933 if (dcount < 8)
6935 regs.sd.d[dcount++] = V_R8(arg);
6937 else
6939 argspos += (argspos % 2); /* align argspos to 8-bytes */
6940 memcpy( &args[argspos], &V_R8(arg), sizeof(V_R8(arg)) );
6941 argspos += sizeof(V_R8(arg)) / sizeof(DWORD);
6943 break;
6944 #endif
6945 case VT_I8: /* these must be 8-byte aligned, and put in 'r' regs or stack, as they are long-longs */
6946 case VT_UI8:
6947 case VT_CY:
6948 if (rcount < 3)
6950 rcount += (rcount % 2); /* align rcount to 8-byte register pair */
6951 memcpy( &regs.r[rcount], &V_UI8(arg), sizeof(V_UI8(arg)) );
6952 rcount += sizeof(V_UI8(arg)) / sizeof(DWORD);
6954 else
6956 rcount = 4; /* Make sure we flag that all 'r' regs are full */
6957 argspos += (argspos % 2); /* align argspos to 8-bytes */
6958 memcpy( &args[argspos], &V_UI8(arg), sizeof(V_UI8(arg)) );
6959 argspos += sizeof(V_UI8(arg)) / sizeof(DWORD);
6961 break;
6962 case VT_DECIMAL: /* these structures are 8-byte aligned, and put in 'r' regs or stack, can be split between the two */
6963 case VT_VARIANT:
6964 /* 8-byte align 'r' and/or stack: */
6965 if (rcount < 3)
6966 rcount += (rcount % 2);
6967 else
6969 rcount = 4;
6970 argspos += (argspos % 2);
6972 ntemp = sizeof(*arg) / sizeof(DWORD);
6973 while (ntemp > 0)
6975 if (rcount < 4)
6976 regs.r[rcount++] = *pdwarg++;
6977 else
6978 args[argspos++] = *pdwarg++;
6979 --ntemp;
6981 break;
6982 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6983 if (rcount < 4)
6984 regs.r[rcount++] = V_BOOL(arg);
6985 else
6986 args[argspos++] = V_BOOL(arg);
6987 break;
6988 case VT_R4: /* these must be 4-byte aligned, and put in 's' regs or stack, as they are single-floats */
6989 #ifndef __SOFTFP__
6990 if (!(scount % 2)) scount = max( scount, dcount * 2 );
6991 if (scount < 16)
6992 regs.sd.s[scount++] = V_R4(arg);
6993 else
6994 args[argspos++] = V_UI4(arg);
6995 break;
6996 #endif
6997 default:
6998 if (rcount < 4)
6999 regs.r[rcount++] = V_UI4(arg);
7000 else
7001 args[argspos++] = V_UI4(arg);
7002 break;
7004 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
7007 argspos += (argspos % 2); /* Make sure stack function alignment is 8-byte */
7009 switch (vtReturn)
7011 case VT_EMPTY: /* EMPTY = no return value */
7012 case VT_DECIMAL: /* DECIMAL and VARIANT already have a pointer argument passed (see above) */
7013 case VT_VARIANT:
7014 call_method( func, argspos, args, (DWORD*)&regs );
7015 break;
7016 case VT_R4:
7017 V_R4(pvargResult) = call_float_method( func, argspos, args, (DWORD*)&regs );
7018 break;
7019 case VT_R8:
7020 case VT_DATE:
7021 V_R8(pvargResult) = call_double_method( func, argspos, args, (DWORD*)&regs );
7022 break;
7023 case VT_I8:
7024 case VT_UI8:
7025 case VT_CY:
7026 V_UI8(pvargResult) = call_method( func, argspos, args, (DWORD*)&regs );
7027 break;
7028 default:
7029 V_UI4(pvargResult) = call_method( func, argspos, args, (DWORD*)&regs );
7030 break;
7032 heap_free( args );
7033 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
7034 TRACE("retval: %s\n", debugstr_variant(pvargResult));
7035 return S_OK;
7037 #else
7038 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
7039 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
7040 return E_NOTIMPL;
7041 #endif
7044 static inline BOOL func_restricted( const FUNCDESC *desc )
7046 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
7049 #define INVBUF_ELEMENT_SIZE \
7050 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
7051 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
7052 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
7053 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
7054 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
7055 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
7056 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
7057 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
7059 static HRESULT WINAPI ITypeInfo_fnInvoke(
7060 ITypeInfo2 *iface,
7061 VOID *pIUnk,
7062 MEMBERID memid,
7063 UINT16 wFlags,
7064 DISPPARAMS *pDispParams,
7065 VARIANT *pVarResult,
7066 EXCEPINFO *pExcepInfo,
7067 UINT *pArgErr)
7069 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7070 int i;
7071 unsigned int var_index;
7072 TYPEKIND type_kind;
7073 HRESULT hres;
7074 const TLBFuncDesc *pFuncInfo;
7075 UINT fdc;
7077 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
7078 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
7081 if( This->typeattr.wTypeFlags & TYPEFLAG_FRESTRICTED )
7082 return DISP_E_MEMBERNOTFOUND;
7084 if (!pDispParams)
7086 ERR("NULL pDispParams not allowed\n");
7087 return E_INVALIDARG;
7090 dump_DispParms(pDispParams);
7092 if (pDispParams->cNamedArgs > pDispParams->cArgs)
7094 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
7095 pDispParams->cNamedArgs, pDispParams->cArgs);
7096 return E_INVALIDARG;
7099 /* we do this instead of using GetFuncDesc since it will return a fake
7100 * FUNCDESC for dispinterfaces and we want the real function description */
7101 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
7102 pFuncInfo = &This->funcdescs[fdc];
7103 if ((memid == pFuncInfo->funcdesc.memid) &&
7104 (wFlags & pFuncInfo->funcdesc.invkind) &&
7105 !func_restricted( &pFuncInfo->funcdesc ))
7106 break;
7109 if (fdc < This->typeattr.cFuncs) {
7110 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
7112 if (TRACE_ON(ole))
7114 TRACE("invoking:\n");
7115 dump_TLBFuncDescOne(pFuncInfo);
7118 switch (func_desc->funckind) {
7119 case FUNC_PUREVIRTUAL:
7120 case FUNC_VIRTUAL: {
7121 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
7122 VARIANT varresult;
7123 VARIANT retval; /* pointer for storing byref retvals in */
7124 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
7125 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
7126 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
7127 UINT cNamedArgs = pDispParams->cNamedArgs;
7128 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
7129 UINT vargs_converted=0;
7131 hres = S_OK;
7133 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
7135 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
7137 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
7138 hres = DISP_E_PARAMNOTFOUND;
7139 goto func_fail;
7143 if (func_desc->cParamsOpt < 0 && cNamedArgs)
7145 ERR("functions with the vararg attribute do not support named arguments\n");
7146 hres = DISP_E_NONAMEDARGS;
7147 goto func_fail;
7150 for (i = 0; i < func_desc->cParams; i++)
7152 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7153 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
7154 if (FAILED(hres))
7155 goto func_fail;
7158 TRACE("changing args\n");
7159 for (i = 0; i < func_desc->cParams; i++)
7161 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7162 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7163 VARIANTARG *src_arg;
7165 if (wParamFlags & PARAMFLAG_FLCID)
7167 VARIANTARG *arg;
7168 arg = prgpvarg[i] = &rgvarg[i];
7169 V_VT(arg) = VT_I4;
7170 V_I4(arg) = This->pTypeLib->lcid;
7171 continue;
7174 src_arg = NULL;
7176 if (cNamedArgs)
7178 USHORT j;
7179 for (j = 0; j < cNamedArgs; j++)
7180 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
7182 src_arg = &pDispParams->rgvarg[j];
7183 break;
7187 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
7189 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7190 vargs_converted++;
7193 if (wParamFlags & PARAMFLAG_FRETVAL)
7195 /* under most conditions the caller is not allowed to
7196 * pass in a dispparam arg in the index of what would be
7197 * the retval parameter. however, there is an exception
7198 * where the extra parameter is used in an extra
7199 * IDispatch::Invoke below */
7200 if ((i < pDispParams->cArgs) &&
7201 ((func_desc->cParams != 1) || !pVarResult ||
7202 !(func_desc->invkind & INVOKE_PROPERTYGET)))
7204 hres = DISP_E_BADPARAMCOUNT;
7205 break;
7208 /* note: this check is placed so that if the caller passes
7209 * in a VARIANTARG for the retval we just ignore it, like
7210 * native does */
7211 if (i == func_desc->cParams - 1)
7213 VARIANTARG *arg;
7214 arg = prgpvarg[i] = &rgvarg[i];
7215 memset(arg, 0, sizeof(*arg));
7216 V_VT(arg) = rgvt[i];
7217 memset(&retval, 0, sizeof(retval));
7218 V_BYREF(arg) = &retval;
7220 else
7222 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
7223 hres = E_UNEXPECTED;
7224 break;
7227 else if (src_arg && !((wParamFlags & PARAMFLAG_FOPT) &&
7228 V_VT(src_arg) == VT_ERROR && V_ERROR(src_arg) == DISP_E_PARAMNOTFOUND))
7230 TRACE("%s\n", debugstr_variant(src_arg));
7232 if(rgvt[i]!=V_VT(src_arg))
7234 if (rgvt[i] == VT_VARIANT)
7235 hres = VariantCopy(&rgvarg[i], src_arg);
7236 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
7238 if (rgvt[i] == V_VT(src_arg))
7239 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
7240 else
7242 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7243 if (wParamFlags & PARAMFLAG_FIN)
7244 hres = VariantCopy(&missing_arg[i], src_arg);
7245 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
7247 V_VT(&rgvarg[i]) = rgvt[i];
7249 else if ((rgvt[i] == (VT_VARIANT | VT_ARRAY) || rgvt[i] == (VT_VARIANT | VT_ARRAY | VT_BYREF)) && func_desc->cParamsOpt < 0)
7251 SAFEARRAY *a;
7252 SAFEARRAYBOUND bound;
7253 VARIANT *v;
7254 LONG j;
7255 bound.lLbound = 0;
7256 bound.cElements = pDispParams->cArgs-i;
7257 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
7259 ERR("SafeArrayCreate failed\n");
7260 break;
7262 hres = SafeArrayAccessData(a, (LPVOID)&v);
7263 if (hres != S_OK)
7265 ERR("SafeArrayAccessData failed with %x\n", hres);
7266 SafeArrayDestroy(a);
7267 break;
7269 for (j = 0; j < bound.cElements; j++)
7270 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
7271 hres = SafeArrayUnaccessData(a);
7272 if (hres != S_OK)
7274 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7275 SafeArrayDestroy(a);
7276 break;
7278 if (rgvt[i] & VT_BYREF)
7279 V_BYREF(&rgvarg[i]) = &a;
7280 else
7281 V_ARRAY(&rgvarg[i]) = a;
7282 V_VT(&rgvarg[i]) = rgvt[i];
7284 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
7286 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7287 if (wParamFlags & PARAMFLAG_FIN)
7288 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
7289 else
7290 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
7291 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
7292 V_VT(&rgvarg[i]) = rgvt[i];
7294 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
7296 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
7297 V_VT(&rgvarg[i]) = rgvt[i];
7299 else
7301 /* FIXME: this doesn't work for VT_BYREF arguments if
7302 * they are not the same type as in the paramdesc */
7303 V_VT(&rgvarg[i]) = V_VT(src_arg);
7304 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
7305 V_VT(&rgvarg[i]) = rgvt[i];
7308 if (FAILED(hres))
7310 ERR("failed to convert param %d to %s from %s\n", i,
7311 debugstr_vt(rgvt[i]), debugstr_variant(src_arg));
7312 break;
7314 prgpvarg[i] = &rgvarg[i];
7316 else
7318 prgpvarg[i] = src_arg;
7321 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
7322 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
7323 && V_UNKNOWN(prgpvarg[i])) {
7324 IUnknown *userdefined_iface;
7325 GUID guid;
7327 if (tdesc->vt == VT_PTR)
7328 tdesc = tdesc->u.lptdesc;
7330 hres = get_iface_guid((ITypeInfo*)iface, tdesc->u.hreftype, &guid);
7331 if(FAILED(hres))
7332 break;
7334 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
7335 if(FAILED(hres)) {
7336 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
7337 break;
7340 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
7341 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
7344 else if (wParamFlags & PARAMFLAG_FOPT)
7346 VARIANTARG *arg;
7347 arg = prgpvarg[i] = &rgvarg[i];
7348 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7350 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
7351 if (FAILED(hres))
7352 break;
7354 else
7356 VARIANTARG *missing_arg;
7357 /* if the function wants a pointer to a variant then
7358 * set that up, otherwise just pass the VT_ERROR in
7359 * the argument by value */
7360 if (rgvt[i] & VT_BYREF)
7362 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
7363 V_VT(arg) = VT_VARIANT | VT_BYREF;
7364 V_VARIANTREF(arg) = missing_arg;
7366 else
7367 missing_arg = arg;
7368 V_VT(missing_arg) = VT_ERROR;
7369 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
7372 else
7374 hres = DISP_E_BADPARAMCOUNT;
7375 break;
7378 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7380 /* VT_VOID is a special case for return types, so it is not
7381 * handled in the general function */
7382 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
7383 V_VT(&varresult) = VT_EMPTY;
7384 else
7386 V_VT(&varresult) = 0;
7387 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
7388 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7391 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv,
7392 V_VT(&varresult), func_desc->cParams, rgvt,
7393 prgpvarg, &varresult);
7395 vargs_converted = 0;
7397 for (i = 0; i < func_desc->cParams; i++)
7399 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7400 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7402 if (wParamFlags & PARAMFLAG_FLCID)
7403 continue;
7404 else if (wParamFlags & PARAMFLAG_FRETVAL)
7406 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg[i]));
7408 if (pVarResult)
7410 VariantInit(pVarResult);
7411 /* deref return value */
7412 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
7415 VARIANT_ClearInd(prgpvarg[i]);
7417 else if (vargs_converted < pDispParams->cArgs)
7419 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7420 if (wParamFlags & PARAMFLAG_FOUT)
7422 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
7424 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
7426 if (FAILED(hres))
7428 ERR("failed to convert param %d to vt %d\n", i,
7429 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
7430 break;
7434 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
7435 func_desc->cParamsOpt < 0 &&
7436 i == func_desc->cParams-1)
7438 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
7439 LONG j, ubound;
7440 VARIANT *v;
7441 hres = SafeArrayGetUBound(a, 1, &ubound);
7442 if (hres != S_OK)
7444 ERR("SafeArrayGetUBound failed with %x\n", hres);
7445 break;
7447 hres = SafeArrayAccessData(a, (LPVOID)&v);
7448 if (hres != S_OK)
7450 ERR("SafeArrayAccessData failed with %x\n", hres);
7451 break;
7453 for (j = 0; j <= ubound; j++)
7454 VariantClear(&v[j]);
7455 hres = SafeArrayUnaccessData(a);
7456 if (hres != S_OK)
7458 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7459 break;
7462 VariantClear(&rgvarg[i]);
7463 vargs_converted++;
7465 else if (wParamFlags & PARAMFLAG_FOPT)
7467 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7468 VariantClear(&rgvarg[i]);
7471 VariantClear(&missing_arg[i]);
7474 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
7476 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
7477 hres = DISP_E_EXCEPTION;
7478 if (pExcepInfo)
7480 IErrorInfo *pErrorInfo;
7481 pExcepInfo->scode = V_ERROR(&varresult);
7482 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
7484 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
7485 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
7486 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
7487 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
7489 IErrorInfo_Release(pErrorInfo);
7493 if (V_VT(&varresult) != VT_ERROR)
7495 TRACE("varresult value: %s\n", debugstr_variant(&varresult));
7497 if (pVarResult)
7499 VariantClear(pVarResult);
7500 *pVarResult = varresult;
7502 else
7503 VariantClear(&varresult);
7506 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
7507 (func_desc->invkind & INVOKE_PROPERTYGET) &&
7508 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
7509 (pDispParams->cArgs != 0))
7511 if (V_VT(pVarResult) == VT_DISPATCH)
7513 IDispatch *pDispatch = V_DISPATCH(pVarResult);
7514 /* Note: not VariantClear; we still need the dispatch
7515 * pointer to be valid */
7516 VariantInit(pVarResult);
7517 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
7518 GetSystemDefaultLCID(), wFlags,
7519 pDispParams, pVarResult, pExcepInfo, pArgErr);
7520 IDispatch_Release(pDispatch);
7522 else
7524 VariantClear(pVarResult);
7525 hres = DISP_E_NOTACOLLECTION;
7529 func_fail:
7530 heap_free(buffer);
7531 break;
7533 case FUNC_DISPATCH: {
7534 IDispatch *disp;
7536 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
7537 if (SUCCEEDED(hres)) {
7538 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7539 hres = IDispatch_Invoke(
7540 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
7541 pVarResult,pExcepInfo,pArgErr
7543 if (FAILED(hres))
7544 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
7545 IDispatch_Release(disp);
7546 } else
7547 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7548 break;
7550 default:
7551 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
7552 hres = E_FAIL;
7553 break;
7556 TRACE("-- 0x%08x\n", hres);
7557 return hres;
7559 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
7560 VARDESC *var_desc;
7562 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
7563 if(FAILED(hres)) return hres;
7565 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7566 dump_VARDESC(var_desc);
7567 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
7568 return E_NOTIMPL;
7571 /* not found, look for it in inherited interfaces */
7572 ITypeInfo2_GetTypeKind(iface, &type_kind);
7573 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
7574 if(This->impltypes) {
7575 /* recursive search */
7576 ITypeInfo *pTInfo;
7577 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7578 if(SUCCEEDED(hres)){
7579 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
7580 ITypeInfo_Release(pTInfo);
7581 return hres;
7583 WARN("Could not search inherited interface!\n");
7586 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
7587 return DISP_E_MEMBERNOTFOUND;
7590 /* ITypeInfo::GetDocumentation
7592 * Retrieves the documentation string, the complete Help file name and path,
7593 * and the context ID for the Help topic for a specified type description.
7595 * (Can be tested by the Visual Basic Editor in Word for instance.)
7597 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
7598 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
7599 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
7601 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7602 const TLBFuncDesc *pFDesc;
7603 const TLBVarDesc *pVDesc;
7604 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7605 " HelpContext(%p) HelpFile(%p)\n",
7606 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
7607 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7608 if(pBstrName)
7609 *pBstrName=SysAllocString(TLB_get_bstr(This->Name));
7610 if(pBstrDocString)
7611 *pBstrDocString=SysAllocString(TLB_get_bstr(This->DocString));
7612 if(pdwHelpContext)
7613 *pdwHelpContext=This->dwHelpContext;
7614 if(pBstrHelpFile)
7615 *pBstrHelpFile=SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7616 return S_OK;
7617 }else {/* for a member */
7618 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->typeattr.cFuncs, memid);
7619 if(pFDesc){
7620 if(pBstrName)
7621 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Name));
7622 if(pBstrDocString)
7623 *pBstrDocString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7624 if(pdwHelpContext)
7625 *pdwHelpContext=pFDesc->helpcontext;
7626 if(pBstrHelpFile)
7627 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7628 return S_OK;
7630 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->typeattr.cVars, memid);
7631 if(pVDesc){
7632 if(pBstrName)
7633 *pBstrName = SysAllocString(TLB_get_bstr(pVDesc->Name));
7634 if(pBstrDocString)
7635 *pBstrDocString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7636 if(pdwHelpContext)
7637 *pdwHelpContext=pVDesc->HelpContext;
7638 if(pBstrHelpFile)
7639 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7640 return S_OK;
7644 if(This->impltypes &&
7645 (This->typeattr.typekind == TKIND_INTERFACE || This->typeattr.typekind == TKIND_DISPATCH)) {
7646 /* recursive search */
7647 ITypeInfo *pTInfo;
7648 HRESULT result;
7649 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7650 if(SUCCEEDED(result)) {
7651 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
7652 pBstrDocString, pdwHelpContext, pBstrHelpFile);
7653 ITypeInfo_Release(pTInfo);
7654 return result;
7656 WARN("Could not search inherited interface!\n");
7659 WARN("member %d not found\n", memid);
7660 return TYPE_E_ELEMENTNOTFOUND;
7663 /* ITypeInfo::GetDllEntry
7665 * Retrieves a description or specification of an entry point for a function
7666 * in a DLL.
7668 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
7669 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
7670 WORD *pwOrdinal)
7672 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7673 const TLBFuncDesc *pFDesc;
7675 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
7677 if (pBstrDllName) *pBstrDllName = NULL;
7678 if (pBstrName) *pBstrName = NULL;
7679 if (pwOrdinal) *pwOrdinal = 0;
7681 if (This->typeattr.typekind != TKIND_MODULE)
7682 return TYPE_E_BADMODULEKIND;
7684 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->typeattr.cFuncs, memid);
7685 if(pFDesc){
7686 dump_TypeInfo(This);
7687 if (TRACE_ON(ole))
7688 dump_TLBFuncDescOne(pFDesc);
7690 if (pBstrDllName)
7691 *pBstrDllName = SysAllocString(TLB_get_bstr(This->DllName));
7693 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
7694 if (pBstrName)
7695 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Entry));
7696 if (pwOrdinal)
7697 *pwOrdinal = -1;
7698 return S_OK;
7700 if (pBstrName)
7701 *pBstrName = NULL;
7702 if (pwOrdinal)
7703 *pwOrdinal = LOWORD(pFDesc->Entry);
7704 return S_OK;
7706 return TYPE_E_ELEMENTNOTFOUND;
7709 /* internal function to make the inherited interfaces' methods appear
7710 * part of the interface */
7711 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7712 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7714 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7715 HRESULT hr;
7717 TRACE("%p, 0x%x\n", iface, *hRefType);
7719 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7721 ITypeInfo *pSubTypeInfo;
7723 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7724 if (FAILED(hr))
7725 return hr;
7727 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7728 hRefType, ppTInfo);
7729 ITypeInfo_Release(pSubTypeInfo);
7730 if (SUCCEEDED(hr))
7731 return hr;
7733 *hRefType -= DISPATCH_HREF_OFFSET;
7735 if (!(*hRefType & DISPATCH_HREF_MASK))
7736 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7737 else
7738 return E_FAIL;
7741 struct search_res_tlb_params
7743 const GUID *guid;
7744 ITypeLib *pTLib;
7747 static BOOL CALLBACK search_res_tlb(HMODULE hModule, LPCWSTR lpszType, LPWSTR lpszName, LONG_PTR lParam)
7749 struct search_res_tlb_params *params = (LPVOID)lParam;
7750 static const WCHAR formatW[] = {'\\','%','d',0};
7751 WCHAR szPath[MAX_PATH+1];
7752 ITypeLib *pTLib = NULL;
7753 HRESULT ret;
7754 DWORD len;
7756 if (IS_INTRESOURCE(lpszName) == FALSE)
7757 return TRUE;
7759 if (!(len = GetModuleFileNameW(hModule, szPath, MAX_PATH)))
7760 return TRUE;
7762 if (swprintf(szPath + len, ARRAY_SIZE(szPath) - len, formatW, LOWORD(lpszName)) < 0)
7763 return TRUE;
7765 ret = LoadTypeLibEx(szPath, REGKIND_NONE, &pTLib);
7766 if (SUCCEEDED(ret))
7768 ITypeLibImpl *impl = impl_from_ITypeLib(pTLib);
7769 if (IsEqualGUID(params->guid, impl->guid))
7771 params->pTLib = pTLib;
7772 return FALSE; /* stop enumeration */
7774 ITypeLib_Release(pTLib);
7777 return TRUE;
7780 /* ITypeInfo::GetRefTypeInfo
7782 * If a type description references other type descriptions, it retrieves
7783 * the referenced type descriptions.
7785 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7786 ITypeInfo2 *iface,
7787 HREFTYPE hRefType,
7788 ITypeInfo **ppTInfo)
7790 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7791 HRESULT result = E_FAIL;
7793 if(!ppTInfo)
7794 return E_INVALIDARG;
7796 if ((INT)hRefType < 0) {
7797 ITypeInfoImpl *pTypeInfoImpl;
7799 if (!(This->typeattr.wTypeFlags & TYPEFLAG_FDUAL) ||
7800 !(This->typeattr.typekind == TKIND_INTERFACE ||
7801 This->typeattr.typekind == TKIND_DISPATCH))
7802 return TYPE_E_ELEMENTNOTFOUND;
7804 /* when we meet a DUAL typeinfo, we must create the alternate
7805 * version of it.
7807 pTypeInfoImpl = ITypeInfoImpl_Constructor();
7809 *pTypeInfoImpl = *This;
7810 pTypeInfoImpl->ref = 0;
7811 list_init(&pTypeInfoImpl->custdata_list);
7813 if (This->typeattr.typekind == TKIND_INTERFACE)
7814 pTypeInfoImpl->typeattr.typekind = TKIND_DISPATCH;
7815 else
7816 pTypeInfoImpl->typeattr.typekind = TKIND_INTERFACE;
7818 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface;
7819 /* the AddRef implicitly adds a reference to the parent typelib, which
7820 * stops the copied data from being destroyed until the new typeinfo's
7821 * refcount goes to zero, but we need to signal to the new instance to
7822 * not free its data structures when it is destroyed */
7823 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7825 ITypeInfo_AddRef(*ppTInfo);
7827 result = S_OK;
7828 } else if ((hRefType & DISPATCH_HREF_MASK) &&
7829 (This->typeattr.typekind == TKIND_DISPATCH))
7831 HREFTYPE href_dispatch = hRefType;
7832 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
7833 } else {
7834 TLBRefType *ref_type;
7835 ITypeLib *pTLib = NULL;
7836 UINT i;
7838 if(!(hRefType & 0x1)){
7839 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
7841 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
7843 result = S_OK;
7844 *ppTInfo = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
7845 ITypeInfo_AddRef(*ppTInfo);
7846 goto end;
7851 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7853 if(ref_type->reference == (hRefType & (~0x3)))
7854 break;
7856 if(&ref_type->entry == &This->pTypeLib->ref_list)
7858 FIXME("Can't find pRefType for ref %x\n", hRefType);
7859 goto end;
7862 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7863 UINT Index;
7864 TRACE("internal reference\n");
7865 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7866 } else {
7867 if(ref_type->pImpTLInfo->pImpTypeLib) {
7868 TRACE("typeinfo in imported typelib that is already loaded\n");
7869 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
7870 ITypeLib_AddRef(pTLib);
7871 result = S_OK;
7872 } else {
7873 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
7874 struct search_res_tlb_params params;
7875 BSTR libnam;
7877 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7879 /* Search in resource table */
7880 params.guid = TLB_get_guid_null(ref_type->pImpTLInfo->guid);
7881 params.pTLib = NULL;
7882 EnumResourceNamesW(NULL, TYPELIBW, search_res_tlb, (LONG_PTR)&params);
7883 pTLib = params.pTLib;
7884 result = S_OK;
7886 if (!pTLib)
7888 /* Search on disk */
7889 result = query_typelib_path(TLB_get_guid_null(ref_type->pImpTLInfo->guid),
7890 ref_type->pImpTLInfo->wVersionMajor,
7891 ref_type->pImpTLInfo->wVersionMinor,
7892 This->pTypeLib->syskind,
7893 ref_type->pImpTLInfo->lcid, &libnam, TRUE);
7894 if (FAILED(result))
7895 libnam = SysAllocString(ref_type->pImpTLInfo->name);
7897 result = LoadTypeLib(libnam, &pTLib);
7898 SysFreeString(libnam);
7901 if(SUCCEEDED(result)) {
7902 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
7903 ITypeLib_AddRef(pTLib);
7907 if(SUCCEEDED(result)) {
7908 if(ref_type->index == TLB_REF_USE_GUID)
7909 result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), ppTInfo);
7910 else
7911 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, ppTInfo);
7913 if (pTLib != NULL)
7914 ITypeLib_Release(pTLib);
7917 end:
7918 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
7919 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
7920 return result;
7923 /* ITypeInfo::AddressOfMember
7925 * Retrieves the addresses of static functions or variables, such as those
7926 * defined in a DLL.
7928 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
7929 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
7931 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7932 HRESULT hr;
7933 BSTR dll, entry;
7934 WORD ordinal;
7935 HMODULE module;
7937 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
7939 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
7940 if (FAILED(hr))
7941 return hr;
7943 module = LoadLibraryW(dll);
7944 if (!module)
7946 ERR("couldn't load %s\n", debugstr_w(dll));
7947 SysFreeString(dll);
7948 SysFreeString(entry);
7949 return STG_E_FILENOTFOUND;
7951 /* FIXME: store library somewhere where we can free it */
7953 if (entry)
7955 LPSTR entryA;
7956 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
7957 entryA = heap_alloc(len);
7958 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
7960 *ppv = GetProcAddress(module, entryA);
7961 if (!*ppv)
7962 ERR("function not found %s\n", debugstr_a(entryA));
7964 heap_free(entryA);
7966 else
7968 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7969 if (!*ppv)
7970 ERR("function not found %d\n", ordinal);
7973 SysFreeString(dll);
7974 SysFreeString(entry);
7976 if (!*ppv)
7977 return TYPE_E_DLLFUNCTIONNOTFOUND;
7979 return S_OK;
7982 /* ITypeInfo::CreateInstance
7984 * Creates a new instance of a type that describes a component object class
7985 * (coclass).
7987 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7988 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7990 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7991 HRESULT hr;
7992 TYPEATTR *pTA;
7994 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7996 *ppvObj = NULL;
7998 if(pOuterUnk)
8000 WARN("Not able to aggregate\n");
8001 return CLASS_E_NOAGGREGATION;
8004 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
8005 if(FAILED(hr)) return hr;
8007 if(pTA->typekind != TKIND_COCLASS)
8009 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
8010 hr = E_INVALIDARG;
8011 goto end;
8014 hr = S_FALSE;
8015 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
8017 IUnknown *pUnk;
8018 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
8019 TRACE("GetActiveObject rets %08x\n", hr);
8020 if(hr == S_OK)
8022 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
8023 IUnknown_Release(pUnk);
8027 if(hr != S_OK)
8028 hr = CoCreateInstance(&pTA->guid, NULL,
8029 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
8030 riid, ppvObj);
8032 end:
8033 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
8034 return hr;
8037 /* ITypeInfo::GetMops
8039 * Retrieves marshalling information.
8041 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
8042 BSTR *pBstrMops)
8044 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8045 FIXME("(%p %d) stub!\n", This, memid);
8046 *pBstrMops = NULL;
8047 return S_OK;
8050 /* ITypeInfo::GetContainingTypeLib
8052 * Retrieves the containing type library and the index of the type description
8053 * within that type library.
8055 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
8056 ITypeLib * *ppTLib, UINT *pIndex)
8058 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8060 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
8061 if (pIndex) {
8062 *pIndex=This->index;
8063 TRACE("returning pIndex=%d\n", *pIndex);
8066 if (ppTLib) {
8067 *ppTLib = (ITypeLib *)&This->pTypeLib->ITypeLib2_iface;
8068 ITypeLib_AddRef(*ppTLib);
8069 TRACE("returning ppTLib=%p\n", *ppTLib);
8072 return S_OK;
8075 /* ITypeInfo::ReleaseTypeAttr
8077 * Releases a TYPEATTR previously returned by Get
8080 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
8081 TYPEATTR* pTypeAttr)
8083 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8084 TRACE("(%p)->(%p)\n", This, pTypeAttr);
8085 heap_free(pTypeAttr);
8088 /* ITypeInfo::ReleaseFuncDesc
8090 * Releases a FUNCDESC previously returned by GetFuncDesc. *
8092 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
8093 ITypeInfo2 *iface,
8094 FUNCDESC *pFuncDesc)
8096 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8097 SHORT i;
8099 TRACE("(%p)->(%p)\n", This, pFuncDesc);
8101 for (i = 0; i < pFuncDesc->cParams; i++)
8102 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
8103 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
8105 SysFreeString((BSTR)pFuncDesc);
8108 /* ITypeInfo::ReleaseVarDesc
8110 * Releases a VARDESC previously returned by GetVarDesc.
8112 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
8113 VARDESC *pVarDesc)
8115 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8116 TRACE("(%p)->(%p)\n", This, pVarDesc);
8118 TLB_FreeVarDesc(pVarDesc);
8121 /* ITypeInfo2::GetTypeKind
8123 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
8126 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
8127 TYPEKIND *pTypeKind)
8129 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8130 *pTypeKind = This->typeattr.typekind;
8131 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
8132 return S_OK;
8135 /* ITypeInfo2::GetTypeFlags
8137 * Returns the type flags without any allocations. This returns a DWORD type
8138 * flag, which expands the type flags without growing the TYPEATTR (type
8139 * attribute).
8142 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
8144 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8145 *pTypeFlags=This->typeattr.wTypeFlags;
8146 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
8147 return S_OK;
8150 /* ITypeInfo2::GetFuncIndexOfMemId
8151 * Binds to a specific member based on a known DISPID, where the member name
8152 * is not known (for example, when binding to a default member).
8155 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
8156 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
8158 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8159 UINT fdc;
8160 HRESULT result;
8162 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
8163 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
8164 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
8165 break;
8167 if(fdc < This->typeattr.cFuncs) {
8168 *pFuncIndex = fdc;
8169 result = S_OK;
8170 } else
8171 result = TYPE_E_ELEMENTNOTFOUND;
8173 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
8174 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
8175 return result;
8178 /* TypeInfo2::GetVarIndexOfMemId
8180 * Binds to a specific member based on a known DISPID, where the member name
8181 * is not known (for example, when binding to a default member).
8184 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
8185 MEMBERID memid, UINT *pVarIndex)
8187 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8188 TLBVarDesc *pVarInfo;
8190 TRACE("%p %d %p\n", iface, memid, pVarIndex);
8192 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->typeattr.cVars, memid);
8193 if(!pVarInfo)
8194 return TYPE_E_ELEMENTNOTFOUND;
8196 *pVarIndex = (pVarInfo - This->vardescs);
8198 return S_OK;
8201 /* ITypeInfo2::GetCustData
8203 * Gets the custom data
8205 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
8206 ITypeInfo2 * iface,
8207 REFGUID guid,
8208 VARIANT *pVarVal)
8210 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8211 TLBCustData *pCData;
8213 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8215 if(!guid || !pVarVal)
8216 return E_INVALIDARG;
8218 pCData = TLB_get_custdata_by_guid(This->pcustdata_list, guid);
8220 VariantInit( pVarVal);
8221 if (pCData)
8222 VariantCopy( pVarVal, &pCData->data);
8223 else
8224 VariantClear( pVarVal );
8225 return S_OK;
8228 /* ITypeInfo2::GetFuncCustData
8230 * Gets the custom data
8232 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
8233 ITypeInfo2 * iface,
8234 UINT index,
8235 REFGUID guid,
8236 VARIANT *pVarVal)
8238 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8239 TLBCustData *pCData;
8240 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8242 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8244 if(index >= This->typeattr.cFuncs)
8245 return TYPE_E_ELEMENTNOTFOUND;
8247 pCData = TLB_get_custdata_by_guid(&pFDesc->custdata_list, guid);
8248 if(!pCData)
8249 return TYPE_E_ELEMENTNOTFOUND;
8251 VariantInit(pVarVal);
8252 VariantCopy(pVarVal, &pCData->data);
8254 return S_OK;
8257 /* ITypeInfo2::GetParamCustData
8259 * Gets the custom data
8261 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
8262 ITypeInfo2 * iface,
8263 UINT indexFunc,
8264 UINT indexParam,
8265 REFGUID guid,
8266 VARIANT *pVarVal)
8268 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8269 TLBCustData *pCData;
8270 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8272 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
8273 debugstr_guid(guid), pVarVal);
8275 if(indexFunc >= This->typeattr.cFuncs)
8276 return TYPE_E_ELEMENTNOTFOUND;
8278 if(indexParam >= pFDesc->funcdesc.cParams)
8279 return TYPE_E_ELEMENTNOTFOUND;
8281 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
8282 if(!pCData)
8283 return TYPE_E_ELEMENTNOTFOUND;
8285 VariantInit(pVarVal);
8286 VariantCopy(pVarVal, &pCData->data);
8288 return S_OK;
8291 /* ITypeInfo2::GetVarCustData
8293 * Gets the custom data
8295 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
8296 ITypeInfo2 * iface,
8297 UINT index,
8298 REFGUID guid,
8299 VARIANT *pVarVal)
8301 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8302 TLBCustData *pCData;
8303 TLBVarDesc *pVDesc = &This->vardescs[index];
8305 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8307 if(index >= This->typeattr.cVars)
8308 return TYPE_E_ELEMENTNOTFOUND;
8310 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
8311 if(!pCData)
8312 return TYPE_E_ELEMENTNOTFOUND;
8314 VariantInit(pVarVal);
8315 VariantCopy(pVarVal, &pCData->data);
8317 return S_OK;
8320 /* ITypeInfo2::GetImplCustData
8322 * Gets the custom data
8324 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
8325 ITypeInfo2 * iface,
8326 UINT index,
8327 REFGUID guid,
8328 VARIANT *pVarVal)
8330 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8331 TLBCustData *pCData;
8332 TLBImplType *pRDesc = &This->impltypes[index];
8334 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8336 if(index >= This->typeattr.cImplTypes)
8337 return TYPE_E_ELEMENTNOTFOUND;
8339 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
8340 if(!pCData)
8341 return TYPE_E_ELEMENTNOTFOUND;
8343 VariantInit(pVarVal);
8344 VariantCopy(pVarVal, &pCData->data);
8346 return S_OK;
8349 /* ITypeInfo2::GetDocumentation2
8351 * Retrieves the documentation string, the complete Help file name and path,
8352 * the localization context to use, and the context ID for the library Help
8353 * topic in the Help file.
8356 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
8357 ITypeInfo2 * iface,
8358 MEMBERID memid,
8359 LCID lcid,
8360 BSTR *pbstrHelpString,
8361 DWORD *pdwHelpStringContext,
8362 BSTR *pbstrHelpStringDll)
8364 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8365 const TLBFuncDesc *pFDesc;
8366 const TLBVarDesc *pVDesc;
8367 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8368 "HelpStringContext(%p) HelpStringDll(%p)\n",
8369 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
8370 pbstrHelpStringDll );
8371 /* the help string should be obtained from the helpstringdll,
8372 * using the _DLLGetDocumentation function, based on the supplied
8373 * lcid. Nice to do sometime...
8375 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
8376 if(pbstrHelpString)
8377 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->Name));
8378 if(pdwHelpStringContext)
8379 *pdwHelpStringContext=This->dwHelpStringContext;
8380 if(pbstrHelpStringDll)
8381 *pbstrHelpStringDll=
8382 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8383 return S_OK;
8384 }else {/* for a member */
8385 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->typeattr.cFuncs, memid);
8386 if(pFDesc){
8387 if(pbstrHelpString)
8388 *pbstrHelpString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
8389 if(pdwHelpStringContext)
8390 *pdwHelpStringContext=pFDesc->HelpStringContext;
8391 if(pbstrHelpStringDll)
8392 *pbstrHelpStringDll=
8393 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8394 return S_OK;
8396 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->typeattr.cVars, memid);
8397 if(pVDesc){
8398 if(pbstrHelpString)
8399 *pbstrHelpString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
8400 if(pdwHelpStringContext)
8401 *pdwHelpStringContext=pVDesc->HelpStringContext;
8402 if(pbstrHelpStringDll)
8403 *pbstrHelpStringDll=
8404 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8405 return S_OK;
8408 return TYPE_E_ELEMENTNOTFOUND;
8411 /* ITypeInfo2::GetAllCustData
8413 * Gets all custom data items for the Type info.
8416 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
8417 ITypeInfo2 * iface,
8418 CUSTDATA *pCustData)
8420 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8422 TRACE("%p %p\n", This, pCustData);
8424 return TLB_copy_all_custdata(This->pcustdata_list, pCustData);
8427 /* ITypeInfo2::GetAllFuncCustData
8429 * Gets all custom data items for the specified Function
8432 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
8433 ITypeInfo2 * iface,
8434 UINT index,
8435 CUSTDATA *pCustData)
8437 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8438 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8440 TRACE("%p %u %p\n", This, index, pCustData);
8442 if(index >= This->typeattr.cFuncs)
8443 return TYPE_E_ELEMENTNOTFOUND;
8445 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
8448 /* ITypeInfo2::GetAllParamCustData
8450 * Gets all custom data items for the Functions
8453 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
8454 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
8456 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8457 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8459 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
8461 if(indexFunc >= This->typeattr.cFuncs)
8462 return TYPE_E_ELEMENTNOTFOUND;
8464 if(indexParam >= pFDesc->funcdesc.cParams)
8465 return TYPE_E_ELEMENTNOTFOUND;
8467 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
8470 /* ITypeInfo2::GetAllVarCustData
8472 * Gets all custom data items for the specified Variable
8475 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
8476 UINT index, CUSTDATA *pCustData)
8478 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8479 TLBVarDesc * pVDesc = &This->vardescs[index];
8481 TRACE("%p %u %p\n", This, index, pCustData);
8483 if(index >= This->typeattr.cVars)
8484 return TYPE_E_ELEMENTNOTFOUND;
8486 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
8489 /* ITypeInfo2::GetAllImplCustData
8491 * Gets all custom data items for the specified implementation type
8494 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
8495 ITypeInfo2 * iface,
8496 UINT index,
8497 CUSTDATA *pCustData)
8499 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8500 TLBImplType *pRDesc = &This->impltypes[index];
8502 TRACE("%p %u %p\n", This, index, pCustData);
8504 if(index >= This->typeattr.cImplTypes)
8505 return TYPE_E_ELEMENTNOTFOUND;
8507 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
8510 static const ITypeInfo2Vtbl tinfvt =
8513 ITypeInfo_fnQueryInterface,
8514 ITypeInfo_fnAddRef,
8515 ITypeInfo_fnRelease,
8517 ITypeInfo_fnGetTypeAttr,
8518 ITypeInfo_fnGetTypeComp,
8519 ITypeInfo_fnGetFuncDesc,
8520 ITypeInfo_fnGetVarDesc,
8521 ITypeInfo_fnGetNames,
8522 ITypeInfo_fnGetRefTypeOfImplType,
8523 ITypeInfo_fnGetImplTypeFlags,
8524 ITypeInfo_fnGetIDsOfNames,
8525 ITypeInfo_fnInvoke,
8526 ITypeInfo_fnGetDocumentation,
8527 ITypeInfo_fnGetDllEntry,
8528 ITypeInfo_fnGetRefTypeInfo,
8529 ITypeInfo_fnAddressOfMember,
8530 ITypeInfo_fnCreateInstance,
8531 ITypeInfo_fnGetMops,
8532 ITypeInfo_fnGetContainingTypeLib,
8533 ITypeInfo_fnReleaseTypeAttr,
8534 ITypeInfo_fnReleaseFuncDesc,
8535 ITypeInfo_fnReleaseVarDesc,
8537 ITypeInfo2_fnGetTypeKind,
8538 ITypeInfo2_fnGetTypeFlags,
8539 ITypeInfo2_fnGetFuncIndexOfMemId,
8540 ITypeInfo2_fnGetVarIndexOfMemId,
8541 ITypeInfo2_fnGetCustData,
8542 ITypeInfo2_fnGetFuncCustData,
8543 ITypeInfo2_fnGetParamCustData,
8544 ITypeInfo2_fnGetVarCustData,
8545 ITypeInfo2_fnGetImplTypeCustData,
8546 ITypeInfo2_fnGetDocumentation2,
8547 ITypeInfo2_fnGetAllCustData,
8548 ITypeInfo2_fnGetAllFuncCustData,
8549 ITypeInfo2_fnGetAllParamCustData,
8550 ITypeInfo2_fnGetAllVarCustData,
8551 ITypeInfo2_fnGetAllImplTypeCustData,
8554 /******************************************************************************
8555 * CreateDispTypeInfo [OLEAUT32.31]
8557 * Build type information for an object so it can be called through an
8558 * IDispatch interface.
8560 * RETURNS
8561 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8562 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8564 * NOTES
8565 * This call allows an objects methods to be accessed through IDispatch, by
8566 * building an ITypeInfo object that IDispatch can use to call through.
8568 HRESULT WINAPI CreateDispTypeInfo(
8569 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
8570 LCID lcid, /* [I] Locale Id */
8571 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
8573 ITypeInfoImpl *pTIClass, *pTIIface;
8574 ITypeLibImpl *pTypeLibImpl;
8575 unsigned int param, func;
8576 TLBFuncDesc *pFuncDesc;
8577 TLBRefType *ref;
8579 TRACE("\n");
8580 pTypeLibImpl = TypeLibImpl_Constructor();
8581 if (!pTypeLibImpl) return E_FAIL;
8583 pTypeLibImpl->TypeInfoCount = 2;
8584 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
8586 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
8587 pTIIface->pTypeLib = pTypeLibImpl;
8588 pTIIface->index = 0;
8589 pTIIface->Name = NULL;
8590 pTIIface->dwHelpContext = -1;
8591 pTIIface->guid = NULL;
8592 pTIIface->typeattr.lcid = lcid;
8593 pTIIface->typeattr.typekind = TKIND_INTERFACE;
8594 pTIIface->typeattr.wMajorVerNum = 0;
8595 pTIIface->typeattr.wMinorVerNum = 0;
8596 pTIIface->typeattr.cbAlignment = 2;
8597 pTIIface->typeattr.cbSizeInstance = -1;
8598 pTIIface->typeattr.cbSizeVft = -1;
8599 pTIIface->typeattr.cFuncs = 0;
8600 pTIIface->typeattr.cImplTypes = 0;
8601 pTIIface->typeattr.cVars = 0;
8602 pTIIface->typeattr.wTypeFlags = 0;
8603 pTIIface->hreftype = 0;
8605 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers);
8606 pFuncDesc = pTIIface->funcdescs;
8607 for(func = 0; func < pidata->cMembers; func++) {
8608 METHODDATA *md = pidata->pmethdata + func;
8609 pFuncDesc->Name = TLB_append_str(&pTypeLibImpl->name_list, md->szName);
8610 pFuncDesc->funcdesc.memid = md->dispid;
8611 pFuncDesc->funcdesc.lprgscode = NULL;
8612 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
8613 pFuncDesc->funcdesc.invkind = md->wFlags;
8614 pFuncDesc->funcdesc.callconv = md->cc;
8615 pFuncDesc->funcdesc.cParams = md->cArgs;
8616 pFuncDesc->funcdesc.cParamsOpt = 0;
8617 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
8618 pFuncDesc->funcdesc.cScodes = 0;
8619 pFuncDesc->funcdesc.wFuncFlags = 0;
8620 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
8621 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
8622 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
8623 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8624 md->cArgs * sizeof(ELEMDESC));
8625 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
8626 for(param = 0; param < md->cArgs; param++) {
8627 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
8628 pFuncDesc->pParamDesc[param].Name = TLB_append_str(&pTypeLibImpl->name_list, md->ppdata[param].szName);
8630 pFuncDesc->helpcontext = 0;
8631 pFuncDesc->HelpStringContext = 0;
8632 pFuncDesc->HelpString = NULL;
8633 pFuncDesc->Entry = NULL;
8634 list_init(&pFuncDesc->custdata_list);
8635 pTIIface->typeattr.cFuncs++;
8636 ++pFuncDesc;
8639 dump_TypeInfo(pTIIface);
8641 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
8642 pTIClass->pTypeLib = pTypeLibImpl;
8643 pTIClass->index = 1;
8644 pTIClass->Name = NULL;
8645 pTIClass->dwHelpContext = -1;
8646 pTIClass->guid = NULL;
8647 pTIClass->typeattr.lcid = lcid;
8648 pTIClass->typeattr.typekind = TKIND_COCLASS;
8649 pTIClass->typeattr.wMajorVerNum = 0;
8650 pTIClass->typeattr.wMinorVerNum = 0;
8651 pTIClass->typeattr.cbAlignment = 2;
8652 pTIClass->typeattr.cbSizeInstance = -1;
8653 pTIClass->typeattr.cbSizeVft = -1;
8654 pTIClass->typeattr.cFuncs = 0;
8655 pTIClass->typeattr.cImplTypes = 1;
8656 pTIClass->typeattr.cVars = 0;
8657 pTIClass->typeattr.wTypeFlags = 0;
8658 pTIClass->hreftype = sizeof(MSFT_TypeInfoBase);
8660 pTIClass->impltypes = TLBImplType_Alloc(1);
8662 ref = heap_alloc_zero(sizeof(*ref));
8663 ref->pImpTLInfo = TLB_REF_INTERNAL;
8664 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
8666 dump_TypeInfo(pTIClass);
8668 *pptinfo = (ITypeInfo *)&pTIClass->ITypeInfo2_iface;
8670 ITypeInfo_AddRef(*pptinfo);
8671 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
8673 return S_OK;
8677 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
8679 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8681 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, ppv);
8684 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
8686 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8688 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
8691 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
8693 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8695 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
8698 static HRESULT WINAPI ITypeComp_fnBind(
8699 ITypeComp * iface,
8700 OLECHAR * szName,
8701 ULONG lHash,
8702 WORD wFlags,
8703 ITypeInfo ** ppTInfo,
8704 DESCKIND * pDescKind,
8705 BINDPTR * pBindPtr)
8707 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8708 const TLBFuncDesc *pFDesc;
8709 const TLBVarDesc *pVDesc;
8710 HRESULT hr = DISP_E_MEMBERNOTFOUND;
8711 UINT fdc;
8713 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8715 *pDescKind = DESCKIND_NONE;
8716 pBindPtr->lpfuncdesc = NULL;
8717 *ppTInfo = NULL;
8719 for(fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
8720 pFDesc = &This->funcdescs[fdc];
8721 if (!lstrcmpiW(TLB_get_bstr(pFDesc->Name), szName)) {
8722 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
8723 break;
8724 else
8725 /* name found, but wrong flags */
8726 hr = TYPE_E_TYPEMISMATCH;
8730 if (fdc < This->typeattr.cFuncs)
8732 HRESULT hr = TLB_AllocAndInitFuncDesc(
8733 &pFDesc->funcdesc,
8734 &pBindPtr->lpfuncdesc,
8735 This->typeattr.typekind == TKIND_DISPATCH);
8736 if (FAILED(hr))
8737 return hr;
8738 *pDescKind = DESCKIND_FUNCDESC;
8739 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8740 ITypeInfo_AddRef(*ppTInfo);
8741 return S_OK;
8742 } else {
8743 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->typeattr.cVars, szName);
8744 if(pVDesc){
8745 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
8746 if (FAILED(hr))
8747 return hr;
8748 *pDescKind = DESCKIND_VARDESC;
8749 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8750 ITypeInfo_AddRef(*ppTInfo);
8751 return S_OK;
8755 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
8756 /* recursive search */
8757 ITypeInfo *pTInfo;
8758 ITypeComp *pTComp;
8759 HRESULT hr;
8760 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
8761 if (SUCCEEDED(hr))
8763 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
8764 ITypeInfo_Release(pTInfo);
8766 if (SUCCEEDED(hr))
8768 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8769 ITypeComp_Release(pTComp);
8770 if (SUCCEEDED(hr) && *pDescKind == DESCKIND_FUNCDESC &&
8771 This->typeattr.typekind == TKIND_DISPATCH)
8773 FUNCDESC *tmp = pBindPtr->lpfuncdesc;
8774 hr = TLB_AllocAndInitFuncDesc(tmp, &pBindPtr->lpfuncdesc, TRUE);
8775 SysFreeString((BSTR)tmp);
8777 return hr;
8779 WARN("Could not search inherited interface!\n");
8781 if (hr == DISP_E_MEMBERNOTFOUND)
8782 hr = S_OK;
8783 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
8784 return hr;
8787 static HRESULT WINAPI ITypeComp_fnBindType(
8788 ITypeComp * iface,
8789 OLECHAR * szName,
8790 ULONG lHash,
8791 ITypeInfo ** ppTInfo,
8792 ITypeComp ** ppTComp)
8794 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
8796 /* strange behaviour (does nothing) but like the
8797 * original */
8799 if (!ppTInfo || !ppTComp)
8800 return E_POINTER;
8802 *ppTInfo = NULL;
8803 *ppTComp = NULL;
8805 return S_OK;
8808 static const ITypeCompVtbl tcompvt =
8811 ITypeComp_fnQueryInterface,
8812 ITypeComp_fnAddRef,
8813 ITypeComp_fnRelease,
8815 ITypeComp_fnBind,
8816 ITypeComp_fnBindType
8819 HRESULT WINAPI CreateTypeLib2(SYSKIND syskind, LPCOLESTR szFile,
8820 ICreateTypeLib2** ppctlib)
8822 ITypeLibImpl *This;
8823 HRESULT hres;
8825 TRACE("(%d,%s,%p)\n", syskind, debugstr_w(szFile), ppctlib);
8827 if (!szFile) return E_INVALIDARG;
8829 This = TypeLibImpl_Constructor();
8830 if (!This)
8831 return E_OUTOFMEMORY;
8833 This->lcid = GetSystemDefaultLCID();
8834 This->syskind = syskind;
8835 This->ptr_size = get_ptr_size(syskind);
8837 This->path = heap_alloc((lstrlenW(szFile) + 1) * sizeof(WCHAR));
8838 if (!This->path) {
8839 ITypeLib2_Release(&This->ITypeLib2_iface);
8840 return E_OUTOFMEMORY;
8842 lstrcpyW(This->path, szFile);
8844 hres = ITypeLib2_QueryInterface(&This->ITypeLib2_iface, &IID_ICreateTypeLib2, (LPVOID*)ppctlib);
8845 ITypeLib2_Release(&This->ITypeLib2_iface);
8846 return hres;
8849 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
8850 REFIID riid, void **object)
8852 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8854 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, object);
8857 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
8859 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8861 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
8864 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
8866 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8868 return ITypeLib2_Release(&This->ITypeLib2_iface);
8871 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
8872 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
8874 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8875 ITypeInfoImpl *info;
8876 HRESULT hres;
8878 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo);
8880 if (!ctinfo || !name)
8881 return E_INVALIDARG;
8883 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, name);
8884 if (info)
8885 return TYPE_E_NAMECONFLICT;
8887 if (This->typeinfos)
8888 This->typeinfos = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->typeinfos,
8889 sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1));
8890 else
8891 This->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*));
8893 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor();
8895 info->pTypeLib = This;
8896 info->Name = TLB_append_str(&This->name_list, name);
8897 info->index = This->TypeInfoCount;
8898 info->typeattr.typekind = kind;
8899 info->typeattr.cbAlignment = 4;
8901 switch (info->typeattr.typekind) {
8902 case TKIND_ENUM:
8903 case TKIND_INTERFACE:
8904 case TKIND_DISPATCH:
8905 case TKIND_COCLASS:
8906 info->typeattr.cbSizeInstance = This->ptr_size;
8907 break;
8908 case TKIND_RECORD:
8909 case TKIND_UNION:
8910 info->typeattr.cbSizeInstance = 0;
8911 break;
8912 case TKIND_MODULE:
8913 info->typeattr.cbSizeInstance = 2;
8914 break;
8915 case TKIND_ALIAS:
8916 info->typeattr.cbSizeInstance = -0x75;
8917 break;
8918 default:
8919 FIXME("unrecognized typekind %d\n", info->typeattr.typekind);
8920 info->typeattr.cbSizeInstance = 0xdeadbeef;
8921 break;
8924 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface,
8925 &IID_ICreateTypeInfo, (void **)ctinfo);
8926 if (FAILED(hres)) {
8927 ITypeInfo2_Release(&info->ITypeInfo2_iface);
8928 return hres;
8931 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase);
8933 ++This->TypeInfoCount;
8935 return S_OK;
8938 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
8939 LPOLESTR name)
8941 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8943 TRACE("%p %s\n", This, wine_dbgstr_w(name));
8945 if (!name)
8946 return E_INVALIDARG;
8948 This->Name = TLB_append_str(&This->name_list, name);
8950 return S_OK;
8953 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
8954 WORD majorVerNum, WORD minorVerNum)
8956 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8958 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
8960 This->ver_major = majorVerNum;
8961 This->ver_minor = minorVerNum;
8963 return S_OK;
8966 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
8967 REFGUID guid)
8969 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8971 TRACE("%p %s\n", This, debugstr_guid(guid));
8973 This->guid = TLB_append_guid(&This->guid_list, guid, -2);
8975 return S_OK;
8978 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
8979 LPOLESTR doc)
8981 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8983 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
8985 if (!doc)
8986 return E_INVALIDARG;
8988 This->DocString = TLB_append_str(&This->string_list, doc);
8990 return S_OK;
8993 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
8994 LPOLESTR helpFileName)
8996 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8998 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
9000 if (!helpFileName)
9001 return E_INVALIDARG;
9003 This->HelpFile = TLB_append_str(&This->string_list, helpFileName);
9005 return S_OK;
9008 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
9009 DWORD helpContext)
9011 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9013 TRACE("%p %d\n", This, helpContext);
9015 This->dwHelpContext = helpContext;
9017 return S_OK;
9020 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
9021 LCID lcid)
9023 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9025 TRACE("%p %x\n", This, lcid);
9027 This->set_lcid = lcid;
9029 return S_OK;
9032 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
9033 UINT libFlags)
9035 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9037 TRACE("%p %x\n", This, libFlags);
9039 This->libflags = libFlags;
9041 return S_OK;
9044 typedef struct tagWMSFT_SegContents {
9045 DWORD len;
9046 void *data;
9047 } WMSFT_SegContents;
9049 typedef struct tagWMSFT_TLBFile {
9050 MSFT_Header header;
9051 WMSFT_SegContents typeinfo_seg;
9052 WMSFT_SegContents impfile_seg;
9053 WMSFT_SegContents impinfo_seg;
9054 WMSFT_SegContents ref_seg;
9055 WMSFT_SegContents guidhash_seg;
9056 WMSFT_SegContents guid_seg;
9057 WMSFT_SegContents namehash_seg;
9058 WMSFT_SegContents name_seg;
9059 WMSFT_SegContents string_seg;
9060 WMSFT_SegContents typdesc_seg;
9061 WMSFT_SegContents arraydesc_seg;
9062 WMSFT_SegContents custdata_seg;
9063 WMSFT_SegContents cdguids_seg;
9064 MSFT_SegDir segdir;
9065 WMSFT_SegContents aux_seg;
9066 } WMSFT_TLBFile;
9068 static HRESULT WMSFT_compile_strings(ITypeLibImpl *This,
9069 WMSFT_TLBFile *file)
9071 TLBString *str;
9072 UINT last_offs;
9073 char *data;
9075 file->string_seg.len = 0;
9076 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
9077 int size;
9079 size = WideCharToMultiByte(CP_ACP, 0, str->str, lstrlenW(str->str), NULL, 0, NULL, NULL);
9080 if (size == 0)
9081 return E_UNEXPECTED;
9083 size += sizeof(INT16);
9084 if (size % 4)
9085 size = (size + 4) & ~0x3;
9086 if (size < 8)
9087 size = 8;
9089 file->string_seg.len += size;
9091 /* temporarily use str->offset to store the length of the aligned,
9092 * converted string */
9093 str->offset = size;
9096 file->string_seg.data = data = heap_alloc(file->string_seg.len);
9098 last_offs = 0;
9099 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
9100 int size;
9102 size = WideCharToMultiByte(CP_ACP, 0, str->str, lstrlenW(str->str),
9103 data + sizeof(INT16), file->string_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9104 if (size == 0) {
9105 heap_free(file->string_seg.data);
9106 return E_UNEXPECTED;
9109 *((INT16*)data) = size;
9111 memset(data + sizeof(INT16) + size, 0x57, str->offset - size - sizeof(INT16));
9113 size = str->offset;
9114 data += size;
9115 str->offset = last_offs;
9116 last_offs += size;
9119 return S_OK;
9122 static HRESULT WMSFT_compile_names(ITypeLibImpl *This,
9123 WMSFT_TLBFile *file)
9125 TLBString *str;
9126 UINT last_offs;
9127 char *data;
9128 MSFT_NameIntro *last_intro = NULL;
9130 file->header.nametablecount = 0;
9131 file->header.nametablechars = 0;
9133 file->name_seg.len = 0;
9134 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
9135 int size;
9137 size = lstrlenW(str->str);
9138 file->header.nametablechars += size;
9139 file->header.nametablecount++;
9141 size = WideCharToMultiByte(CP_ACP, 0, str->str, size, NULL, 0, NULL, NULL);
9142 if (size == 0)
9143 return E_UNEXPECTED;
9145 size += sizeof(MSFT_NameIntro);
9146 if (size % 4)
9147 size = (size + 4) & ~0x3;
9148 if (size < 8)
9149 size = 8;
9151 file->name_seg.len += size;
9153 /* temporarily use str->offset to store the length of the aligned,
9154 * converted string */
9155 str->offset = size;
9158 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
9159 file->name_seg.data = data = heap_alloc(file->name_seg.len+1);
9161 last_offs = 0;
9162 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
9163 int size, hash;
9164 MSFT_NameIntro *intro = (MSFT_NameIntro*)data;
9166 size = WideCharToMultiByte(CP_ACP, 0, str->str, lstrlenW(str->str),
9167 data + sizeof(MSFT_NameIntro),
9168 file->name_seg.len - last_offs - sizeof(MSFT_NameIntro), NULL, NULL);
9169 if (size == 0) {
9170 heap_free(file->name_seg.data);
9171 return E_UNEXPECTED;
9173 data[sizeof(MSFT_NameIntro) + size] = '\0';
9175 intro->hreftype = -1; /* TODO? */
9176 intro->namelen = size & 0xFF;
9177 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9178 hash = LHashValOfNameSysA(This->syskind, This->lcid, data + sizeof(MSFT_NameIntro));
9179 intro->namelen |= hash << 16;
9180 intro->next_hash = ((DWORD*)file->namehash_seg.data)[hash & 0x7f];
9181 ((DWORD*)file->namehash_seg.data)[hash & 0x7f] = last_offs;
9183 memset(data + sizeof(MSFT_NameIntro) + size, 0x57,
9184 str->offset - size - sizeof(MSFT_NameIntro));
9186 /* update str->offset to actual value to use in other
9187 * compilation functions that require positions within
9188 * the string table */
9189 last_intro = intro;
9190 size = str->offset;
9191 data += size;
9192 str->offset = last_offs;
9193 last_offs += size;
9196 if(last_intro)
9197 last_intro->hreftype = 0; /* last one is 0? */
9199 return S_OK;
9202 static inline int hash_guid(GUID *guid)
9204 int i, hash = 0;
9206 for (i = 0; i < 8; i ++)
9207 hash ^= ((const short *)guid)[i];
9209 return hash & 0x1f;
9212 static HRESULT WMSFT_compile_guids(ITypeLibImpl *This, WMSFT_TLBFile *file)
9214 TLBGuid *guid;
9215 MSFT_GuidEntry *entry;
9216 DWORD offs;
9217 int hash_key, *guidhashtab;
9219 file->guid_seg.len = sizeof(MSFT_GuidEntry) * list_count(&This->guid_list);
9220 file->guid_seg.data = heap_alloc(file->guid_seg.len);
9222 entry = file->guid_seg.data;
9223 offs = 0;
9224 guidhashtab = file->guidhash_seg.data;
9225 LIST_FOR_EACH_ENTRY(guid, &This->guid_list, TLBGuid, entry){
9226 memcpy(&entry->guid, &guid->guid, sizeof(GUID));
9227 entry->hreftype = guid->hreftype;
9229 hash_key = hash_guid(&guid->guid);
9230 entry->next_hash = guidhashtab[hash_key];
9231 guidhashtab[hash_key] = offs;
9233 guid->offset = offs;
9234 offs += sizeof(MSFT_GuidEntry);
9235 ++entry;
9238 return S_OK;
9241 static DWORD WMSFT_encode_variant(VARIANT *value, WMSFT_TLBFile *file)
9243 VARIANT v = *value;
9244 VARTYPE arg_type = V_VT(value);
9245 int mask = 0;
9246 HRESULT hres;
9247 DWORD ret = file->custdata_seg.len;
9249 if(arg_type == VT_INT)
9250 arg_type = VT_I4;
9251 if(arg_type == VT_UINT)
9252 arg_type = VT_UI4;
9254 v = *value;
9255 if(V_VT(value) != arg_type) {
9256 hres = VariantChangeType(&v, value, 0, arg_type);
9257 if(FAILED(hres)){
9258 ERR("VariantChangeType failed: %08x\n", hres);
9259 return -1;
9263 /* Check if default value can be stored in-place */
9264 switch(arg_type){
9265 case VT_I4:
9266 case VT_UI4:
9267 mask = 0x3ffffff;
9268 if(V_UI4(&v) > 0x3ffffff)
9269 break;
9270 /* fall through */
9271 case VT_I1:
9272 case VT_UI1:
9273 case VT_BOOL:
9274 if(!mask)
9275 mask = 0xff;
9276 /* fall through */
9277 case VT_I2:
9278 case VT_UI2:
9279 if(!mask)
9280 mask = 0xffff;
9281 return ((0x80 + 0x4 * V_VT(value)) << 24) | (V_UI4(&v) & mask);
9284 /* have to allocate space in custdata_seg */
9285 switch(arg_type) {
9286 case VT_I4:
9287 case VT_R4:
9288 case VT_UI4:
9289 case VT_INT:
9290 case VT_UINT:
9291 case VT_HRESULT:
9292 case VT_PTR: {
9293 /* Construct the data to be allocated */
9294 int *data;
9296 if(file->custdata_seg.data){
9297 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + sizeof(int) * 2);
9298 data = (int *)(((char *)file->custdata_seg.data) + file->custdata_seg.len);
9299 file->custdata_seg.len += sizeof(int) * 2;
9300 }else{
9301 file->custdata_seg.len = sizeof(int) * 2;
9302 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9305 data[0] = V_VT(value) + (V_UI4(&v) << 16);
9306 data[1] = (V_UI4(&v) >> 16) + 0x57570000;
9308 /* TODO: Check if the encoded data is already present in custdata_seg */
9310 return ret;
9313 case VT_BSTR: {
9314 int i, len = (6+SysStringLen(V_BSTR(&v))+3) & ~0x3;
9315 char *data;
9317 if(file->custdata_seg.data){
9318 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + len);
9319 data = ((char *)file->custdata_seg.data) + file->custdata_seg.len;
9320 file->custdata_seg.len += len;
9321 }else{
9322 file->custdata_seg.len = len;
9323 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9326 *((unsigned short *)data) = V_VT(value);
9327 *((unsigned int *)(data+2)) = SysStringLen(V_BSTR(&v));
9328 for(i=0; i<SysStringLen(V_BSTR(&v)); i++) {
9329 if(V_BSTR(&v)[i] <= 0x7f)
9330 data[i+6] = V_BSTR(&v)[i];
9331 else
9332 data[i+6] = '?';
9334 WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], len-6, NULL, NULL);
9335 for(i=6+SysStringLen(V_BSTR(&v)); i<len; i++)
9336 data[i] = 0x57;
9338 /* TODO: Check if the encoded data is already present in custdata_seg */
9340 return ret;
9342 default:
9343 FIXME("Argument type not yet handled\n");
9344 return -1;
9348 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size);
9350 static DWORD WMSFT_append_arraydesc(ARRAYDESC *desc, WMSFT_TLBFile *file)
9352 DWORD offs = file->arraydesc_seg.len;
9353 DWORD *encoded;
9354 USHORT i;
9356 /* TODO: we should check for duplicates, but that's harder because each
9357 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9358 * at the library-level) */
9360 file->arraydesc_seg.len += (2 + desc->cDims * 2) * sizeof(DWORD);
9361 if(!file->arraydesc_seg.data)
9362 file->arraydesc_seg.data = heap_alloc(file->arraydesc_seg.len);
9363 else
9364 file->arraydesc_seg.data = heap_realloc(file->arraydesc_seg.data, file->arraydesc_seg.len);
9365 encoded = (DWORD*)((char *)file->arraydesc_seg.data + offs);
9367 encoded[0] = WMSFT_append_typedesc(&desc->tdescElem, file, NULL, NULL);
9368 encoded[1] = desc->cDims | ((desc->cDims * 2 * sizeof(DWORD)) << 16);
9369 for(i = 0; i < desc->cDims; ++i){
9370 encoded[2 + i * 2] = desc->rgbounds[i].cElements;
9371 encoded[2 + i * 2 + 1] = desc->rgbounds[i].lLbound;
9374 return offs;
9377 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size)
9379 DWORD junk;
9380 INT16 junk2;
9381 DWORD offs = 0;
9382 DWORD encoded[2];
9383 VARTYPE vt, subtype;
9384 char *data;
9386 if(!desc)
9387 return -1;
9389 if(!out_mix)
9390 out_mix = &junk;
9391 if(!out_size)
9392 out_size = &junk2;
9394 vt = desc->vt & VT_TYPEMASK;
9396 if(vt == VT_PTR || vt == VT_SAFEARRAY){
9397 DWORD mix;
9398 encoded[1] = WMSFT_append_typedesc(desc->u.lptdesc, file, &mix, out_size);
9399 encoded[0] = desc->vt | ((mix | VT_BYREF) << 16);
9400 *out_mix = 0x7FFF;
9401 *out_size += 2 * sizeof(DWORD);
9402 }else if(vt == VT_CARRAY){
9403 encoded[0] = desc->vt | (0x7FFE << 16);
9404 encoded[1] = WMSFT_append_arraydesc(desc->u.lpadesc, file);
9405 *out_mix = 0x7FFE;
9406 }else if(vt == VT_USERDEFINED){
9407 encoded[0] = desc->vt | (0x7FFF << 16);
9408 encoded[1] = desc->u.hreftype;
9409 *out_mix = 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9410 }else{
9411 TRACE("Mixing in-place, VT: 0x%x\n", desc->vt);
9413 switch(vt){
9414 case VT_INT:
9415 subtype = VT_I4;
9416 break;
9417 case VT_UINT:
9418 subtype = VT_UI4;
9419 break;
9420 case VT_VOID:
9421 subtype = VT_EMPTY;
9422 break;
9423 default:
9424 subtype = vt;
9425 break;
9428 *out_mix = subtype;
9429 return 0x80000000 | (subtype << 16) | desc->vt;
9432 data = file->typdesc_seg.data;
9433 while(offs < file->typdesc_seg.len){
9434 if(!memcmp(&data[offs], encoded, sizeof(encoded)))
9435 return offs;
9436 offs += sizeof(encoded);
9439 file->typdesc_seg.len += sizeof(encoded);
9440 if(!file->typdesc_seg.data)
9441 data = file->typdesc_seg.data = heap_alloc(file->typdesc_seg.len);
9442 else
9443 data = file->typdesc_seg.data = heap_realloc(file->typdesc_seg.data, file->typdesc_seg.len);
9445 memcpy(&data[offs], encoded, sizeof(encoded));
9447 return offs;
9450 static DWORD WMSFT_compile_custdata(struct list *custdata_list, WMSFT_TLBFile *file)
9452 WMSFT_SegContents *cdguids_seg = &file->cdguids_seg;
9453 DWORD ret = cdguids_seg->len, offs;
9454 MSFT_CDGuid *cdguid;
9455 TLBCustData *cd;
9457 if(list_empty(custdata_list))
9458 return -1;
9460 cdguids_seg->len += sizeof(MSFT_CDGuid) * list_count(custdata_list);
9461 if(!cdguids_seg->data){
9462 cdguid = cdguids_seg->data = heap_alloc(cdguids_seg->len);
9463 }else {
9464 cdguids_seg->data = heap_realloc(cdguids_seg->data, cdguids_seg->len);
9465 cdguid = (MSFT_CDGuid*)((char*)cdguids_seg->data + ret);
9468 offs = ret + sizeof(MSFT_CDGuid);
9469 LIST_FOR_EACH_ENTRY(cd, custdata_list, TLBCustData, entry){
9470 cdguid->GuidOffset = cd->guid->offset;
9471 cdguid->DataOffset = WMSFT_encode_variant(&cd->data, file);
9472 cdguid->next = offs;
9473 offs += sizeof(MSFT_CDGuid);
9474 ++cdguid;
9477 --cdguid;
9478 cdguid->next = -1;
9480 return ret;
9483 static DWORD WMSFT_compile_typeinfo_aux(ITypeInfoImpl *info,
9484 WMSFT_TLBFile *file)
9486 WMSFT_SegContents *aux_seg = &file->aux_seg;
9487 DWORD ret = aux_seg->len, i, j, recorded_size = 0, extra_size = 0;
9488 MSFT_VarRecord *varrecord;
9489 MSFT_FuncRecord *funcrecord;
9490 MEMBERID *memid;
9491 DWORD *name, *offsets, offs;
9493 for(i = 0; i < info->typeattr.cFuncs; ++i){
9494 TLBFuncDesc *desc = &info->funcdescs[i];
9496 recorded_size += 6 * sizeof(INT); /* mandatory fields */
9498 /* optional fields */
9499 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9500 if(!list_empty(&desc->custdata_list))
9501 recorded_size += 7 * sizeof(INT);
9502 else if(desc->HelpStringContext != 0)
9503 recorded_size += 6 * sizeof(INT);
9504 /* res9? resA? */
9505 else if(desc->Entry)
9506 recorded_size += 3 * sizeof(INT);
9507 else if(desc->HelpString)
9508 recorded_size += 2 * sizeof(INT);
9509 else if(desc->helpcontext)
9510 recorded_size += sizeof(INT);
9512 recorded_size += desc->funcdesc.cParams * sizeof(MSFT_ParameterInfo);
9514 for(j = 0; j < desc->funcdesc.cParams; ++j){
9515 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9516 recorded_size += desc->funcdesc.cParams * sizeof(INT);
9517 break;
9521 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9524 for(i = 0; i < info->typeattr.cVars; ++i){
9525 TLBVarDesc *desc = &info->vardescs[i];
9527 recorded_size += 5 * sizeof(INT); /* mandatory fields */
9529 /* optional fields */
9530 if(desc->HelpStringContext != 0)
9531 recorded_size += 5 * sizeof(INT);
9532 else if(!list_empty(&desc->custdata_list))
9533 recorded_size += 4 * sizeof(INT);
9534 /* res9? */
9535 else if(desc->HelpString)
9536 recorded_size += 2 * sizeof(INT);
9537 else if(desc->HelpContext != 0)
9538 recorded_size += sizeof(INT);
9540 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9543 if(!recorded_size && !extra_size)
9544 return ret;
9546 extra_size += sizeof(INT); /* total aux size for this typeinfo */
9548 aux_seg->len += recorded_size + extra_size;
9550 aux_seg->len += sizeof(INT) * (info->typeattr.cVars + info->typeattr.cFuncs); /* offsets at the end */
9552 if(aux_seg->data)
9553 aux_seg->data = heap_realloc(aux_seg->data, aux_seg->len);
9554 else
9555 aux_seg->data = heap_alloc(aux_seg->len);
9557 *((DWORD*)((char *)aux_seg->data + ret)) = recorded_size;
9559 offsets = (DWORD*)((char *)aux_seg->data + ret + recorded_size + extra_size);
9560 offs = 0;
9562 funcrecord = (MSFT_FuncRecord*)(((char *)aux_seg->data) + ret + sizeof(INT));
9563 for(i = 0; i < info->typeattr.cFuncs; ++i){
9564 TLBFuncDesc *desc = &info->funcdescs[i];
9565 DWORD size = 6 * sizeof(INT), paramdefault_size = 0, *paramdefault;
9567 funcrecord->funcdescsize = sizeof(desc->funcdesc) + desc->funcdesc.cParams * sizeof(ELEMDESC);
9568 funcrecord->DataType = WMSFT_append_typedesc(&desc->funcdesc.elemdescFunc.tdesc, file, NULL, &funcrecord->funcdescsize);
9569 funcrecord->Flags = desc->funcdesc.wFuncFlags;
9570 funcrecord->VtableOffset = desc->funcdesc.oVft;
9572 /* FKCCIC:
9573 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9574 * ^^^funckind
9575 * ^^^ ^invkind
9576 * ^has_cust_data
9577 * ^^^^callconv
9578 * ^has_param_defaults
9579 * ^oEntry_is_intresource
9581 funcrecord->FKCCIC =
9582 desc->funcdesc.funckind |
9583 (desc->funcdesc.invkind << 3) |
9584 (list_empty(&desc->custdata_list) ? 0 : 0x80) |
9585 (desc->funcdesc.callconv << 8);
9587 if(desc->Entry && desc->Entry != (TLBString*)-1 && IS_INTRESOURCE(desc->Entry))
9588 funcrecord->FKCCIC |= 0x2000;
9590 for(j = 0; j < desc->funcdesc.cParams; ++j){
9591 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9592 paramdefault_size = sizeof(INT) * desc->funcdesc.cParams;
9593 funcrecord->funcdescsize += sizeof(PARAMDESCEX);
9596 if(paramdefault_size > 0)
9597 funcrecord->FKCCIC |= 0x1000;
9599 funcrecord->nrargs = desc->funcdesc.cParams;
9600 funcrecord->nroargs = desc->funcdesc.cParamsOpt;
9602 /* optional fields */
9603 /* res9? resA? */
9604 if(!list_empty(&desc->custdata_list)){
9605 size += 7 * sizeof(INT);
9606 funcrecord->HelpContext = desc->helpcontext;
9607 if(desc->HelpString)
9608 funcrecord->oHelpString = desc->HelpString->offset;
9609 else
9610 funcrecord->oHelpString = -1;
9611 if(!desc->Entry)
9612 funcrecord->oEntry = -1;
9613 else if(IS_INTRESOURCE(desc->Entry))
9614 funcrecord->oEntry = LOWORD(desc->Entry);
9615 else
9616 funcrecord->oEntry = desc->Entry->offset;
9617 funcrecord->res9 = -1;
9618 funcrecord->resA = -1;
9619 funcrecord->HelpStringContext = desc->HelpStringContext;
9620 funcrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9621 }else if(desc->HelpStringContext != 0){
9622 size += 6 * sizeof(INT);
9623 funcrecord->HelpContext = desc->helpcontext;
9624 if(desc->HelpString)
9625 funcrecord->oHelpString = desc->HelpString->offset;
9626 else
9627 funcrecord->oHelpString = -1;
9628 if(!desc->Entry)
9629 funcrecord->oEntry = -1;
9630 else if(IS_INTRESOURCE(desc->Entry))
9631 funcrecord->oEntry = LOWORD(desc->Entry);
9632 else
9633 funcrecord->oEntry = desc->Entry->offset;
9634 funcrecord->res9 = -1;
9635 funcrecord->resA = -1;
9636 funcrecord->HelpStringContext = desc->HelpStringContext;
9637 }else if(desc->Entry){
9638 size += 3 * sizeof(INT);
9639 funcrecord->HelpContext = desc->helpcontext;
9640 if(desc->HelpString)
9641 funcrecord->oHelpString = desc->HelpString->offset;
9642 else
9643 funcrecord->oHelpString = -1;
9644 if(!desc->Entry)
9645 funcrecord->oEntry = -1;
9646 else if(IS_INTRESOURCE(desc->Entry))
9647 funcrecord->oEntry = LOWORD(desc->Entry);
9648 else
9649 funcrecord->oEntry = desc->Entry->offset;
9650 }else if(desc->HelpString){
9651 size += 2 * sizeof(INT);
9652 funcrecord->HelpContext = desc->helpcontext;
9653 funcrecord->oHelpString = desc->HelpString->offset;
9654 }else if(desc->helpcontext){
9655 size += sizeof(INT);
9656 funcrecord->HelpContext = desc->helpcontext;
9659 paramdefault = (DWORD*)((char *)funcrecord + size);
9660 size += paramdefault_size;
9662 for(j = 0; j < desc->funcdesc.cParams; ++j){
9663 MSFT_ParameterInfo *info = (MSFT_ParameterInfo*)(((char *)funcrecord) + size);
9665 info->DataType = WMSFT_append_typedesc(&desc->funcdesc.lprgelemdescParam[j].tdesc, file, NULL, &funcrecord->funcdescsize);
9666 if(desc->pParamDesc[j].Name)
9667 info->oName = desc->pParamDesc[j].Name->offset;
9668 else
9669 info->oName = -1;
9670 info->Flags = desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags;
9672 if(paramdefault_size){
9673 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
9674 *paramdefault = WMSFT_encode_variant(&desc->funcdesc.lprgelemdescParam[j].u.paramdesc.pparamdescex->varDefaultValue, file);
9675 else if(paramdefault_size)
9676 *paramdefault = -1;
9677 ++paramdefault;
9680 size += sizeof(MSFT_ParameterInfo);
9683 funcrecord->Info = size | (i << 16); /* is it just the index? */
9685 *offsets = offs;
9686 offs += size;
9687 ++offsets;
9689 funcrecord = (MSFT_FuncRecord*)(((char*)funcrecord) + size);
9692 varrecord = (MSFT_VarRecord*)funcrecord;
9693 for(i = 0; i < info->typeattr.cVars; ++i){
9694 TLBVarDesc *desc = &info->vardescs[i];
9695 DWORD size = 5 * sizeof(INT);
9697 varrecord->vardescsize = sizeof(desc->vardesc);
9698 varrecord->DataType = WMSFT_append_typedesc(&desc->vardesc.elemdescVar.tdesc, file, NULL, &varrecord->vardescsize);
9699 varrecord->Flags = desc->vardesc.wVarFlags;
9700 varrecord->VarKind = desc->vardesc.varkind;
9702 if(desc->vardesc.varkind == VAR_CONST){
9703 varrecord->vardescsize += sizeof(VARIANT);
9704 varrecord->OffsValue = WMSFT_encode_variant(desc->vardesc.u.lpvarValue, file);
9705 }else
9706 varrecord->OffsValue = desc->vardesc.u.oInst;
9708 /* res9? */
9709 if(desc->HelpStringContext != 0){
9710 size += 5 * sizeof(INT);
9711 varrecord->HelpContext = desc->HelpContext;
9712 if(desc->HelpString)
9713 varrecord->HelpString = desc->HelpString->offset;
9714 else
9715 varrecord->HelpString = -1;
9716 varrecord->res9 = -1;
9717 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9718 varrecord->HelpStringContext = desc->HelpStringContext;
9719 }else if(!list_empty(&desc->custdata_list)){
9720 size += 4 * sizeof(INT);
9721 varrecord->HelpContext = desc->HelpContext;
9722 if(desc->HelpString)
9723 varrecord->HelpString = desc->HelpString->offset;
9724 else
9725 varrecord->HelpString = -1;
9726 varrecord->res9 = -1;
9727 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9728 }else if(desc->HelpString){
9729 size += 2 * sizeof(INT);
9730 varrecord->HelpContext = desc->HelpContext;
9731 if(desc->HelpString)
9732 varrecord->HelpString = desc->HelpString->offset;
9733 else
9734 varrecord->HelpString = -1;
9735 }else if(desc->HelpContext != 0){
9736 size += sizeof(INT);
9737 varrecord->HelpContext = desc->HelpContext;
9740 varrecord->Info = size | (i << 16);
9742 *offsets = offs;
9743 offs += size;
9744 ++offsets;
9746 varrecord = (MSFT_VarRecord*)(((char*)varrecord) + size);
9749 memid = (MEMBERID*)varrecord;
9750 for(i = 0; i < info->typeattr.cFuncs; ++i){
9751 TLBFuncDesc *desc = &info->funcdescs[i];
9752 *memid = desc->funcdesc.memid;
9753 ++memid;
9755 for(i = 0; i < info->typeattr.cVars; ++i){
9756 TLBVarDesc *desc = &info->vardescs[i];
9757 *memid = desc->vardesc.memid;
9758 ++memid;
9761 name = (UINT*)memid;
9762 for(i = 0; i < info->typeattr.cFuncs; ++i){
9763 TLBFuncDesc *desc = &info->funcdescs[i];
9764 if(desc->Name)
9765 *name = desc->Name->offset;
9766 else
9767 *name = -1;
9768 ++name;
9770 for(i = 0; i < info->typeattr.cVars; ++i){
9771 TLBVarDesc *desc = &info->vardescs[i];
9772 if(desc->Name)
9773 *name = desc->Name->offset;
9774 else
9775 *name = -1;
9776 ++name;
9779 return ret;
9782 typedef struct tagWMSFT_RefChunk {
9783 DWORD href;
9784 DWORD res04;
9785 DWORD res08;
9786 DWORD next;
9787 } WMSFT_RefChunk;
9789 static DWORD WMSFT_compile_typeinfo_ref(ITypeInfoImpl *info, WMSFT_TLBFile *file)
9791 DWORD offs = file->ref_seg.len, i;
9792 WMSFT_RefChunk *chunk;
9794 file->ref_seg.len += info->typeattr.cImplTypes * sizeof(WMSFT_RefChunk);
9795 if(!file->ref_seg.data)
9796 file->ref_seg.data = heap_alloc(file->ref_seg.len);
9797 else
9798 file->ref_seg.data = heap_realloc(file->ref_seg.data, file->ref_seg.len);
9800 chunk = (WMSFT_RefChunk*)((char*)file->ref_seg.data + offs);
9802 for(i = 0; i < info->typeattr.cImplTypes; ++i){
9803 chunk->href = info->impltypes[i].hRef;
9804 chunk->res04 = info->impltypes[i].implflags;
9805 chunk->res08 = -1;
9806 if(i < info->typeattr.cImplTypes - 1)
9807 chunk->next = offs + sizeof(WMSFT_RefChunk) * (i + 1);
9808 else
9809 chunk->next = -1;
9810 ++chunk;
9813 return offs;
9816 static DWORD WMSFT_compile_typeinfo(ITypeInfoImpl *info, INT16 index, WMSFT_TLBFile *file, char *data)
9818 DWORD size;
9820 size = sizeof(MSFT_TypeInfoBase);
9822 if(data){
9823 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase*)data;
9824 if(info->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
9825 base->typekind = TKIND_DISPATCH;
9826 else
9827 base->typekind = info->typeattr.typekind;
9828 base->typekind |= index << 16; /* TODO: There are some other flags here */
9829 base->typekind |= (info->typeattr.cbAlignment << 11) | (info->typeattr.cbAlignment << 6);
9830 base->memoffset = WMSFT_compile_typeinfo_aux(info, file);
9831 base->res2 = 0;
9832 base->res3 = 0;
9833 base->res4 = 3;
9834 base->res5 = 0;
9835 base->cElement = (info->typeattr.cVars << 16) | info->typeattr.cFuncs;
9836 base->res7 = 0;
9837 base->res8 = 0;
9838 base->res9 = 0;
9839 base->resA = 0;
9840 if(info->guid)
9841 base->posguid = info->guid->offset;
9842 else
9843 base->posguid = -1;
9844 base->flags = info->typeattr.wTypeFlags;
9845 if(info->Name) {
9846 base->NameOffset = info->Name->offset;
9848 ((unsigned char*)file->name_seg.data)[info->Name->offset+9] = 0x38;
9849 *(HREFTYPE*)((unsigned char*)file->name_seg.data+info->Name->offset) = info->hreftype;
9850 }else {
9851 base->NameOffset = -1;
9853 base->version = (info->typeattr.wMinorVerNum << 16) | info->typeattr.wMajorVerNum;
9854 if(info->DocString)
9855 base->docstringoffs = info->DocString->offset;
9856 else
9857 base->docstringoffs = -1;
9858 base->helpstringcontext = info->dwHelpStringContext;
9859 base->helpcontext = info->dwHelpContext;
9860 base->oCustData = WMSFT_compile_custdata(info->pcustdata_list, file);
9861 base->cImplTypes = info->typeattr.cImplTypes;
9862 base->cbSizeVft = info->typeattr.cbSizeVft;
9863 base->size = info->typeattr.cbSizeInstance;
9864 if(info->typeattr.typekind == TKIND_COCLASS){
9865 base->datatype1 = WMSFT_compile_typeinfo_ref(info, file);
9866 }else if(info->typeattr.typekind == TKIND_ALIAS){
9867 base->datatype1 = WMSFT_append_typedesc(info->tdescAlias, file, NULL, NULL);
9868 }else if(info->typeattr.typekind == TKIND_MODULE){
9869 if(info->DllName)
9870 base->datatype1 = info->DllName->offset;
9871 else
9872 base->datatype1 = -1;
9873 }else{
9874 if(info->typeattr.cImplTypes > 0)
9875 base->datatype1 = info->impltypes[0].hRef;
9876 else
9877 base->datatype1 = -1;
9879 base->datatype2 = index; /* FIXME: i think there's more here */
9880 base->res18 = 0;
9881 base->res19 = -1;
9884 return size;
9887 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl *This, WMSFT_TLBFile *file, DWORD *junk)
9889 UINT i;
9891 file->typeinfo_seg.len = 0;
9892 for(i = 0; i < This->TypeInfoCount; ++i){
9893 ITypeInfoImpl *info = This->typeinfos[i];
9894 *junk = file->typeinfo_seg.len;
9895 ++junk;
9896 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, NULL, NULL);
9899 file->typeinfo_seg.data = heap_alloc(file->typeinfo_seg.len);
9900 memset(file->typeinfo_seg.data, 0x96, file->typeinfo_seg.len);
9902 file->aux_seg.len = 0;
9903 file->aux_seg.data = NULL;
9905 file->typeinfo_seg.len = 0;
9906 for(i = 0; i < This->TypeInfoCount; ++i){
9907 ITypeInfoImpl *info = This->typeinfos[i];
9908 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, file,
9909 ((char *)file->typeinfo_seg.data) + file->typeinfo_seg.len);
9913 typedef struct tagWMSFT_ImpFile {
9914 INT guid_offs;
9915 LCID lcid;
9916 DWORD version;
9917 } WMSFT_ImpFile;
9919 static void WMSFT_compile_impfile(ITypeLibImpl *This, WMSFT_TLBFile *file)
9921 TLBImpLib *implib;
9922 WMSFT_ImpFile *impfile;
9923 char *data;
9924 DWORD last_offs = 0;
9926 file->impfile_seg.len = 0;
9927 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9928 int size = 0;
9930 if(implib->name){
9931 WCHAR *path = wcsrchr(implib->name, '\\');
9932 if(path)
9933 ++path;
9934 else
9935 path = implib->name;
9936 size = WideCharToMultiByte(CP_ACP, 0, path, lstrlenW(path), NULL, 0, NULL, NULL);
9937 if (size == 0)
9938 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9941 size += sizeof(INT16);
9942 if (size % 4)
9943 size = (size + 4) & ~0x3;
9944 if (size < 8)
9945 size = 8;
9947 file->impfile_seg.len += sizeof(WMSFT_ImpFile) + size;
9950 data = file->impfile_seg.data = heap_alloc(file->impfile_seg.len);
9952 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9953 int strlen = 0, size;
9955 impfile = (WMSFT_ImpFile*)data;
9956 impfile->guid_offs = implib->guid->offset;
9957 impfile->lcid = implib->lcid;
9958 impfile->version = (implib->wVersionMinor << 16) | implib->wVersionMajor;
9960 data += sizeof(WMSFT_ImpFile);
9962 if(implib->name){
9963 WCHAR *path= wcsrchr(implib->name, '\\');
9964 if(path)
9965 ++path;
9966 else
9967 path = implib->name;
9968 strlen = WideCharToMultiByte(CP_ACP, 0, path, lstrlenW(path),
9969 data + sizeof(INT16), file->impfile_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9970 if (strlen == 0)
9971 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9974 *((INT16*)data) = (strlen << 2) | 1; /* FIXME: is that a flag, or what? */
9976 size = strlen + sizeof(INT16);
9977 if (size % 4)
9978 size = (size + 4) & ~0x3;
9979 if (size < 8)
9980 size = 8;
9981 memset(data + sizeof(INT16) + strlen, 0x57, size - strlen - sizeof(INT16));
9983 data += size;
9984 implib->offset = last_offs;
9985 last_offs += size + sizeof(WMSFT_ImpFile);
9989 static void WMSFT_compile_impinfo(ITypeLibImpl *This, WMSFT_TLBFile *file)
9991 MSFT_ImpInfo *info;
9992 TLBRefType *ref_type;
9993 UINT i = 0;
9995 WMSFT_compile_impfile(This, file);
9997 file->impinfo_seg.len = sizeof(MSFT_ImpInfo) * list_count(&This->ref_list);
9998 info = file->impinfo_seg.data = heap_alloc(file->impinfo_seg.len);
10000 LIST_FOR_EACH_ENTRY(ref_type, &This->ref_list, TLBRefType, entry){
10001 info->flags = i | ((ref_type->tkind & 0xFF) << 24);
10002 if(ref_type->index == TLB_REF_USE_GUID){
10003 info->flags |= MSFT_IMPINFO_OFFSET_IS_GUID;
10004 info->oGuid = ref_type->guid->offset;
10005 }else
10006 info->oGuid = ref_type->index;
10007 info->oImpFile = ref_type->pImpTLInfo->offset;
10008 ++i;
10009 ++info;
10013 static void WMSFT_compile_guidhash(ITypeLibImpl *This, WMSFT_TLBFile *file)
10015 file->guidhash_seg.len = 0x80;
10016 file->guidhash_seg.data = heap_alloc(file->guidhash_seg.len);
10017 memset(file->guidhash_seg.data, 0xFF, file->guidhash_seg.len);
10020 static void WMSFT_compile_namehash(ITypeLibImpl *This, WMSFT_TLBFile *file)
10022 file->namehash_seg.len = 0x200;
10023 file->namehash_seg.data = heap_alloc(file->namehash_seg.len);
10024 memset(file->namehash_seg.data, 0xFF, file->namehash_seg.len);
10027 static void tmp_fill_segdir_seg(MSFT_pSeg *segdir, WMSFT_SegContents *contents, DWORD *running_offset)
10029 if(contents && contents->len){
10030 segdir->offset = *running_offset;
10031 segdir->length = contents->len;
10032 *running_offset += segdir->length;
10033 }else{
10034 segdir->offset = -1;
10035 segdir->length = 0;
10038 /* TODO: do these ever change? */
10039 segdir->res08 = -1;
10040 segdir->res0c = 0xf;
10043 static void WMSFT_write_segment(HANDLE outfile, WMSFT_SegContents *segment)
10045 DWORD written;
10046 if(segment)
10047 WriteFile(outfile, segment->data, segment->len, &written, NULL);
10050 static HRESULT WMSFT_fixup_typeinfos(ITypeLibImpl *This, WMSFT_TLBFile *file,
10051 DWORD file_len)
10053 DWORD i;
10054 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase *)file->typeinfo_seg.data;
10056 for(i = 0; i < This->TypeInfoCount; ++i){
10057 base->memoffset += file_len;
10058 ++base;
10061 return S_OK;
10064 static void WMSFT_free_file(WMSFT_TLBFile *file)
10066 HeapFree(GetProcessHeap(), 0, file->typeinfo_seg.data);
10067 HeapFree(GetProcessHeap(), 0, file->guidhash_seg.data);
10068 HeapFree(GetProcessHeap(), 0, file->guid_seg.data);
10069 HeapFree(GetProcessHeap(), 0, file->ref_seg.data);
10070 HeapFree(GetProcessHeap(), 0, file->impinfo_seg.data);
10071 HeapFree(GetProcessHeap(), 0, file->impfile_seg.data);
10072 HeapFree(GetProcessHeap(), 0, file->namehash_seg.data);
10073 HeapFree(GetProcessHeap(), 0, file->name_seg.data);
10074 HeapFree(GetProcessHeap(), 0, file->string_seg.data);
10075 HeapFree(GetProcessHeap(), 0, file->typdesc_seg.data);
10076 HeapFree(GetProcessHeap(), 0, file->arraydesc_seg.data);
10077 HeapFree(GetProcessHeap(), 0, file->custdata_seg.data);
10078 HeapFree(GetProcessHeap(), 0, file->cdguids_seg.data);
10079 HeapFree(GetProcessHeap(), 0, file->aux_seg.data);
10082 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
10084 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10085 WMSFT_TLBFile file;
10086 DWORD written, junk_size, junk_offs, running_offset;
10087 BOOL br;
10088 HANDLE outfile;
10089 HRESULT hres;
10090 DWORD *junk;
10091 UINT i;
10093 TRACE("%p\n", This);
10095 for(i = 0; i < This->TypeInfoCount; ++i)
10096 if(This->typeinfos[i]->needs_layout)
10097 ICreateTypeInfo2_LayOut(&This->typeinfos[i]->ICreateTypeInfo2_iface);
10099 memset(&file, 0, sizeof(file));
10101 file.header.magic1 = 0x5446534D;
10102 file.header.magic2 = 0x00010002;
10103 file.header.lcid = This->set_lcid ? This->set_lcid : MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
10104 file.header.lcid2 = This->set_lcid;
10105 file.header.varflags = 0x40 | This->syskind;
10106 if (This->HelpFile)
10107 file.header.varflags |= 0x10;
10108 if (This->HelpStringDll)
10109 file.header.varflags |= HELPDLLFLAG;
10110 file.header.version = (This->ver_minor << 16) | This->ver_major;
10111 file.header.flags = This->libflags;
10112 file.header.helpstringcontext = 0; /* TODO - SetHelpStringContext not implemented yet */
10113 file.header.helpcontext = This->dwHelpContext;
10114 file.header.res44 = 0x20;
10115 file.header.res48 = 0x80;
10116 file.header.dispatchpos = This->dispatch_href;
10118 WMSFT_compile_namehash(This, &file);
10119 /* do name and string compilation to get offsets for other compilations */
10120 hres = WMSFT_compile_names(This, &file);
10121 if (FAILED(hres)){
10122 WMSFT_free_file(&file);
10123 return hres;
10126 hres = WMSFT_compile_strings(This, &file);
10127 if (FAILED(hres)){
10128 WMSFT_free_file(&file);
10129 return hres;
10132 WMSFT_compile_guidhash(This, &file);
10133 hres = WMSFT_compile_guids(This, &file);
10134 if (FAILED(hres)){
10135 WMSFT_free_file(&file);
10136 return hres;
10139 if(This->HelpFile)
10140 file.header.helpfile = This->HelpFile->offset;
10141 else
10142 file.header.helpfile = -1;
10144 if(This->DocString)
10145 file.header.helpstring = This->DocString->offset;
10146 else
10147 file.header.helpstring = -1;
10149 /* do some more segment compilation */
10150 file.header.nimpinfos = list_count(&This->ref_list);
10151 file.header.nrtypeinfos = This->TypeInfoCount;
10153 if(This->Name)
10154 file.header.NameOffset = This->Name->offset;
10155 else
10156 file.header.NameOffset = -1;
10158 file.header.CustomDataOffset = WMSFT_compile_custdata(&This->custdata_list, &file);
10160 if(This->guid)
10161 file.header.posguid = This->guid->offset;
10162 else
10163 file.header.posguid = -1;
10165 junk_size = file.header.nrtypeinfos * sizeof(DWORD);
10166 if(file.header.varflags & HELPDLLFLAG)
10167 junk_size += sizeof(DWORD);
10168 if(junk_size){
10169 junk = heap_alloc_zero(junk_size);
10170 if(file.header.varflags & HELPDLLFLAG){
10171 *junk = This->HelpStringDll->offset;
10172 junk_offs = 1;
10173 }else
10174 junk_offs = 0;
10175 }else{
10176 junk = NULL;
10177 junk_offs = 0;
10180 WMSFT_compile_typeinfo_seg(This, &file, junk + junk_offs);
10181 WMSFT_compile_impinfo(This, &file);
10183 running_offset = 0;
10185 TRACE("header at: 0x%x\n", running_offset);
10186 running_offset += sizeof(file.header);
10188 TRACE("junk at: 0x%x\n", running_offset);
10189 running_offset += junk_size;
10191 TRACE("segdir at: 0x%x\n", running_offset);
10192 running_offset += sizeof(file.segdir);
10194 TRACE("typeinfo at: 0x%x\n", running_offset);
10195 tmp_fill_segdir_seg(&file.segdir.pTypeInfoTab, &file.typeinfo_seg, &running_offset);
10197 TRACE("guidhashtab at: 0x%x\n", running_offset);
10198 tmp_fill_segdir_seg(&file.segdir.pGuidHashTab, &file.guidhash_seg, &running_offset);
10200 TRACE("guidtab at: 0x%x\n", running_offset);
10201 tmp_fill_segdir_seg(&file.segdir.pGuidTab, &file.guid_seg, &running_offset);
10203 TRACE("reftab at: 0x%x\n", running_offset);
10204 tmp_fill_segdir_seg(&file.segdir.pRefTab, &file.ref_seg, &running_offset);
10206 TRACE("impinfo at: 0x%x\n", running_offset);
10207 tmp_fill_segdir_seg(&file.segdir.pImpInfo, &file.impinfo_seg, &running_offset);
10209 TRACE("impfiles at: 0x%x\n", running_offset);
10210 tmp_fill_segdir_seg(&file.segdir.pImpFiles, &file.impfile_seg, &running_offset);
10212 TRACE("namehashtab at: 0x%x\n", running_offset);
10213 tmp_fill_segdir_seg(&file.segdir.pNameHashTab, &file.namehash_seg, &running_offset);
10215 TRACE("nametab at: 0x%x\n", running_offset);
10216 tmp_fill_segdir_seg(&file.segdir.pNametab, &file.name_seg, &running_offset);
10218 TRACE("stringtab at: 0x%x\n", running_offset);
10219 tmp_fill_segdir_seg(&file.segdir.pStringtab, &file.string_seg, &running_offset);
10221 TRACE("typdesc at: 0x%x\n", running_offset);
10222 tmp_fill_segdir_seg(&file.segdir.pTypdescTab, &file.typdesc_seg, &running_offset);
10224 TRACE("arraydescriptions at: 0x%x\n", running_offset);
10225 tmp_fill_segdir_seg(&file.segdir.pArrayDescriptions, &file.arraydesc_seg, &running_offset);
10227 TRACE("custdata at: 0x%x\n", running_offset);
10228 tmp_fill_segdir_seg(&file.segdir.pCustData, &file.custdata_seg, &running_offset);
10230 TRACE("cdguids at: 0x%x\n", running_offset);
10231 tmp_fill_segdir_seg(&file.segdir.pCDGuids, &file.cdguids_seg, &running_offset);
10233 TRACE("res0e at: 0x%x\n", running_offset);
10234 tmp_fill_segdir_seg(&file.segdir.res0e, NULL, &running_offset);
10236 TRACE("res0f at: 0x%x\n", running_offset);
10237 tmp_fill_segdir_seg(&file.segdir.res0f, NULL, &running_offset);
10239 TRACE("aux_seg at: 0x%x\n", running_offset);
10241 WMSFT_fixup_typeinfos(This, &file, running_offset);
10243 outfile = CreateFileW(This->path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
10244 FILE_ATTRIBUTE_NORMAL, 0);
10245 if (outfile == INVALID_HANDLE_VALUE){
10246 WMSFT_free_file(&file);
10247 heap_free(junk);
10248 return TYPE_E_IOERROR;
10251 br = WriteFile(outfile, &file.header, sizeof(file.header), &written, NULL);
10252 if (!br) {
10253 WMSFT_free_file(&file);
10254 CloseHandle(outfile);
10255 heap_free(junk);
10256 return TYPE_E_IOERROR;
10259 br = WriteFile(outfile, junk, junk_size, &written, NULL);
10260 heap_free(junk);
10261 if (!br) {
10262 WMSFT_free_file(&file);
10263 CloseHandle(outfile);
10264 return TYPE_E_IOERROR;
10267 br = WriteFile(outfile, &file.segdir, sizeof(file.segdir), &written, NULL);
10268 if (!br) {
10269 WMSFT_free_file(&file);
10270 CloseHandle(outfile);
10271 return TYPE_E_IOERROR;
10274 WMSFT_write_segment(outfile, &file.typeinfo_seg);
10275 WMSFT_write_segment(outfile, &file.guidhash_seg);
10276 WMSFT_write_segment(outfile, &file.guid_seg);
10277 WMSFT_write_segment(outfile, &file.ref_seg);
10278 WMSFT_write_segment(outfile, &file.impinfo_seg);
10279 WMSFT_write_segment(outfile, &file.impfile_seg);
10280 WMSFT_write_segment(outfile, &file.namehash_seg);
10281 WMSFT_write_segment(outfile, &file.name_seg);
10282 WMSFT_write_segment(outfile, &file.string_seg);
10283 WMSFT_write_segment(outfile, &file.typdesc_seg);
10284 WMSFT_write_segment(outfile, &file.arraydesc_seg);
10285 WMSFT_write_segment(outfile, &file.custdata_seg);
10286 WMSFT_write_segment(outfile, &file.cdguids_seg);
10287 WMSFT_write_segment(outfile, &file.aux_seg);
10289 WMSFT_free_file(&file);
10291 CloseHandle(outfile);
10293 return S_OK;
10296 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
10297 LPOLESTR name)
10299 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10300 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
10301 return E_NOTIMPL;
10304 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
10305 REFGUID guid, VARIANT *varVal)
10307 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10308 TLBGuid *tlbguid;
10310 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
10312 if (!guid || !varVal)
10313 return E_INVALIDARG;
10315 tlbguid = TLB_append_guid(&This->guid_list, guid, -1);
10317 return TLB_set_custdata(&This->custdata_list, tlbguid, varVal);
10320 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
10321 ULONG helpStringContext)
10323 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10324 FIXME("%p %u - stub\n", This, helpStringContext);
10325 return E_NOTIMPL;
10328 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
10329 LPOLESTR filename)
10331 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10332 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
10334 if (!filename)
10335 return E_INVALIDARG;
10337 This->HelpStringDll = TLB_append_str(&This->string_list, filename);
10339 return S_OK;
10342 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
10343 ICreateTypeLib2_fnQueryInterface,
10344 ICreateTypeLib2_fnAddRef,
10345 ICreateTypeLib2_fnRelease,
10346 ICreateTypeLib2_fnCreateTypeInfo,
10347 ICreateTypeLib2_fnSetName,
10348 ICreateTypeLib2_fnSetVersion,
10349 ICreateTypeLib2_fnSetGuid,
10350 ICreateTypeLib2_fnSetDocString,
10351 ICreateTypeLib2_fnSetHelpFileName,
10352 ICreateTypeLib2_fnSetHelpContext,
10353 ICreateTypeLib2_fnSetLcid,
10354 ICreateTypeLib2_fnSetLibFlags,
10355 ICreateTypeLib2_fnSaveAllChanges,
10356 ICreateTypeLib2_fnDeleteTypeInfo,
10357 ICreateTypeLib2_fnSetCustData,
10358 ICreateTypeLib2_fnSetHelpStringContext,
10359 ICreateTypeLib2_fnSetHelpStringDll
10362 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
10363 REFIID riid, void **object)
10365 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10367 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, object);
10370 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
10372 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10374 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
10377 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
10379 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10381 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
10384 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
10385 REFGUID guid)
10387 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10389 TRACE("%p %s\n", This, debugstr_guid(guid));
10391 This->guid = TLB_append_guid(&This->pTypeLib->guid_list, guid, This->hreftype);
10393 return S_OK;
10396 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
10397 UINT typeFlags)
10399 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10400 WORD old_flags;
10401 HRESULT hres;
10403 TRACE("%p %x\n", This, typeFlags);
10405 if (typeFlags & TYPEFLAG_FDUAL) {
10406 static const WCHAR stdole2tlb[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10407 ITypeLib *stdole;
10408 ITypeInfo *dispatch;
10409 HREFTYPE hreftype;
10410 HRESULT hres;
10412 hres = LoadTypeLib(stdole2tlb, &stdole);
10413 if(FAILED(hres))
10414 return hres;
10416 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
10417 ITypeLib_Release(stdole);
10418 if(FAILED(hres))
10419 return hres;
10421 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
10422 ITypeInfo_Release(dispatch);
10423 if(FAILED(hres))
10424 return hres;
10427 old_flags = This->typeattr.wTypeFlags;
10428 This->typeattr.wTypeFlags = typeFlags;
10430 hres = ICreateTypeInfo2_LayOut(iface);
10431 if (FAILED(hres)) {
10432 This->typeattr.wTypeFlags = old_flags;
10433 return hres;
10436 return S_OK;
10439 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
10440 LPOLESTR doc)
10442 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10444 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
10446 if (!doc)
10447 return E_INVALIDARG;
10449 This->DocString = TLB_append_str(&This->pTypeLib->string_list, doc);
10451 return S_OK;
10454 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
10455 DWORD helpContext)
10457 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10459 TRACE("%p %d\n", This, helpContext);
10461 This->dwHelpContext = helpContext;
10463 return S_OK;
10466 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
10467 WORD majorVerNum, WORD minorVerNum)
10469 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10471 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
10473 This->typeattr.wMajorVerNum = majorVerNum;
10474 This->typeattr.wMinorVerNum = minorVerNum;
10476 return S_OK;
10479 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
10480 ITypeInfo *typeInfo, HREFTYPE *refType)
10482 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10483 UINT index;
10484 ITypeLib *container;
10485 TLBRefType *ref_type;
10486 TLBImpLib *implib;
10487 TYPEATTR *typeattr;
10488 TLIBATTR *libattr;
10489 HRESULT hres;
10491 TRACE("%p %p %p\n", This, typeInfo, refType);
10493 if (!typeInfo || !refType)
10494 return E_INVALIDARG;
10496 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
10497 if (FAILED(hres))
10498 return hres;
10500 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
10501 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
10503 ITypeLib_Release(container);
10505 *refType = target->hreftype;
10507 return S_OK;
10510 hres = ITypeLib_GetLibAttr(container, &libattr);
10511 if (FAILED(hres)) {
10512 ITypeLib_Release(container);
10513 return hres;
10516 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
10517 if(IsEqualGUID(&implib->guid->guid, &libattr->guid) &&
10518 implib->lcid == libattr->lcid &&
10519 implib->wVersionMajor == libattr->wMajorVerNum &&
10520 implib->wVersionMinor == libattr->wMinorVerNum)
10521 break;
10524 if(&implib->entry == &This->pTypeLib->implib_list){
10525 implib = heap_alloc_zero(sizeof(TLBImpLib));
10527 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
10528 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
10529 implib->name = SysAllocString(our_container->path);
10530 }else{
10531 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
10532 libattr->wMinorVerNum, libattr->lcid, &implib->name);
10533 if(FAILED(hres)){
10534 implib->name = NULL;
10535 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres);
10539 implib->guid = TLB_append_guid(&This->pTypeLib->guid_list, &libattr->guid, 2);
10540 implib->lcid = libattr->lcid;
10541 implib->wVersionMajor = libattr->wMajorVerNum;
10542 implib->wVersionMinor = libattr->wMinorVerNum;
10544 list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
10547 ITypeLib_ReleaseTLibAttr(container, libattr);
10548 ITypeLib_Release(container);
10550 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
10551 if (FAILED(hres))
10552 return hres;
10554 index = 0;
10555 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
10556 if(ref_type->index == TLB_REF_USE_GUID &&
10557 IsEqualGUID(&ref_type->guid->guid, &typeattr->guid) &&
10558 ref_type->tkind == typeattr->typekind)
10559 break;
10560 ++index;
10563 if(&ref_type->entry == &This->pTypeLib->ref_list){
10564 ref_type = heap_alloc_zero(sizeof(TLBRefType));
10566 ref_type->tkind = typeattr->typekind;
10567 ref_type->pImpTLInfo = implib;
10568 ref_type->reference = index * sizeof(MSFT_ImpInfo);
10570 ref_type->index = TLB_REF_USE_GUID;
10572 ref_type->guid = TLB_append_guid(&This->pTypeLib->guid_list, &typeattr->guid, ref_type->reference+1);
10574 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
10577 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
10579 *refType = ref_type->reference | 0x1;
10581 if(IsEqualGUID(&ref_type->guid->guid, &IID_IDispatch))
10582 This->pTypeLib->dispatch_href = *refType;
10584 return S_OK;
10587 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
10588 UINT index, FUNCDESC *funcDesc)
10590 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10591 TLBFuncDesc tmp_func_desc, *func_desc;
10592 int buf_size, i;
10593 char *buffer;
10594 HRESULT hres;
10596 TRACE("%p %u %p\n", This, index, funcDesc);
10598 if (!funcDesc || funcDesc->oVft & 3)
10599 return E_INVALIDARG;
10601 switch (This->typeattr.typekind) {
10602 case TKIND_MODULE:
10603 if (funcDesc->funckind != FUNC_STATIC)
10604 return TYPE_E_BADMODULEKIND;
10605 break;
10606 case TKIND_DISPATCH:
10607 if (funcDesc->funckind != FUNC_DISPATCH)
10608 return TYPE_E_BADMODULEKIND;
10609 break;
10610 default:
10611 if (funcDesc->funckind != FUNC_PUREVIRTUAL)
10612 return TYPE_E_BADMODULEKIND;
10615 if (index > This->typeattr.cFuncs)
10616 return TYPE_E_ELEMENTNOTFOUND;
10618 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) &&
10619 !funcDesc->cParams)
10620 return TYPE_E_INCONSISTENTPROPFUNCS;
10622 #ifdef _WIN64
10623 if(This->pTypeLib->syskind == SYS_WIN64 &&
10624 funcDesc->oVft % 8 != 0)
10625 return E_INVALIDARG;
10626 #endif
10628 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc));
10629 TLBFuncDesc_Constructor(&tmp_func_desc);
10631 tmp_func_desc.funcdesc = *funcDesc;
10633 if (tmp_func_desc.funcdesc.oVft != 0)
10634 tmp_func_desc.funcdesc.oVft |= 1;
10636 if (funcDesc->cScodes && funcDesc->lprgscode) {
10637 tmp_func_desc.funcdesc.lprgscode = heap_alloc(sizeof(SCODE) * funcDesc->cScodes);
10638 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes);
10639 } else {
10640 tmp_func_desc.funcdesc.lprgscode = NULL;
10641 tmp_func_desc.funcdesc.cScodes = 0;
10644 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc);
10645 for (i = 0; i < funcDesc->cParams; ++i) {
10646 buf_size += sizeof(ELEMDESC);
10647 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i);
10649 tmp_func_desc.funcdesc.lprgelemdescParam = heap_alloc(buf_size);
10650 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams);
10652 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer);
10653 if (FAILED(hres)) {
10654 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10655 heap_free(tmp_func_desc.funcdesc.lprgscode);
10656 return hres;
10659 for (i = 0; i < funcDesc->cParams; ++i) {
10660 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i,
10661 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer);
10662 if (FAILED(hres)) {
10663 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10664 heap_free(tmp_func_desc.funcdesc.lprgscode);
10665 return hres;
10667 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT &&
10668 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT &&
10669 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){
10670 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
10671 if (FAILED(hres)) {
10672 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10673 heap_free(tmp_func_desc.funcdesc.lprgscode);
10674 return hres;
10679 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams);
10681 if (This->funcdescs) {
10682 This->funcdescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->funcdescs,
10683 sizeof(TLBFuncDesc) * (This->typeattr.cFuncs + 1));
10685 if (index < This->typeattr.cFuncs) {
10686 memmove(This->funcdescs + index + 1, This->funcdescs + index,
10687 (This->typeattr.cFuncs - index) * sizeof(TLBFuncDesc));
10688 func_desc = This->funcdescs + index;
10689 } else
10690 func_desc = This->funcdescs + This->typeattr.cFuncs;
10692 /* move custdata lists to the new memory location */
10693 for(i = 0; i < This->typeattr.cFuncs + 1; ++i){
10694 if(index != i){
10695 TLBFuncDesc *fd = &This->funcdescs[i];
10696 if(fd->custdata_list.prev == fd->custdata_list.next)
10697 list_init(&fd->custdata_list);
10698 else{
10699 fd->custdata_list.prev->next = &fd->custdata_list;
10700 fd->custdata_list.next->prev = &fd->custdata_list;
10704 } else
10705 func_desc = This->funcdescs = heap_alloc(sizeof(TLBFuncDesc));
10707 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc));
10708 list_init(&func_desc->custdata_list);
10710 ++This->typeattr.cFuncs;
10712 This->needs_layout = TRUE;
10714 return S_OK;
10717 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
10718 UINT index, HREFTYPE refType)
10720 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10721 TLBImplType *impl_type;
10722 HRESULT hres;
10724 TRACE("%p %u %d\n", This, index, refType);
10726 switch(This->typeattr.typekind){
10727 case TKIND_COCLASS: {
10728 if (index == -1) {
10729 FIXME("Unhandled index: -1\n");
10730 return E_NOTIMPL;
10733 if(index != This->typeattr.cImplTypes)
10734 return TYPE_E_ELEMENTNOTFOUND;
10736 break;
10738 case TKIND_INTERFACE:
10739 case TKIND_DISPATCH:
10740 if (index != 0 || This->typeattr.cImplTypes)
10741 return TYPE_E_ELEMENTNOTFOUND;
10742 break;
10743 default:
10744 FIXME("Unimplemented typekind: %d\n", This->typeattr.typekind);
10745 return E_NOTIMPL;
10748 if (This->impltypes){
10749 UINT i;
10751 This->impltypes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->impltypes,
10752 sizeof(TLBImplType) * (This->typeattr.cImplTypes + 1));
10754 if (index < This->typeattr.cImplTypes) {
10755 memmove(This->impltypes + index + 1, This->impltypes + index,
10756 (This->typeattr.cImplTypes - index) * sizeof(TLBImplType));
10757 impl_type = This->impltypes + index;
10758 } else
10759 impl_type = This->impltypes + This->typeattr.cImplTypes;
10761 /* move custdata lists to the new memory location */
10762 for(i = 0; i < This->typeattr.cImplTypes + 1; ++i){
10763 if(index != i){
10764 TLBImplType *it = &This->impltypes[i];
10765 if(it->custdata_list.prev == it->custdata_list.next)
10766 list_init(&it->custdata_list);
10767 else{
10768 it->custdata_list.prev->next = &it->custdata_list;
10769 it->custdata_list.next->prev = &it->custdata_list;
10773 } else
10774 impl_type = This->impltypes = heap_alloc(sizeof(TLBImplType));
10776 memset(impl_type, 0, sizeof(TLBImplType));
10777 TLBImplType_Constructor(impl_type);
10778 impl_type->hRef = refType;
10780 ++This->typeattr.cImplTypes;
10782 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
10783 This->typeattr.wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
10785 hres = ICreateTypeInfo2_LayOut(iface);
10786 if (FAILED(hres))
10787 return hres;
10789 return S_OK;
10792 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
10793 UINT index, INT implTypeFlags)
10795 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10796 TLBImplType *impl_type = &This->impltypes[index];
10798 TRACE("%p %u %x\n", This, index, implTypeFlags);
10800 if (This->typeattr.typekind != TKIND_COCLASS)
10801 return TYPE_E_BADMODULEKIND;
10803 if (index >= This->typeattr.cImplTypes)
10804 return TYPE_E_ELEMENTNOTFOUND;
10806 impl_type->implflags = implTypeFlags;
10808 return S_OK;
10811 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
10812 WORD alignment)
10814 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10816 TRACE("%p %d\n", This, alignment);
10818 This->typeattr.cbAlignment = alignment;
10820 return S_OK;
10823 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
10824 LPOLESTR schema)
10826 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10828 TRACE("%p %s\n", This, wine_dbgstr_w(schema));
10830 if (!schema)
10831 return E_INVALIDARG;
10833 This->Schema = TLB_append_str(&This->pTypeLib->string_list, schema);
10835 This->typeattr.lpstrSchema = This->Schema->str;
10837 return S_OK;
10840 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
10841 UINT index, VARDESC *varDesc)
10843 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10844 TLBVarDesc *var_desc;
10846 TRACE("%p %u %p\n", This, index, varDesc);
10848 if (This->vardescs){
10849 UINT i;
10851 This->vardescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->vardescs,
10852 sizeof(TLBVarDesc) * (This->typeattr.cVars + 1));
10854 if (index < This->typeattr.cVars) {
10855 memmove(This->vardescs + index + 1, This->vardescs + index,
10856 (This->typeattr.cVars - index) * sizeof(TLBVarDesc));
10857 var_desc = This->vardescs + index;
10858 } else
10859 var_desc = This->vardescs + This->typeattr.cVars;
10861 /* move custdata lists to the new memory location */
10862 for(i = 0; i < This->typeattr.cVars + 1; ++i){
10863 if(index != i){
10864 TLBVarDesc *var = &This->vardescs[i];
10865 if(var->custdata_list.prev == var->custdata_list.next)
10866 list_init(&var->custdata_list);
10867 else{
10868 var->custdata_list.prev->next = &var->custdata_list;
10869 var->custdata_list.next->prev = &var->custdata_list;
10873 } else
10874 var_desc = This->vardescs = heap_alloc_zero(sizeof(TLBVarDesc));
10876 TLBVarDesc_Constructor(var_desc);
10877 TLB_AllocAndInitVarDesc(varDesc, &var_desc->vardesc_create);
10878 var_desc->vardesc = *var_desc->vardesc_create;
10880 ++This->typeattr.cVars;
10882 This->needs_layout = TRUE;
10884 return S_OK;
10887 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
10888 UINT index, LPOLESTR *names, UINT numNames)
10890 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10891 TLBFuncDesc *func_desc = &This->funcdescs[index];
10892 int i;
10894 TRACE("%p %u %p %u\n", This, index, names, numNames);
10896 if (!names)
10897 return E_INVALIDARG;
10899 if (index >= This->typeattr.cFuncs || numNames == 0)
10900 return TYPE_E_ELEMENTNOTFOUND;
10902 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){
10903 if(numNames > func_desc->funcdesc.cParams)
10904 return TYPE_E_ELEMENTNOTFOUND;
10905 } else
10906 if(numNames > func_desc->funcdesc.cParams + 1)
10907 return TYPE_E_ELEMENTNOTFOUND;
10909 for(i = 0; i < This->typeattr.cFuncs; ++i) {
10910 TLBFuncDesc *iter = &This->funcdescs[i];
10911 if (iter->Name && !wcscmp(TLB_get_bstr(iter->Name), *names)) {
10912 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10913 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10914 func_desc->funcdesc.invkind != iter->funcdesc.invkind)
10915 continue;
10916 return TYPE_E_AMBIGUOUSNAME;
10920 func_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *names);
10922 for (i = 1; i < numNames; ++i) {
10923 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1;
10924 par_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *(names + i));
10927 return S_OK;
10930 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
10931 UINT index, LPOLESTR name)
10933 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10935 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(name));
10937 if(!name)
10938 return E_INVALIDARG;
10940 if(index >= This->typeattr.cVars)
10941 return TYPE_E_ELEMENTNOTFOUND;
10943 This->vardescs[index].Name = TLB_append_str(&This->pTypeLib->name_list, name);
10944 return S_OK;
10947 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
10948 TYPEDESC *tdescAlias)
10950 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10951 HRESULT hr;
10953 TRACE("%p %p\n", This, tdescAlias);
10955 if(!tdescAlias)
10956 return E_INVALIDARG;
10958 if(This->typeattr.typekind != TKIND_ALIAS)
10959 return TYPE_E_BADMODULEKIND;
10961 hr = TLB_size_instance(This, This->pTypeLib->syskind, tdescAlias, &This->typeattr.cbSizeInstance, &This->typeattr.cbAlignment);
10962 if(FAILED(hr))
10963 return hr;
10965 heap_free(This->tdescAlias);
10966 This->tdescAlias = heap_alloc(TLB_SizeTypeDesc(tdescAlias, TRUE));
10967 TLB_CopyTypeDesc(NULL, tdescAlias, This->tdescAlias);
10969 return S_OK;
10972 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
10973 UINT index, LPOLESTR dllName, LPOLESTR procName)
10975 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10976 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
10977 return E_NOTIMPL;
10980 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
10981 UINT index, LPOLESTR docString)
10983 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10984 TLBFuncDesc *func_desc = &This->funcdescs[index];
10986 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10988 if(!docString)
10989 return E_INVALIDARG;
10991 if(index >= This->typeattr.cFuncs)
10992 return TYPE_E_ELEMENTNOTFOUND;
10994 func_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10996 return S_OK;
10999 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
11000 UINT index, LPOLESTR docString)
11002 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11003 TLBVarDesc *var_desc = &This->vardescs[index];
11005 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
11007 if(!docString)
11008 return E_INVALIDARG;
11010 if(index >= This->typeattr.cVars)
11011 return TYPE_E_ELEMENTNOTFOUND;
11013 var_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
11015 return S_OK;
11018 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
11019 UINT index, DWORD helpContext)
11021 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11022 TLBFuncDesc *func_desc = &This->funcdescs[index];
11024 TRACE("%p %u %d\n", This, index, helpContext);
11026 if(index >= This->typeattr.cFuncs)
11027 return TYPE_E_ELEMENTNOTFOUND;
11029 func_desc->helpcontext = helpContext;
11031 return S_OK;
11034 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
11035 UINT index, DWORD helpContext)
11037 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11038 TLBVarDesc *var_desc = &This->vardescs[index];
11040 TRACE("%p %u %d\n", This, index, helpContext);
11042 if(index >= This->typeattr.cVars)
11043 return TYPE_E_ELEMENTNOTFOUND;
11045 var_desc->HelpContext = helpContext;
11047 return S_OK;
11050 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
11051 UINT index, BSTR bstrMops)
11053 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11054 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
11055 return E_NOTIMPL;
11058 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
11059 IDLDESC *idlDesc)
11061 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11063 TRACE("%p %p\n", This, idlDesc);
11065 if (!idlDesc)
11066 return E_INVALIDARG;
11068 This->typeattr.idldescType.dwReserved = idlDesc->dwReserved;
11069 This->typeattr.idldescType.wIDLFlags = idlDesc->wIDLFlags;
11071 return S_OK;
11074 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
11076 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11077 ITypeInfo *tinfo;
11078 TLBFuncDesc *func_desc;
11079 UINT user_vft = 0, i, depth = 0;
11080 HRESULT hres = S_OK;
11082 TRACE("%p\n", This);
11084 This->needs_layout = FALSE;
11086 hres = ICreateTypeInfo2_QueryInterface(iface, &IID_ITypeInfo, (LPVOID*)&tinfo);
11087 if (FAILED(hres))
11088 return hres;
11090 if (This->typeattr.typekind == TKIND_INTERFACE) {
11091 ITypeInfo *inh;
11092 TYPEATTR *attr;
11093 HREFTYPE inh_href;
11095 hres = ITypeInfo_GetRefTypeOfImplType(tinfo, 0, &inh_href);
11097 if (SUCCEEDED(hres)) {
11098 hres = ITypeInfo_GetRefTypeInfo(tinfo, inh_href, &inh);
11100 if (SUCCEEDED(hres)) {
11101 hres = ITypeInfo_GetTypeAttr(inh, &attr);
11102 if (FAILED(hres)) {
11103 ITypeInfo_Release(inh);
11104 ITypeInfo_Release(tinfo);
11105 return hres;
11107 This->typeattr.cbSizeVft = attr->cbSizeVft;
11108 ITypeInfo_ReleaseTypeAttr(inh, attr);
11111 ++depth;
11112 hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href);
11113 if(SUCCEEDED(hres)){
11114 ITypeInfo *next;
11115 hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next);
11116 if(SUCCEEDED(hres)){
11117 ITypeInfo_Release(inh);
11118 inh = next;
11121 }while(SUCCEEDED(hres));
11122 hres = S_OK;
11124 ITypeInfo_Release(inh);
11125 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
11126 This->typeattr.cbSizeVft = 0;
11127 hres = S_OK;
11128 } else {
11129 ITypeInfo_Release(tinfo);
11130 return hres;
11132 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
11133 This->typeattr.cbSizeVft = 0;
11134 hres = S_OK;
11135 } else {
11136 ITypeInfo_Release(tinfo);
11137 return hres;
11139 } else if (This->typeattr.typekind == TKIND_DISPATCH)
11140 This->typeattr.cbSizeVft = 7 * This->pTypeLib->ptr_size;
11141 else
11142 This->typeattr.cbSizeVft = 0;
11144 func_desc = This->funcdescs;
11145 i = 0;
11146 while (i < This->typeattr.cFuncs) {
11147 if (!(func_desc->funcdesc.oVft & 0x1))
11148 func_desc->funcdesc.oVft = This->typeattr.cbSizeVft;
11150 if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft)
11151 user_vft = func_desc->funcdesc.oVft & 0xFFFC;
11153 This->typeattr.cbSizeVft += This->pTypeLib->ptr_size;
11155 if (func_desc->funcdesc.memid == MEMBERID_NIL) {
11156 TLBFuncDesc *iter;
11157 UINT j = 0;
11158 BOOL reset = FALSE;
11160 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i;
11162 iter = This->funcdescs;
11163 while (j < This->typeattr.cFuncs) {
11164 if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) {
11165 if (!reset) {
11166 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->typeattr.cFuncs;
11167 reset = TRUE;
11168 } else
11169 ++func_desc->funcdesc.memid;
11170 iter = This->funcdescs;
11171 j = 0;
11172 } else {
11173 ++iter;
11174 ++j;
11179 ++func_desc;
11180 ++i;
11183 if (user_vft > This->typeattr.cbSizeVft)
11184 This->typeattr.cbSizeVft = user_vft + This->pTypeLib->ptr_size;
11186 for(i = 0; i < This->typeattr.cVars; ++i){
11187 TLBVarDesc *var_desc = &This->vardescs[i];
11188 if(var_desc->vardesc.memid == MEMBERID_NIL){
11189 UINT j = 0;
11190 BOOL reset = FALSE;
11191 TLBVarDesc *iter;
11193 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + i;
11195 iter = This->vardescs;
11196 while (j < This->typeattr.cVars) {
11197 if (iter != var_desc && iter->vardesc.memid == var_desc->vardesc.memid) {
11198 if (!reset) {
11199 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + This->typeattr.cVars;
11200 reset = TRUE;
11201 } else
11202 ++var_desc->vardesc.memid;
11203 iter = This->vardescs;
11204 j = 0;
11205 } else {
11206 ++iter;
11207 ++j;
11213 ITypeInfo_Release(tinfo);
11214 return hres;
11217 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
11218 UINT index)
11220 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11221 FIXME("%p %u - stub\n", This, index);
11222 return E_NOTIMPL;
11225 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
11226 MEMBERID memid, INVOKEKIND invKind)
11228 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11229 FIXME("%p %x %d - stub\n", This, memid, invKind);
11230 return E_NOTIMPL;
11233 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
11234 UINT index)
11236 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11237 FIXME("%p %u - stub\n", This, index);
11238 return E_NOTIMPL;
11241 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
11242 MEMBERID memid)
11244 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11245 FIXME("%p %x - stub\n", This, memid);
11246 return E_NOTIMPL;
11249 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
11250 UINT index)
11252 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11253 FIXME("%p %u - stub\n", This, index);
11254 return E_NOTIMPL;
11257 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
11258 REFGUID guid, VARIANT *varVal)
11260 TLBGuid *tlbguid;
11262 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11264 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
11266 if (!guid || !varVal)
11267 return E_INVALIDARG;
11269 tlbguid = TLB_append_guid(&This->pTypeLib->guid_list, guid, -1);
11271 return TLB_set_custdata(This->pcustdata_list, tlbguid, varVal);
11274 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
11275 UINT index, REFGUID guid, VARIANT *varVal)
11277 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11278 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11279 return E_NOTIMPL;
11282 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
11283 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
11285 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11286 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
11287 return E_NOTIMPL;
11290 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
11291 UINT index, REFGUID guid, VARIANT *varVal)
11293 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11294 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11295 return E_NOTIMPL;
11298 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
11299 UINT index, REFGUID guid, VARIANT *varVal)
11301 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11302 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11303 return E_NOTIMPL;
11306 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
11307 ULONG helpStringContext)
11309 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11311 TRACE("%p %u\n", This, helpStringContext);
11313 This->dwHelpStringContext = helpStringContext;
11315 return S_OK;
11318 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
11319 UINT index, ULONG helpStringContext)
11321 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11322 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11323 return E_NOTIMPL;
11326 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
11327 UINT index, ULONG helpStringContext)
11329 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11330 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11331 return E_NOTIMPL;
11334 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
11336 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11337 FIXME("%p - stub\n", This);
11338 return E_NOTIMPL;
11341 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
11342 LPOLESTR name)
11344 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11346 TRACE("%p %s\n", This, wine_dbgstr_w(name));
11348 if (!name)
11349 return E_INVALIDARG;
11351 This->Name = TLB_append_str(&This->pTypeLib->name_list, name);
11353 return S_OK;
11356 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
11357 ICreateTypeInfo2_fnQueryInterface,
11358 ICreateTypeInfo2_fnAddRef,
11359 ICreateTypeInfo2_fnRelease,
11360 ICreateTypeInfo2_fnSetGuid,
11361 ICreateTypeInfo2_fnSetTypeFlags,
11362 ICreateTypeInfo2_fnSetDocString,
11363 ICreateTypeInfo2_fnSetHelpContext,
11364 ICreateTypeInfo2_fnSetVersion,
11365 ICreateTypeInfo2_fnAddRefTypeInfo,
11366 ICreateTypeInfo2_fnAddFuncDesc,
11367 ICreateTypeInfo2_fnAddImplType,
11368 ICreateTypeInfo2_fnSetImplTypeFlags,
11369 ICreateTypeInfo2_fnSetAlignment,
11370 ICreateTypeInfo2_fnSetSchema,
11371 ICreateTypeInfo2_fnAddVarDesc,
11372 ICreateTypeInfo2_fnSetFuncAndParamNames,
11373 ICreateTypeInfo2_fnSetVarName,
11374 ICreateTypeInfo2_fnSetTypeDescAlias,
11375 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
11376 ICreateTypeInfo2_fnSetFuncDocString,
11377 ICreateTypeInfo2_fnSetVarDocString,
11378 ICreateTypeInfo2_fnSetFuncHelpContext,
11379 ICreateTypeInfo2_fnSetVarHelpContext,
11380 ICreateTypeInfo2_fnSetMops,
11381 ICreateTypeInfo2_fnSetTypeIdldesc,
11382 ICreateTypeInfo2_fnLayOut,
11383 ICreateTypeInfo2_fnDeleteFuncDesc,
11384 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
11385 ICreateTypeInfo2_fnDeleteVarDesc,
11386 ICreateTypeInfo2_fnDeleteVarDescByMemId,
11387 ICreateTypeInfo2_fnDeleteImplType,
11388 ICreateTypeInfo2_fnSetCustData,
11389 ICreateTypeInfo2_fnSetFuncCustData,
11390 ICreateTypeInfo2_fnSetParamCustData,
11391 ICreateTypeInfo2_fnSetVarCustData,
11392 ICreateTypeInfo2_fnSetImplTypeCustData,
11393 ICreateTypeInfo2_fnSetHelpStringContext,
11394 ICreateTypeInfo2_fnSetFuncHelpStringContext,
11395 ICreateTypeInfo2_fnSetVarHelpStringContext,
11396 ICreateTypeInfo2_fnInvalidate,
11397 ICreateTypeInfo2_fnSetName
11400 /******************************************************************************
11401 * ClearCustData (OLEAUT32.171)
11403 * Clear a custom data type's data.
11405 * PARAMS
11406 * lpCust [I] The custom data type instance
11408 * RETURNS
11409 * Nothing.
11411 void WINAPI ClearCustData(CUSTDATA *lpCust)
11413 if (lpCust && lpCust->cCustData)
11415 if (lpCust->prgCustData)
11417 DWORD i;
11419 for (i = 0; i < lpCust->cCustData; i++)
11420 VariantClear(&lpCust->prgCustData[i].varValue);
11422 CoTaskMemFree(lpCust->prgCustData);
11423 lpCust->prgCustData = NULL;
11425 lpCust->cCustData = 0;