amstream: Return E_POINTER on NULL stream in IMediaStreamFilter::GetMediaStream().
[wine/zf.git] / dlls / oleaut32 / typelib.c
blob01bb16efbc4aba52ebf8962d6c4794afe42d1fda
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(ITypeLib *ptlib, const WCHAR *szFullPath, const WCHAR *szHelpDir)
648 HRESULT res;
649 TLIBATTR *attr;
650 WCHAR keyName[60];
651 WCHAR tmp[16];
652 HKEY key, subKey;
653 UINT types, tidx;
654 TYPEKIND kind;
655 DWORD disposition;
657 if (ptlib == NULL || szFullPath == NULL)
658 return E_INVALIDARG;
660 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
661 return E_FAIL;
663 #ifndef _WIN64
664 if (attr->syskind == SYS_WIN64) return TYPE_E_BADMODULEKIND;
665 #endif
667 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
669 res = S_OK;
670 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
671 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
673 LPOLESTR doc;
675 /* Set the human-readable name of the typelib */
676 if (FAILED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
677 res = E_FAIL;
678 else if (doc)
680 if (RegSetValueExW(key, NULL, 0, REG_SZ,
681 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
682 res = E_FAIL;
684 SysFreeString(doc);
687 /* Make up the name of the typelib path subkey */
688 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
690 /* Create the typelib path subkey */
691 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
692 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
694 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
695 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
696 res = E_FAIL;
698 RegCloseKey(subKey);
700 else
701 res = E_FAIL;
703 /* Create the flags subkey */
704 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
705 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
707 /* FIXME: is %u correct? */
708 static const WCHAR formatW[] = {'%','u',0};
709 WCHAR buf[20];
710 swprintf(buf, ARRAY_SIZE(buf), formatW, attr->wLibFlags);
711 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
712 (BYTE *)buf, (lstrlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
713 res = E_FAIL;
715 RegCloseKey(subKey);
717 else
718 res = E_FAIL;
720 /* create the helpdir subkey */
721 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
722 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
724 BSTR freeHelpDir = NULL;
725 WCHAR *file_name;
727 /* if we created a new key, and helpDir was null, set the helpdir
728 to the directory which contains the typelib. However,
729 if we just opened an existing key, we leave the helpdir alone */
730 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
731 szHelpDir = freeHelpDir = SysAllocString(szFullPath);
732 file_name = wcsrchr(szHelpDir, '\\');
733 if (file_name && file_name[0]) {
734 /* possible remove a numeric \index (resource-id) */
735 WCHAR *end_ptr = file_name + 1;
736 while ('0' <= *end_ptr && *end_ptr <= '9') end_ptr++;
737 if (!*end_ptr)
739 *file_name = 0;
740 file_name = wcsrchr(szHelpDir, '\\');
743 if (file_name)
744 *file_name = 0;
747 /* if we have an szHelpDir, set it! */
748 if (szHelpDir != NULL) {
749 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
750 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
751 res = E_FAIL;
755 SysFreeString(freeHelpDir);
756 RegCloseKey(subKey);
757 } else {
758 res = E_FAIL;
761 RegCloseKey(key);
763 else
764 res = E_FAIL;
766 /* register OLE Automation-compatible interfaces for this typelib */
767 types = ITypeLib_GetTypeInfoCount(ptlib);
768 for (tidx=0; tidx<types; tidx++) {
769 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
770 LPOLESTR name = NULL;
771 ITypeInfo *tinfo = NULL;
773 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
775 switch (kind) {
776 case TKIND_INTERFACE:
777 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
778 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
779 break;
781 case TKIND_DISPATCH:
782 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
783 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
784 break;
786 default:
787 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
788 break;
791 if (tinfo) {
792 TYPEATTR *tattr = NULL;
793 ITypeInfo_GetTypeAttr(tinfo, &tattr);
795 if (tattr) {
796 TRACE_(typelib)("guid=%s, flags=%04x (",
797 debugstr_guid(&tattr->guid),
798 tattr->wTypeFlags);
800 if (TRACE_ON(typelib)) {
801 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
802 XX(FAPPOBJECT);
803 XX(FCANCREATE);
804 XX(FLICENSED);
805 XX(FPREDECLID);
806 XX(FHIDDEN);
807 XX(FCONTROL);
808 XX(FDUAL);
809 XX(FNONEXTENSIBLE);
810 XX(FOLEAUTOMATION);
811 XX(FRESTRICTED);
812 XX(FAGGREGATABLE);
813 XX(FREPLACEABLE);
814 XX(FDISPATCHABLE);
815 XX(FREVERSEBIND);
816 XX(FPROXY);
817 #undef XX
818 MESSAGE("\n");
821 /* Register all dispinterfaces (which includes dual interfaces) and
822 oleautomation interfaces */
823 if ((kind == TKIND_INTERFACE && (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
824 kind == TKIND_DISPATCH)
826 BOOL is_wow64;
827 DWORD opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
829 /* register interface<->typelib coupling */
830 TLB_register_interface(attr, name, tattr, 0);
832 /* register TLBs into the opposite registry view, too */
833 if(opposite == KEY_WOW64_32KEY ||
834 (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64))
835 TLB_register_interface(attr, name, tattr, opposite);
838 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
841 ITypeInfo_Release(tinfo);
844 SysFreeString(name);
848 ITypeLib_ReleaseTLibAttr(ptlib, attr);
850 return res;
853 static void TLB_unregister_interface(GUID *guid, REGSAM flag)
855 WCHAR subKeyName[50];
856 HKEY subKey;
858 /* the path to the type */
859 get_interface_key( guid, subKeyName );
861 /* Delete its bits */
862 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE | flag, &subKey) != ERROR_SUCCESS)
863 return;
865 RegDeleteKeyW(subKey, ProxyStubClsidW);
866 RegDeleteKeyW(subKey, ProxyStubClsid32W);
867 RegDeleteKeyW(subKey, TypeLibW);
868 RegCloseKey(subKey);
869 RegDeleteKeyExW(HKEY_CLASSES_ROOT, subKeyName, flag, 0);
872 /******************************************************************************
873 * UnRegisterTypeLib [OLEAUT32.186]
874 * Removes information about a type library from the System Registry
875 * NOTES
877 * RETURNS
878 * Success: S_OK
879 * Failure: Status
881 HRESULT WINAPI UnRegisterTypeLib(
882 REFGUID libid, /* [in] Guid of the library */
883 WORD wVerMajor, /* [in] major version */
884 WORD wVerMinor, /* [in] minor version */
885 LCID lcid, /* [in] locale id */
886 SYSKIND syskind)
888 BSTR tlibPath = NULL;
889 DWORD tmpLength;
890 WCHAR keyName[60];
891 WCHAR subKeyName[50];
892 int result = S_OK;
893 DWORD i = 0;
894 BOOL deleteOtherStuff;
895 HKEY key = NULL;
896 TYPEATTR* typeAttr = NULL;
897 TYPEKIND kind;
898 ITypeInfo* typeInfo = NULL;
899 ITypeLib* typeLib = NULL;
900 int numTypes;
902 TRACE("(IID: %s)\n",debugstr_guid(libid));
904 /* Create the path to the key */
905 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
907 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
909 TRACE("Unsupported syskind %i\n", syskind);
910 result = E_INVALIDARG;
911 goto end;
914 /* get the path to the typelib on disk */
915 if (query_typelib_path(libid, wVerMajor, wVerMinor, syskind, lcid, &tlibPath, FALSE) != S_OK) {
916 result = E_INVALIDARG;
917 goto end;
920 /* Try and open the key to the type library. */
921 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
922 result = E_INVALIDARG;
923 goto end;
926 /* Try and load the type library */
927 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib) != S_OK) {
928 result = TYPE_E_INVALIDSTATE;
929 goto end;
932 /* remove any types registered with this typelib */
933 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
934 for (i=0; i<numTypes; i++) {
935 /* get the kind of type */
936 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
937 goto enddeleteloop;
940 /* skip non-interfaces, and get type info for the type */
941 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
942 goto enddeleteloop;
944 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
945 goto enddeleteloop;
947 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
948 goto enddeleteloop;
951 if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
952 kind == TKIND_DISPATCH)
954 BOOL is_wow64;
955 REGSAM opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
957 TLB_unregister_interface(&typeAttr->guid, 0);
959 /* unregister TLBs into the opposite registry view, too */
960 if(opposite == KEY_WOW64_32KEY ||
961 (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64)) {
962 TLB_unregister_interface(&typeAttr->guid, opposite);
966 enddeleteloop:
967 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
968 typeAttr = NULL;
969 if (typeInfo) ITypeInfo_Release(typeInfo);
970 typeInfo = NULL;
973 /* Now, delete the type library path subkey */
974 get_lcid_subkey( lcid, syskind, subKeyName );
975 RegDeleteKeyW(key, subKeyName);
976 *wcsrchr( subKeyName, '\\' ) = 0; /* remove last path component */
977 RegDeleteKeyW(key, subKeyName);
979 /* check if there is anything besides the FLAGS/HELPDIR keys.
980 If there is, we don't delete them */
981 tmpLength = ARRAY_SIZE(subKeyName);
982 deleteOtherStuff = TRUE;
983 i = 0;
984 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
985 tmpLength = ARRAY_SIZE(subKeyName);
987 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
988 if (!wcscmp(subKeyName, FLAGSW)) continue;
989 if (!wcscmp(subKeyName, HELPDIRW)) continue;
990 deleteOtherStuff = FALSE;
991 break;
994 /* only delete the other parts of the key if we're absolutely sure */
995 if (deleteOtherStuff) {
996 RegDeleteKeyW(key, FLAGSW);
997 RegDeleteKeyW(key, HELPDIRW);
998 RegCloseKey(key);
999 key = NULL;
1001 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
1002 *wcsrchr( keyName, '\\' ) = 0; /* remove last path component */
1003 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
1006 end:
1007 SysFreeString(tlibPath);
1008 if (typeLib) ITypeLib_Release(typeLib);
1009 if (key) RegCloseKey(key);
1010 return result;
1013 /******************************************************************************
1014 * RegisterTypeLibForUser [OLEAUT32.442]
1015 * Adds information about a type library to the user registry
1016 * NOTES
1017 * Docs: ITypeLib FAR * ptlib
1018 * Docs: OLECHAR FAR* szFullPath
1019 * Docs: OLECHAR FAR* szHelpDir
1021 * RETURNS
1022 * Success: S_OK
1023 * Failure: Status
1025 HRESULT WINAPI RegisterTypeLibForUser(
1026 ITypeLib * ptlib, /* [in] Pointer to the library*/
1027 OLECHAR * szFullPath, /* [in] full Path of the library*/
1028 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
1029 may be NULL*/
1031 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib,
1032 debugstr_w(szFullPath), debugstr_w(szHelpDir));
1033 return RegisterTypeLib(ptlib, szFullPath, szHelpDir);
1036 /******************************************************************************
1037 * UnRegisterTypeLibForUser [OLEAUT32.443]
1038 * Removes information about a type library from the user registry
1040 * RETURNS
1041 * Success: S_OK
1042 * Failure: Status
1044 HRESULT WINAPI UnRegisterTypeLibForUser(
1045 REFGUID libid, /* [in] GUID of the library */
1046 WORD wVerMajor, /* [in] major version */
1047 WORD wVerMinor, /* [in] minor version */
1048 LCID lcid, /* [in] locale id */
1049 SYSKIND syskind)
1051 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
1052 debugstr_guid(libid), wVerMajor, wVerMinor, lcid, syskind);
1053 return UnRegisterTypeLib(libid, wVerMajor, wVerMinor, lcid, syskind);
1056 /*======================= ITypeLib implementation =======================*/
1058 typedef struct tagTLBGuid {
1059 GUID guid;
1060 INT hreftype;
1061 UINT offset;
1062 struct list entry;
1063 } TLBGuid;
1065 typedef struct tagTLBCustData
1067 TLBGuid *guid;
1068 VARIANT data;
1069 struct list entry;
1070 } TLBCustData;
1072 /* data structure for import typelibs */
1073 typedef struct tagTLBImpLib
1075 int offset; /* offset in the file (MSFT)
1076 offset in nametable (SLTG)
1077 just used to identify library while reading
1078 data from file */
1079 TLBGuid *guid; /* libid */
1080 BSTR name; /* name */
1082 LCID lcid; /* lcid of imported typelib */
1084 WORD wVersionMajor; /* major version number */
1085 WORD wVersionMinor; /* minor version number */
1087 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
1088 NULL if not yet loaded */
1089 struct list entry;
1090 } TLBImpLib;
1092 typedef struct tagTLBString {
1093 BSTR str;
1094 UINT offset;
1095 struct list entry;
1096 } TLBString;
1098 /* internal ITypeLib data */
1099 typedef struct tagITypeLibImpl
1101 ITypeLib2 ITypeLib2_iface;
1102 ITypeComp ITypeComp_iface;
1103 ICreateTypeLib2 ICreateTypeLib2_iface;
1104 LONG ref;
1105 TLBGuid *guid;
1106 LCID lcid;
1107 SYSKIND syskind;
1108 int ptr_size;
1109 WORD ver_major;
1110 WORD ver_minor;
1111 WORD libflags;
1112 LCID set_lcid;
1114 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1115 * exported to the application as a UNICODE string.
1117 struct list string_list;
1118 struct list name_list;
1119 struct list guid_list;
1121 const TLBString *Name;
1122 const TLBString *DocString;
1123 const TLBString *HelpFile;
1124 const TLBString *HelpStringDll;
1125 DWORD dwHelpContext;
1126 int TypeInfoCount; /* nr of typeinfo's in librarry */
1127 struct tagITypeInfoImpl **typeinfos;
1128 struct list custdata_list;
1129 struct list implib_list;
1130 int ctTypeDesc; /* number of items in type desc array */
1131 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1132 library. Only used while reading MSFT
1133 typelibs */
1134 struct list ref_list; /* list of ref types in this typelib */
1135 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1138 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1139 struct list entry;
1140 WCHAR *path;
1141 INT index;
1142 } ITypeLibImpl;
1144 static const ITypeLib2Vtbl tlbvt;
1145 static const ITypeCompVtbl tlbtcvt;
1146 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl;
1148 static inline ITypeLibImpl *impl_from_ITypeLib2(ITypeLib2 *iface)
1150 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeLib2_iface);
1153 static inline ITypeLibImpl *impl_from_ITypeLib(ITypeLib *iface)
1155 return impl_from_ITypeLib2((ITypeLib2*)iface);
1158 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1160 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeComp_iface);
1163 static inline ITypeLibImpl *impl_from_ICreateTypeLib2( ICreateTypeLib2 *iface )
1165 return CONTAINING_RECORD(iface, ITypeLibImpl, ICreateTypeLib2_iface);
1168 /* ITypeLib methods */
1169 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1170 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1172 /*======================= ITypeInfo implementation =======================*/
1174 /* data for referenced types */
1175 typedef struct tagTLBRefType
1177 INT index; /* Type index for internal ref or for external ref
1178 it the format is SLTG. -2 indicates to
1179 use guid */
1181 TYPEKIND tkind;
1182 TLBGuid *guid; /* guid of the referenced type */
1183 /* if index == TLB_REF_USE_GUID */
1185 HREFTYPE reference; /* The href of this ref */
1186 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1187 TLB_REF_INTERNAL for internal refs
1188 TLB_REF_NOT_FOUND for broken refs */
1190 struct list entry;
1191 } TLBRefType;
1193 #define TLB_REF_USE_GUID -2
1195 #define TLB_REF_INTERNAL (void*)-2
1196 #define TLB_REF_NOT_FOUND (void*)-1
1198 /* internal Parameter data */
1199 typedef struct tagTLBParDesc
1201 const TLBString *Name;
1202 struct list custdata_list;
1203 } TLBParDesc;
1205 /* internal Function data */
1206 typedef struct tagTLBFuncDesc
1208 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1209 const TLBString *Name; /* the name of this function */
1210 TLBParDesc *pParamDesc; /* array with param names and custom data */
1211 int helpcontext;
1212 int HelpStringContext;
1213 const TLBString *HelpString;
1214 const TLBString *Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1215 struct list custdata_list;
1216 } TLBFuncDesc;
1218 /* internal Variable data */
1219 typedef struct tagTLBVarDesc
1221 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1222 VARDESC *vardesc_create; /* additional data needed for storing VARDESC */
1223 const TLBString *Name; /* the name of this variable */
1224 int HelpContext;
1225 int HelpStringContext;
1226 const TLBString *HelpString;
1227 struct list custdata_list;
1228 } TLBVarDesc;
1230 /* internal implemented interface data */
1231 typedef struct tagTLBImplType
1233 HREFTYPE hRef; /* hRef of interface */
1234 int implflags; /* IMPLFLAG_*s */
1235 struct list custdata_list;
1236 } TLBImplType;
1238 /* internal TypeInfo data */
1239 typedef struct tagITypeInfoImpl
1241 ITypeInfo2 ITypeInfo2_iface;
1242 ITypeComp ITypeComp_iface;
1243 ICreateTypeInfo2 ICreateTypeInfo2_iface;
1244 LONG ref;
1245 BOOL not_attached_to_typelib;
1246 BOOL needs_layout;
1248 TLBGuid *guid;
1249 TYPEATTR typeattr;
1250 TYPEDESC *tdescAlias;
1252 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1253 int index; /* index in this typelib; */
1254 HREFTYPE hreftype; /* hreftype for app object binding */
1255 /* type libs seem to store the doc strings in ascii
1256 * so why should we do it in unicode?
1258 const TLBString *Name;
1259 const TLBString *DocString;
1260 const TLBString *DllName;
1261 const TLBString *Schema;
1262 DWORD dwHelpContext;
1263 DWORD dwHelpStringContext;
1265 /* functions */
1266 TLBFuncDesc *funcdescs;
1268 /* variables */
1269 TLBVarDesc *vardescs;
1271 /* Implemented Interfaces */
1272 TLBImplType *impltypes;
1274 struct list *pcustdata_list;
1275 struct list custdata_list;
1276 } ITypeInfoImpl;
1278 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1280 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeComp_iface);
1283 static inline ITypeInfoImpl *impl_from_ITypeInfo2( ITypeInfo2 *iface )
1285 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeInfo2_iface);
1288 static inline ITypeInfoImpl *impl_from_ITypeInfo( ITypeInfo *iface )
1290 return impl_from_ITypeInfo2((ITypeInfo2*)iface);
1293 static inline ITypeInfoImpl *info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2 *iface )
1295 return CONTAINING_RECORD(iface, ITypeInfoImpl, ICreateTypeInfo2_iface);
1298 static const ITypeInfo2Vtbl tinfvt;
1299 static const ITypeCompVtbl tcompvt;
1300 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl;
1302 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1303 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1305 typedef struct tagTLBContext
1307 unsigned int oStart; /* start of TLB in file */
1308 unsigned int pos; /* current pos */
1309 unsigned int length; /* total length */
1310 void *mapping; /* memory mapping */
1311 MSFT_SegDir * pTblDir;
1312 ITypeLibImpl* pLibInfo;
1313 } TLBContext;
1316 static inline BSTR TLB_get_bstr(const TLBString *str)
1318 return str != NULL ? str->str : NULL;
1321 static inline int TLB_str_memcmp(void *left, const TLBString *str, DWORD len)
1323 if(!str)
1324 return 1;
1325 return memcmp(left, str->str, len);
1328 static inline const GUID *TLB_get_guidref(const TLBGuid *guid)
1330 return guid != NULL ? &guid->guid : NULL;
1333 static inline const GUID *TLB_get_guid_null(const TLBGuid *guid)
1335 return guid != NULL ? &guid->guid : &GUID_NULL;
1338 static int get_ptr_size(SYSKIND syskind)
1340 switch(syskind){
1341 case SYS_WIN64:
1342 return 8;
1343 case SYS_WIN32:
1344 case SYS_MAC:
1345 case SYS_WIN16:
1346 return 4;
1348 WARN("Unhandled syskind: 0x%x\n", syskind);
1349 return 4;
1353 debug
1355 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1356 if (pTD->vt & VT_RESERVED)
1357 szVarType += strlen(strcpy(szVarType, "reserved | "));
1358 if (pTD->vt & VT_BYREF)
1359 szVarType += strlen(strcpy(szVarType, "ref to "));
1360 if (pTD->vt & VT_ARRAY)
1361 szVarType += strlen(strcpy(szVarType, "array of "));
1362 if (pTD->vt & VT_VECTOR)
1363 szVarType += strlen(strcpy(szVarType, "vector of "));
1364 switch(pTD->vt & VT_TYPEMASK) {
1365 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1366 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1367 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1368 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1369 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1370 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1371 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1372 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1373 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1374 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1375 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1376 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1377 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1378 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1379 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1380 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1381 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1382 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1383 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1384 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1385 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1386 pTD->u.hreftype); break;
1387 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1388 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1389 case VT_PTR: sprintf(szVarType, "ptr to ");
1390 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1391 break;
1392 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1393 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1394 break;
1395 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1396 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1397 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1398 break;
1400 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1404 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1405 char buf[200];
1406 USHORT flags = edesc->u.paramdesc.wParamFlags;
1407 dump_TypeDesc(&edesc->tdesc,buf);
1408 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1409 MESSAGE("\t\tu.paramdesc.wParamFlags");
1410 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1411 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1412 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1413 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1414 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1415 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1416 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1417 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1418 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1420 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1421 int i;
1422 MESSAGE("memid is %08x\n",funcdesc->memid);
1423 for (i=0;i<funcdesc->cParams;i++) {
1424 MESSAGE("Param %d:\n",i);
1425 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1427 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1428 switch (funcdesc->funckind) {
1429 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1430 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1431 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1432 case FUNC_STATIC: MESSAGE("static");break;
1433 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1434 default: MESSAGE("unknown");break;
1436 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1437 switch (funcdesc->invkind) {
1438 case INVOKE_FUNC: MESSAGE("func");break;
1439 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1440 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1441 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1443 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1444 switch (funcdesc->callconv) {
1445 case CC_CDECL: MESSAGE("cdecl");break;
1446 case CC_PASCAL: MESSAGE("pascal");break;
1447 case CC_STDCALL: MESSAGE("stdcall");break;
1448 case CC_SYSCALL: MESSAGE("syscall");break;
1449 default:break;
1451 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1452 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1453 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1455 MESSAGE("\telemdescFunc (return value type):\n");
1456 dump_ELEMDESC(&funcdesc->elemdescFunc);
1459 static const char * const typekind_desc[] =
1461 "TKIND_ENUM",
1462 "TKIND_RECORD",
1463 "TKIND_MODULE",
1464 "TKIND_INTERFACE",
1465 "TKIND_DISPATCH",
1466 "TKIND_COCLASS",
1467 "TKIND_ALIAS",
1468 "TKIND_UNION",
1469 "TKIND_MAX"
1472 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1474 int i;
1475 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd->Name)), pfd->funcdesc.cParams);
1476 for (i=0;i<pfd->funcdesc.cParams;i++)
1477 MESSAGE("\tparm%d: %s\n",i,debugstr_w(TLB_get_bstr(pfd->pParamDesc[i].Name)));
1480 dump_FUNCDESC(&(pfd->funcdesc));
1482 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd->HelpString)));
1483 if(pfd->Entry == NULL)
1484 MESSAGE("\tentry: (null)\n");
1485 else if(pfd->Entry == (void*)-1)
1486 MESSAGE("\tentry: invalid\n");
1487 else if(IS_INTRESOURCE(pfd->Entry))
1488 MESSAGE("\tentry: %p\n", pfd->Entry);
1489 else
1490 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd->Entry)));
1492 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1494 while (n)
1496 dump_TLBFuncDescOne(pfd);
1497 ++pfd;
1498 --n;
1501 static void dump_TLBVarDesc(const TLBVarDesc * pvd, UINT n)
1503 while (n)
1505 TRACE_(typelib)("%s\n", debugstr_w(TLB_get_bstr(pvd->Name)));
1506 ++pvd;
1507 --n;
1511 static void dump_TLBImpLib(const TLBImpLib *import)
1513 TRACE_(typelib)("%s %s\n", debugstr_guid(TLB_get_guidref(import->guid)),
1514 debugstr_w(import->name));
1515 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1516 import->wVersionMinor, import->lcid, import->offset);
1519 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1521 TLBRefType *ref;
1523 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1525 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1526 if(ref->index == -1)
1527 TRACE_(typelib)("%s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
1528 else
1529 TRACE_(typelib)("type no: %d\n", ref->index);
1531 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1533 TRACE_(typelib)("in lib\n");
1534 dump_TLBImpLib(ref->pImpTLInfo);
1539 static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1541 if(!impl)
1542 return;
1543 while (n) {
1544 TRACE_(typelib)("implementing/inheriting interface hRef = %x implflags %x\n",
1545 impl->hRef, impl->implflags);
1546 ++impl;
1547 --n;
1551 static void dump_DispParms(const DISPPARAMS * pdp)
1553 unsigned int index;
1555 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1557 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1559 TRACE("named args:\n");
1560 for (index = 0; index < pdp->cNamedArgs; index++)
1561 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1564 if (pdp->cArgs && pdp->rgvarg)
1566 TRACE("args:\n");
1567 for (index = 0; index < pdp->cArgs; index++)
1568 TRACE(" [%d] %s\n", index, debugstr_variant(pdp->rgvarg+index));
1572 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1574 TRACE("%p ref=%u\n", pty, pty->ref);
1575 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty->Name)), debugstr_w(TLB_get_bstr(pty->DocString)));
1576 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty->guid)));
1577 TRACE("kind:%s\n", typekind_desc[pty->typeattr.typekind]);
1578 TRACE("fct:%u var:%u impl:%u\n", pty->typeattr.cFuncs, pty->typeattr.cVars, pty->typeattr.cImplTypes);
1579 TRACE("wTypeFlags: 0x%04x\n", pty->typeattr.wTypeFlags);
1580 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1581 if (pty->typeattr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty->DllName)));
1582 if (TRACE_ON(ole))
1583 dump_TLBFuncDesc(pty->funcdescs, pty->typeattr.cFuncs);
1584 dump_TLBVarDesc(pty->vardescs, pty->typeattr.cVars);
1585 dump_TLBImplType(pty->impltypes, pty->typeattr.cImplTypes);
1588 static void dump_VARDESC(const VARDESC *v)
1590 MESSAGE("memid %d\n",v->memid);
1591 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1592 MESSAGE("oInst %d\n",v->u.oInst);
1593 dump_ELEMDESC(&(v->elemdescVar));
1594 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1595 MESSAGE("varkind %d\n",v->varkind);
1598 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1600 /* VT_LPWSTR is largest type that, may appear in type description */
1601 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1602 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1603 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1604 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1605 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1606 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1607 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1608 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1611 static void TLB_abort(void)
1613 DebugBreak();
1616 /* returns the size required for a deep copy of a typedesc into a
1617 * flat buffer */
1618 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1620 SIZE_T size = 0;
1622 if (alloc_initial_space)
1623 size += sizeof(TYPEDESC);
1625 switch (tdesc->vt)
1627 case VT_PTR:
1628 case VT_SAFEARRAY:
1629 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1630 break;
1631 case VT_CARRAY:
1632 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1633 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1634 break;
1636 return size;
1639 /* deep copy a typedesc into a flat buffer */
1640 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1642 if (!dest)
1644 dest = buffer;
1645 buffer = (char *)buffer + sizeof(TYPEDESC);
1648 *dest = *src;
1650 switch (src->vt)
1652 case VT_PTR:
1653 case VT_SAFEARRAY:
1654 dest->u.lptdesc = buffer;
1655 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1656 break;
1657 case VT_CARRAY:
1658 dest->u.lpadesc = buffer;
1659 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1660 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1661 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1662 break;
1664 return buffer;
1667 /* free custom data allocated by MSFT_CustData */
1668 static inline void TLB_FreeCustData(struct list *custdata_list)
1670 TLBCustData *cd, *cdn;
1671 LIST_FOR_EACH_ENTRY_SAFE(cd, cdn, custdata_list, TLBCustData, entry)
1673 list_remove(&cd->entry);
1674 VariantClear(&cd->data);
1675 heap_free(cd);
1679 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1681 DWORD len;
1682 BSTR ret;
1684 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1685 ret = SysAllocStringLen(NULL, len - 1);
1686 if (!ret) return ret;
1687 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1688 return ret;
1691 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(ITypeInfoImpl *typeinfo, MEMBERID memid)
1693 int i;
1695 for (i = 0; i < typeinfo->typeattr.cFuncs; ++i)
1697 if (typeinfo->funcdescs[i].funcdesc.memid == memid)
1698 return &typeinfo->funcdescs[i];
1701 return NULL;
1704 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid_invkind(ITypeInfoImpl *typeinfo, MEMBERID memid, INVOKEKIND invkind)
1706 int i;
1708 for (i = 0; i < typeinfo->typeattr.cFuncs; ++i)
1710 if (typeinfo->funcdescs[i].funcdesc.memid == memid && typeinfo->funcdescs[i].funcdesc.invkind == invkind)
1711 return &typeinfo->funcdescs[i];
1714 return NULL;
1717 static inline TLBVarDesc *TLB_get_vardesc_by_memberid(ITypeInfoImpl *typeinfo, MEMBERID memid)
1719 int i;
1721 for (i = 0; i < typeinfo->typeattr.cVars; ++i)
1723 if (typeinfo->vardescs[i].vardesc.memid == memid)
1724 return &typeinfo->vardescs[i];
1727 return NULL;
1730 static inline TLBVarDesc *TLB_get_vardesc_by_name(ITypeInfoImpl *typeinfo, const OLECHAR *name)
1732 int i;
1734 for (i = 0; i < typeinfo->typeattr.cVars; ++i)
1736 if (!lstrcmpiW(TLB_get_bstr(typeinfo->vardescs[i].Name), name))
1737 return &typeinfo->vardescs[i];
1740 return NULL;
1743 static inline TLBCustData *TLB_get_custdata_by_guid(const struct list *custdata_list, REFGUID guid)
1745 TLBCustData *cust_data;
1746 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1747 if(IsEqualIID(TLB_get_guid_null(cust_data->guid), guid))
1748 return cust_data;
1749 return NULL;
1752 static inline ITypeInfoImpl *TLB_get_typeinfo_by_name(ITypeLibImpl *typelib, const OLECHAR *name)
1754 int i;
1756 for (i = 0; i < typelib->TypeInfoCount; ++i)
1758 if (!lstrcmpiW(TLB_get_bstr(typelib->typeinfos[i]->Name), name))
1759 return typelib->typeinfos[i];
1762 return NULL;
1765 static void TLBVarDesc_Constructor(TLBVarDesc *var_desc)
1767 list_init(&var_desc->custdata_list);
1770 static TLBVarDesc *TLBVarDesc_Alloc(UINT n)
1772 TLBVarDesc *ret;
1774 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1775 if(!ret)
1776 return NULL;
1778 while(n){
1779 TLBVarDesc_Constructor(&ret[n-1]);
1780 --n;
1783 return ret;
1786 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1788 TLBParDesc *ret;
1790 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1791 if(!ret)
1792 return NULL;
1794 while(n){
1795 list_init(&ret[n-1].custdata_list);
1796 --n;
1799 return ret;
1802 static void TLBFuncDesc_Constructor(TLBFuncDesc *func_desc)
1804 list_init(&func_desc->custdata_list);
1807 static TLBFuncDesc *TLBFuncDesc_Alloc(UINT n)
1809 TLBFuncDesc *ret;
1811 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1812 if(!ret)
1813 return NULL;
1815 while(n){
1816 TLBFuncDesc_Constructor(&ret[n-1]);
1817 --n;
1820 return ret;
1823 static void TLBImplType_Constructor(TLBImplType *impl)
1825 list_init(&impl->custdata_list);
1828 static TLBImplType *TLBImplType_Alloc(UINT n)
1830 TLBImplType *ret;
1832 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1833 if(!ret)
1834 return NULL;
1836 while(n){
1837 TLBImplType_Constructor(&ret[n-1]);
1838 --n;
1841 return ret;
1844 static TLBGuid *TLB_append_guid(struct list *guid_list,
1845 const GUID *new_guid, HREFTYPE hreftype)
1847 TLBGuid *guid;
1849 LIST_FOR_EACH_ENTRY(guid, guid_list, TLBGuid, entry) {
1850 if (IsEqualGUID(&guid->guid, new_guid))
1851 return guid;
1854 guid = heap_alloc(sizeof(TLBGuid));
1855 if (!guid)
1856 return NULL;
1858 memcpy(&guid->guid, new_guid, sizeof(GUID));
1859 guid->hreftype = hreftype;
1861 list_add_tail(guid_list, &guid->entry);
1863 return guid;
1866 static HRESULT TLB_set_custdata(struct list *custdata_list, TLBGuid *tlbguid, VARIANT *var)
1868 TLBCustData *cust_data;
1870 switch(V_VT(var)){
1871 case VT_I4:
1872 case VT_R4:
1873 case VT_UI4:
1874 case VT_INT:
1875 case VT_UINT:
1876 case VT_HRESULT:
1877 case VT_BSTR:
1878 break;
1879 default:
1880 return DISP_E_BADVARTYPE;
1883 cust_data = TLB_get_custdata_by_guid(custdata_list, TLB_get_guid_null(tlbguid));
1885 if (!cust_data) {
1886 cust_data = heap_alloc(sizeof(TLBCustData));
1887 if (!cust_data)
1888 return E_OUTOFMEMORY;
1890 cust_data->guid = tlbguid;
1891 VariantInit(&cust_data->data);
1893 list_add_tail(custdata_list, &cust_data->entry);
1894 }else
1895 VariantClear(&cust_data->data);
1897 return VariantCopy(&cust_data->data, var);
1900 /* Used to update list pointers after list itself was moved. */
1901 static void TLB_relink_custdata(struct list *custdata_list)
1903 if (custdata_list->prev == custdata_list->next)
1904 list_init(custdata_list);
1905 else
1907 custdata_list->prev->next = custdata_list;
1908 custdata_list->next->prev = custdata_list;
1912 static TLBString *TLB_append_str(struct list *string_list, BSTR new_str)
1914 TLBString *str;
1916 if(!new_str)
1917 return NULL;
1919 LIST_FOR_EACH_ENTRY(str, string_list, TLBString, entry) {
1920 if (wcscmp(str->str, new_str) == 0)
1921 return str;
1924 str = heap_alloc(sizeof(TLBString));
1925 if (!str)
1926 return NULL;
1928 str->str = SysAllocString(new_str);
1929 if (!str->str) {
1930 heap_free(str);
1931 return NULL;
1934 list_add_tail(string_list, &str->entry);
1936 return str;
1939 static HRESULT TLB_get_size_from_hreftype(ITypeInfoImpl *info, HREFTYPE href,
1940 ULONG *size, WORD *align)
1942 ITypeInfo *other;
1943 TYPEATTR *attr;
1944 HRESULT hr;
1946 hr = ITypeInfo2_GetRefTypeInfo(&info->ITypeInfo2_iface, href, &other);
1947 if(FAILED(hr))
1948 return hr;
1950 hr = ITypeInfo_GetTypeAttr(other, &attr);
1951 if(FAILED(hr)){
1952 ITypeInfo_Release(other);
1953 return hr;
1956 if(size)
1957 *size = attr->cbSizeInstance;
1958 if(align)
1959 *align = attr->cbAlignment;
1961 ITypeInfo_ReleaseTypeAttr(other, attr);
1962 ITypeInfo_Release(other);
1964 return S_OK;
1967 static HRESULT TLB_size_instance(ITypeInfoImpl *info, SYSKIND sys,
1968 TYPEDESC *tdesc, ULONG *size, WORD *align)
1970 ULONG i, sub, ptr_size;
1971 HRESULT hr;
1973 ptr_size = get_ptr_size(sys);
1975 switch(tdesc->vt){
1976 case VT_VOID:
1977 *size = 0;
1978 break;
1979 case VT_I1:
1980 case VT_UI1:
1981 *size = 1;
1982 break;
1983 case VT_I2:
1984 case VT_BOOL:
1985 case VT_UI2:
1986 *size = 2;
1987 break;
1988 case VT_I4:
1989 case VT_R4:
1990 case VT_ERROR:
1991 case VT_UI4:
1992 case VT_INT:
1993 case VT_UINT:
1994 case VT_HRESULT:
1995 *size = 4;
1996 break;
1997 case VT_R8:
1998 case VT_I8:
1999 case VT_UI8:
2000 *size = 8;
2001 break;
2002 case VT_BSTR:
2003 case VT_DISPATCH:
2004 case VT_UNKNOWN:
2005 case VT_PTR:
2006 case VT_SAFEARRAY:
2007 case VT_LPSTR:
2008 case VT_LPWSTR:
2009 *size = ptr_size;
2010 break;
2011 case VT_DATE:
2012 *size = sizeof(DATE);
2013 break;
2014 case VT_VARIANT:
2015 *size = sizeof(VARIANT);
2016 #ifdef _WIN64
2017 if(sys == SYS_WIN32)
2018 *size -= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
2019 #endif
2020 break;
2021 case VT_DECIMAL:
2022 *size = sizeof(DECIMAL);
2023 break;
2024 case VT_CY:
2025 *size = sizeof(CY);
2026 break;
2027 case VT_CARRAY:
2028 *size = 0;
2029 for(i = 0; i < tdesc->u.lpadesc->cDims; ++i)
2030 *size += tdesc->u.lpadesc->rgbounds[i].cElements;
2031 hr = TLB_size_instance(info, sys, &tdesc->u.lpadesc->tdescElem, &sub, align);
2032 if(FAILED(hr))
2033 return hr;
2034 *size *= sub;
2035 return S_OK;
2036 case VT_USERDEFINED:
2037 return TLB_get_size_from_hreftype(info, tdesc->u.hreftype, size, align);
2038 default:
2039 FIXME("Unsized VT: 0x%x\n", tdesc->vt);
2040 return E_FAIL;
2043 if(align){
2044 if(*size < 4)
2045 *align = *size;
2046 else
2047 *align = 4;
2050 return S_OK;
2053 /**********************************************************************
2055 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2058 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
2060 if (where != DO_NOT_SEEK)
2062 where += pcx->oStart;
2063 if (where > pcx->length)
2065 /* FIXME */
2066 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
2067 TLB_abort();
2069 pcx->pos = where;
2073 /* read function */
2074 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
2076 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2077 pcx->pos, count, pcx->oStart, pcx->length, where);
2079 MSFT_Seek(pcx, where);
2080 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
2081 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
2082 pcx->pos += count;
2083 return count;
2086 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
2087 LONG where )
2089 DWORD ret;
2091 ret = MSFT_Read(buffer, count, pcx, where);
2092 FromLEDWords(buffer, ret);
2094 return ret;
2097 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
2098 LONG where )
2100 DWORD ret;
2102 ret = MSFT_Read(buffer, count, pcx, where);
2103 FromLEWords(buffer, ret);
2105 return ret;
2108 static HRESULT MSFT_ReadAllGuids(TLBContext *pcx)
2110 TLBGuid *guid;
2111 MSFT_GuidEntry entry;
2112 int offs = 0;
2114 MSFT_Seek(pcx, pcx->pTblDir->pGuidTab.offset);
2115 while (1) {
2116 if (offs >= pcx->pTblDir->pGuidTab.length)
2117 return S_OK;
2119 MSFT_ReadLEWords(&entry, sizeof(MSFT_GuidEntry), pcx, DO_NOT_SEEK);
2121 guid = heap_alloc(sizeof(TLBGuid));
2123 guid->offset = offs;
2124 guid->guid = entry.guid;
2125 guid->hreftype = entry.hreftype;
2127 list_add_tail(&pcx->pLibInfo->guid_list, &guid->entry);
2129 offs += sizeof(MSFT_GuidEntry);
2133 static TLBGuid *MSFT_ReadGuid( int offset, TLBContext *pcx)
2135 TLBGuid *ret;
2137 LIST_FOR_EACH_ENTRY(ret, &pcx->pLibInfo->guid_list, TLBGuid, entry){
2138 if(ret->offset == offset){
2139 TRACE_(typelib)("%s\n", debugstr_guid(&ret->guid));
2140 return ret;
2144 return NULL;
2147 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
2149 MSFT_NameIntro niName;
2151 if (offset < 0)
2153 ERR_(typelib)("bad offset %d\n", offset);
2154 return -1;
2157 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
2158 pcx->pTblDir->pNametab.offset+offset);
2160 return niName.hreftype;
2163 static HRESULT MSFT_ReadAllNames(TLBContext *pcx)
2165 char *string;
2166 MSFT_NameIntro intro;
2167 INT16 len_piece;
2168 int offs = 0, lengthInChars;
2170 MSFT_Seek(pcx, pcx->pTblDir->pNametab.offset);
2171 while (1) {
2172 TLBString *tlbstr;
2174 if (offs >= pcx->pTblDir->pNametab.length)
2175 return S_OK;
2177 MSFT_ReadLEWords(&intro, sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2178 intro.namelen &= 0xFF;
2179 len_piece = intro.namelen + sizeof(MSFT_NameIntro);
2180 if(len_piece % 4)
2181 len_piece = (len_piece + 4) & ~0x3;
2182 if(len_piece < 8)
2183 len_piece = 8;
2185 string = heap_alloc(len_piece + 1);
2186 MSFT_Read(string, len_piece - sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2187 string[intro.namelen] = '\0';
2189 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2190 string, -1, NULL, 0);
2191 if (!lengthInChars) {
2192 heap_free(string);
2193 return E_UNEXPECTED;
2196 tlbstr = heap_alloc(sizeof(TLBString));
2198 tlbstr->offset = offs;
2199 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2200 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2202 heap_free(string);
2204 list_add_tail(&pcx->pLibInfo->name_list, &tlbstr->entry);
2206 offs += len_piece;
2210 static TLBString *MSFT_ReadName( TLBContext *pcx, int offset)
2212 TLBString *tlbstr;
2214 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->name_list, TLBString, entry) {
2215 if (tlbstr->offset == offset) {
2216 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2217 return tlbstr;
2221 return NULL;
2224 static TLBString *MSFT_ReadString( TLBContext *pcx, int offset)
2226 TLBString *tlbstr;
2228 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->string_list, TLBString, entry) {
2229 if (tlbstr->offset == offset) {
2230 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2231 return tlbstr;
2235 return NULL;
2239 * read a value and fill a VARIANT structure
2241 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
2243 int size;
2245 TRACE_(typelib)("\n");
2247 if(offset <0) { /* data are packed in here */
2248 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
2249 V_I4(pVar) = offset & 0x3ffffff;
2250 return;
2252 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
2253 pcx->pTblDir->pCustData.offset + offset );
2254 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
2255 switch (V_VT(pVar)){
2256 case VT_EMPTY: /* FIXME: is this right? */
2257 case VT_NULL: /* FIXME: is this right? */
2258 case VT_I2 : /* this should not happen */
2259 case VT_I4 :
2260 case VT_R4 :
2261 case VT_ERROR :
2262 case VT_BOOL :
2263 case VT_I1 :
2264 case VT_UI1 :
2265 case VT_UI2 :
2266 case VT_UI4 :
2267 case VT_INT :
2268 case VT_UINT :
2269 case VT_VOID : /* FIXME: is this right? */
2270 case VT_HRESULT :
2271 size=4; break;
2272 case VT_R8 :
2273 case VT_CY :
2274 case VT_DATE :
2275 case VT_I8 :
2276 case VT_UI8 :
2277 case VT_DECIMAL : /* FIXME: is this right? */
2278 case VT_FILETIME :
2279 size=8;break;
2280 /* pointer types with known behaviour */
2281 case VT_BSTR :{
2282 char * ptr;
2283 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
2284 if(size == -1){
2285 V_BSTR(pVar) = NULL;
2286 }else{
2287 ptr = heap_alloc_zero(size);
2288 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);
2289 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
2290 /* FIXME: do we need a AtoW conversion here? */
2291 V_UNION(pVar, bstrVal[size])='\0';
2292 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
2293 heap_free(ptr);
2296 size=-4; break;
2297 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2298 case VT_DISPATCH :
2299 case VT_VARIANT :
2300 case VT_UNKNOWN :
2301 case VT_PTR :
2302 case VT_SAFEARRAY :
2303 case VT_CARRAY :
2304 case VT_USERDEFINED :
2305 case VT_LPSTR :
2306 case VT_LPWSTR :
2307 case VT_BLOB :
2308 case VT_STREAM :
2309 case VT_STORAGE :
2310 case VT_STREAMED_OBJECT :
2311 case VT_STORED_OBJECT :
2312 case VT_BLOB_OBJECT :
2313 case VT_CF :
2314 case VT_CLSID :
2315 default:
2316 size=0;
2317 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2318 V_VT(pVar));
2321 if(size>0) /* (big|small) endian correct? */
2322 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
2323 return;
2326 * create a linked list with custom data
2328 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
2330 MSFT_CDGuid entry;
2331 TLBCustData* pNew;
2332 int count=0;
2334 TRACE_(typelib)("\n");
2336 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
2338 while(offset >=0){
2339 count++;
2340 pNew=heap_alloc_zero(sizeof(TLBCustData));
2341 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
2342 pNew->guid = MSFT_ReadGuid(entry.GuidOffset, pcx);
2343 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
2344 list_add_head(custdata_list, &pNew->entry);
2345 offset = entry.next;
2347 return count;
2350 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd)
2352 if(type <0)
2353 pTd->vt=type & VT_TYPEMASK;
2354 else
2355 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
2357 TRACE_(typelib)("vt type = %X\n", pTd->vt);
2360 static BOOL TLB_is_propgetput(INVOKEKIND invkind)
2362 return (invkind == INVOKE_PROPERTYGET ||
2363 invkind == INVOKE_PROPERTYPUT ||
2364 invkind == INVOKE_PROPERTYPUTREF);
2367 static void
2368 MSFT_DoFuncs(TLBContext* pcx,
2369 ITypeInfoImpl* pTI,
2370 int cFuncs,
2371 int cVars,
2372 int offset,
2373 TLBFuncDesc** pptfd)
2376 * member information is stored in a data structure at offset
2377 * indicated by the memoffset field of the typeinfo structure
2378 * There are several distinctive parts.
2379 * The first part starts with a field that holds the total length
2380 * of this (first) part excluding this field. Then follow the records,
2381 * for each member there is one record.
2383 * The first entry is always the length of the record (including this
2384 * length word).
2385 * The rest of the record depends on the type of the member. If there is
2386 * a field indicating the member type (function, variable, interface, etc)
2387 * I have not found it yet. At this time we depend on the information
2388 * in the type info and the usual order how things are stored.
2390 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2391 * for each member;
2393 * Third is an equal sized array with file offsets to the name entry
2394 * of each member.
2396 * The fourth and last (?) part is an array with offsets to the records
2397 * in the first part of this file segment.
2400 int infolen, nameoffset, reclength, i;
2401 int recoffset = offset + sizeof(INT);
2403 char *recbuf = heap_alloc(0xffff);
2404 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2405 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2407 TRACE_(typelib)("\n");
2409 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2411 *pptfd = TLBFuncDesc_Alloc(cFuncs);
2412 ptfd = *pptfd;
2413 for ( i = 0; i < cFuncs ; i++ )
2415 int optional;
2417 /* name, eventually add to a hash table */
2418 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2419 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2421 /* read the function information record */
2422 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2424 reclength &= 0xffff;
2426 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2428 /* size without argument data */
2429 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2430 if (pFuncRec->FKCCIC & 0x1000)
2431 optional -= pFuncRec->nrargs * sizeof(INT);
2433 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2434 ptfd->helpcontext = pFuncRec->HelpContext;
2436 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2437 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2439 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2441 if (pFuncRec->FKCCIC & 0x2000 )
2443 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2444 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2445 ptfd->Entry = (TLBString*)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2447 else
2448 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2450 else
2451 ptfd->Entry = (TLBString*)-1;
2453 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2454 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2456 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2457 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2459 /* fill the FuncDesc Structure */
2460 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2461 offset + infolen + ( i + 1) * sizeof(INT));
2463 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2464 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2465 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2466 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2467 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2468 ptfd->funcdesc.oVft = (pFuncRec->VtableOffset & ~1) * sizeof(void *) / pTI->pTypeLib->ptr_size;
2469 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2471 /* nameoffset is sometimes -1 on the second half of a propget/propput
2472 * pair of functions */
2473 if ((nameoffset == -1) && (i > 0) &&
2474 TLB_is_propgetput(ptfd_prev->funcdesc.invkind) &&
2475 TLB_is_propgetput(ptfd->funcdesc.invkind))
2476 ptfd->Name = ptfd_prev->Name;
2477 else
2478 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2480 MSFT_GetTdesc(pcx,
2481 pFuncRec->DataType,
2482 &ptfd->funcdesc.elemdescFunc.tdesc);
2484 /* do the parameters/arguments */
2485 if(pFuncRec->nrargs)
2487 int j = 0;
2488 MSFT_ParameterInfo paraminfo;
2490 ptfd->funcdesc.lprgelemdescParam =
2491 heap_alloc_zero(pFuncRec->nrargs * (sizeof(ELEMDESC) + sizeof(PARAMDESCEX)));
2493 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2495 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2496 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2498 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2500 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2502 MSFT_GetTdesc(pcx,
2503 paraminfo.DataType,
2504 &elemdesc->tdesc);
2506 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2508 /* name */
2509 if (paraminfo.oName != -1)
2510 ptfd->pParamDesc[j].Name =
2511 MSFT_ReadName( pcx, paraminfo.oName );
2512 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(TLB_get_bstr(ptfd->pParamDesc[j].Name)));
2514 /* default value */
2515 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2516 (pFuncRec->FKCCIC & 0x1000) )
2518 INT* pInt = (INT *)((char *)pFuncRec +
2519 reclength -
2520 (pFuncRec->nrargs * 4) * sizeof(INT) );
2522 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2524 pParamDesc->pparamdescex = (PARAMDESCEX*)(ptfd->funcdesc.lprgelemdescParam+pFuncRec->nrargs)+j;
2525 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2527 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2528 pInt[j], pcx);
2530 else
2531 elemdesc->u.paramdesc.pparamdescex = NULL;
2533 /* custom info */
2534 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2535 j*sizeof(pFuncRec->oArgCustData[0])) &&
2536 pFuncRec->FKCCIC & 0x80 )
2538 MSFT_CustData(pcx,
2539 pFuncRec->oArgCustData[j],
2540 &ptfd->pParamDesc[j].custdata_list);
2543 /* SEEK value = jump to offset,
2544 * from there jump to the end of record,
2545 * go back by (j-1) arguments
2547 MSFT_ReadLEDWords( &paraminfo ,
2548 sizeof(MSFT_ParameterInfo), pcx,
2549 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2550 * sizeof(MSFT_ParameterInfo)));
2554 /* scode is not used: archaic win16 stuff FIXME: right? */
2555 ptfd->funcdesc.cScodes = 0 ;
2556 ptfd->funcdesc.lprgscode = NULL ;
2558 ptfd_prev = ptfd;
2559 ++ptfd;
2560 recoffset += reclength;
2562 heap_free(recbuf);
2565 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2566 int cVars, int offset, TLBVarDesc ** pptvd)
2568 int infolen, nameoffset, reclength;
2569 char recbuf[256];
2570 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2571 TLBVarDesc *ptvd;
2572 int i;
2573 int recoffset;
2575 TRACE_(typelib)("\n");
2577 ptvd = *pptvd = TLBVarDesc_Alloc(cVars);
2578 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2579 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2580 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2581 recoffset += offset+sizeof(INT);
2582 for(i=0;i<cVars;i++, ++ptvd){
2583 /* name, eventually add to a hash table */
2584 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2585 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2586 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2587 /* read the variable information record */
2588 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2589 reclength &= 0xff;
2590 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2592 /* optional data */
2593 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2594 ptvd->HelpContext = pVarRec->HelpContext;
2596 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2597 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2599 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2600 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2602 /* fill the VarDesc Structure */
2603 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2604 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2605 ptvd->vardesc.varkind = pVarRec->VarKind;
2606 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2607 MSFT_GetTdesc(pcx, pVarRec->DataType,
2608 &ptvd->vardesc.elemdescVar.tdesc);
2609 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2610 if(pVarRec->VarKind == VAR_CONST ){
2611 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2612 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2613 pVarRec->OffsValue, pcx);
2614 } else
2615 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2616 recoffset += reclength;
2620 /* process Implemented Interfaces of a com class */
2621 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2622 int offset)
2624 int i;
2625 MSFT_RefRecord refrec;
2626 TLBImplType *pImpl;
2628 TRACE_(typelib)("\n");
2630 pTI->impltypes = TLBImplType_Alloc(count);
2631 pImpl = pTI->impltypes;
2632 for(i=0;i<count;i++){
2633 if(offset<0) break; /* paranoia */
2634 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2635 pImpl->hRef = refrec.reftype;
2636 pImpl->implflags=refrec.flags;
2637 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2638 offset=refrec.onext;
2639 ++pImpl;
2643 #ifdef _WIN64
2644 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2645 * and some structures, and fix the alignment */
2646 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl *info)
2648 if(info->typeattr.typekind == TKIND_ALIAS){
2649 switch(info->tdescAlias->vt){
2650 case VT_BSTR:
2651 case VT_DISPATCH:
2652 case VT_UNKNOWN:
2653 case VT_PTR:
2654 case VT_SAFEARRAY:
2655 case VT_LPSTR:
2656 case VT_LPWSTR:
2657 info->typeattr.cbSizeInstance = sizeof(void*);
2658 info->typeattr.cbAlignment = sizeof(void*);
2659 break;
2660 case VT_CARRAY:
2661 case VT_USERDEFINED:
2662 TLB_size_instance(info, SYS_WIN64, info->tdescAlias, &info->typeattr.cbSizeInstance, &info->typeattr.cbAlignment);
2663 break;
2664 case VT_VARIANT:
2665 info->typeattr.cbSizeInstance = sizeof(VARIANT);
2666 info->typeattr.cbAlignment = 8;
2667 default:
2668 if(info->typeattr.cbSizeInstance < sizeof(void*))
2669 info->typeattr.cbAlignment = info->typeattr.cbSizeInstance;
2670 else
2671 info->typeattr.cbAlignment = sizeof(void*);
2672 break;
2674 }else if(info->typeattr.typekind == TKIND_INTERFACE ||
2675 info->typeattr.typekind == TKIND_DISPATCH ||
2676 info->typeattr.typekind == TKIND_COCLASS){
2677 info->typeattr.cbSizeInstance = sizeof(void*);
2678 info->typeattr.cbAlignment = sizeof(void*);
2681 #endif
2684 * process a typeinfo record
2686 static ITypeInfoImpl * MSFT_DoTypeInfo(
2687 TLBContext *pcx,
2688 int count,
2689 ITypeLibImpl * pLibInfo)
2691 MSFT_TypeInfoBase tiBase;
2692 ITypeInfoImpl *ptiRet;
2694 TRACE_(typelib)("count=%u\n", count);
2696 ptiRet = ITypeInfoImpl_Constructor();
2697 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2698 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2700 /* this is where we are coming from */
2701 ptiRet->pTypeLib = pLibInfo;
2702 ptiRet->index=count;
2704 ptiRet->guid = MSFT_ReadGuid(tiBase.posguid, pcx);
2705 ptiRet->typeattr.lcid = pLibInfo->set_lcid; /* FIXME: correct? */
2706 ptiRet->typeattr.lpstrSchema = NULL; /* reserved */
2707 ptiRet->typeattr.cbSizeInstance = tiBase.size;
2708 ptiRet->typeattr.typekind = tiBase.typekind & 0xF;
2709 ptiRet->typeattr.cFuncs = LOWORD(tiBase.cElement);
2710 ptiRet->typeattr.cVars = HIWORD(tiBase.cElement);
2711 ptiRet->typeattr.cbAlignment = (tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2712 ptiRet->typeattr.wTypeFlags = tiBase.flags;
2713 ptiRet->typeattr.wMajorVerNum = LOWORD(tiBase.version);
2714 ptiRet->typeattr.wMinorVerNum = HIWORD(tiBase.version);
2715 ptiRet->typeattr.cImplTypes = tiBase.cImplTypes;
2716 ptiRet->typeattr.cbSizeVft = tiBase.cbSizeVft;
2717 if (ptiRet->typeattr.typekind == TKIND_ALIAS) {
2718 TYPEDESC tmp;
2719 MSFT_GetTdesc(pcx, tiBase.datatype1, &tmp);
2720 ptiRet->tdescAlias = heap_alloc(TLB_SizeTypeDesc(&tmp, TRUE));
2721 TLB_CopyTypeDesc(NULL, &tmp, ptiRet->tdescAlias);
2724 /* FIXME: */
2725 /* IDLDESC idldescType; *//* never saw this one != zero */
2727 /* name, eventually add to a hash table */
2728 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2729 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2730 TRACE_(typelib)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet->Name)));
2731 /* help info */
2732 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2733 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2734 ptiRet->dwHelpContext=tiBase.helpcontext;
2736 if (ptiRet->typeattr.typekind == TKIND_MODULE)
2737 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2739 /* note: InfoType's Help file and HelpStringDll come from the containing
2740 * library. Further HelpString and Docstring appear to be the same thing :(
2742 /* functions */
2743 if(ptiRet->typeattr.cFuncs >0 )
2744 MSFT_DoFuncs(pcx, ptiRet, ptiRet->typeattr.cFuncs,
2745 ptiRet->typeattr.cVars,
2746 tiBase.memoffset, &ptiRet->funcdescs);
2747 /* variables */
2748 if(ptiRet->typeattr.cVars >0 )
2749 MSFT_DoVars(pcx, ptiRet, ptiRet->typeattr.cFuncs,
2750 ptiRet->typeattr.cVars,
2751 tiBase.memoffset, &ptiRet->vardescs);
2752 if(ptiRet->typeattr.cImplTypes >0 ) {
2753 switch(ptiRet->typeattr.typekind)
2755 case TKIND_COCLASS:
2756 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->typeattr.cImplTypes,
2757 tiBase.datatype1);
2758 break;
2759 case TKIND_DISPATCH:
2760 /* This is not -1 when the interface is a non-base dual interface or
2761 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2762 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2763 not this interface.
2766 if (tiBase.datatype1 != -1)
2768 ptiRet->impltypes = TLBImplType_Alloc(1);
2769 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2771 break;
2772 default:
2773 ptiRet->impltypes = TLBImplType_Alloc(1);
2774 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2775 break;
2778 MSFT_CustData(pcx, tiBase.oCustData, ptiRet->pcustdata_list);
2780 TRACE_(typelib)("%s guid: %s kind:%s\n",
2781 debugstr_w(TLB_get_bstr(ptiRet->Name)),
2782 debugstr_guid(TLB_get_guidref(ptiRet->guid)),
2783 typekind_desc[ptiRet->typeattr.typekind]);
2784 if (TRACE_ON(typelib))
2785 dump_TypeInfo(ptiRet);
2787 return ptiRet;
2790 static HRESULT MSFT_ReadAllStrings(TLBContext *pcx)
2792 char *string;
2793 INT16 len_str, len_piece;
2794 int offs = 0, lengthInChars;
2796 MSFT_Seek(pcx, pcx->pTblDir->pStringtab.offset);
2797 while (1) {
2798 TLBString *tlbstr;
2800 if (offs >= pcx->pTblDir->pStringtab.length)
2801 return S_OK;
2803 MSFT_ReadLEWords(&len_str, sizeof(INT16), pcx, DO_NOT_SEEK);
2804 len_piece = len_str + sizeof(INT16);
2805 if(len_piece % 4)
2806 len_piece = (len_piece + 4) & ~0x3;
2807 if(len_piece < 8)
2808 len_piece = 8;
2810 string = heap_alloc(len_piece + 1);
2811 MSFT_Read(string, len_piece - sizeof(INT16), pcx, DO_NOT_SEEK);
2812 string[len_str] = '\0';
2814 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2815 string, -1, NULL, 0);
2816 if (!lengthInChars) {
2817 heap_free(string);
2818 return E_UNEXPECTED;
2821 tlbstr = heap_alloc(sizeof(TLBString));
2823 tlbstr->offset = offs;
2824 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2825 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2827 heap_free(string);
2829 list_add_tail(&pcx->pLibInfo->string_list, &tlbstr->entry);
2831 offs += len_piece;
2835 static HRESULT MSFT_ReadAllRefs(TLBContext *pcx)
2837 TLBRefType *ref;
2838 int offs = 0;
2840 MSFT_Seek(pcx, pcx->pTblDir->pImpInfo.offset);
2841 while (offs < pcx->pTblDir->pImpInfo.length) {
2842 MSFT_ImpInfo impinfo;
2843 TLBImpLib *pImpLib;
2845 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx, DO_NOT_SEEK);
2847 ref = heap_alloc_zero(sizeof(TLBRefType));
2848 list_add_tail(&pcx->pLibInfo->ref_list, &ref->entry);
2850 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2851 if(pImpLib->offset==impinfo.oImpFile)
2852 break;
2854 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2855 ref->reference = offs;
2856 ref->pImpTLInfo = pImpLib;
2857 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2858 ref->guid = MSFT_ReadGuid(impinfo.oGuid, pcx);
2859 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
2860 ref->index = TLB_REF_USE_GUID;
2861 } else
2862 ref->index = impinfo.oGuid;
2863 }else{
2864 ERR("Cannot find a reference\n");
2865 ref->reference = -1;
2866 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2869 offs += sizeof(impinfo);
2872 return S_OK;
2875 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2876 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2877 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2878 * tradeoff here.
2880 static struct list tlb_cache = LIST_INIT(tlb_cache);
2881 static CRITICAL_SECTION cache_section;
2882 static CRITICAL_SECTION_DEBUG cache_section_debug =
2884 0, 0, &cache_section,
2885 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2886 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2888 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2891 typedef struct TLB_PEFile
2893 IUnknown IUnknown_iface;
2894 LONG refs;
2895 HMODULE dll;
2896 HRSRC typelib_resource;
2897 HGLOBAL typelib_global;
2898 LPVOID typelib_base;
2899 } TLB_PEFile;
2901 static inline TLB_PEFile *pefile_impl_from_IUnknown(IUnknown *iface)
2903 return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2906 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2908 if (IsEqualIID(riid, &IID_IUnknown))
2910 *ppv = iface;
2911 IUnknown_AddRef(iface);
2912 return S_OK;
2914 *ppv = NULL;
2915 return E_NOINTERFACE;
2918 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2920 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2921 return InterlockedIncrement(&This->refs);
2924 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2926 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2927 ULONG refs = InterlockedDecrement(&This->refs);
2928 if (!refs)
2930 if (This->typelib_global)
2931 FreeResource(This->typelib_global);
2932 if (This->dll)
2933 FreeLibrary(This->dll);
2934 heap_free(This);
2936 return refs;
2939 static const IUnknownVtbl TLB_PEFile_Vtable =
2941 TLB_PEFile_QueryInterface,
2942 TLB_PEFile_AddRef,
2943 TLB_PEFile_Release
2946 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2948 TLB_PEFile *This;
2949 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2951 This = heap_alloc(sizeof(TLB_PEFile));
2952 if (!This)
2953 return E_OUTOFMEMORY;
2955 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
2956 This->refs = 1;
2957 This->dll = NULL;
2958 This->typelib_resource = NULL;
2959 This->typelib_global = NULL;
2960 This->typelib_base = NULL;
2962 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2963 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2965 if (This->dll)
2967 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2968 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2969 if (This->typelib_resource)
2971 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2972 if (This->typelib_global)
2974 This->typelib_base = LockResource(This->typelib_global);
2976 if (This->typelib_base)
2978 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2979 *ppBase = This->typelib_base;
2980 *ppFile = &This->IUnknown_iface;
2981 return S_OK;
2986 TRACE("No TYPELIB resource found\n");
2987 hr = E_FAIL;
2990 TLB_PEFile_Release(&This->IUnknown_iface);
2991 return hr;
2994 typedef struct TLB_NEFile
2996 IUnknown IUnknown_iface;
2997 LONG refs;
2998 LPVOID typelib_base;
2999 } TLB_NEFile;
3001 static inline TLB_NEFile *nefile_impl_from_IUnknown(IUnknown *iface)
3003 return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
3006 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3008 if (IsEqualIID(riid, &IID_IUnknown))
3010 *ppv = iface;
3011 IUnknown_AddRef(iface);
3012 return S_OK;
3014 *ppv = NULL;
3015 return E_NOINTERFACE;
3018 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
3020 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
3021 return InterlockedIncrement(&This->refs);
3024 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
3026 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
3027 ULONG refs = InterlockedDecrement(&This->refs);
3028 if (!refs)
3030 heap_free(This->typelib_base);
3031 heap_free(This);
3033 return refs;
3036 static const IUnknownVtbl TLB_NEFile_Vtable =
3038 TLB_NEFile_QueryInterface,
3039 TLB_NEFile_AddRef,
3040 TLB_NEFile_Release
3043 /***********************************************************************
3044 * read_xx_header [internal]
3046 static int read_xx_header( HFILE lzfd )
3048 IMAGE_DOS_HEADER mzh;
3049 char magic[3];
3051 LZSeek( lzfd, 0, SEEK_SET );
3052 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
3053 return 0;
3054 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
3055 return 0;
3057 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3058 if ( 2 != LZRead( lzfd, magic, 2 ) )
3059 return 0;
3061 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3063 if ( magic[0] == 'N' && magic[1] == 'E' )
3064 return IMAGE_OS2_SIGNATURE;
3065 if ( magic[0] == 'P' && magic[1] == 'E' )
3066 return IMAGE_NT_SIGNATURE;
3068 magic[2] = '\0';
3069 WARN("Can't handle %s files.\n", magic );
3070 return 0;
3074 /***********************************************************************
3075 * find_ne_resource [internal]
3077 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
3078 DWORD *resLen, DWORD *resOff )
3080 IMAGE_OS2_HEADER nehd;
3081 NE_TYPEINFO *typeInfo;
3082 NE_NAMEINFO *nameInfo;
3083 DWORD nehdoffset;
3084 LPBYTE resTab;
3085 DWORD resTabSize;
3086 int count;
3088 /* Read in NE header */
3089 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
3090 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return FALSE;
3092 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
3093 if ( !resTabSize )
3095 TRACE("No resources in NE dll\n" );
3096 return FALSE;
3099 /* Read in resource table */
3100 resTab = heap_alloc( resTabSize );
3101 if ( !resTab ) return FALSE;
3103 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
3104 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
3106 heap_free( resTab );
3107 return FALSE;
3110 /* Find resource */
3111 typeInfo = (NE_TYPEINFO *)(resTab + 2);
3113 if (!IS_INTRESOURCE(typeid)) /* named type */
3115 BYTE len = strlen( typeid );
3116 while (typeInfo->type_id)
3118 if (!(typeInfo->type_id & 0x8000))
3120 BYTE *p = resTab + typeInfo->type_id;
3121 if ((*p == len) && !_strnicmp( (char*)p+1, typeid, len )) goto found_type;
3123 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3124 typeInfo->count * sizeof(NE_NAMEINFO));
3127 else /* numeric type id */
3129 WORD id = LOWORD(typeid) | 0x8000;
3130 while (typeInfo->type_id)
3132 if (typeInfo->type_id == id) goto found_type;
3133 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3134 typeInfo->count * sizeof(NE_NAMEINFO));
3137 TRACE("No typeid entry found for %p\n", typeid );
3138 heap_free( resTab );
3139 return FALSE;
3141 found_type:
3142 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
3144 if (!IS_INTRESOURCE(resid)) /* named resource */
3146 BYTE len = strlen( resid );
3147 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3149 BYTE *p = resTab + nameInfo->id;
3150 if (nameInfo->id & 0x8000) continue;
3151 if ((*p == len) && !_strnicmp( (char*)p+1, resid, len )) goto found_name;
3154 else /* numeric resource id */
3156 WORD id = LOWORD(resid) | 0x8000;
3157 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3158 if (nameInfo->id == id) goto found_name;
3160 TRACE("No resid entry found for %p\n", typeid );
3161 heap_free( resTab );
3162 return FALSE;
3164 found_name:
3165 /* Return resource data */
3166 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
3167 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
3169 heap_free( resTab );
3170 return TRUE;
3173 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
3175 HFILE lzfd = -1;
3176 OFSTRUCT ofs;
3177 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
3178 TLB_NEFile *This;
3180 This = heap_alloc(sizeof(TLB_NEFile));
3181 if (!This) return E_OUTOFMEMORY;
3183 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
3184 This->refs = 1;
3185 This->typelib_base = NULL;
3187 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
3188 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
3190 DWORD reslen, offset;
3191 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
3193 This->typelib_base = heap_alloc(reslen);
3194 if( !This->typelib_base )
3195 hr = E_OUTOFMEMORY;
3196 else
3198 LZSeek( lzfd, offset, SEEK_SET );
3199 reslen = LZRead( lzfd, This->typelib_base, reslen );
3200 LZClose( lzfd );
3201 *ppBase = This->typelib_base;
3202 *pdwTLBLength = reslen;
3203 *ppFile = &This->IUnknown_iface;
3204 return S_OK;
3209 if( lzfd >= 0) LZClose( lzfd );
3210 TLB_NEFile_Release(&This->IUnknown_iface);
3211 return hr;
3214 typedef struct TLB_Mapping
3216 IUnknown IUnknown_iface;
3217 LONG refs;
3218 HANDLE file;
3219 HANDLE mapping;
3220 LPVOID typelib_base;
3221 } TLB_Mapping;
3223 static inline TLB_Mapping *mapping_impl_from_IUnknown(IUnknown *iface)
3225 return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
3228 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3230 if (IsEqualIID(riid, &IID_IUnknown))
3232 *ppv = iface;
3233 IUnknown_AddRef(iface);
3234 return S_OK;
3236 *ppv = NULL;
3237 return E_NOINTERFACE;
3240 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
3242 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3243 return InterlockedIncrement(&This->refs);
3246 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
3248 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3249 ULONG refs = InterlockedDecrement(&This->refs);
3250 if (!refs)
3252 if (This->typelib_base)
3253 UnmapViewOfFile(This->typelib_base);
3254 if (This->mapping)
3255 CloseHandle(This->mapping);
3256 if (This->file != INVALID_HANDLE_VALUE)
3257 CloseHandle(This->file);
3258 heap_free(This);
3260 return refs;
3263 static const IUnknownVtbl TLB_Mapping_Vtable =
3265 TLB_Mapping_QueryInterface,
3266 TLB_Mapping_AddRef,
3267 TLB_Mapping_Release
3270 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
3272 TLB_Mapping *This;
3274 This = heap_alloc(sizeof(TLB_Mapping));
3275 if (!This)
3276 return E_OUTOFMEMORY;
3278 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
3279 This->refs = 1;
3280 This->file = INVALID_HANDLE_VALUE;
3281 This->mapping = NULL;
3282 This->typelib_base = NULL;
3284 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3285 if (INVALID_HANDLE_VALUE != This->file)
3287 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
3288 if (This->mapping)
3290 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
3291 if(This->typelib_base)
3293 /* retrieve file size */
3294 *pdwTLBLength = GetFileSize(This->file, NULL);
3295 *ppBase = This->typelib_base;
3296 *ppFile = &This->IUnknown_iface;
3297 return S_OK;
3302 IUnknown_Release(&This->IUnknown_iface);
3303 return TYPE_E_CANTLOADLIBRARY;
3306 /****************************************************************************
3307 * TLB_ReadTypeLib
3309 * find the type of the typelib file and map the typelib resource into
3310 * the memory
3313 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3314 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
3316 ITypeLibImpl *entry;
3317 HRESULT ret;
3318 INT index = 1;
3319 LPWSTR index_str, file = (LPWSTR)pszFileName;
3320 LPVOID pBase = NULL;
3321 DWORD dwTLBLength = 0;
3322 IUnknown *pFile = NULL;
3323 HANDLE h;
3325 *ppTypeLib = NULL;
3327 index_str = wcsrchr(pszFileName, '\\');
3328 if(index_str && *++index_str != '\0')
3330 LPWSTR end_ptr;
3331 LONG idx = wcstol(index_str, &end_ptr, 10);
3332 if(*end_ptr == '\0')
3334 int str_len = index_str - pszFileName - 1;
3335 index = idx;
3336 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
3337 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
3338 file[str_len] = 0;
3342 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
3344 if(wcschr(file, '\\'))
3346 lstrcpyW(pszPath, file);
3348 else
3350 int len = GetSystemDirectoryW(pszPath, cchPath);
3351 pszPath[len] = '\\';
3352 memcpy(pszPath + len + 1, file, (lstrlenW(file) + 1) * sizeof(WCHAR));
3356 if(file != pszFileName) heap_free(file);
3358 h = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
3359 if(h != INVALID_HANDLE_VALUE){
3360 GetFinalPathNameByHandleW(h, pszPath, cchPath, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
3361 CloseHandle(h);
3364 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
3366 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3367 EnterCriticalSection(&cache_section);
3368 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
3370 if (!wcsicmp(entry->path, pszPath) && entry->index == index)
3372 TRACE("cache hit\n");
3373 *ppTypeLib = &entry->ITypeLib2_iface;
3374 ITypeLib2_AddRef(*ppTypeLib);
3375 LeaveCriticalSection(&cache_section);
3376 return S_OK;
3379 LeaveCriticalSection(&cache_section);
3381 /* now actually load and parse the typelib */
3383 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3384 if (ret == TYPE_E_CANTLOADLIBRARY)
3385 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3386 if (ret == TYPE_E_CANTLOADLIBRARY)
3387 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
3388 if (SUCCEEDED(ret))
3390 if (dwTLBLength >= 4)
3392 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
3393 if (dwSignature == MSFT_SIGNATURE)
3394 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
3395 else if (dwSignature == SLTG_SIGNATURE)
3396 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
3397 else
3399 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
3400 ret = TYPE_E_CANTLOADLIBRARY;
3403 else
3404 ret = TYPE_E_CANTLOADLIBRARY;
3405 IUnknown_Release(pFile);
3408 if(*ppTypeLib) {
3409 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
3411 TRACE("adding to cache\n");
3412 impl->path = heap_alloc((lstrlenW(pszPath)+1) * sizeof(WCHAR));
3413 lstrcpyW(impl->path, pszPath);
3414 /* We should really canonicalise the path here. */
3415 impl->index = index;
3417 /* FIXME: check if it has added already in the meantime */
3418 EnterCriticalSection(&cache_section);
3419 list_add_head(&tlb_cache, &impl->entry);
3420 LeaveCriticalSection(&cache_section);
3421 ret = S_OK;
3423 else
3425 if(ret != E_FAIL)
3426 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
3428 ret = TYPE_E_CANTLOADLIBRARY;
3432 return ret;
3435 /*================== ITypeLib(2) Methods ===================================*/
3437 static ITypeLibImpl* TypeLibImpl_Constructor(void)
3439 ITypeLibImpl* pTypeLibImpl;
3441 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
3442 if (!pTypeLibImpl) return NULL;
3444 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3445 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3446 pTypeLibImpl->ICreateTypeLib2_iface.lpVtbl = &CreateTypeLib2Vtbl;
3447 pTypeLibImpl->ref = 1;
3449 list_init(&pTypeLibImpl->implib_list);
3450 list_init(&pTypeLibImpl->custdata_list);
3451 list_init(&pTypeLibImpl->name_list);
3452 list_init(&pTypeLibImpl->string_list);
3453 list_init(&pTypeLibImpl->guid_list);
3454 list_init(&pTypeLibImpl->ref_list);
3455 pTypeLibImpl->dispatch_href = -1;
3457 return pTypeLibImpl;
3460 /****************************************************************************
3461 * ITypeLib2_Constructor_MSFT
3463 * loading an MSFT typelib from an in-memory image
3465 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3467 TLBContext cx;
3468 LONG lPSegDir;
3469 MSFT_Header tlbHeader;
3470 MSFT_SegDir tlbSegDir;
3471 ITypeLibImpl * pTypeLibImpl;
3472 int i;
3474 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3476 pTypeLibImpl = TypeLibImpl_Constructor();
3477 if (!pTypeLibImpl) return NULL;
3479 /* get pointer to beginning of typelib data */
3480 cx.pos = 0;
3481 cx.oStart=0;
3482 cx.mapping = pLib;
3483 cx.pLibInfo = pTypeLibImpl;
3484 cx.length = dwTLBLength;
3486 /* read header */
3487 MSFT_ReadLEDWords(&tlbHeader, sizeof(tlbHeader), &cx, 0);
3488 TRACE_(typelib)("header:\n");
3489 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3490 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3491 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3492 return NULL;
3494 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3496 /* there is a small amount of information here until the next important
3497 * part:
3498 * the segment directory . Try to calculate the amount of data */
3499 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3501 /* now read the segment directory */
3502 TRACE("read segment directory (at %d)\n",lPSegDir);
3503 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3504 cx.pTblDir = &tlbSegDir;
3506 /* just check two entries */
3507 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3509 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3510 heap_free(pTypeLibImpl);
3511 return NULL;
3514 MSFT_ReadAllNames(&cx);
3515 MSFT_ReadAllStrings(&cx);
3516 MSFT_ReadAllGuids(&cx);
3518 /* now fill our internal data */
3519 /* TLIBATTR fields */
3520 pTypeLibImpl->guid = MSFT_ReadGuid(tlbHeader.posguid, &cx);
3522 pTypeLibImpl->syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3523 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3524 pTypeLibImpl->ver_major = LOWORD(tlbHeader.version);
3525 pTypeLibImpl->ver_minor = HIWORD(tlbHeader.version);
3526 pTypeLibImpl->libflags = ((WORD) tlbHeader.flags & 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE;
3528 pTypeLibImpl->set_lcid = tlbHeader.lcid2;
3529 pTypeLibImpl->lcid = tlbHeader.lcid;
3531 /* name, eventually add to a hash table */
3532 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3534 /* help info */
3535 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3536 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3538 if( tlbHeader.varflags & HELPDLLFLAG)
3540 int offset;
3541 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3542 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3545 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3547 /* custom data */
3548 if(tlbHeader.CustomDataOffset >= 0)
3550 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3553 /* fill in type descriptions */
3554 if(tlbSegDir.pTypdescTab.length > 0)
3556 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3557 INT16 td[4];
3558 pTypeLibImpl->ctTypeDesc = cTD;
3559 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3560 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3561 for(i=0; i<cTD; )
3563 /* FIXME: add several sanity checks here */
3564 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3565 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3567 /* FIXME: check safearray */
3568 if(td[3] < 0)
3569 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3570 else
3571 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3573 else if(td[0] == VT_CARRAY)
3575 /* array descr table here */
3576 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3578 else if(td[0] == VT_USERDEFINED)
3580 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3582 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3585 /* second time around to fill the array subscript info */
3586 for(i=0;i<cTD;i++)
3588 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3589 if(tlbSegDir.pArrayDescriptions.offset>0)
3591 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3592 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3594 if(td[1]<0)
3595 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3596 else
3597 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3599 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3601 for(j = 0; j<td[2]; j++)
3603 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3604 sizeof(INT), &cx, DO_NOT_SEEK);
3605 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3606 sizeof(INT), &cx, DO_NOT_SEEK);
3609 else
3611 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3612 ERR("didn't find array description data\n");
3617 /* imported type libs */
3618 if(tlbSegDir.pImpFiles.offset>0)
3620 TLBImpLib *pImpLib;
3621 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3622 UINT16 size;
3624 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3626 char *name;
3628 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3629 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3630 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3632 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3633 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3634 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3635 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3637 size >>= 2;
3638 name = heap_alloc_zero(size+1);
3639 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3640 pImpLib->name = TLB_MultiByteToBSTR(name);
3641 heap_free(name);
3643 pImpLib->guid = MSFT_ReadGuid(oGuid, &cx);
3644 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3646 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3650 MSFT_ReadAllRefs(&cx);
3652 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3654 /* type infos */
3655 if(tlbHeader.nrtypeinfos >= 0 )
3657 ITypeInfoImpl **ppTI;
3659 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3661 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3663 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3665 ++ppTI;
3666 (pTypeLibImpl->TypeInfoCount)++;
3670 #ifdef _WIN64
3671 if(pTypeLibImpl->syskind == SYS_WIN32){
3672 for(i = 0; i < pTypeLibImpl->TypeInfoCount; ++i)
3673 TLB_fix_32on64_typeinfo(pTypeLibImpl->typeinfos[i]);
3675 #endif
3677 TRACE("(%p)\n", pTypeLibImpl);
3678 return &pTypeLibImpl->ITypeLib2_iface;
3682 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3684 char b[3];
3685 int i;
3686 short s;
3688 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3689 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3690 return FALSE;
3693 guid->Data4[0] = s >> 8;
3694 guid->Data4[1] = s & 0xff;
3696 b[2] = '\0';
3697 for(i = 0; i < 6; i++) {
3698 memcpy(b, str + 24 + 2 * i, 2);
3699 guid->Data4[i + 2] = strtol(b, NULL, 16);
3701 return TRUE;
3704 static WORD SLTG_ReadString(const char *ptr, const TLBString **pStr, ITypeLibImpl *lib)
3706 WORD bytelen;
3707 DWORD len;
3708 BSTR tmp_str;
3710 *pStr = NULL;
3711 bytelen = *(const WORD*)ptr;
3712 if(bytelen == 0xffff) return 2;
3714 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3715 tmp_str = SysAllocStringLen(NULL, len);
3716 if (tmp_str) {
3717 MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, tmp_str, len);
3718 *pStr = TLB_append_str(&lib->string_list, tmp_str);
3719 SysFreeString(tmp_str);
3721 return bytelen + 2;
3724 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3726 WORD bytelen;
3728 *str = NULL;
3729 bytelen = *(const WORD*)ptr;
3730 if(bytelen == 0xffff) return 2;
3731 *str = heap_alloc(bytelen + 1);
3732 memcpy(*str, ptr + 2, bytelen);
3733 (*str)[bytelen] = '\0';
3734 return bytelen + 2;
3737 static TLBString *SLTG_ReadName(const char *pNameTable, int offset, ITypeLibImpl *lib)
3739 BSTR tmp_str;
3740 TLBString *tlbstr;
3742 LIST_FOR_EACH_ENTRY(tlbstr, &lib->name_list, TLBString, entry) {
3743 if (tlbstr->offset == offset)
3744 return tlbstr;
3747 tmp_str = TLB_MultiByteToBSTR(pNameTable + offset);
3748 tlbstr = TLB_append_str(&lib->name_list, tmp_str);
3749 SysFreeString(tmp_str);
3751 return tlbstr;
3754 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3756 char *ptr = pLibBlk;
3757 WORD w;
3759 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3760 FIXME("libblk magic = %04x\n", w);
3761 return 0;
3764 ptr += 6;
3765 if((w = *(WORD*)ptr) != 0xffff) {
3766 FIXME("LibBlk.res06 = %04x. Assuming string and skipping\n", w);
3767 ptr += w;
3769 ptr += 2;
3771 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString, pTypeLibImpl);
3773 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile, pTypeLibImpl);
3775 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3776 ptr += 4;
3778 pTypeLibImpl->syskind = *(WORD*)ptr;
3779 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3780 ptr += 2;
3782 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3783 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3784 else
3785 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = 0;
3786 ptr += 2;
3788 ptr += 4; /* skip res12 */
3790 pTypeLibImpl->libflags = *(WORD*)ptr;
3791 ptr += 2;
3793 pTypeLibImpl->ver_major = *(WORD*)ptr;
3794 ptr += 2;
3796 pTypeLibImpl->ver_minor = *(WORD*)ptr;
3797 ptr += 2;
3799 pTypeLibImpl->guid = TLB_append_guid(&pTypeLibImpl->guid_list, (GUID*)ptr, -2);
3800 ptr += sizeof(GUID);
3802 return ptr - (char*)pLibBlk;
3805 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3806 typedef struct
3808 unsigned int num;
3809 HREFTYPE refs[1];
3810 } sltg_ref_lookup_t;
3812 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3813 HREFTYPE *typelib_ref)
3815 if(table && typeinfo_ref < table->num)
3817 *typelib_ref = table->refs[typeinfo_ref];
3818 return S_OK;
3821 ERR_(typelib)("Unable to find reference\n");
3822 *typelib_ref = -1;
3823 return E_FAIL;
3826 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3828 BOOL done = FALSE;
3830 while(!done) {
3831 if((*pType & 0xe00) == 0xe00) {
3832 pTD->vt = VT_PTR;
3833 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3834 pTD = pTD->u.lptdesc;
3836 switch(*pType & 0x3f) {
3837 case VT_PTR:
3838 pTD->vt = VT_PTR;
3839 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3840 pTD = pTD->u.lptdesc;
3841 break;
3843 case VT_USERDEFINED:
3844 pTD->vt = VT_USERDEFINED;
3845 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3846 done = TRUE;
3847 break;
3849 case VT_CARRAY:
3851 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3852 array */
3854 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3856 pTD->vt = VT_CARRAY;
3857 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3858 pTD->u.lpadesc->cDims = pSA->cDims;
3859 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3860 pSA->cDims * sizeof(SAFEARRAYBOUND));
3862 pTD = &pTD->u.lpadesc->tdescElem;
3863 break;
3866 case VT_SAFEARRAY:
3868 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3869 useful? */
3871 pType++;
3872 pTD->vt = VT_SAFEARRAY;
3873 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3874 pTD = pTD->u.lptdesc;
3875 break;
3877 default:
3878 pTD->vt = *pType & 0x3f;
3879 done = TRUE;
3880 break;
3882 pType++;
3884 return pType;
3887 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3888 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3890 /* Handle [in/out] first */
3891 if((*pType & 0xc000) == 0xc000)
3892 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3893 else if(*pType & 0x8000)
3894 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3895 else if(*pType & 0x4000)
3896 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3897 else
3898 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3900 if(*pType & 0x2000)
3901 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3903 if(*pType & 0x80)
3904 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3906 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3910 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3911 char *pNameTable)
3913 unsigned int ref;
3914 char *name;
3915 TLBRefType *ref_type;
3916 sltg_ref_lookup_t *table;
3917 HREFTYPE typelib_ref;
3919 if(pRef->magic != SLTG_REF_MAGIC) {
3920 FIXME("Ref magic = %x\n", pRef->magic);
3921 return NULL;
3923 name = ( (char*)pRef->names + pRef->number);
3925 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3926 table->num = pRef->number >> 3;
3928 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3930 /* We don't want the first href to be 0 */
3931 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3933 for(ref = 0; ref < pRef->number >> 3; ref++) {
3934 char *refname;
3935 unsigned int lib_offs, type_num;
3937 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3939 name += SLTG_ReadStringA(name, &refname);
3940 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3941 FIXME_(typelib)("Can't sscanf ref\n");
3942 if(lib_offs != 0xffff) {
3943 TLBImpLib *import;
3945 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
3946 if(import->offset == lib_offs)
3947 break;
3949 if(&import->entry == &pTL->implib_list) {
3950 char fname[MAX_PATH+1];
3951 int len;
3952 GUID tmpguid;
3954 import = heap_alloc_zero(sizeof(*import));
3955 import->offset = lib_offs;
3956 TLB_GUIDFromString( pNameTable + lib_offs + 4, &tmpguid);
3957 import->guid = TLB_append_guid(&pTL->guid_list, &tmpguid, 2);
3958 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3959 &import->wVersionMajor,
3960 &import->wVersionMinor,
3961 &import->lcid, fname) != 4) {
3962 FIXME_(typelib)("can't sscanf ref %s\n",
3963 pNameTable + lib_offs + 40);
3965 len = strlen(fname);
3966 if(fname[len-1] != '#')
3967 FIXME("fname = %s\n", fname);
3968 fname[len-1] = '\0';
3969 import->name = TLB_MultiByteToBSTR(fname);
3970 list_add_tail(&pTL->implib_list, &import->entry);
3972 ref_type->pImpTLInfo = import;
3974 /* Store a reference to IDispatch */
3975 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid->guid, &IID_StdOle) && type_num == 4)
3976 pTL->dispatch_href = typelib_ref;
3978 } else { /* internal ref */
3979 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3981 ref_type->reference = typelib_ref;
3982 ref_type->index = type_num;
3984 heap_free(refname);
3985 list_add_tail(&pTL->ref_list, &ref_type->entry);
3987 table->refs[ref] = typelib_ref;
3988 typelib_ref += 4;
3990 if((BYTE)*name != SLTG_REF_MAGIC)
3991 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3992 dump_TLBRefType(pTL);
3993 return table;
3996 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3997 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3999 SLTG_ImplInfo *info;
4000 TLBImplType *pImplType;
4001 /* I don't really get this structure, usually it's 0x16 bytes
4002 long, but iuser.tlb contains some that are 0x18 bytes long.
4003 That's ok because we can use the next ptr to jump to the next
4004 one. But how do we know the length of the last one? The WORD
4005 at offs 0x8 might be the clue. For now I'm just assuming that
4006 the last one is the regular 0x16 bytes. */
4008 info = (SLTG_ImplInfo*)pBlk;
4009 while(1){
4010 pTI->typeattr.cImplTypes++;
4011 if(info->next == 0xffff)
4012 break;
4013 info = (SLTG_ImplInfo*)(pBlk + info->next);
4016 info = (SLTG_ImplInfo*)pBlk;
4017 pTI->impltypes = TLBImplType_Alloc(pTI->typeattr.cImplTypes);
4018 pImplType = pTI->impltypes;
4019 while(1) {
4020 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
4021 pImplType->implflags = info->impltypeflags;
4022 ++pImplType;
4024 if(info->next == 0xffff)
4025 break;
4026 if(OneOnly)
4027 FIXME_(typelib)("Interface inheriting more than one interface\n");
4028 info = (SLTG_ImplInfo*)(pBlk + info->next);
4030 info++; /* see comment at top of function */
4031 return (char*)info;
4034 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
4035 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4037 TLBVarDesc *pVarDesc;
4038 const TLBString *prevName = NULL;
4039 SLTG_Variable *pItem;
4040 unsigned short i;
4041 WORD *pType;
4043 pVarDesc = pTI->vardescs = TLBVarDesc_Alloc(cVars);
4045 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
4046 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
4048 pVarDesc->vardesc.memid = pItem->memid;
4050 if (pItem->magic != SLTG_VAR_MAGIC &&
4051 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
4052 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
4053 return;
4056 if (pItem->name == 0xfffe)
4057 pVarDesc->Name = prevName;
4058 else
4059 pVarDesc->Name = SLTG_ReadName(pNameTable, pItem->name, pTI->pTypeLib);
4061 TRACE_(typelib)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc->Name)));
4062 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
4063 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
4065 if(pItem->flags & 0x02)
4066 pType = &pItem->type;
4067 else
4068 pType = (WORD*)(pBlk + pItem->type);
4070 if (pItem->flags & ~0xda)
4071 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
4073 SLTG_DoElem(pType, pBlk,
4074 &pVarDesc->vardesc.elemdescVar, ref_lookup);
4076 if (TRACE_ON(typelib)) {
4077 char buf[300];
4078 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
4079 TRACE_(typelib)("elemdescVar: %s\n", buf);
4082 if (pItem->flags & 0x40) {
4083 TRACE_(typelib)("VAR_DISPATCH\n");
4084 pVarDesc->vardesc.varkind = VAR_DISPATCH;
4086 else if (pItem->flags & 0x10) {
4087 TRACE_(typelib)("VAR_CONST\n");
4088 pVarDesc->vardesc.varkind = VAR_CONST;
4089 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
4090 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
4091 if (pItem->flags & 0x08)
4092 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
4093 else {
4094 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
4096 case VT_LPSTR:
4097 case VT_LPWSTR:
4098 case VT_BSTR:
4100 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
4101 BSTR str;
4102 TRACE_(typelib)("len = %u\n", len);
4103 if (len == 0xffff) {
4104 str = NULL;
4105 } else {
4106 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
4107 str = SysAllocStringLen(NULL, alloc_len);
4108 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
4110 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
4111 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
4112 break;
4114 case VT_I2:
4115 case VT_UI2:
4116 case VT_I4:
4117 case VT_UI4:
4118 case VT_INT:
4119 case VT_UINT:
4120 V_INT(pVarDesc->vardesc.u.lpvarValue) =
4121 *(INT*)(pBlk + pItem->byte_offs);
4122 break;
4123 default:
4124 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
4128 else {
4129 TRACE_(typelib)("VAR_PERINSTANCE\n");
4130 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
4131 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
4134 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
4135 pVarDesc->vardesc.wVarFlags = pItem->varflags;
4137 if (pItem->flags & 0x80)
4138 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
4140 prevName = pVarDesc->Name;
4142 pTI->typeattr.cVars = cVars;
4145 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
4146 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4148 SLTG_Function *pFunc;
4149 unsigned short i;
4150 TLBFuncDesc *pFuncDesc;
4152 pTI->funcdescs = TLBFuncDesc_Alloc(cFuncs);
4154 pFuncDesc = pTI->funcdescs;
4155 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
4156 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
4158 int param;
4159 WORD *pType, *pArg;
4161 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
4162 case SLTG_FUNCTION_MAGIC:
4163 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
4164 break;
4165 case SLTG_DISPATCH_FUNCTION_MAGIC:
4166 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
4167 break;
4168 case SLTG_STATIC_FUNCTION_MAGIC:
4169 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
4170 break;
4171 default:
4172 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
4173 continue;
4175 pFuncDesc->Name = SLTG_ReadName(pNameTable, pFunc->name, pTI->pTypeLib);
4177 pFuncDesc->funcdesc.memid = pFunc->dispid;
4178 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
4179 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
4180 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
4181 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
4182 pFuncDesc->funcdesc.oVft = (pFunc->vtblpos & ~1) * sizeof(void *) / pTI->pTypeLib->ptr_size;
4184 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
4185 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
4187 if(pFunc->retnextopt & 0x80)
4188 pType = &pFunc->rettype;
4189 else
4190 pType = (WORD*)(pBlk + pFunc->rettype);
4192 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
4194 pFuncDesc->funcdesc.lprgelemdescParam =
4195 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
4196 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
4198 pArg = (WORD*)(pBlk + pFunc->arg_off);
4200 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
4201 char *paramName = pNameTable + *pArg;
4202 BOOL HaveOffs;
4203 /* If arg type follows then paramName points to the 2nd
4204 letter of the name, else the next WORD is an offset to
4205 the arg type and paramName points to the first letter.
4206 So let's take one char off paramName and see if we're
4207 pointing at an alphanumeric char. However if *pArg is
4208 0xffff or 0xfffe then the param has no name, the former
4209 meaning that the next WORD is the type, the latter
4210 meaning that the next WORD is an offset to the type. */
4212 HaveOffs = FALSE;
4213 if(*pArg == 0xffff)
4214 paramName = NULL;
4215 else if(*pArg == 0xfffe) {
4216 paramName = NULL;
4217 HaveOffs = TRUE;
4219 else if(paramName[-1] && !isalnum(paramName[-1]))
4220 HaveOffs = TRUE;
4222 pArg++;
4224 if(HaveOffs) { /* the next word is an offset to type */
4225 pType = (WORD*)(pBlk + *pArg);
4226 SLTG_DoElem(pType, pBlk,
4227 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4228 pArg++;
4229 } else {
4230 if(paramName)
4231 paramName--;
4232 pArg = SLTG_DoElem(pArg, pBlk,
4233 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4236 /* Are we an optional param ? */
4237 if(pFuncDesc->funcdesc.cParams - param <=
4238 pFuncDesc->funcdesc.cParamsOpt)
4239 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
4241 if(paramName) {
4242 pFuncDesc->pParamDesc[param].Name = SLTG_ReadName(pNameTable,
4243 paramName - pNameTable, pTI->pTypeLib);
4244 } else {
4245 pFuncDesc->pParamDesc[param].Name = pFuncDesc->Name;
4249 pTI->typeattr.cFuncs = cFuncs;
4252 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
4253 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4254 SLTG_TypeInfoTail *pTITail)
4256 char *pFirstItem;
4257 sltg_ref_lookup_t *ref_lookup = NULL;
4259 if(pTIHeader->href_table != 0xffffffff) {
4260 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4261 pNameTable);
4264 pFirstItem = pBlk;
4266 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4267 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
4269 heap_free(ref_lookup);
4273 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
4274 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4275 const SLTG_TypeInfoTail *pTITail)
4277 char *pFirstItem;
4278 sltg_ref_lookup_t *ref_lookup = NULL;
4280 if(pTIHeader->href_table != 0xffffffff) {
4281 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4282 pNameTable);
4285 pFirstItem = pBlk;
4287 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4288 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
4291 if (pTITail->funcs_off != 0xffff)
4292 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4294 heap_free(ref_lookup);
4296 if (TRACE_ON(typelib))
4297 dump_TLBFuncDesc(pTI->funcdescs, pTI->typeattr.cFuncs);
4300 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
4301 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4302 const SLTG_TypeInfoTail *pTITail)
4304 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4307 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
4308 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4309 const SLTG_TypeInfoTail *pTITail)
4311 WORD *pType;
4312 sltg_ref_lookup_t *ref_lookup = NULL;
4314 if (pTITail->simple_alias) {
4315 /* if simple alias, no more processing required */
4316 pTI->tdescAlias = heap_alloc_zero(sizeof(TYPEDESC));
4317 pTI->tdescAlias->vt = pTITail->tdescalias_vt;
4318 return;
4321 if(pTIHeader->href_table != 0xffffffff) {
4322 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4323 pNameTable);
4326 /* otherwise it is an offset to a type */
4327 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
4329 pTI->tdescAlias = heap_alloc(sizeof(TYPEDESC));
4330 SLTG_DoType(pType, pBlk, pTI->tdescAlias, ref_lookup);
4332 heap_free(ref_lookup);
4335 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
4336 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4337 const SLTG_TypeInfoTail *pTITail)
4339 sltg_ref_lookup_t *ref_lookup = NULL;
4340 if (pTIHeader->href_table != 0xffffffff)
4341 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4342 pNameTable);
4344 if (pTITail->vars_off != 0xffff)
4345 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4347 if (pTITail->funcs_off != 0xffff)
4348 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4350 if (pTITail->impls_off != 0xffff)
4351 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
4353 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4354 * of dispinterface functions including the IDispatch ones, so
4355 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4356 pTI->typeattr.cbSizeVft = pTI->typeattr.cFuncs * pTI->pTypeLib->ptr_size;
4358 heap_free(ref_lookup);
4359 if (TRACE_ON(typelib))
4360 dump_TLBFuncDesc(pTI->funcdescs, pTI->typeattr.cFuncs);
4363 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
4364 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4365 const SLTG_TypeInfoTail *pTITail)
4367 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4370 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
4371 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4372 const SLTG_TypeInfoTail *pTITail)
4374 sltg_ref_lookup_t *ref_lookup = NULL;
4375 if (pTIHeader->href_table != 0xffffffff)
4376 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4377 pNameTable);
4379 if (pTITail->vars_off != 0xffff)
4380 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4382 if (pTITail->funcs_off != 0xffff)
4383 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4384 heap_free(ref_lookup);
4385 if (TRACE_ON(typelib))
4386 dump_TypeInfo(pTI);
4389 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4390 manageable copy of it into this */
4391 typedef struct {
4392 WORD small_no;
4393 char *index_name;
4394 char *other_name;
4395 WORD res1a;
4396 WORD name_offs;
4397 WORD more_bytes;
4398 char *extra;
4399 WORD res20;
4400 DWORD helpcontext;
4401 WORD res26;
4402 GUID uuid;
4403 } SLTG_InternalOtherTypeInfo;
4405 /****************************************************************************
4406 * ITypeLib2_Constructor_SLTG
4408 * loading a SLTG typelib from an in-memory image
4410 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
4412 ITypeLibImpl *pTypeLibImpl;
4413 SLTG_Header *pHeader;
4414 SLTG_BlkEntry *pBlkEntry;
4415 SLTG_Magic *pMagic;
4416 SLTG_Index *pIndex;
4417 SLTG_Pad9 *pPad9;
4418 LPVOID pBlk, pFirstBlk;
4419 SLTG_LibBlk *pLibBlk;
4420 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
4421 char *pAfterOTIBlks = NULL;
4422 char *pNameTable, *ptr;
4423 int i;
4424 DWORD len, order;
4425 ITypeInfoImpl **ppTypeInfoImpl;
4427 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
4430 pTypeLibImpl = TypeLibImpl_Constructor();
4431 if (!pTypeLibImpl) return NULL;
4433 pHeader = pLib;
4435 TRACE_(typelib)("header:\n");
4436 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
4437 pHeader->nrOfFileBlks );
4438 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
4439 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
4440 pHeader->SLTG_magic);
4441 return NULL;
4444 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4445 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
4447 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4448 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
4450 /* Next we have a magic block */
4451 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
4453 /* Let's see if we're still in sync */
4454 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
4455 sizeof(SLTG_COMPOBJ_MAGIC))) {
4456 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
4457 return NULL;
4459 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
4460 sizeof(SLTG_DIR_MAGIC))) {
4461 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
4462 return NULL;
4465 pIndex = (SLTG_Index*)(pMagic+1);
4467 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
4469 pFirstBlk = pPad9 + 1;
4471 /* We'll set up a ptr to the main library block, which is the last one. */
4473 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1;
4474 pBlkEntry[order].next != 0;
4475 order = pBlkEntry[order].next - 1) {
4476 pBlk = (char*)pBlk + pBlkEntry[order].len;
4478 pLibBlk = pBlk;
4480 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
4482 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4483 interspersed */
4485 len += 0x40;
4487 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4489 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
4492 ptr = (char*)pLibBlk + len;
4494 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4495 WORD w, extra;
4496 len = 0;
4498 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
4500 w = *(WORD*)(ptr + 2);
4501 if(w != 0xffff) {
4502 len += w;
4503 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
4504 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4505 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4507 w = *(WORD*)(ptr + 4 + len);
4508 if(w != 0xffff) {
4509 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4510 len += w;
4511 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4512 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4513 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4515 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4516 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4517 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4518 if(extra) {
4519 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4520 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4521 len += extra;
4523 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4524 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4525 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4526 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4527 len += sizeof(SLTG_OtherTypeInfo);
4528 ptr += len;
4531 pAfterOTIBlks = ptr;
4533 /* Skip this WORD and get the next DWORD */
4534 len = *(DWORD*)(pAfterOTIBlks + 2);
4536 /* Now add this to pLibBLk look at what we're pointing at and
4537 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4538 dust and we should be pointing at the beginning of the name
4539 table */
4541 pNameTable = (char*)pLibBlk + len;
4543 switch(*(WORD*)pNameTable) {
4544 case 0xffff:
4545 break;
4546 case 0x0200:
4547 pNameTable += 0x20;
4548 break;
4549 default:
4550 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4551 break;
4554 pNameTable += 0x216;
4556 pNameTable += 2;
4558 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4560 pTypeLibImpl->Name = SLTG_ReadName(pNameTable, pLibBlk->name, pTypeLibImpl);
4563 /* Hopefully we now have enough ptrs set up to actually read in
4564 some TypeInfos. It's not clear which order to do them in, so
4565 I'll just follow the links along the BlkEntry chain and read
4566 them in the order in which they are in the file */
4568 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4569 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4571 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4572 pBlkEntry[order].next != 0;
4573 order = pBlkEntry[order].next - 1, i++) {
4575 SLTG_TypeInfoHeader *pTIHeader;
4576 SLTG_TypeInfoTail *pTITail;
4577 SLTG_MemberHeader *pMemHeader;
4579 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4580 FIXME_(typelib)("Index strings don't match\n");
4581 heap_free(pOtherTypeInfoBlks);
4582 return NULL;
4585 pTIHeader = pBlk;
4586 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4587 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4588 heap_free(pOtherTypeInfoBlks);
4589 return NULL;
4591 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4592 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4593 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4595 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4596 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4597 (*ppTypeInfoImpl)->index = i;
4598 (*ppTypeInfoImpl)->Name = SLTG_ReadName(pNameTable, pOtherTypeInfoBlks[i].name_offs, pTypeLibImpl);
4599 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4600 (*ppTypeInfoImpl)->guid = TLB_append_guid(&pTypeLibImpl->guid_list, &pOtherTypeInfoBlks[i].uuid, 2);
4601 (*ppTypeInfoImpl)->typeattr.typekind = pTIHeader->typekind;
4602 (*ppTypeInfoImpl)->typeattr.wMajorVerNum = pTIHeader->major_version;
4603 (*ppTypeInfoImpl)->typeattr.wMinorVerNum = pTIHeader->minor_version;
4604 (*ppTypeInfoImpl)->typeattr.wTypeFlags =
4605 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4607 if((*ppTypeInfoImpl)->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
4608 (*ppTypeInfoImpl)->typeattr.typekind = TKIND_DISPATCH;
4610 if((pTIHeader->typeflags1 & 7) != 2)
4611 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4612 if(pTIHeader->typeflags3 != 2)
4613 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4615 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4616 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl)->Name)),
4617 typekind_desc[pTIHeader->typekind],
4618 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl)->guid)),
4619 (*ppTypeInfoImpl)->typeattr.wTypeFlags);
4621 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4623 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4625 (*ppTypeInfoImpl)->typeattr.cbAlignment = pTITail->cbAlignment;
4626 (*ppTypeInfoImpl)->typeattr.cbSizeInstance = pTITail->cbSizeInstance;
4627 (*ppTypeInfoImpl)->typeattr.cbSizeVft = pTITail->cbSizeVft;
4629 switch(pTIHeader->typekind) {
4630 case TKIND_ENUM:
4631 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4632 pTIHeader, pTITail);
4633 break;
4635 case TKIND_RECORD:
4636 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4637 pTIHeader, pTITail);
4638 break;
4640 case TKIND_INTERFACE:
4641 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4642 pTIHeader, pTITail);
4643 break;
4645 case TKIND_COCLASS:
4646 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4647 pTIHeader, pTITail);
4648 break;
4650 case TKIND_ALIAS:
4651 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4652 pTIHeader, pTITail);
4653 break;
4655 case TKIND_DISPATCH:
4656 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4657 pTIHeader, pTITail);
4658 break;
4660 case TKIND_MODULE:
4661 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4662 pTIHeader, pTITail);
4663 break;
4665 default:
4666 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4667 break;
4671 /* could get cFuncs, cVars and cImplTypes from here
4672 but we've already set those */
4673 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4674 X(06);
4675 X(16);
4676 X(18);
4677 X(1a);
4678 X(1e);
4679 X(24);
4680 X(26);
4681 X(2a);
4682 X(2c);
4683 X(2e);
4684 X(30);
4685 X(32);
4686 X(34);
4687 #undef X
4688 ++ppTypeInfoImpl;
4689 pBlk = (char*)pBlk + pBlkEntry[order].len;
4692 if(i != pTypeLibImpl->TypeInfoCount) {
4693 FIXME("Somehow processed %d TypeInfos\n", i);
4694 heap_free(pOtherTypeInfoBlks);
4695 return NULL;
4698 heap_free(pOtherTypeInfoBlks);
4699 return &pTypeLibImpl->ITypeLib2_iface;
4702 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4704 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4706 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4708 if(IsEqualIID(riid, &IID_IUnknown) ||
4709 IsEqualIID(riid,&IID_ITypeLib)||
4710 IsEqualIID(riid,&IID_ITypeLib2))
4712 *ppv = &This->ITypeLib2_iface;
4714 else if(IsEqualIID(riid, &IID_ICreateTypeLib) ||
4715 IsEqualIID(riid, &IID_ICreateTypeLib2))
4717 *ppv = &This->ICreateTypeLib2_iface;
4719 else
4721 *ppv = NULL;
4722 TRACE("-- Interface: E_NOINTERFACE\n");
4723 return E_NOINTERFACE;
4726 IUnknown_AddRef((IUnknown*)*ppv);
4727 return S_OK;
4730 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4732 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4733 ULONG ref = InterlockedIncrement(&This->ref);
4735 TRACE("(%p) ref=%u\n", This, ref);
4737 return ref;
4740 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4742 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4743 ULONG ref = InterlockedDecrement(&This->ref);
4745 TRACE("(%p) ref=%u\n",This, ref);
4747 if (!ref)
4749 TLBImpLib *pImpLib, *pImpLibNext;
4750 TLBRefType *ref_type, *ref_type_next;
4751 TLBString *tlbstr, *tlbstr_next;
4752 TLBGuid *tlbguid, *tlbguid_next;
4753 int i;
4755 /* remove cache entry */
4756 if(This->path)
4758 TRACE("removing from cache list\n");
4759 EnterCriticalSection(&cache_section);
4760 if(This->entry.next)
4761 list_remove(&This->entry);
4762 LeaveCriticalSection(&cache_section);
4763 heap_free(This->path);
4765 TRACE(" destroying ITypeLib(%p)\n",This);
4767 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->string_list, TLBString, entry) {
4768 list_remove(&tlbstr->entry);
4769 SysFreeString(tlbstr->str);
4770 heap_free(tlbstr);
4773 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->name_list, TLBString, entry) {
4774 list_remove(&tlbstr->entry);
4775 SysFreeString(tlbstr->str);
4776 heap_free(tlbstr);
4779 LIST_FOR_EACH_ENTRY_SAFE(tlbguid, tlbguid_next, &This->guid_list, TLBGuid, entry) {
4780 list_remove(&tlbguid->entry);
4781 heap_free(tlbguid);
4784 TLB_FreeCustData(&This->custdata_list);
4786 for (i = 0; i < This->ctTypeDesc; i++)
4787 if (This->pTypeDesc[i].vt == VT_CARRAY)
4788 heap_free(This->pTypeDesc[i].u.lpadesc);
4790 heap_free(This->pTypeDesc);
4792 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4794 if (pImpLib->pImpTypeLib)
4795 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4796 SysFreeString(pImpLib->name);
4798 list_remove(&pImpLib->entry);
4799 heap_free(pImpLib);
4802 LIST_FOR_EACH_ENTRY_SAFE(ref_type, ref_type_next, &This->ref_list, TLBRefType, entry)
4804 list_remove(&ref_type->entry);
4805 heap_free(ref_type);
4808 for (i = 0; i < This->TypeInfoCount; ++i){
4809 heap_free(This->typeinfos[i]->tdescAlias);
4810 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4812 heap_free(This->typeinfos);
4813 heap_free(This);
4814 return 0;
4817 return ref;
4820 /* ITypeLib::GetTypeInfoCount
4822 * Returns the number of type descriptions in the type library
4824 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4826 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4827 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4828 return This->TypeInfoCount;
4831 /* ITypeLib::GetTypeInfo
4833 * retrieves the specified type description in the library.
4835 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4836 ITypeLib2 *iface,
4837 UINT index,
4838 ITypeInfo **ppTInfo)
4840 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4842 TRACE("%p %u %p\n", This, index, ppTInfo);
4844 if(!ppTInfo)
4845 return E_INVALIDARG;
4847 if(index >= This->TypeInfoCount)
4848 return TYPE_E_ELEMENTNOTFOUND;
4850 *ppTInfo = (ITypeInfo *)&This->typeinfos[index]->ITypeInfo2_iface;
4851 ITypeInfo_AddRef(*ppTInfo);
4853 return S_OK;
4857 /* ITypeLibs::GetTypeInfoType
4859 * Retrieves the type of a type description.
4861 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4862 ITypeLib2 *iface,
4863 UINT index,
4864 TYPEKIND *pTKind)
4866 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4868 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4870 if(!pTKind)
4871 return E_INVALIDARG;
4873 if(index >= This->TypeInfoCount)
4874 return TYPE_E_ELEMENTNOTFOUND;
4876 *pTKind = This->typeinfos[index]->typeattr.typekind;
4878 return S_OK;
4881 /* ITypeLib::GetTypeInfoOfGuid
4883 * Retrieves the type description that corresponds to the specified GUID.
4886 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4887 ITypeLib2 *iface,
4888 REFGUID guid,
4889 ITypeInfo **ppTInfo)
4891 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4892 int i;
4894 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4896 for(i = 0; i < This->TypeInfoCount; ++i){
4897 if(IsEqualIID(TLB_get_guid_null(This->typeinfos[i]->guid), guid)){
4898 *ppTInfo = (ITypeInfo *)&This->typeinfos[i]->ITypeInfo2_iface;
4899 ITypeInfo_AddRef(*ppTInfo);
4900 return S_OK;
4904 return TYPE_E_ELEMENTNOTFOUND;
4907 /* ITypeLib::GetLibAttr
4909 * Retrieves the structure that contains the library's attributes.
4912 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4913 ITypeLib2 *iface,
4914 LPTLIBATTR *attr)
4916 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4918 TRACE("(%p, %p)\n", This, attr);
4920 if (!attr) return E_INVALIDARG;
4922 *attr = heap_alloc(sizeof(**attr));
4923 if (!*attr) return E_OUTOFMEMORY;
4925 (*attr)->guid = *TLB_get_guid_null(This->guid);
4926 (*attr)->lcid = This->set_lcid;
4927 (*attr)->syskind = This->syskind;
4928 (*attr)->wMajorVerNum = This->ver_major;
4929 (*attr)->wMinorVerNum = This->ver_minor;
4930 (*attr)->wLibFlags = This->libflags;
4932 return S_OK;
4935 /* ITypeLib::GetTypeComp
4937 * Enables a client compiler to bind to a library's types, variables,
4938 * constants, and global functions.
4941 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4942 ITypeLib2 *iface,
4943 ITypeComp **ppTComp)
4945 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4947 TRACE("(%p)->(%p)\n",This,ppTComp);
4948 *ppTComp = &This->ITypeComp_iface;
4949 ITypeComp_AddRef(*ppTComp);
4951 return S_OK;
4954 /* ITypeLib::GetDocumentation
4956 * Retrieves the library's documentation string, the complete Help file name
4957 * and path, and the context identifier for the library Help topic in the Help
4958 * file.
4960 * On a successful return all non-null BSTR pointers will have been set,
4961 * possibly to NULL.
4963 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4964 ITypeLib2 *iface,
4965 INT index,
4966 BSTR *pBstrName,
4967 BSTR *pBstrDocString,
4968 DWORD *pdwHelpContext,
4969 BSTR *pBstrHelpFile)
4971 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4972 HRESULT result = E_INVALIDARG;
4973 ITypeInfo *pTInfo;
4975 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4976 This, index,
4977 pBstrName, pBstrDocString,
4978 pdwHelpContext, pBstrHelpFile);
4980 if(index<0)
4982 /* documentation for the typelib */
4983 if(pBstrName)
4985 if (This->Name)
4987 if(!(*pBstrName = SysAllocString(TLB_get_bstr(This->Name))))
4988 goto memerr1;
4990 else
4991 *pBstrName = NULL;
4993 if(pBstrDocString)
4995 if (This->DocString)
4997 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->DocString))))
4998 goto memerr2;
5000 else
5001 *pBstrDocString = NULL;
5003 if(pdwHelpContext)
5005 *pdwHelpContext = This->dwHelpContext;
5007 if(pBstrHelpFile)
5009 if (This->HelpFile)
5011 if(!(*pBstrHelpFile = SysAllocString(TLB_get_bstr(This->HelpFile))))
5012 goto memerr3;
5014 else
5015 *pBstrHelpFile = NULL;
5018 result = S_OK;
5020 else
5022 /* for a typeinfo */
5023 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
5025 if(SUCCEEDED(result))
5027 result = ITypeInfo_GetDocumentation(pTInfo,
5028 MEMBERID_NIL,
5029 pBstrName,
5030 pBstrDocString,
5031 pdwHelpContext, pBstrHelpFile);
5033 ITypeInfo_Release(pTInfo);
5036 return result;
5037 memerr3:
5038 if (pBstrDocString) SysFreeString (*pBstrDocString);
5039 memerr2:
5040 if (pBstrName) SysFreeString (*pBstrName);
5041 memerr1:
5042 return STG_E_INSUFFICIENTMEMORY;
5045 /* ITypeLib::IsName
5047 * Indicates whether a passed-in string contains the name of a type or member
5048 * described in the library.
5051 static HRESULT WINAPI ITypeLib2_fnIsName(
5052 ITypeLib2 *iface,
5053 LPOLESTR szNameBuf,
5054 ULONG lHashVal,
5055 BOOL *pfName)
5057 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5058 int tic;
5059 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
5061 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
5062 pfName);
5064 *pfName=TRUE;
5065 for(tic = 0; tic < This->TypeInfoCount; ++tic){
5066 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5067 if(!TLB_str_memcmp(szNameBuf, pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5068 for(fdc = 0; fdc < pTInfo->typeattr.cFuncs; ++fdc) {
5069 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
5070 int pc;
5071 if(!TLB_str_memcmp(szNameBuf, pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5072 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++){
5073 if(!TLB_str_memcmp(szNameBuf, pFInfo->pParamDesc[pc].Name, nNameBufLen))
5074 goto ITypeLib2_fnIsName_exit;
5077 for(vrc = 0; vrc < pTInfo->typeattr.cVars; ++vrc){
5078 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
5079 if(!TLB_str_memcmp(szNameBuf, pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5083 *pfName=FALSE;
5085 ITypeLib2_fnIsName_exit:
5086 TRACE("(%p)slow! search for %s: %sfound!\n", This,
5087 debugstr_w(szNameBuf), *pfName ? "" : "NOT ");
5089 return S_OK;
5092 /* ITypeLib::FindName
5094 * Finds occurrences of a type description in a type library. This may be used
5095 * to quickly verify that a name exists in a type library.
5098 static HRESULT WINAPI ITypeLib2_fnFindName(
5099 ITypeLib2 *iface,
5100 LPOLESTR name,
5101 ULONG hash,
5102 ITypeInfo **ppTInfo,
5103 MEMBERID *memid,
5104 UINT16 *found)
5106 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5107 int tic;
5108 UINT count = 0;
5109 UINT len;
5111 TRACE("(%p)->(%s %u %p %p %p)\n", This, debugstr_w(name), hash, ppTInfo, memid, found);
5113 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
5114 return E_INVALIDARG;
5116 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
5117 for(tic = 0; count < *found && tic < This->TypeInfoCount; ++tic) {
5118 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5119 TLBVarDesc *var;
5120 UINT fdc;
5122 if(!TLB_str_memcmp(name, pTInfo->Name, len)) {
5123 memid[count] = MEMBERID_NIL;
5124 goto ITypeLib2_fnFindName_exit;
5127 for(fdc = 0; fdc < pTInfo->typeattr.cFuncs; ++fdc) {
5128 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
5130 if(!TLB_str_memcmp(name, func->Name, len)) {
5131 memid[count] = func->funcdesc.memid;
5132 goto ITypeLib2_fnFindName_exit;
5136 var = TLB_get_vardesc_by_name(pTInfo, name);
5137 if (var) {
5138 memid[count] = var->vardesc.memid;
5139 goto ITypeLib2_fnFindName_exit;
5142 continue;
5143 ITypeLib2_fnFindName_exit:
5144 ITypeInfo2_AddRef(&pTInfo->ITypeInfo2_iface);
5145 ppTInfo[count] = (ITypeInfo *)&pTInfo->ITypeInfo2_iface;
5146 count++;
5148 TRACE("found %d typeinfos\n", count);
5150 *found = count;
5152 return S_OK;
5155 /* ITypeLib::ReleaseTLibAttr
5157 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5160 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
5161 ITypeLib2 *iface,
5162 TLIBATTR *pTLibAttr)
5164 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5165 TRACE("(%p)->(%p)\n", This, pTLibAttr);
5166 heap_free(pTLibAttr);
5169 /* ITypeLib2::GetCustData
5171 * gets the custom data
5173 static HRESULT WINAPI ITypeLib2_fnGetCustData(
5174 ITypeLib2 * iface,
5175 REFGUID guid,
5176 VARIANT *pVarVal)
5178 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5179 TLBCustData *pCData;
5181 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
5183 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
5184 if(!pCData)
5185 return TYPE_E_ELEMENTNOTFOUND;
5187 VariantInit(pVarVal);
5188 VariantCopy(pVarVal, &pCData->data);
5190 return S_OK;
5193 /* ITypeLib2::GetLibStatistics
5195 * Returns statistics about a type library that are required for efficient
5196 * sizing of hash tables.
5199 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
5200 ITypeLib2 * iface,
5201 ULONG *pcUniqueNames,
5202 ULONG *pcchUniqueNames)
5204 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5206 FIXME("(%p): stub!\n", This);
5208 if(pcUniqueNames) *pcUniqueNames=1;
5209 if(pcchUniqueNames) *pcchUniqueNames=1;
5210 return S_OK;
5213 /* ITypeLib2::GetDocumentation2
5215 * Retrieves the library's documentation string, the complete Help file name
5216 * and path, the localization context to use, and the context ID for the
5217 * library Help topic in the Help file.
5220 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
5221 ITypeLib2 * iface,
5222 INT index,
5223 LCID lcid,
5224 BSTR *pbstrHelpString,
5225 DWORD *pdwHelpStringContext,
5226 BSTR *pbstrHelpStringDll)
5228 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5229 HRESULT result;
5230 ITypeInfo *pTInfo;
5232 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
5234 /* the help string should be obtained from the helpstringdll,
5235 * using the _DLLGetDocumentation function, based on the supplied
5236 * lcid. Nice to do sometime...
5238 if(index<0)
5240 /* documentation for the typelib */
5241 if(pbstrHelpString)
5242 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->DocString));
5243 if(pdwHelpStringContext)
5244 *pdwHelpStringContext=This->dwHelpContext;
5245 if(pbstrHelpStringDll)
5246 *pbstrHelpStringDll=SysAllocString(TLB_get_bstr(This->HelpStringDll));
5248 result = S_OK;
5250 else
5252 /* for a typeinfo */
5253 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
5255 if(SUCCEEDED(result))
5257 ITypeInfo2 * pTInfo2;
5258 result = ITypeInfo_QueryInterface(pTInfo,
5259 &IID_ITypeInfo2,
5260 (LPVOID*) &pTInfo2);
5262 if(SUCCEEDED(result))
5264 result = ITypeInfo2_GetDocumentation2(pTInfo2,
5265 MEMBERID_NIL,
5266 lcid,
5267 pbstrHelpString,
5268 pdwHelpStringContext,
5269 pbstrHelpStringDll);
5271 ITypeInfo2_Release(pTInfo2);
5274 ITypeInfo_Release(pTInfo);
5277 return result;
5280 static HRESULT TLB_copy_all_custdata(const struct list *custdata_list, CUSTDATA *pCustData)
5282 TLBCustData *pCData;
5283 unsigned int ct;
5284 CUSTDATAITEM *cdi;
5286 ct = list_count(custdata_list);
5288 pCustData->prgCustData = CoTaskMemAlloc(ct * sizeof(CUSTDATAITEM));
5289 if(!pCustData->prgCustData)
5290 return E_OUTOFMEMORY;
5292 pCustData->cCustData = ct;
5294 cdi = pCustData->prgCustData;
5295 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
5296 cdi->guid = *TLB_get_guid_null(pCData->guid);
5297 VariantCopy(&cdi->varValue, &pCData->data);
5298 ++cdi;
5301 return S_OK;
5305 /* ITypeLib2::GetAllCustData
5307 * Gets all custom data items for the library.
5310 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
5311 ITypeLib2 * iface,
5312 CUSTDATA *pCustData)
5314 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5315 TRACE("(%p)->(%p)\n", This, pCustData);
5316 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
5319 static const ITypeLib2Vtbl tlbvt = {
5320 ITypeLib2_fnQueryInterface,
5321 ITypeLib2_fnAddRef,
5322 ITypeLib2_fnRelease,
5323 ITypeLib2_fnGetTypeInfoCount,
5324 ITypeLib2_fnGetTypeInfo,
5325 ITypeLib2_fnGetTypeInfoType,
5326 ITypeLib2_fnGetTypeInfoOfGuid,
5327 ITypeLib2_fnGetLibAttr,
5328 ITypeLib2_fnGetTypeComp,
5329 ITypeLib2_fnGetDocumentation,
5330 ITypeLib2_fnIsName,
5331 ITypeLib2_fnFindName,
5332 ITypeLib2_fnReleaseTLibAttr,
5334 ITypeLib2_fnGetCustData,
5335 ITypeLib2_fnGetLibStatistics,
5336 ITypeLib2_fnGetDocumentation2,
5337 ITypeLib2_fnGetAllCustData
5341 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5343 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5345 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
5348 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
5350 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5352 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
5355 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
5357 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5359 return ITypeLib2_Release(&This->ITypeLib2_iface);
5362 static HRESULT WINAPI ITypeLibComp_fnBind(
5363 ITypeComp * iface,
5364 OLECHAR * szName,
5365 ULONG lHash,
5366 WORD wFlags,
5367 ITypeInfo ** ppTInfo,
5368 DESCKIND * pDescKind,
5369 BINDPTR * pBindPtr)
5371 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5372 BOOL typemismatch = FALSE;
5373 int i;
5375 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5377 *pDescKind = DESCKIND_NONE;
5378 pBindPtr->lptcomp = NULL;
5379 *ppTInfo = NULL;
5381 for(i = 0; i < This->TypeInfoCount; ++i){
5382 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5383 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo->Name)));
5385 /* FIXME: check wFlags here? */
5386 /* FIXME: we should use a hash table to look this info up using lHash
5387 * instead of an O(n) search */
5388 if ((pTypeInfo->typeattr.typekind == TKIND_ENUM) ||
5389 (pTypeInfo->typeattr.typekind == TKIND_MODULE))
5391 if (pTypeInfo->Name && !wcscmp(pTypeInfo->Name->str, szName))
5393 *pDescKind = DESCKIND_TYPECOMP;
5394 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
5395 ITypeComp_AddRef(pBindPtr->lptcomp);
5396 TRACE("module or enum: %s\n", debugstr_w(szName));
5397 return S_OK;
5401 if ((pTypeInfo->typeattr.typekind == TKIND_MODULE) ||
5402 (pTypeInfo->typeattr.typekind == TKIND_ENUM))
5404 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5405 HRESULT hr;
5407 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5408 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
5410 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
5411 return S_OK;
5413 else if (hr == TYPE_E_TYPEMISMATCH)
5414 typemismatch = TRUE;
5417 if ((pTypeInfo->typeattr.typekind == TKIND_COCLASS) &&
5418 (pTypeInfo->typeattr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
5420 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5421 HRESULT hr;
5422 ITypeInfo *subtypeinfo;
5423 BINDPTR subbindptr;
5424 DESCKIND subdesckind;
5426 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
5427 &subtypeinfo, &subdesckind, &subbindptr);
5428 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
5430 TYPEDESC tdesc_appobject;
5431 const VARDESC vardesc_appobject =
5433 -2, /* memid */
5434 NULL, /* lpstrSchema */
5436 0 /* oInst */
5439 /* ELEMDESC */
5441 /* TYPEDESC */
5443 &tdesc_appobject
5445 VT_PTR
5448 0, /* wVarFlags */
5449 VAR_STATIC /* varkind */
5452 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
5453 tdesc_appobject.vt = VT_USERDEFINED;
5455 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
5457 /* cleanup things filled in by Bind call so we can put our
5458 * application object data in there instead */
5459 switch (subdesckind)
5461 case DESCKIND_FUNCDESC:
5462 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
5463 break;
5464 case DESCKIND_VARDESC:
5465 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
5466 break;
5467 default:
5468 break;
5470 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
5472 if (pTypeInfo->hreftype == -1)
5473 FIXME("no hreftype for interface %p\n", pTypeInfo);
5475 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
5476 if (FAILED(hr))
5477 return hr;
5479 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5480 *ppTInfo = (ITypeInfo *)&pTypeInfo->ITypeInfo2_iface;
5481 ITypeInfo_AddRef(*ppTInfo);
5482 return S_OK;
5484 else if (hr == TYPE_E_TYPEMISMATCH)
5485 typemismatch = TRUE;
5489 if (typemismatch)
5491 TRACE("type mismatch %s\n", debugstr_w(szName));
5492 return TYPE_E_TYPEMISMATCH;
5494 else
5496 TRACE("name not found %s\n", debugstr_w(szName));
5497 return S_OK;
5501 static HRESULT WINAPI ITypeLibComp_fnBindType(
5502 ITypeComp * iface,
5503 OLECHAR * szName,
5504 ULONG lHash,
5505 ITypeInfo ** ppTInfo,
5506 ITypeComp ** ppTComp)
5508 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5509 ITypeInfoImpl *info;
5511 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5513 if(!szName || !ppTInfo || !ppTComp)
5514 return E_INVALIDARG;
5516 info = TLB_get_typeinfo_by_name(This, szName);
5517 if(!info){
5518 *ppTInfo = NULL;
5519 *ppTComp = NULL;
5520 return S_OK;
5523 *ppTInfo = (ITypeInfo *)&info->ITypeInfo2_iface;
5524 ITypeInfo_AddRef(*ppTInfo);
5525 *ppTComp = &info->ITypeComp_iface;
5526 ITypeComp_AddRef(*ppTComp);
5528 return S_OK;
5531 static const ITypeCompVtbl tlbtcvt =
5534 ITypeLibComp_fnQueryInterface,
5535 ITypeLibComp_fnAddRef,
5536 ITypeLibComp_fnRelease,
5538 ITypeLibComp_fnBind,
5539 ITypeLibComp_fnBindType
5542 /*================== ITypeInfo(2) Methods ===================================*/
5543 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5545 ITypeInfoImpl *pTypeInfoImpl;
5547 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5548 if (pTypeInfoImpl)
5550 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5551 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5552 pTypeInfoImpl->ICreateTypeInfo2_iface.lpVtbl = &CreateTypeInfo2Vtbl;
5553 pTypeInfoImpl->ref = 0;
5554 pTypeInfoImpl->hreftype = -1;
5555 pTypeInfoImpl->typeattr.memidConstructor = MEMBERID_NIL;
5556 pTypeInfoImpl->typeattr.memidDestructor = MEMBERID_NIL;
5557 pTypeInfoImpl->pcustdata_list = &pTypeInfoImpl->custdata_list;
5558 list_init(pTypeInfoImpl->pcustdata_list);
5560 TRACE("(%p)\n", pTypeInfoImpl);
5561 return pTypeInfoImpl;
5564 /* ITypeInfo::QueryInterface
5566 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5567 ITypeInfo2 *iface,
5568 REFIID riid,
5569 VOID **ppvObject)
5571 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5573 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5575 *ppvObject=NULL;
5576 if(IsEqualIID(riid, &IID_IUnknown) ||
5577 IsEqualIID(riid,&IID_ITypeInfo)||
5578 IsEqualIID(riid,&IID_ITypeInfo2))
5579 *ppvObject = &This->ITypeInfo2_iface;
5580 else if(IsEqualIID(riid, &IID_ICreateTypeInfo) ||
5581 IsEqualIID(riid, &IID_ICreateTypeInfo2))
5582 *ppvObject = &This->ICreateTypeInfo2_iface;
5583 else if(IsEqualIID(riid, &IID_ITypeComp))
5584 *ppvObject = &This->ITypeComp_iface;
5586 if(*ppvObject){
5587 IUnknown_AddRef((IUnknown*)*ppvObject);
5588 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5589 return S_OK;
5591 TRACE("-- Interface: E_NOINTERFACE\n");
5592 return E_NOINTERFACE;
5595 /* ITypeInfo::AddRef
5597 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5599 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5600 ULONG ref = InterlockedIncrement(&This->ref);
5602 TRACE("(%p)->ref is %u\n",This, ref);
5604 if (ref == 1 /* incremented from 0 */)
5605 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5607 return ref;
5610 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5612 UINT i;
5614 TRACE("destroying ITypeInfo(%p)\n",This);
5616 for (i = 0; i < This->typeattr.cFuncs; ++i)
5618 int j;
5619 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5620 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5622 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5623 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5624 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5625 TLB_FreeCustData(&pFInfo->pParamDesc[j].custdata_list);
5627 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5628 heap_free(pFInfo->pParamDesc);
5629 TLB_FreeCustData(&pFInfo->custdata_list);
5631 heap_free(This->funcdescs);
5633 for(i = 0; i < This->typeattr.cVars; ++i)
5635 TLBVarDesc *pVInfo = &This->vardescs[i];
5636 if (pVInfo->vardesc_create) {
5637 TLB_FreeVarDesc(pVInfo->vardesc_create);
5638 } else if (pVInfo->vardesc.varkind == VAR_CONST) {
5639 VariantClear(pVInfo->vardesc.u.lpvarValue);
5640 heap_free(pVInfo->vardesc.u.lpvarValue);
5642 TLB_FreeCustData(&pVInfo->custdata_list);
5644 heap_free(This->vardescs);
5646 if(This->impltypes){
5647 for (i = 0; i < This->typeattr.cImplTypes; ++i){
5648 TLBImplType *pImpl = &This->impltypes[i];
5649 TLB_FreeCustData(&pImpl->custdata_list);
5651 heap_free(This->impltypes);
5654 TLB_FreeCustData(&This->custdata_list);
5656 heap_free(This);
5659 /* ITypeInfo::Release
5661 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5663 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5664 ULONG ref = InterlockedDecrement(&This->ref);
5666 TRACE("(%p)->(%u)\n",This, ref);
5668 if (!ref)
5670 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5671 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5672 if (not_attached_to_typelib)
5673 heap_free(This);
5674 /* otherwise This will be freed when typelib is freed */
5677 return ref;
5680 /* ITypeInfo::GetTypeAttr
5682 * Retrieves a TYPEATTR structure that contains the attributes of the type
5683 * description.
5686 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5687 LPTYPEATTR *ppTypeAttr)
5689 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5690 SIZE_T size;
5692 TRACE("(%p)\n",This);
5694 size = sizeof(**ppTypeAttr);
5695 if (This->typeattr.typekind == TKIND_ALIAS && This->tdescAlias)
5696 size += TLB_SizeTypeDesc(This->tdescAlias, FALSE);
5698 *ppTypeAttr = heap_alloc(size);
5699 if (!*ppTypeAttr)
5700 return E_OUTOFMEMORY;
5702 **ppTypeAttr = This->typeattr;
5703 (*ppTypeAttr)->guid = *TLB_get_guid_null(This->guid);
5705 if (This->tdescAlias)
5706 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias, This->tdescAlias, *ppTypeAttr + 1);
5708 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5709 /* This should include all the inherited funcs */
5710 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / This->pTypeLib->ptr_size;
5711 /* This is always the size of IDispatch's vtbl */
5712 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5713 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5715 return S_OK;
5718 /* ITypeInfo::GetTypeComp
5720 * Retrieves the ITypeComp interface for the type description, which enables a
5721 * client compiler to bind to the type description's members.
5724 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5725 ITypeComp * *ppTComp)
5727 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5729 TRACE("(%p)->(%p)\n", This, ppTComp);
5731 *ppTComp = &This->ITypeComp_iface;
5732 ITypeComp_AddRef(*ppTComp);
5733 return S_OK;
5736 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5738 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5739 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5740 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5741 return size;
5744 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5746 *dest = *src;
5747 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5748 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5750 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5751 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5752 *buffer += sizeof(PARAMDESCEX);
5753 *pparamdescex_dest = *pparamdescex_src;
5754 pparamdescex_dest->cBytes = sizeof(PARAMDESCEX);
5755 VariantInit(&pparamdescex_dest->varDefaultValue);
5756 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5757 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5759 else
5760 dest->u.paramdesc.pparamdescex = NULL;
5761 return S_OK;
5764 static HRESULT TLB_SanitizeBSTR(BSTR str)
5766 UINT len = SysStringLen(str), i;
5767 for (i = 0; i < len; ++i)
5768 if (str[i] > 0x7f)
5769 str[i] = '?';
5770 return S_OK;
5773 static HRESULT TLB_SanitizeVariant(VARIANT *var)
5775 if (V_VT(var) == VT_INT)
5776 return VariantChangeType(var, var, 0, VT_I4);
5777 else if (V_VT(var) == VT_UINT)
5778 return VariantChangeType(var, var, 0, VT_UI4);
5779 else if (V_VT(var) == VT_BSTR)
5780 return TLB_SanitizeBSTR(V_BSTR(var));
5782 return S_OK;
5785 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5787 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5788 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5791 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5793 FUNCDESC *dest;
5794 char *buffer;
5795 SIZE_T size = sizeof(*src);
5796 SHORT i;
5797 HRESULT hr;
5799 size += sizeof(*src->lprgscode) * src->cScodes;
5800 size += TLB_SizeElemDesc(&src->elemdescFunc);
5801 for (i = 0; i < src->cParams; i++)
5803 size += sizeof(ELEMDESC);
5804 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5807 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5808 if (!dest) return E_OUTOFMEMORY;
5810 *dest = *src;
5811 if (dispinterface) /* overwrite funckind */
5812 dest->funckind = FUNC_DISPATCH;
5813 buffer = (char *)(dest + 1);
5815 dest->oVft = dest->oVft & 0xFFFC;
5817 if (dest->cScodes) {
5818 dest->lprgscode = (SCODE *)buffer;
5819 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5820 buffer += sizeof(*src->lprgscode) * src->cScodes;
5821 } else
5822 dest->lprgscode = NULL;
5824 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5825 if (FAILED(hr))
5827 SysFreeString((BSTR)dest);
5828 return hr;
5831 if (dest->cParams) {
5832 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5833 buffer += sizeof(ELEMDESC) * src->cParams;
5834 for (i = 0; i < src->cParams; i++)
5836 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5837 if (FAILED(hr))
5838 break;
5840 if (FAILED(hr))
5842 /* undo the above actions */
5843 for (i = i - 1; i >= 0; i--)
5844 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5845 TLB_FreeElemDesc(&dest->elemdescFunc);
5846 SysFreeString((BSTR)dest);
5847 return hr;
5849 } else
5850 dest->lprgelemdescParam = NULL;
5852 /* special treatment for dispinterfaces: this makes functions appear
5853 * to return their [retval] value when it is really returning an
5854 * HRESULT */
5855 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5857 if (dest->cParams &&
5858 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5860 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5861 if (elemdesc->tdesc.vt != VT_PTR)
5863 ERR("elemdesc should have started with VT_PTR instead of:\n");
5864 if (ERR_ON(ole))
5865 dump_ELEMDESC(elemdesc);
5866 return E_UNEXPECTED;
5869 /* copy last parameter to the return value. we are using a flat
5870 * buffer so there is no danger of leaking memory in
5871 * elemdescFunc */
5872 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5874 /* remove the last parameter */
5875 dest->cParams--;
5877 else
5878 /* otherwise this function is made to appear to have no return
5879 * value */
5880 dest->elemdescFunc.tdesc.vt = VT_VOID;
5884 *dest_ptr = dest;
5885 return S_OK;
5888 static void TLB_FreeVarDesc(VARDESC *var_desc)
5890 TLB_FreeElemDesc(&var_desc->elemdescVar);
5891 if (var_desc->varkind == VAR_CONST)
5892 VariantClear(var_desc->u.lpvarValue);
5893 SysFreeString((BSTR)var_desc);
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 TLBFuncDesc **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 index -= implemented_funcs;
5939 if (index >= This->typeattr.cFuncs)
5940 return TYPE_E_ELEMENTNOTFOUND;
5942 *ppFuncDesc = &This->funcdescs[index];
5943 return S_OK;
5946 static HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const TLBFuncDesc **func_desc, UINT *hrefoffset )
5948 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5950 if (This->typeattr.typekind == TKIND_DISPATCH)
5951 return ITypeInfoImpl_GetInternalDispatchFuncDesc(iface, index, func_desc, NULL, hrefoffset);
5953 if (index >= This->typeattr.cFuncs)
5954 return TYPE_E_ELEMENTNOTFOUND;
5956 *func_desc = &This->funcdescs[index];
5957 return S_OK;
5960 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5962 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5963 while (TRUE)
5965 switch (pTypeDesc->vt)
5967 case VT_USERDEFINED:
5968 pTypeDesc->u.hreftype += hrefoffset;
5969 return;
5970 case VT_PTR:
5971 case VT_SAFEARRAY:
5972 pTypeDesc = pTypeDesc->u.lptdesc;
5973 break;
5974 case VT_CARRAY:
5975 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5976 break;
5977 default:
5978 return;
5983 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5985 SHORT i;
5986 for (i = 0; i < pFuncDesc->cParams; i++)
5987 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5988 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5991 /* ITypeInfo::GetFuncDesc
5993 * Retrieves the FUNCDESC structure that contains information about a
5994 * specified function.
5997 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5998 LPFUNCDESC *ppFuncDesc)
6000 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6001 const TLBFuncDesc *internal_funcdesc;
6002 HRESULT hr;
6003 UINT hrefoffset = 0;
6005 TRACE("(%p) index %d\n", This, index);
6007 if (!ppFuncDesc)
6008 return E_INVALIDARG;
6010 if (This->needs_layout)
6011 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6013 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
6014 &internal_funcdesc, &hrefoffset);
6015 if (FAILED(hr))
6017 WARN("description for function %d not found\n", index);
6018 return hr;
6021 hr = TLB_AllocAndInitFuncDesc(
6022 &internal_funcdesc->funcdesc,
6023 ppFuncDesc,
6024 This->typeattr.typekind == TKIND_DISPATCH);
6026 if ((This->typeattr.typekind == TKIND_DISPATCH) && hrefoffset)
6027 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
6029 TRACE("-- 0x%08x\n", hr);
6030 return hr;
6033 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
6035 VARDESC *dest;
6036 char *buffer;
6037 SIZE_T size = sizeof(*src);
6038 HRESULT hr;
6040 if (src->lpstrSchema) size += (lstrlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
6041 if (src->varkind == VAR_CONST)
6042 size += sizeof(VARIANT);
6043 size += TLB_SizeElemDesc(&src->elemdescVar);
6045 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
6046 if (!dest) return E_OUTOFMEMORY;
6048 *dest = *src;
6049 buffer = (char *)(dest + 1);
6050 if (src->lpstrSchema)
6052 int len;
6053 dest->lpstrSchema = (LPOLESTR)buffer;
6054 len = lstrlenW(src->lpstrSchema);
6055 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
6056 buffer += (len + 1) * sizeof(WCHAR);
6059 if (src->varkind == VAR_CONST)
6061 HRESULT hr;
6063 dest->u.lpvarValue = (VARIANT *)buffer;
6064 *dest->u.lpvarValue = *src->u.lpvarValue;
6065 buffer += sizeof(VARIANT);
6066 VariantInit(dest->u.lpvarValue);
6067 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
6068 if (FAILED(hr))
6070 SysFreeString((BSTR)dest);
6071 return hr;
6074 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
6075 if (FAILED(hr))
6077 if (src->varkind == VAR_CONST)
6078 VariantClear(dest->u.lpvarValue);
6079 SysFreeString((BSTR)dest);
6080 return hr;
6082 *dest_ptr = dest;
6083 return S_OK;
6086 /* ITypeInfo::GetVarDesc
6088 * Retrieves a VARDESC structure that describes the specified variable.
6091 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
6092 LPVARDESC *ppVarDesc)
6094 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6095 const TLBVarDesc *pVDesc = &This->vardescs[index];
6097 TRACE("(%p) index %d\n", This, index);
6099 if(index >= This->typeattr.cVars)
6100 return TYPE_E_ELEMENTNOTFOUND;
6102 if (This->needs_layout)
6103 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6105 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
6108 /* ITypeInfo_GetNames
6110 * Retrieves the variable with the specified member ID (or the name of the
6111 * property or method and its parameters) that correspond to the specified
6112 * function ID.
6114 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
6115 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
6117 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6118 const TLBFuncDesc *pFDesc;
6119 const TLBVarDesc *pVDesc;
6120 int i;
6121 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
6123 if(!rgBstrNames)
6124 return E_INVALIDARG;
6126 *pcNames = 0;
6128 pFDesc = TLB_get_funcdesc_by_memberid(This, memid);
6129 if(pFDesc)
6131 if(!cMaxNames || !pFDesc->Name)
6132 return S_OK;
6134 *rgBstrNames = SysAllocString(TLB_get_bstr(pFDesc->Name));
6135 ++(*pcNames);
6137 for(i = 0; i < pFDesc->funcdesc.cParams; ++i){
6138 if(*pcNames >= cMaxNames || !pFDesc->pParamDesc[i].Name)
6139 return S_OK;
6140 rgBstrNames[*pcNames] = SysAllocString(TLB_get_bstr(pFDesc->pParamDesc[i].Name));
6141 ++(*pcNames);
6143 return S_OK;
6146 pVDesc = TLB_get_vardesc_by_memberid(This, memid);
6147 if(pVDesc)
6149 *rgBstrNames=SysAllocString(TLB_get_bstr(pVDesc->Name));
6150 *pcNames=1;
6152 else
6154 if(This->impltypes &&
6155 (This->typeattr.typekind == TKIND_INTERFACE || This->typeattr.typekind == TKIND_DISPATCH)) {
6156 /* recursive search */
6157 ITypeInfo *pTInfo;
6158 HRESULT result;
6159 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6160 if(SUCCEEDED(result))
6162 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
6163 ITypeInfo_Release(pTInfo);
6164 return result;
6166 WARN("Could not search inherited interface!\n");
6168 else
6170 WARN("no names found\n");
6172 *pcNames=0;
6173 return TYPE_E_ELEMENTNOTFOUND;
6175 return S_OK;
6179 /* ITypeInfo::GetRefTypeOfImplType
6181 * If a type description describes a COM class, it retrieves the type
6182 * description of the implemented interface types. For an interface,
6183 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6184 * if any exist.
6187 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
6188 ITypeInfo2 *iface,
6189 UINT index,
6190 HREFTYPE *pRefType)
6192 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6193 HRESULT hr = S_OK;
6195 TRACE("(%p) index %d\n", This, index);
6196 if (TRACE_ON(ole)) dump_TypeInfo(This);
6198 if(index==(UINT)-1)
6200 /* only valid on dual interfaces;
6201 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6204 if (This->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
6206 *pRefType = -2;
6208 else
6210 hr = TYPE_E_ELEMENTNOTFOUND;
6213 else if(index == 0 && This->typeattr.typekind == TKIND_DISPATCH)
6215 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6216 *pRefType = This->pTypeLib->dispatch_href;
6218 else
6220 if(index >= This->typeattr.cImplTypes)
6221 hr = TYPE_E_ELEMENTNOTFOUND;
6222 else{
6223 *pRefType = This->impltypes[index].hRef;
6224 if (This->typeattr.typekind == TKIND_INTERFACE)
6225 *pRefType |= 0x2;
6229 if(TRACE_ON(ole))
6231 if(SUCCEEDED(hr))
6232 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
6233 else
6234 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
6237 return hr;
6240 /* ITypeInfo::GetImplTypeFlags
6242 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6243 * or base interface in a type description.
6245 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
6246 UINT index, INT *pImplTypeFlags)
6248 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6250 TRACE("(%p) index %d\n", This, index);
6252 if(!pImplTypeFlags)
6253 return E_INVALIDARG;
6255 if(This->typeattr.typekind == TKIND_DISPATCH && index == 0){
6256 *pImplTypeFlags = 0;
6257 return S_OK;
6260 if(index >= This->typeattr.cImplTypes)
6261 return TYPE_E_ELEMENTNOTFOUND;
6263 *pImplTypeFlags = This->impltypes[index].implflags;
6265 return S_OK;
6268 /* GetIDsOfNames
6269 * Maps between member names and member IDs, and parameter names and
6270 * parameter IDs.
6272 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
6273 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
6275 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6276 const TLBVarDesc *pVDesc;
6277 HRESULT ret=S_OK;
6278 UINT i, fdc;
6280 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
6281 cNames);
6283 /* init out parameters in case of failure */
6284 for (i = 0; i < cNames; i++)
6285 pMemId[i] = MEMBERID_NIL;
6287 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc) {
6288 int j;
6289 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
6290 if(!lstrcmpiW(*rgszNames, TLB_get_bstr(pFDesc->Name))) {
6291 if(cNames) *pMemId=pFDesc->funcdesc.memid;
6292 for(i=1; i < cNames; i++){
6293 for(j=0; j<pFDesc->funcdesc.cParams; j++)
6294 if(!lstrcmpiW(rgszNames[i],TLB_get_bstr(pFDesc->pParamDesc[j].Name)))
6295 break;
6296 if( j<pFDesc->funcdesc.cParams)
6297 pMemId[i]=j;
6298 else
6299 ret=DISP_E_UNKNOWNNAME;
6301 TRACE("-- 0x%08x\n", ret);
6302 return ret;
6305 pVDesc = TLB_get_vardesc_by_name(This, *rgszNames);
6306 if(pVDesc){
6307 if(cNames)
6308 *pMemId = pVDesc->vardesc.memid;
6309 return ret;
6311 /* not found, see if it can be found in an inherited interface */
6312 if(This->impltypes) {
6313 /* recursive search */
6314 ITypeInfo *pTInfo;
6315 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6316 if(SUCCEEDED(ret)){
6317 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
6318 ITypeInfo_Release(pTInfo);
6319 return ret;
6321 WARN("Could not search inherited interface!\n");
6322 } else
6323 WARN("no names found\n");
6324 return DISP_E_UNKNOWNNAME;
6328 #ifdef __i386__
6330 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6331 extern double call_double_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6332 __ASM_GLOBAL_FUNC( call_method,
6333 "pushl %ebp\n\t"
6334 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6335 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6336 "movl %esp,%ebp\n\t"
6337 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6338 "pushl %esi\n\t"
6339 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6340 "pushl %edi\n\t"
6341 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6342 "movl 12(%ebp),%edx\n\t"
6343 "movl %esp,%edi\n\t"
6344 "shll $2,%edx\n\t"
6345 "jz 1f\n\t"
6346 "subl %edx,%edi\n\t"
6347 "andl $~15,%edi\n\t"
6348 "movl %edi,%esp\n\t"
6349 "movl 12(%ebp),%ecx\n\t"
6350 "movl 16(%ebp),%esi\n\t"
6351 "cld\n\t"
6352 "rep; movsl\n"
6353 "1:\tcall *8(%ebp)\n\t"
6354 "subl %esp,%edi\n\t"
6355 "movl 20(%ebp),%ecx\n\t"
6356 "movl %edi,(%ecx)\n\t"
6357 "leal -8(%ebp),%esp\n\t"
6358 "popl %edi\n\t"
6359 __ASM_CFI(".cfi_same_value %edi\n\t")
6360 "popl %esi\n\t"
6361 __ASM_CFI(".cfi_same_value %esi\n\t")
6362 "popl %ebp\n\t"
6363 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6364 __ASM_CFI(".cfi_same_value %ebp\n\t")
6365 "ret" )
6366 __ASM_GLOBAL_FUNC( call_double_method,
6367 "jmp " __ASM_NAME("call_method") )
6369 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
6370 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
6372 int argspos = 0, stack_offset;
6373 void *func;
6374 UINT i;
6375 DWORD *args;
6377 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6378 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6379 pvargResult, V_VT(pvargResult));
6381 if (cc != CC_STDCALL && cc != CC_CDECL)
6383 FIXME("unsupported calling convention %d\n",cc);
6384 return E_INVALIDARG;
6387 /* maximum size for an argument is sizeof(VARIANT) */
6388 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6390 if (pvInstance)
6392 const FARPROC *vtable = *(FARPROC **)pvInstance;
6393 func = vtable[oVft/sizeof(void *)];
6394 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6396 else func = (void *)oVft;
6398 switch (vtReturn)
6400 case VT_DECIMAL:
6401 case VT_VARIANT:
6402 args[argspos++] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6403 break;
6404 case VT_HRESULT:
6405 WARN("invalid return type %u\n", vtReturn);
6406 heap_free( args );
6407 return E_INVALIDARG;
6408 default:
6409 break;
6412 for (i = 0; i < cActuals; i++)
6414 VARIANT *arg = prgpvarg[i];
6416 switch (prgvt[i])
6418 case VT_EMPTY:
6419 break;
6420 case VT_I8:
6421 case VT_UI8:
6422 case VT_R8:
6423 case VT_DATE:
6424 case VT_CY:
6425 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6426 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6427 break;
6428 case VT_DECIMAL:
6429 case VT_VARIANT:
6430 memcpy( &args[argspos], arg, sizeof(*arg) );
6431 argspos += sizeof(*arg) / sizeof(DWORD);
6432 break;
6433 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6434 args[argspos++] = V_BOOL(arg);
6435 break;
6436 default:
6437 args[argspos++] = V_UI4(arg);
6438 break;
6440 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6443 switch (vtReturn)
6445 case VT_EMPTY:
6446 case VT_DECIMAL:
6447 case VT_VARIANT:
6448 call_method( func, argspos, args, &stack_offset );
6449 break;
6450 case VT_R4:
6451 V_R4(pvargResult) = call_double_method( func, argspos, args, &stack_offset );
6452 break;
6453 case VT_R8:
6454 case VT_DATE:
6455 V_R8(pvargResult) = call_double_method( func, argspos, args, &stack_offset );
6456 break;
6457 case VT_I8:
6458 case VT_UI8:
6459 case VT_CY:
6460 V_UI8(pvargResult) = call_method( func, argspos, args, &stack_offset );
6461 break;
6462 default:
6463 V_UI4(pvargResult) = call_method( func, argspos, args, &stack_offset );
6464 break;
6466 heap_free( args );
6467 if (stack_offset && cc == CC_STDCALL)
6469 WARN( "stack pointer off by %d\n", stack_offset );
6470 return DISP_E_BADCALLEE;
6472 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6473 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6474 return S_OK;
6477 #elif defined(__x86_64__)
6479 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
6480 extern double CDECL call_double_method( void *func, int nb_args, const DWORD_PTR *args );
6481 __ASM_GLOBAL_FUNC( call_method,
6482 "pushq %rbp\n\t"
6483 __ASM_SEH(".seh_pushreg %rbp\n\t")
6484 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6485 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6486 "movq %rsp,%rbp\n\t"
6487 __ASM_SEH(".seh_setframe %rbp,0\n\t")
6488 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6489 "pushq %rsi\n\t"
6490 __ASM_SEH(".seh_pushreg %rsi\n\t")
6491 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6492 "pushq %rdi\n\t"
6493 __ASM_SEH(".seh_pushreg %rdi\n\t")
6494 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6495 __ASM_SEH(".seh_endprologue\n\t")
6496 "movq %rcx,%rax\n\t"
6497 "movq $4,%rcx\n\t"
6498 "cmp %rcx,%rdx\n\t"
6499 "cmovgq %rdx,%rcx\n\t"
6500 "leaq 0(,%rcx,8),%rdx\n\t"
6501 "subq %rdx,%rsp\n\t"
6502 "andq $~15,%rsp\n\t"
6503 "movq %rsp,%rdi\n\t"
6504 "movq %r8,%rsi\n\t"
6505 "rep; movsq\n\t"
6506 "movq 0(%rsp),%rcx\n\t"
6507 "movq 8(%rsp),%rdx\n\t"
6508 "movq 16(%rsp),%r8\n\t"
6509 "movq 24(%rsp),%r9\n\t"
6510 "movq 0(%rsp),%xmm0\n\t"
6511 "movq 8(%rsp),%xmm1\n\t"
6512 "movq 16(%rsp),%xmm2\n\t"
6513 "movq 24(%rsp),%xmm3\n\t"
6514 "callq *%rax\n\t"
6515 "leaq -16(%rbp),%rsp\n\t"
6516 "popq %rdi\n\t"
6517 __ASM_CFI(".cfi_same_value %rdi\n\t")
6518 "popq %rsi\n\t"
6519 __ASM_CFI(".cfi_same_value %rsi\n\t")
6520 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6521 "popq %rbp\n\t"
6522 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6523 __ASM_CFI(".cfi_same_value %rbp\n\t")
6524 "ret")
6525 __ASM_GLOBAL_FUNC( call_double_method,
6526 "jmp " __ASM_NAME("call_method") )
6528 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
6529 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
6531 int argspos = 0;
6532 UINT i;
6533 DWORD_PTR *args;
6534 void *func;
6536 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6537 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6538 pvargResult, V_VT(pvargResult));
6540 if (cc != CC_STDCALL && cc != CC_CDECL)
6542 FIXME("unsupported calling convention %d\n",cc);
6543 return E_INVALIDARG;
6546 /* maximum size for an argument is sizeof(DWORD_PTR) */
6547 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6549 if (pvInstance)
6551 const FARPROC *vtable = *(FARPROC **)pvInstance;
6552 func = vtable[oVft/sizeof(void *)];
6553 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6555 else func = (void *)oVft;
6557 switch (vtReturn)
6559 case VT_DECIMAL:
6560 case VT_VARIANT:
6561 args[argspos++] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6562 break;
6563 case VT_HRESULT:
6564 WARN("invalid return type %u\n", vtReturn);
6565 heap_free( args );
6566 return E_INVALIDARG;
6567 default:
6568 break;
6571 for (i = 0; i < cActuals; i++)
6573 VARIANT *arg = prgpvarg[i];
6575 switch (prgvt[i])
6577 case VT_DECIMAL:
6578 case VT_VARIANT:
6579 args[argspos++] = (ULONG_PTR)arg;
6580 break;
6581 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6582 args[argspos++] = V_BOOL(arg);
6583 break;
6584 default:
6585 args[argspos++] = V_UI8(arg);
6586 break;
6588 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6591 switch (vtReturn)
6593 case VT_R4:
6594 V_R4(pvargResult) = call_double_method( func, argspos, args );
6595 break;
6596 case VT_R8:
6597 case VT_DATE:
6598 V_R8(pvargResult) = call_double_method( func, argspos, args );
6599 break;
6600 case VT_DECIMAL:
6601 case VT_VARIANT:
6602 call_method( func, argspos, args );
6603 break;
6604 default:
6605 V_UI8(pvargResult) = call_method( func, argspos, args );
6606 break;
6608 heap_free( args );
6609 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6610 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6611 return S_OK;
6614 #elif defined(__arm__)
6616 extern LONGLONG CDECL call_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6617 extern float CDECL call_float_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6618 extern double CDECL call_double_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6619 __ASM_GLOBAL_FUNC( call_method,
6620 /* r0 = *func
6621 * r1 = nb_stk_args
6622 * r2 = *stk_args (pointer to 'nb_stk_args' DWORD values to push on stack)
6623 * 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)
6626 "push {fp, lr}\n\t" /* Save frame pointer and return address (stack still aligned to 8 bytes) */
6627 "mov fp, sp\n\t" /* Save stack pointer as our frame for cleaning the stack on return */
6629 "lsls r1, r1, #2\n\t" /* r1 = nb_stk_args * sizeof(DWORD) */
6630 "beq 1f\n\t" /* Skip allocation if no stack args */
6631 "add r2, r2, r1\n" /* Calculate ending address of incoming stack data */
6632 "2:\tldr ip, [r2, #-4]!\n\t" /* Get next value */
6633 "str ip, [sp, #-4]!\n\t" /* Push it on the stack */
6634 "subs r1, r1, #4\n\t" /* Decrement count */
6635 "bgt 2b\n\t" /* Loop till done */
6637 "1:\n\t"
6638 #ifndef __SOFTFP__
6639 "vldm r3!, {s0-s15}\n\t" /* Load the s0-s15/d0-d7 arguments */
6640 #endif
6641 "mov ip, r0\n\t" /* Save the function call address to ip before we nuke r0 with arguments to pass */
6642 "ldm r3, {r0-r3}\n\t" /* Load the r0-r3 arguments */
6644 "blx ip\n\t" /* Call the target function */
6646 "mov sp, fp\n\t" /* Clean the stack using fp */
6647 "pop {fp, pc}\n\t" /* Restore fp and return */
6649 __ASM_GLOBAL_FUNC( call_float_method,
6650 "b " __ASM_NAME("call_method") )
6651 __ASM_GLOBAL_FUNC( call_double_method,
6652 "b " __ASM_NAME("call_method") )
6654 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
6655 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
6657 int argspos;
6658 void *func;
6659 UINT i;
6660 DWORD *args;
6661 struct {
6662 #ifndef __SOFTFP__
6663 union {
6664 float s[16];
6665 double d[8];
6666 } sd;
6667 #endif
6668 DWORD r[4];
6669 } regs;
6670 int rcount; /* 32-bit register index count */
6671 #ifndef __SOFTFP__
6672 int scount = 0; /* single-precision float register index count */
6673 int dcount = 0; /* double-precision float register index count */
6674 #endif
6676 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6677 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6679 if (cc != CC_STDCALL && cc != CC_CDECL)
6681 FIXME("unsupported calling convention %d\n",cc);
6682 return E_INVALIDARG;
6685 argspos = 0;
6686 rcount = 0;
6688 if (pvInstance)
6690 const FARPROC *vtable = *(FARPROC **)pvInstance;
6691 func = vtable[oVft/sizeof(void *)];
6692 regs.r[rcount++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6694 else func = (void *)oVft;
6696 /* Determine if we need to pass a pointer for the return value as arg 0. If so, do that */
6697 /* first as it will need to be in the 'r' registers: */
6698 switch (vtReturn)
6700 case VT_DECIMAL:
6701 case VT_VARIANT:
6702 regs.r[rcount++] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6703 break;
6704 case VT_HRESULT:
6705 WARN("invalid return type %u\n", vtReturn);
6706 return E_INVALIDARG;
6707 default: /* And all others are in 'r', 's', or 'd' registers or have no return value */
6708 break;
6711 /* maximum size for an argument is sizeof(VARIANT). Also allow for return pointer and stack alignment. */
6712 args = heap_alloc( sizeof(VARIANT) * cActuals + sizeof(DWORD) * 4 );
6714 for (i = 0; i < cActuals; i++)
6716 VARIANT *arg = prgpvarg[i];
6717 DWORD *pdwarg = (DWORD *)(arg); /* a reinterpret_cast of the variant, used for copying structures when they are split between registers and stack */
6718 int ntemp; /* Used for counting words split between registers and stack */
6720 switch (prgvt[i])
6722 case VT_EMPTY:
6723 break;
6724 case VT_R8: /* these must be 8-byte aligned, and put in 'd' regs or stack, as they are double-floats */
6725 case VT_DATE:
6726 #ifndef __SOFTFP__
6727 dcount = max( (scount + 1) / 2, dcount );
6728 if (dcount < 8)
6730 regs.sd.d[dcount++] = V_R8(arg);
6732 else
6734 argspos += (argspos % 2); /* align argspos to 8-bytes */
6735 memcpy( &args[argspos], &V_R8(arg), sizeof(V_R8(arg)) );
6736 argspos += sizeof(V_R8(arg)) / sizeof(DWORD);
6738 break;
6739 #endif
6740 case VT_I8: /* these must be 8-byte aligned, and put in 'r' regs or stack, as they are long-longs */
6741 case VT_UI8:
6742 case VT_CY:
6743 if (rcount < 3)
6745 rcount += (rcount % 2); /* align rcount to 8-byte register pair */
6746 memcpy( &regs.r[rcount], &V_UI8(arg), sizeof(V_UI8(arg)) );
6747 rcount += sizeof(V_UI8(arg)) / sizeof(DWORD);
6749 else
6751 rcount = 4; /* Make sure we flag that all 'r' regs are full */
6752 argspos += (argspos % 2); /* align argspos to 8-bytes */
6753 memcpy( &args[argspos], &V_UI8(arg), sizeof(V_UI8(arg)) );
6754 argspos += sizeof(V_UI8(arg)) / sizeof(DWORD);
6756 break;
6757 case VT_DECIMAL: /* these structures are 8-byte aligned, and put in 'r' regs or stack, can be split between the two */
6758 case VT_VARIANT:
6759 /* 8-byte align 'r' and/or stack: */
6760 if (rcount < 3)
6761 rcount += (rcount % 2);
6762 else
6764 rcount = 4;
6765 argspos += (argspos % 2);
6767 ntemp = sizeof(*arg) / sizeof(DWORD);
6768 while (ntemp > 0)
6770 if (rcount < 4)
6771 regs.r[rcount++] = *pdwarg++;
6772 else
6773 args[argspos++] = *pdwarg++;
6774 --ntemp;
6776 break;
6777 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6778 if (rcount < 4)
6779 regs.r[rcount++] = V_BOOL(arg);
6780 else
6781 args[argspos++] = V_BOOL(arg);
6782 break;
6783 case VT_R4: /* these must be 4-byte aligned, and put in 's' regs or stack, as they are single-floats */
6784 #ifndef __SOFTFP__
6785 if (!(scount % 2)) scount = max( scount, dcount * 2 );
6786 if (scount < 16)
6787 regs.sd.s[scount++] = V_R4(arg);
6788 else
6789 args[argspos++] = V_UI4(arg);
6790 break;
6791 #endif
6792 default:
6793 if (rcount < 4)
6794 regs.r[rcount++] = V_UI4(arg);
6795 else
6796 args[argspos++] = V_UI4(arg);
6797 break;
6799 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6802 argspos += (argspos % 2); /* Make sure stack function alignment is 8-byte */
6804 switch (vtReturn)
6806 case VT_EMPTY: /* EMPTY = no return value */
6807 case VT_DECIMAL: /* DECIMAL and VARIANT already have a pointer argument passed (see above) */
6808 case VT_VARIANT:
6809 call_method( func, argspos, args, (DWORD*)&regs );
6810 break;
6811 case VT_R4:
6812 V_R4(pvargResult) = call_float_method( func, argspos, args, (DWORD*)&regs );
6813 break;
6814 case VT_R8:
6815 case VT_DATE:
6816 V_R8(pvargResult) = call_double_method( func, argspos, args, (DWORD*)&regs );
6817 break;
6818 case VT_I8:
6819 case VT_UI8:
6820 case VT_CY:
6821 V_UI8(pvargResult) = call_method( func, argspos, args, (DWORD*)&regs );
6822 break;
6823 default:
6824 V_UI4(pvargResult) = call_method( func, argspos, args, (DWORD*)&regs );
6825 break;
6827 heap_free( args );
6828 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6829 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6830 return S_OK;
6833 #elif defined(__aarch64__)
6835 extern DWORD_PTR CDECL call_method( void *func, int nb_stk_args, const DWORD_PTR *stk_args, const DWORD_PTR *reg_args );
6836 extern float CDECL call_float_method( void *func, int nb_stk_args, const DWORD_PTR *stk_args, const DWORD_PTR *reg_args );
6837 extern double CDECL call_double_method( void *func, int nb_stk_args, const DWORD_PTR *stk_args, const DWORD_PTR *reg_args );
6838 __ASM_GLOBAL_FUNC( call_method,
6839 "stp x29, x30, [sp, #-16]!\n\t"
6840 "mov x29, sp\n\t"
6841 "sub sp, sp, x1, lsl #3\n\t"
6842 "cbz x1, 2f\n"
6843 "1:\tsub x1, x1, #1\n\t"
6844 "ldr x4, [x2, x1, lsl #3]\n\t"
6845 "str x4, [sp, x1, lsl #3]\n\t"
6846 "cbnz x1, 1b\n"
6847 "2:\tmov x16, x0\n\t"
6848 "mov x9, x3\n\t"
6849 "ldp d0, d1, [x9]\n\t"
6850 "ldp d2, d3, [x9, #0x10]\n\t"
6851 "ldp d4, d5, [x9, #0x20]\n\t"
6852 "ldp d6, d7, [x9, #0x30]\n\t"
6853 "ldp x0, x1, [x9, #0x40]\n\t"
6854 "ldp x2, x3, [x9, #0x50]\n\t"
6855 "ldp x4, x5, [x9, #0x60]\n\t"
6856 "ldp x6, x7, [x9, #0x70]\n\t"
6857 "ldr x8, [x9, #0x80]\n\t"
6858 "blr x16\n\t"
6859 "mov sp, x29\n\t"
6860 "ldp x29, x30, [sp], #16\n\t"
6861 "ret" )
6862 __ASM_GLOBAL_FUNC( call_float_method,
6863 "b " __ASM_NAME("call_method") )
6864 __ASM_GLOBAL_FUNC( call_double_method,
6865 "b " __ASM_NAME("call_method") )
6867 HRESULT WINAPI DispCallFunc( void *instance, ULONG_PTR offset, CALLCONV cc, VARTYPE ret_type, UINT count,
6868 VARTYPE *types, VARIANTARG **vargs, VARIANT *result )
6870 int argspos;
6871 void *func;
6872 UINT i;
6873 DWORD_PTR *args;
6874 struct
6876 union
6878 float f;
6879 double d;
6880 } fp[8];
6881 DWORD_PTR x[9];
6882 } regs;
6883 int rcount; /* 64-bit register index count */
6884 int fpcount = 0; /* float register index count */
6886 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6887 instance, offset, cc, ret_type, count, types, vargs, result, V_VT(result));
6889 if (cc != CC_STDCALL && cc != CC_CDECL)
6891 FIXME("unsupported calling convention %d\n",cc);
6892 return E_INVALIDARG;
6895 argspos = 0;
6896 rcount = 0;
6898 if (instance)
6900 const FARPROC *vtable = *(FARPROC **)instance;
6901 func = vtable[offset/sizeof(void *)];
6902 regs.x[rcount++] = (DWORD_PTR)instance; /* the This pointer is always the first parameter */
6904 else func = (void *)offset;
6906 /* maximum size for an argument is 16 */
6907 args = heap_alloc( 16 * count );
6909 for (i = 0; i < count; i++)
6911 VARIANT *arg = vargs[i];
6913 switch (types[i])
6915 case VT_R4:
6916 if (fpcount < 8) regs.fp[fpcount++].f = V_R4(arg);
6917 else *(float *)&args[argspos++] = V_R4(arg);
6918 break;
6919 case VT_R8:
6920 case VT_DATE:
6921 if (fpcount < 8) regs.fp[fpcount++].d = V_R8(arg);
6922 else *(double *)&args[argspos++] = V_R8(arg);
6923 break;
6924 case VT_DECIMAL:
6925 if (rcount < 7)
6927 memcpy( &regs.x[rcount], arg, sizeof(*arg) );
6928 rcount += 2;
6930 else
6932 memcpy( &args[argspos], arg, sizeof(*arg) );
6933 argspos += 2;
6935 break;
6936 case VT_VARIANT:
6937 if (rcount < 8) regs.x[rcount++] = (DWORD_PTR)arg;
6938 else args[argspos++] = (DWORD_PTR)arg;
6939 break;
6940 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6941 if (rcount < 8) regs.x[rcount++] = V_BOOL(arg);
6942 else args[argspos++] = V_BOOL(arg);
6943 break;
6944 default:
6945 if (rcount < 8) regs.x[rcount++] = V_UI8(arg);
6946 else args[argspos++] = V_UI8(arg);
6947 break;
6949 TRACE("arg %u: type %s %s\n", i, debugstr_vt(types[i]), debugstr_variant(arg));
6952 argspos += (argspos % 2); /* Make sure stack function alignment is 16-byte */
6954 switch (ret_type)
6956 case VT_HRESULT:
6957 heap_free( args );
6958 return E_INVALIDARG;
6959 case VT_DECIMAL:
6960 case VT_VARIANT:
6961 regs.x[8] = (DWORD_PTR)result; /* x8 is a pointer to the result */
6962 call_method( func, argspos, args, (DWORD_PTR *)&regs );
6963 break;
6964 case VT_R4:
6965 V_R4(result) = call_float_method( func, argspos, args, (DWORD_PTR *)&regs );
6966 break;
6967 case VT_R8:
6968 case VT_DATE:
6969 V_R8(result) = call_double_method( func, argspos, args, (DWORD_PTR *)&regs );
6970 break;
6971 default:
6972 V_UI8(result) = call_method( func, argspos, args, (DWORD_PTR *)&regs );
6973 break;
6975 heap_free( args );
6976 if (ret_type != VT_VARIANT) V_VT(result) = ret_type;
6977 TRACE("retval: %s\n", debugstr_variant(result));
6978 return S_OK;
6981 #else /* __aarch64__ */
6983 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
6984 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
6986 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6987 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6988 return E_NOTIMPL;
6991 #endif
6993 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6995 HRESULT hr = S_OK;
6996 ITypeInfo *tinfo2 = NULL;
6997 TYPEATTR *tattr = NULL;
6999 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
7000 if (hr)
7002 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
7003 "hr = 0x%08x\n",
7004 tdesc->u.hreftype, hr);
7005 return hr;
7007 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
7008 if (hr)
7010 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
7011 ITypeInfo_Release(tinfo2);
7012 return hr;
7015 switch (tattr->typekind)
7017 case TKIND_ENUM:
7018 *vt |= VT_I4;
7019 break;
7021 case TKIND_ALIAS:
7022 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
7023 break;
7025 case TKIND_INTERFACE:
7026 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
7027 *vt |= VT_DISPATCH;
7028 else
7029 *vt |= VT_UNKNOWN;
7030 break;
7032 case TKIND_DISPATCH:
7033 *vt |= VT_DISPATCH;
7034 break;
7036 case TKIND_COCLASS:
7037 *vt |= VT_DISPATCH;
7038 break;
7040 case TKIND_RECORD:
7041 FIXME("TKIND_RECORD unhandled.\n");
7042 hr = E_NOTIMPL;
7043 break;
7045 case TKIND_UNION:
7046 FIXME("TKIND_UNION unhandled.\n");
7047 hr = E_NOTIMPL;
7048 break;
7050 default:
7051 FIXME("TKIND %d unhandled.\n",tattr->typekind);
7052 hr = E_NOTIMPL;
7053 break;
7055 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
7056 ITypeInfo_Release(tinfo2);
7057 return hr;
7060 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
7062 HRESULT hr = S_OK;
7064 /* enforce only one level of pointer indirection */
7065 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
7067 tdesc = tdesc->u.lptdesc;
7069 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
7070 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
7071 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
7072 if ((tdesc->vt == VT_USERDEFINED) ||
7073 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
7075 VARTYPE vt_userdefined = 0;
7076 const TYPEDESC *tdesc_userdefined = tdesc;
7077 if (tdesc->vt == VT_PTR)
7079 vt_userdefined = VT_BYREF;
7080 tdesc_userdefined = tdesc->u.lptdesc;
7082 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
7083 if ((hr == S_OK) &&
7084 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
7085 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
7087 *vt |= vt_userdefined;
7088 return S_OK;
7091 *vt = VT_BYREF;
7094 switch (tdesc->vt)
7096 case VT_HRESULT:
7097 *vt |= VT_ERROR;
7098 break;
7099 case VT_USERDEFINED:
7100 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
7101 break;
7102 case VT_VOID:
7103 case VT_CARRAY:
7104 case VT_PTR:
7105 case VT_LPSTR:
7106 case VT_LPWSTR:
7107 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
7108 hr = DISP_E_BADVARTYPE;
7109 break;
7110 case VT_SAFEARRAY:
7111 *vt |= VT_ARRAY;
7112 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
7113 break;
7114 case VT_INT:
7115 *vt |= VT_I4;
7116 break;
7117 case VT_UINT:
7118 *vt |= VT_UI4;
7119 break;
7120 default:
7121 *vt |= tdesc->vt;
7122 break;
7124 return hr;
7127 static HRESULT get_iface_guid(ITypeInfo *tinfo, HREFTYPE href, GUID *guid)
7129 ITypeInfo *tinfo2;
7130 TYPEATTR *tattr;
7131 HRESULT hres;
7132 int flags, i;
7134 hres = ITypeInfo_GetRefTypeInfo(tinfo, href, &tinfo2);
7135 if(FAILED(hres))
7136 return hres;
7138 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
7139 if(FAILED(hres)) {
7140 ITypeInfo_Release(tinfo2);
7141 return hres;
7144 switch(tattr->typekind) {
7145 case TKIND_ALIAS:
7146 hres = get_iface_guid(tinfo2, tattr->tdescAlias.u.hreftype, guid);
7147 break;
7149 case TKIND_INTERFACE:
7150 case TKIND_DISPATCH:
7151 *guid = tattr->guid;
7152 break;
7154 case TKIND_COCLASS:
7155 for (i = 0; i < tattr->cImplTypes; i++)
7157 ITypeInfo_GetImplTypeFlags(tinfo2, i, &flags);
7158 if (flags & IMPLTYPEFLAG_FDEFAULT)
7159 break;
7162 if (i == tattr->cImplTypes)
7163 i = 0;
7165 hres = ITypeInfo_GetRefTypeOfImplType(tinfo2, i, &href);
7166 if (SUCCEEDED(hres))
7167 hres = get_iface_guid(tinfo2, href, guid);
7168 break;
7170 default:
7171 ERR("Unexpected typekind %d\n", tattr->typekind);
7172 hres = E_UNEXPECTED;
7175 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
7176 ITypeInfo_Release(tinfo2);
7177 return hres;
7180 static inline BOOL func_restricted( const FUNCDESC *desc )
7182 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
7185 #define INVBUF_ELEMENT_SIZE \
7186 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
7187 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
7188 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
7189 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
7190 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
7191 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
7192 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
7193 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
7195 static HRESULT WINAPI ITypeInfo_fnInvoke(
7196 ITypeInfo2 *iface,
7197 VOID *pIUnk,
7198 MEMBERID memid,
7199 UINT16 wFlags,
7200 DISPPARAMS *pDispParams,
7201 VARIANT *pVarResult,
7202 EXCEPINFO *pExcepInfo,
7203 UINT *pArgErr)
7205 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7206 int i;
7207 unsigned int var_index;
7208 TYPEKIND type_kind;
7209 HRESULT hres;
7210 const TLBFuncDesc *pFuncInfo;
7211 UINT fdc;
7213 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
7214 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
7217 if( This->typeattr.wTypeFlags & TYPEFLAG_FRESTRICTED )
7218 return DISP_E_MEMBERNOTFOUND;
7220 if (!pDispParams)
7222 ERR("NULL pDispParams not allowed\n");
7223 return E_INVALIDARG;
7226 dump_DispParms(pDispParams);
7228 if (pDispParams->cNamedArgs > pDispParams->cArgs)
7230 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
7231 pDispParams->cNamedArgs, pDispParams->cArgs);
7232 return E_INVALIDARG;
7235 /* we do this instead of using GetFuncDesc since it will return a fake
7236 * FUNCDESC for dispinterfaces and we want the real function description */
7237 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
7238 pFuncInfo = &This->funcdescs[fdc];
7239 if ((memid == pFuncInfo->funcdesc.memid) &&
7240 (wFlags & pFuncInfo->funcdesc.invkind) &&
7241 !func_restricted( &pFuncInfo->funcdesc ))
7242 break;
7245 if (fdc < This->typeattr.cFuncs) {
7246 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
7248 if (TRACE_ON(ole))
7250 TRACE("invoking:\n");
7251 dump_TLBFuncDescOne(pFuncInfo);
7254 switch (func_desc->funckind) {
7255 case FUNC_PUREVIRTUAL:
7256 case FUNC_VIRTUAL: {
7257 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
7258 VARIANT varresult;
7259 VARIANT retval; /* pointer for storing byref retvals in */
7260 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
7261 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
7262 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
7263 UINT cNamedArgs = pDispParams->cNamedArgs;
7264 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
7265 UINT vargs_converted=0;
7266 SAFEARRAY *a;
7268 hres = S_OK;
7270 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
7272 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
7274 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
7275 hres = DISP_E_PARAMNOTFOUND;
7276 goto func_fail;
7280 if (func_desc->cParamsOpt < 0 && cNamedArgs)
7282 ERR("functions with the vararg attribute do not support named arguments\n");
7283 hres = DISP_E_NONAMEDARGS;
7284 goto func_fail;
7287 for (i = 0; i < func_desc->cParams; i++)
7289 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7290 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
7291 if (FAILED(hres))
7292 goto func_fail;
7295 TRACE("changing args\n");
7296 for (i = 0; i < func_desc->cParams; i++)
7298 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7299 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7300 VARIANTARG *src_arg;
7302 if (wParamFlags & PARAMFLAG_FLCID)
7304 VARIANTARG *arg;
7305 arg = prgpvarg[i] = &rgvarg[i];
7306 V_VT(arg) = VT_I4;
7307 V_I4(arg) = This->pTypeLib->lcid;
7308 continue;
7311 src_arg = NULL;
7313 if (cNamedArgs)
7315 USHORT j;
7316 for (j = 0; j < cNamedArgs; j++)
7317 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
7319 src_arg = &pDispParams->rgvarg[j];
7320 break;
7324 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
7326 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7327 vargs_converted++;
7330 if (wParamFlags & PARAMFLAG_FRETVAL)
7332 /* under most conditions the caller is not allowed to
7333 * pass in a dispparam arg in the index of what would be
7334 * the retval parameter. however, there is an exception
7335 * where the extra parameter is used in an extra
7336 * IDispatch::Invoke below */
7337 if ((i < pDispParams->cArgs) &&
7338 ((func_desc->cParams != 1) || !pVarResult ||
7339 !(func_desc->invkind & INVOKE_PROPERTYGET)))
7341 hres = DISP_E_BADPARAMCOUNT;
7342 break;
7345 /* note: this check is placed so that if the caller passes
7346 * in a VARIANTARG for the retval we just ignore it, like
7347 * native does */
7348 if (i == func_desc->cParams - 1)
7350 VARIANTARG *arg;
7351 arg = prgpvarg[i] = &rgvarg[i];
7352 memset(arg, 0, sizeof(*arg));
7353 V_VT(arg) = rgvt[i];
7354 memset(&retval, 0, sizeof(retval));
7355 V_BYREF(arg) = &retval;
7357 else
7359 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
7360 hres = E_UNEXPECTED;
7361 break;
7364 else if (src_arg && !((wParamFlags & PARAMFLAG_FOPT) &&
7365 V_VT(src_arg) == VT_ERROR && V_ERROR(src_arg) == DISP_E_PARAMNOTFOUND))
7367 TRACE("%s\n", debugstr_variant(src_arg));
7369 if(rgvt[i]!=V_VT(src_arg))
7371 if (rgvt[i] == VT_VARIANT)
7372 hres = VariantCopy(&rgvarg[i], src_arg);
7373 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
7375 if (rgvt[i] == V_VT(src_arg))
7376 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
7377 else
7379 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7380 if (wParamFlags & PARAMFLAG_FIN)
7381 hres = VariantCopy(&missing_arg[i], src_arg);
7382 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
7384 V_VT(&rgvarg[i]) = rgvt[i];
7386 else if ((rgvt[i] == (VT_VARIANT | VT_ARRAY) || rgvt[i] == (VT_VARIANT | VT_ARRAY | VT_BYREF)) && func_desc->cParamsOpt < 0)
7388 SAFEARRAYBOUND bound;
7389 VARIANT *v;
7390 LONG j;
7391 bound.lLbound = 0;
7392 bound.cElements = pDispParams->cArgs-i;
7393 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
7395 ERR("SafeArrayCreate failed\n");
7396 break;
7398 hres = SafeArrayAccessData(a, (LPVOID)&v);
7399 if (hres != S_OK)
7401 ERR("SafeArrayAccessData failed with %x\n", hres);
7402 SafeArrayDestroy(a);
7403 break;
7405 for (j = 0; j < bound.cElements; j++)
7406 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
7407 hres = SafeArrayUnaccessData(a);
7408 if (hres != S_OK)
7410 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7411 SafeArrayDestroy(a);
7412 break;
7414 if (rgvt[i] & VT_BYREF)
7415 V_BYREF(&rgvarg[i]) = &a;
7416 else
7417 V_ARRAY(&rgvarg[i]) = a;
7418 V_VT(&rgvarg[i]) = rgvt[i];
7420 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
7422 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7423 if (wParamFlags & PARAMFLAG_FIN)
7424 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
7425 else
7426 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
7427 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
7428 V_VT(&rgvarg[i]) = rgvt[i];
7430 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
7432 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
7433 V_VT(&rgvarg[i]) = rgvt[i];
7435 else
7437 /* FIXME: this doesn't work for VT_BYREF arguments if
7438 * they are not the same type as in the paramdesc */
7439 V_VT(&rgvarg[i]) = V_VT(src_arg);
7440 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
7441 V_VT(&rgvarg[i]) = rgvt[i];
7444 if (FAILED(hres))
7446 ERR("failed to convert param %d to %s from %s\n", i,
7447 debugstr_vt(rgvt[i]), debugstr_variant(src_arg));
7448 break;
7450 prgpvarg[i] = &rgvarg[i];
7452 else
7454 prgpvarg[i] = src_arg;
7457 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
7458 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
7459 && V_UNKNOWN(prgpvarg[i])) {
7460 IUnknown *userdefined_iface;
7461 GUID guid;
7463 if (tdesc->vt == VT_PTR)
7464 tdesc = tdesc->u.lptdesc;
7466 hres = get_iface_guid((ITypeInfo*)iface, tdesc->u.hreftype, &guid);
7467 if(FAILED(hres))
7468 break;
7470 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
7471 if(FAILED(hres)) {
7472 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
7473 break;
7476 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
7477 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
7480 else if (wParamFlags & PARAMFLAG_FOPT)
7482 VARIANTARG *arg;
7483 arg = prgpvarg[i] = &rgvarg[i];
7484 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7486 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
7487 if (FAILED(hres))
7488 break;
7490 else
7492 VARIANTARG *missing_arg;
7493 /* if the function wants a pointer to a variant then
7494 * set that up, otherwise just pass the VT_ERROR in
7495 * the argument by value */
7496 if (rgvt[i] & VT_BYREF)
7498 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
7499 V_VT(arg) = VT_VARIANT | VT_BYREF;
7500 V_VARIANTREF(arg) = missing_arg;
7502 else
7503 missing_arg = arg;
7504 V_VT(missing_arg) = VT_ERROR;
7505 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
7508 else
7510 hres = DISP_E_BADPARAMCOUNT;
7511 break;
7514 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7516 /* VT_VOID is a special case for return types, so it is not
7517 * handled in the general function */
7518 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
7519 V_VT(&varresult) = VT_EMPTY;
7520 else
7522 V_VT(&varresult) = 0;
7523 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
7524 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7527 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv,
7528 V_VT(&varresult), func_desc->cParams, rgvt,
7529 prgpvarg, &varresult);
7531 vargs_converted = 0;
7533 for (i = 0; i < func_desc->cParams; i++)
7535 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7536 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7538 if (wParamFlags & PARAMFLAG_FLCID)
7539 continue;
7540 else if (wParamFlags & PARAMFLAG_FRETVAL)
7542 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg[i]));
7544 if (pVarResult)
7546 VariantInit(pVarResult);
7547 /* deref return value */
7548 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
7551 VARIANT_ClearInd(prgpvarg[i]);
7553 else if (vargs_converted < pDispParams->cArgs)
7555 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7556 if (wParamFlags & PARAMFLAG_FOUT)
7558 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
7560 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
7562 if (FAILED(hres))
7564 ERR("failed to convert param %d to vt %d\n", i,
7565 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
7566 break;
7570 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
7571 func_desc->cParamsOpt < 0 &&
7572 i == func_desc->cParams-1)
7574 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
7575 LONG j, ubound;
7576 VARIANT *v;
7577 hres = SafeArrayGetUBound(a, 1, &ubound);
7578 if (hres != S_OK)
7580 ERR("SafeArrayGetUBound failed with %x\n", hres);
7581 break;
7583 hres = SafeArrayAccessData(a, (LPVOID)&v);
7584 if (hres != S_OK)
7586 ERR("SafeArrayAccessData failed with %x\n", hres);
7587 break;
7589 for (j = 0; j <= ubound; j++)
7590 VariantClear(&v[j]);
7591 hres = SafeArrayUnaccessData(a);
7592 if (hres != S_OK)
7594 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7595 break;
7598 VariantClear(&rgvarg[i]);
7599 vargs_converted++;
7601 else if (wParamFlags & PARAMFLAG_FOPT)
7603 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7604 VariantClear(&rgvarg[i]);
7607 VariantClear(&missing_arg[i]);
7610 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
7612 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
7613 hres = DISP_E_EXCEPTION;
7614 if (pExcepInfo)
7616 IErrorInfo *pErrorInfo;
7617 pExcepInfo->scode = V_ERROR(&varresult);
7618 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
7620 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
7621 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
7622 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
7623 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
7625 IErrorInfo_Release(pErrorInfo);
7629 if (V_VT(&varresult) != VT_ERROR)
7631 TRACE("varresult value: %s\n", debugstr_variant(&varresult));
7633 if (pVarResult)
7635 VariantClear(pVarResult);
7636 *pVarResult = varresult;
7638 else
7639 VariantClear(&varresult);
7642 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
7643 (func_desc->invkind & INVOKE_PROPERTYGET) &&
7644 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
7645 (pDispParams->cArgs != 0))
7647 if (V_VT(pVarResult) == VT_DISPATCH)
7649 IDispatch *pDispatch = V_DISPATCH(pVarResult);
7650 /* Note: not VariantClear; we still need the dispatch
7651 * pointer to be valid */
7652 VariantInit(pVarResult);
7653 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
7654 GetSystemDefaultLCID(), wFlags,
7655 pDispParams, pVarResult, pExcepInfo, pArgErr);
7656 IDispatch_Release(pDispatch);
7658 else
7660 VariantClear(pVarResult);
7661 hres = DISP_E_NOTACOLLECTION;
7665 func_fail:
7666 heap_free(buffer);
7667 break;
7669 case FUNC_DISPATCH: {
7670 IDispatch *disp;
7672 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
7673 if (SUCCEEDED(hres)) {
7674 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7675 hres = IDispatch_Invoke(
7676 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
7677 pVarResult,pExcepInfo,pArgErr
7679 if (FAILED(hres))
7680 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
7681 IDispatch_Release(disp);
7682 } else
7683 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7684 break;
7686 default:
7687 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
7688 hres = E_FAIL;
7689 break;
7692 TRACE("-- 0x%08x\n", hres);
7693 return hres;
7695 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
7696 VARDESC *var_desc;
7698 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
7699 if(FAILED(hres)) return hres;
7701 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7702 dump_VARDESC(var_desc);
7703 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
7704 return E_NOTIMPL;
7707 /* not found, look for it in inherited interfaces */
7708 ITypeInfo2_GetTypeKind(iface, &type_kind);
7709 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
7710 if(This->impltypes) {
7711 /* recursive search */
7712 ITypeInfo *pTInfo;
7713 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7714 if(SUCCEEDED(hres)){
7715 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
7716 ITypeInfo_Release(pTInfo);
7717 return hres;
7719 WARN("Could not search inherited interface!\n");
7722 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
7723 return DISP_E_MEMBERNOTFOUND;
7726 /* ITypeInfo::GetDocumentation
7728 * Retrieves the documentation string, the complete Help file name and path,
7729 * and the context ID for the Help topic for a specified type description.
7731 * (Can be tested by the Visual Basic Editor in Word for instance.)
7733 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
7734 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
7735 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
7737 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7738 const TLBFuncDesc *pFDesc;
7739 const TLBVarDesc *pVDesc;
7740 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7741 " HelpContext(%p) HelpFile(%p)\n",
7742 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
7743 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7744 if(pBstrName)
7745 *pBstrName=SysAllocString(TLB_get_bstr(This->Name));
7746 if(pBstrDocString)
7747 *pBstrDocString=SysAllocString(TLB_get_bstr(This->DocString));
7748 if(pdwHelpContext)
7749 *pdwHelpContext=This->dwHelpContext;
7750 if(pBstrHelpFile)
7751 *pBstrHelpFile=SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7752 return S_OK;
7753 }else {/* for a member */
7754 pFDesc = TLB_get_funcdesc_by_memberid(This, memid);
7755 if(pFDesc){
7756 if(pBstrName)
7757 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Name));
7758 if(pBstrDocString)
7759 *pBstrDocString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7760 if(pdwHelpContext)
7761 *pdwHelpContext=pFDesc->helpcontext;
7762 if(pBstrHelpFile)
7763 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7764 return S_OK;
7766 pVDesc = TLB_get_vardesc_by_memberid(This, memid);
7767 if(pVDesc){
7768 if(pBstrName)
7769 *pBstrName = SysAllocString(TLB_get_bstr(pVDesc->Name));
7770 if(pBstrDocString)
7771 *pBstrDocString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7772 if(pdwHelpContext)
7773 *pdwHelpContext=pVDesc->HelpContext;
7774 if(pBstrHelpFile)
7775 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7776 return S_OK;
7780 if(This->impltypes &&
7781 (This->typeattr.typekind == TKIND_INTERFACE || This->typeattr.typekind == TKIND_DISPATCH)) {
7782 /* recursive search */
7783 ITypeInfo *pTInfo;
7784 HRESULT result;
7785 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7786 if(SUCCEEDED(result)) {
7787 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
7788 pBstrDocString, pdwHelpContext, pBstrHelpFile);
7789 ITypeInfo_Release(pTInfo);
7790 return result;
7792 WARN("Could not search inherited interface!\n");
7795 WARN("member %d not found\n", memid);
7796 return TYPE_E_ELEMENTNOTFOUND;
7799 /* ITypeInfo::GetDllEntry
7801 * Retrieves a description or specification of an entry point for a function
7802 * in a DLL.
7804 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
7805 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
7806 WORD *pwOrdinal)
7808 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7809 const TLBFuncDesc *pFDesc;
7811 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
7813 if (pBstrDllName) *pBstrDllName = NULL;
7814 if (pBstrName) *pBstrName = NULL;
7815 if (pwOrdinal) *pwOrdinal = 0;
7817 if (This->typeattr.typekind != TKIND_MODULE)
7818 return TYPE_E_BADMODULEKIND;
7820 pFDesc = TLB_get_funcdesc_by_memberid_invkind(This, memid, invKind);
7821 if (!pFDesc) return TYPE_E_ELEMENTNOTFOUND;
7823 dump_TypeInfo(This);
7824 if (TRACE_ON(ole)) dump_TLBFuncDescOne(pFDesc);
7826 if (pBstrDllName) *pBstrDllName = SysAllocString(TLB_get_bstr(This->DllName));
7828 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1))
7830 if (pBstrName) *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Entry));
7831 if (pwOrdinal) *pwOrdinal = -1;
7833 else
7835 if (pBstrName) *pBstrName = NULL;
7836 if (pwOrdinal) *pwOrdinal = LOWORD(pFDesc->Entry);
7838 return S_OK;
7841 /* internal function to make the inherited interfaces' methods appear
7842 * part of the interface */
7843 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7844 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7846 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7847 HRESULT hr;
7849 TRACE("%p, 0x%x\n", iface, *hRefType);
7851 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7853 ITypeInfo *pSubTypeInfo;
7855 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7856 if (FAILED(hr))
7857 return hr;
7859 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7860 hRefType, ppTInfo);
7861 ITypeInfo_Release(pSubTypeInfo);
7862 if (SUCCEEDED(hr))
7863 return hr;
7865 *hRefType -= DISPATCH_HREF_OFFSET;
7867 if (!(*hRefType & DISPATCH_HREF_MASK))
7868 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7869 else
7870 return E_FAIL;
7873 struct search_res_tlb_params
7875 const GUID *guid;
7876 ITypeLib *pTLib;
7879 static BOOL CALLBACK search_res_tlb(HMODULE hModule, LPCWSTR lpszType, LPWSTR lpszName, LONG_PTR lParam)
7881 struct search_res_tlb_params *params = (LPVOID)lParam;
7882 static const WCHAR formatW[] = {'\\','%','d',0};
7883 WCHAR szPath[MAX_PATH+1];
7884 ITypeLib *pTLib = NULL;
7885 HRESULT ret;
7886 DWORD len;
7888 if (IS_INTRESOURCE(lpszName) == FALSE)
7889 return TRUE;
7891 if (!(len = GetModuleFileNameW(hModule, szPath, MAX_PATH)))
7892 return TRUE;
7894 if (swprintf(szPath + len, ARRAY_SIZE(szPath) - len, formatW, LOWORD(lpszName)) < 0)
7895 return TRUE;
7897 ret = LoadTypeLibEx(szPath, REGKIND_NONE, &pTLib);
7898 if (SUCCEEDED(ret))
7900 ITypeLibImpl *impl = impl_from_ITypeLib(pTLib);
7901 if (IsEqualGUID(params->guid, impl->guid))
7903 params->pTLib = pTLib;
7904 return FALSE; /* stop enumeration */
7906 ITypeLib_Release(pTLib);
7909 return TRUE;
7912 /* ITypeInfo::GetRefTypeInfo
7914 * If a type description references other type descriptions, it retrieves
7915 * the referenced type descriptions.
7917 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7918 ITypeInfo2 *iface,
7919 HREFTYPE hRefType,
7920 ITypeInfo **ppTInfo)
7922 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7923 ITypeInfo *type_info = NULL;
7924 HRESULT result = E_FAIL;
7925 TLBRefType *ref_type;
7926 UINT i;
7928 if(!ppTInfo)
7929 return E_INVALIDARG;
7931 if ((INT)hRefType < 0) {
7932 ITypeInfoImpl *pTypeInfoImpl;
7934 if (!(This->typeattr.wTypeFlags & TYPEFLAG_FDUAL) ||
7935 !(This->typeattr.typekind == TKIND_INTERFACE ||
7936 This->typeattr.typekind == TKIND_DISPATCH))
7937 return TYPE_E_ELEMENTNOTFOUND;
7939 /* when we meet a DUAL typeinfo, we must create the alternate
7940 * version of it.
7942 pTypeInfoImpl = ITypeInfoImpl_Constructor();
7944 *pTypeInfoImpl = *This;
7945 pTypeInfoImpl->ref = 0;
7946 list_init(&pTypeInfoImpl->custdata_list);
7948 if (This->typeattr.typekind == TKIND_INTERFACE)
7949 pTypeInfoImpl->typeattr.typekind = TKIND_DISPATCH;
7950 else
7951 pTypeInfoImpl->typeattr.typekind = TKIND_INTERFACE;
7953 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface;
7954 /* the AddRef implicitly adds a reference to the parent typelib, which
7955 * stops the copied data from being destroyed until the new typeinfo's
7956 * refcount goes to zero, but we need to signal to the new instance to
7957 * not free its data structures when it is destroyed */
7958 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7959 ITypeInfo_AddRef(*ppTInfo);
7961 TRACE("got dual interface %p\n", *ppTInfo);
7962 return S_OK;
7965 if ((hRefType & DISPATCH_HREF_MASK) && (This->typeattr.typekind == TKIND_DISPATCH))
7966 return ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &hRefType, ppTInfo);
7968 if(!(hRefType & 0x1))
7970 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
7972 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
7974 result = S_OK;
7975 type_info = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
7976 ITypeInfo_AddRef(type_info);
7977 break;
7982 if (!type_info)
7984 ITypeLib *pTLib = NULL;
7986 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7988 if(ref_type->reference == (hRefType & (~0x3)))
7989 break;
7991 if(&ref_type->entry == &This->pTypeLib->ref_list)
7993 FIXME("Can't find pRefType for ref %x\n", hRefType);
7994 return E_FAIL;
7997 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7998 UINT Index;
7999 TRACE("internal reference\n");
8000 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
8001 } else {
8002 if(ref_type->pImpTLInfo->pImpTypeLib) {
8003 TRACE("typeinfo in imported typelib that is already loaded\n");
8004 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
8005 ITypeLib_AddRef(pTLib);
8006 result = S_OK;
8007 } else {
8008 /* Search in cached typelibs */
8009 ITypeLibImpl *entry;
8011 EnterCriticalSection(&cache_section);
8012 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
8014 if (entry->guid
8015 && IsEqualIID(&entry->guid->guid, TLB_get_guid_null(ref_type->pImpTLInfo->guid))
8016 && entry->ver_major == ref_type->pImpTLInfo->wVersionMajor
8017 && entry->ver_minor == ref_type->pImpTLInfo->wVersionMinor
8018 && entry->set_lcid == ref_type->pImpTLInfo->lcid)
8020 TRACE("got cached %p\n", entry);
8021 pTLib = (ITypeLib*)&entry->ITypeLib2_iface;
8022 ITypeLib_AddRef(pTLib);
8023 result = S_OK;
8024 break;
8027 LeaveCriticalSection(&cache_section);
8029 if (!pTLib)
8031 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
8032 struct search_res_tlb_params params;
8034 TRACE("typeinfo in imported typelib that isn't already loaded\n");
8036 /* Search in resource table */
8037 params.guid = TLB_get_guid_null(ref_type->pImpTLInfo->guid);
8038 params.pTLib = NULL;
8039 EnumResourceNamesW(NULL, TYPELIBW, search_res_tlb, (LONG_PTR)&params);
8040 if(params.pTLib)
8042 pTLib = params.pTLib;
8043 result = S_OK;
8047 if (!pTLib)
8049 BSTR libnam;
8051 /* Search on disk */
8052 result = query_typelib_path(TLB_get_guid_null(ref_type->pImpTLInfo->guid),
8053 ref_type->pImpTLInfo->wVersionMajor,
8054 ref_type->pImpTLInfo->wVersionMinor,
8055 This->pTypeLib->syskind,
8056 ref_type->pImpTLInfo->lcid, &libnam, TRUE);
8057 if (FAILED(result))
8058 libnam = SysAllocString(ref_type->pImpTLInfo->name);
8060 result = LoadTypeLib(libnam, &pTLib);
8061 SysFreeString(libnam);
8064 if(SUCCEEDED(result)) {
8065 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
8066 ITypeLib_AddRef(pTLib);
8070 if(SUCCEEDED(result)) {
8071 if(ref_type->index == TLB_REF_USE_GUID)
8072 result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), &type_info);
8073 else
8074 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, &type_info);
8076 if (pTLib != NULL)
8077 ITypeLib_Release(pTLib);
8078 if (FAILED(result))
8080 WARN("(%p) failed hreftype 0x%04x\n", This, hRefType);
8081 return result;
8085 if ((hRefType & 0x2) && SUCCEEDED(ITypeInfo_GetRefTypeInfo(type_info, -2, ppTInfo)))
8086 ITypeInfo_Release(type_info);
8087 else *ppTInfo = type_info;
8089 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
8090 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
8091 return result;
8094 /* ITypeInfo::AddressOfMember
8096 * Retrieves the addresses of static functions or variables, such as those
8097 * defined in a DLL.
8099 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
8100 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
8102 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8103 HRESULT hr;
8104 BSTR dll, entry;
8105 WORD ordinal;
8106 HMODULE module;
8108 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
8110 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
8111 if (FAILED(hr))
8112 return hr;
8114 module = LoadLibraryW(dll);
8115 if (!module)
8117 ERR("couldn't load %s\n", debugstr_w(dll));
8118 SysFreeString(dll);
8119 SysFreeString(entry);
8120 return STG_E_FILENOTFOUND;
8122 /* FIXME: store library somewhere where we can free it */
8124 if (entry)
8126 LPSTR entryA;
8127 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
8128 entryA = heap_alloc(len);
8129 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
8131 *ppv = GetProcAddress(module, entryA);
8132 if (!*ppv)
8133 ERR("function not found %s\n", debugstr_a(entryA));
8135 heap_free(entryA);
8137 else
8139 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
8140 if (!*ppv)
8141 ERR("function not found %d\n", ordinal);
8144 SysFreeString(dll);
8145 SysFreeString(entry);
8147 if (!*ppv)
8148 return TYPE_E_DLLFUNCTIONNOTFOUND;
8150 return S_OK;
8153 /* ITypeInfo::CreateInstance
8155 * Creates a new instance of a type that describes a component object class
8156 * (coclass).
8158 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
8159 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
8161 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8162 HRESULT hr;
8163 TYPEATTR *pTA;
8165 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
8167 *ppvObj = NULL;
8169 if(pOuterUnk)
8171 WARN("Not able to aggregate\n");
8172 return CLASS_E_NOAGGREGATION;
8175 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
8176 if(FAILED(hr)) return hr;
8178 if(pTA->typekind != TKIND_COCLASS)
8180 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
8181 hr = E_INVALIDARG;
8182 goto end;
8185 hr = S_FALSE;
8186 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
8188 IUnknown *pUnk;
8189 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
8190 TRACE("GetActiveObject rets %08x\n", hr);
8191 if(hr == S_OK)
8193 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
8194 IUnknown_Release(pUnk);
8198 if(hr != S_OK)
8199 hr = CoCreateInstance(&pTA->guid, NULL,
8200 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
8201 riid, ppvObj);
8203 end:
8204 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
8205 return hr;
8208 /* ITypeInfo::GetMops
8210 * Retrieves marshalling information.
8212 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
8213 BSTR *pBstrMops)
8215 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8216 FIXME("(%p %d) stub!\n", This, memid);
8217 *pBstrMops = NULL;
8218 return S_OK;
8221 /* ITypeInfo::GetContainingTypeLib
8223 * Retrieves the containing type library and the index of the type description
8224 * within that type library.
8226 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
8227 ITypeLib * *ppTLib, UINT *pIndex)
8229 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8231 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
8232 if (pIndex) {
8233 *pIndex=This->index;
8234 TRACE("returning pIndex=%d\n", *pIndex);
8237 if (ppTLib) {
8238 *ppTLib = (ITypeLib *)&This->pTypeLib->ITypeLib2_iface;
8239 ITypeLib_AddRef(*ppTLib);
8240 TRACE("returning ppTLib=%p\n", *ppTLib);
8243 return S_OK;
8246 /* ITypeInfo::ReleaseTypeAttr
8248 * Releases a TYPEATTR previously returned by Get
8251 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
8252 TYPEATTR* pTypeAttr)
8254 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8255 TRACE("(%p)->(%p)\n", This, pTypeAttr);
8256 heap_free(pTypeAttr);
8259 /* ITypeInfo::ReleaseFuncDesc
8261 * Releases a FUNCDESC previously returned by GetFuncDesc. *
8263 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
8264 ITypeInfo2 *iface,
8265 FUNCDESC *pFuncDesc)
8267 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8268 SHORT i;
8270 TRACE("(%p)->(%p)\n", This, pFuncDesc);
8272 for (i = 0; i < pFuncDesc->cParams; i++)
8273 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
8274 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
8276 SysFreeString((BSTR)pFuncDesc);
8279 /* ITypeInfo::ReleaseVarDesc
8281 * Releases a VARDESC previously returned by GetVarDesc.
8283 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
8284 VARDESC *pVarDesc)
8286 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8287 TRACE("(%p)->(%p)\n", This, pVarDesc);
8289 TLB_FreeVarDesc(pVarDesc);
8292 /* ITypeInfo2::GetTypeKind
8294 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
8297 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
8298 TYPEKIND *pTypeKind)
8300 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8301 *pTypeKind = This->typeattr.typekind;
8302 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
8303 return S_OK;
8306 /* ITypeInfo2::GetTypeFlags
8308 * Returns the type flags without any allocations. This returns a DWORD type
8309 * flag, which expands the type flags without growing the TYPEATTR (type
8310 * attribute).
8313 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
8315 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8316 *pTypeFlags=This->typeattr.wTypeFlags;
8317 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
8318 return S_OK;
8321 /* ITypeInfo2::GetFuncIndexOfMemId
8322 * Binds to a specific member based on a known DISPID, where the member name
8323 * is not known (for example, when binding to a default member).
8326 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
8327 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
8329 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8330 UINT fdc;
8331 HRESULT result;
8333 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
8334 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
8335 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
8336 break;
8338 if(fdc < This->typeattr.cFuncs) {
8339 *pFuncIndex = fdc;
8340 result = S_OK;
8341 } else
8342 result = TYPE_E_ELEMENTNOTFOUND;
8344 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
8345 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
8346 return result;
8349 /* TypeInfo2::GetVarIndexOfMemId
8351 * Binds to a specific member based on a known DISPID, where the member name
8352 * is not known (for example, when binding to a default member).
8355 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
8356 MEMBERID memid, UINT *pVarIndex)
8358 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8359 TLBVarDesc *pVarInfo;
8361 TRACE("%p %d %p\n", iface, memid, pVarIndex);
8363 pVarInfo = TLB_get_vardesc_by_memberid(This, memid);
8364 if(!pVarInfo)
8365 return TYPE_E_ELEMENTNOTFOUND;
8367 *pVarIndex = (pVarInfo - This->vardescs);
8369 return S_OK;
8372 /* ITypeInfo2::GetCustData
8374 * Gets the custom data
8376 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
8377 ITypeInfo2 * iface,
8378 REFGUID guid,
8379 VARIANT *pVarVal)
8381 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8382 TLBCustData *pCData;
8384 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8386 if(!guid || !pVarVal)
8387 return E_INVALIDARG;
8389 pCData = TLB_get_custdata_by_guid(This->pcustdata_list, guid);
8391 VariantInit( pVarVal);
8392 if (pCData)
8393 VariantCopy( pVarVal, &pCData->data);
8394 else
8395 VariantClear( pVarVal );
8396 return S_OK;
8399 /* ITypeInfo2::GetFuncCustData
8401 * Gets the custom data
8403 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
8404 ITypeInfo2 * iface,
8405 UINT index,
8406 REFGUID guid,
8407 VARIANT *pVarVal)
8409 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8410 const TLBFuncDesc *desc;
8411 TLBCustData *data;
8412 UINT hrefoffset;
8413 HRESULT hr;
8415 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8417 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index, &desc, &hrefoffset);
8418 if (FAILED(hr))
8420 WARN("description for function %d not found\n", index);
8421 return hr;
8424 VariantInit(pVarVal);
8425 data = TLB_get_custdata_by_guid(&desc->custdata_list, guid);
8426 return data ? VariantCopy(pVarVal, &data->data) : S_OK;
8429 /* ITypeInfo2::GetParamCustData
8431 * Gets the custom data
8433 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
8434 ITypeInfo2 * iface,
8435 UINT indexFunc,
8436 UINT indexParam,
8437 REFGUID guid,
8438 VARIANT *pVarVal)
8440 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8441 const TLBFuncDesc *pFDesc;
8442 TLBCustData *pCData;
8443 UINT hrefoffset;
8444 HRESULT hr;
8446 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
8447 debugstr_guid(guid), pVarVal);
8449 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, indexFunc, &pFDesc, &hrefoffset);
8450 if (FAILED(hr))
8451 return hr;
8453 if(indexParam >= pFDesc->funcdesc.cParams)
8454 return TYPE_E_ELEMENTNOTFOUND;
8456 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
8457 if(!pCData)
8458 return TYPE_E_ELEMENTNOTFOUND;
8460 VariantInit(pVarVal);
8461 VariantCopy(pVarVal, &pCData->data);
8463 return S_OK;
8466 /* ITypeInfo2::GetVarCustData
8468 * Gets the custom data
8470 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
8471 ITypeInfo2 * iface,
8472 UINT index,
8473 REFGUID guid,
8474 VARIANT *pVarVal)
8476 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8477 TLBCustData *pCData;
8478 TLBVarDesc *pVDesc = &This->vardescs[index];
8480 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8482 if(index >= This->typeattr.cVars)
8483 return TYPE_E_ELEMENTNOTFOUND;
8485 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
8486 if(!pCData)
8487 return TYPE_E_ELEMENTNOTFOUND;
8489 VariantInit(pVarVal);
8490 VariantCopy(pVarVal, &pCData->data);
8492 return S_OK;
8495 /* ITypeInfo2::GetImplCustData
8497 * Gets the custom data
8499 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
8500 ITypeInfo2 * iface,
8501 UINT index,
8502 REFGUID guid,
8503 VARIANT *pVarVal)
8505 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8506 TLBCustData *pCData;
8507 TLBImplType *pRDesc = &This->impltypes[index];
8509 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8511 if(index >= This->typeattr.cImplTypes)
8512 return TYPE_E_ELEMENTNOTFOUND;
8514 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
8515 if(!pCData)
8516 return TYPE_E_ELEMENTNOTFOUND;
8518 VariantInit(pVarVal);
8519 VariantCopy(pVarVal, &pCData->data);
8521 return S_OK;
8524 /* ITypeInfo2::GetDocumentation2
8526 * Retrieves the documentation string, the complete Help file name and path,
8527 * the localization context to use, and the context ID for the library Help
8528 * topic in the Help file.
8531 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
8532 ITypeInfo2 * iface,
8533 MEMBERID memid,
8534 LCID lcid,
8535 BSTR *pbstrHelpString,
8536 DWORD *pdwHelpStringContext,
8537 BSTR *pbstrHelpStringDll)
8539 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8540 const TLBFuncDesc *pFDesc;
8541 const TLBVarDesc *pVDesc;
8542 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8543 "HelpStringContext(%p) HelpStringDll(%p)\n",
8544 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
8545 pbstrHelpStringDll );
8546 /* the help string should be obtained from the helpstringdll,
8547 * using the _DLLGetDocumentation function, based on the supplied
8548 * lcid. Nice to do sometime...
8550 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
8551 if(pbstrHelpString)
8552 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->Name));
8553 if(pdwHelpStringContext)
8554 *pdwHelpStringContext=This->dwHelpStringContext;
8555 if(pbstrHelpStringDll)
8556 *pbstrHelpStringDll=
8557 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8558 return S_OK;
8559 }else {/* for a member */
8560 pFDesc = TLB_get_funcdesc_by_memberid(This, memid);
8561 if(pFDesc){
8562 if(pbstrHelpString)
8563 *pbstrHelpString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
8564 if(pdwHelpStringContext)
8565 *pdwHelpStringContext=pFDesc->HelpStringContext;
8566 if(pbstrHelpStringDll)
8567 *pbstrHelpStringDll=
8568 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8569 return S_OK;
8571 pVDesc = TLB_get_vardesc_by_memberid(This, memid);
8572 if(pVDesc){
8573 if(pbstrHelpString)
8574 *pbstrHelpString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
8575 if(pdwHelpStringContext)
8576 *pdwHelpStringContext=pVDesc->HelpStringContext;
8577 if(pbstrHelpStringDll)
8578 *pbstrHelpStringDll=
8579 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8580 return S_OK;
8583 return TYPE_E_ELEMENTNOTFOUND;
8586 /* ITypeInfo2::GetAllCustData
8588 * Gets all custom data items for the Type info.
8591 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
8592 ITypeInfo2 * iface,
8593 CUSTDATA *pCustData)
8595 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8597 TRACE("%p %p\n", This, pCustData);
8599 return TLB_copy_all_custdata(This->pcustdata_list, pCustData);
8602 /* ITypeInfo2::GetAllFuncCustData
8604 * Gets all custom data items for the specified Function
8607 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
8608 ITypeInfo2 * iface,
8609 UINT index,
8610 CUSTDATA *pCustData)
8612 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8613 const TLBFuncDesc *pFDesc;
8614 UINT hrefoffset;
8615 HRESULT hr;
8617 TRACE("%p %u %p\n", This, index, pCustData);
8619 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index, &pFDesc, &hrefoffset);
8620 if (FAILED(hr))
8621 return hr;
8623 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
8626 /* ITypeInfo2::GetAllParamCustData
8628 * Gets all custom data items for the Functions
8631 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
8632 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
8634 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8635 const TLBFuncDesc *pFDesc;
8636 UINT hrefoffset;
8637 HRESULT hr;
8639 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
8641 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, indexFunc, &pFDesc, &hrefoffset);
8642 if (FAILED(hr))
8643 return hr;
8645 if(indexParam >= pFDesc->funcdesc.cParams)
8646 return TYPE_E_ELEMENTNOTFOUND;
8648 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
8651 /* ITypeInfo2::GetAllVarCustData
8653 * Gets all custom data items for the specified Variable
8656 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
8657 UINT index, CUSTDATA *pCustData)
8659 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8660 TLBVarDesc * pVDesc = &This->vardescs[index];
8662 TRACE("%p %u %p\n", This, index, pCustData);
8664 if(index >= This->typeattr.cVars)
8665 return TYPE_E_ELEMENTNOTFOUND;
8667 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
8670 /* ITypeInfo2::GetAllImplCustData
8672 * Gets all custom data items for the specified implementation type
8675 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
8676 ITypeInfo2 * iface,
8677 UINT index,
8678 CUSTDATA *pCustData)
8680 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8681 TLBImplType *pRDesc = &This->impltypes[index];
8683 TRACE("%p %u %p\n", This, index, pCustData);
8685 if(index >= This->typeattr.cImplTypes)
8686 return TYPE_E_ELEMENTNOTFOUND;
8688 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
8691 static const ITypeInfo2Vtbl tinfvt =
8694 ITypeInfo_fnQueryInterface,
8695 ITypeInfo_fnAddRef,
8696 ITypeInfo_fnRelease,
8698 ITypeInfo_fnGetTypeAttr,
8699 ITypeInfo_fnGetTypeComp,
8700 ITypeInfo_fnGetFuncDesc,
8701 ITypeInfo_fnGetVarDesc,
8702 ITypeInfo_fnGetNames,
8703 ITypeInfo_fnGetRefTypeOfImplType,
8704 ITypeInfo_fnGetImplTypeFlags,
8705 ITypeInfo_fnGetIDsOfNames,
8706 ITypeInfo_fnInvoke,
8707 ITypeInfo_fnGetDocumentation,
8708 ITypeInfo_fnGetDllEntry,
8709 ITypeInfo_fnGetRefTypeInfo,
8710 ITypeInfo_fnAddressOfMember,
8711 ITypeInfo_fnCreateInstance,
8712 ITypeInfo_fnGetMops,
8713 ITypeInfo_fnGetContainingTypeLib,
8714 ITypeInfo_fnReleaseTypeAttr,
8715 ITypeInfo_fnReleaseFuncDesc,
8716 ITypeInfo_fnReleaseVarDesc,
8718 ITypeInfo2_fnGetTypeKind,
8719 ITypeInfo2_fnGetTypeFlags,
8720 ITypeInfo2_fnGetFuncIndexOfMemId,
8721 ITypeInfo2_fnGetVarIndexOfMemId,
8722 ITypeInfo2_fnGetCustData,
8723 ITypeInfo2_fnGetFuncCustData,
8724 ITypeInfo2_fnGetParamCustData,
8725 ITypeInfo2_fnGetVarCustData,
8726 ITypeInfo2_fnGetImplTypeCustData,
8727 ITypeInfo2_fnGetDocumentation2,
8728 ITypeInfo2_fnGetAllCustData,
8729 ITypeInfo2_fnGetAllFuncCustData,
8730 ITypeInfo2_fnGetAllParamCustData,
8731 ITypeInfo2_fnGetAllVarCustData,
8732 ITypeInfo2_fnGetAllImplTypeCustData,
8735 /******************************************************************************
8736 * CreateDispTypeInfo [OLEAUT32.31]
8738 * Build type information for an object so it can be called through an
8739 * IDispatch interface.
8741 * RETURNS
8742 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8743 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8745 * NOTES
8746 * This call allows an objects methods to be accessed through IDispatch, by
8747 * building an ITypeInfo object that IDispatch can use to call through.
8749 HRESULT WINAPI CreateDispTypeInfo(
8750 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
8751 LCID lcid, /* [I] Locale Id */
8752 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
8754 ITypeInfoImpl *pTIClass, *pTIIface;
8755 ITypeLibImpl *pTypeLibImpl;
8756 unsigned int param, func;
8757 TLBFuncDesc *pFuncDesc;
8758 TLBRefType *ref;
8760 TRACE("\n");
8761 pTypeLibImpl = TypeLibImpl_Constructor();
8762 if (!pTypeLibImpl) return E_FAIL;
8764 pTypeLibImpl->TypeInfoCount = 2;
8765 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
8767 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
8768 pTIIface->pTypeLib = pTypeLibImpl;
8769 pTIIface->index = 0;
8770 pTIIface->Name = NULL;
8771 pTIIface->dwHelpContext = -1;
8772 pTIIface->guid = NULL;
8773 pTIIface->typeattr.lcid = lcid;
8774 pTIIface->typeattr.typekind = TKIND_INTERFACE;
8775 pTIIface->typeattr.wMajorVerNum = 0;
8776 pTIIface->typeattr.wMinorVerNum = 0;
8777 pTIIface->typeattr.cbAlignment = 2;
8778 pTIIface->typeattr.cbSizeInstance = -1;
8779 pTIIface->typeattr.cbSizeVft = -1;
8780 pTIIface->typeattr.cFuncs = 0;
8781 pTIIface->typeattr.cImplTypes = 0;
8782 pTIIface->typeattr.cVars = 0;
8783 pTIIface->typeattr.wTypeFlags = 0;
8784 pTIIface->hreftype = 0;
8786 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers);
8787 pFuncDesc = pTIIface->funcdescs;
8788 for(func = 0; func < pidata->cMembers; func++) {
8789 METHODDATA *md = pidata->pmethdata + func;
8790 pFuncDesc->Name = TLB_append_str(&pTypeLibImpl->name_list, md->szName);
8791 pFuncDesc->funcdesc.memid = md->dispid;
8792 pFuncDesc->funcdesc.lprgscode = NULL;
8793 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
8794 pFuncDesc->funcdesc.invkind = md->wFlags;
8795 pFuncDesc->funcdesc.callconv = md->cc;
8796 pFuncDesc->funcdesc.cParams = md->cArgs;
8797 pFuncDesc->funcdesc.cParamsOpt = 0;
8798 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
8799 pFuncDesc->funcdesc.cScodes = 0;
8800 pFuncDesc->funcdesc.wFuncFlags = 0;
8801 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
8802 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
8803 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
8804 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8805 md->cArgs * sizeof(ELEMDESC));
8806 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
8807 for(param = 0; param < md->cArgs; param++) {
8808 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
8809 pFuncDesc->pParamDesc[param].Name = TLB_append_str(&pTypeLibImpl->name_list, md->ppdata[param].szName);
8811 pFuncDesc->helpcontext = 0;
8812 pFuncDesc->HelpStringContext = 0;
8813 pFuncDesc->HelpString = NULL;
8814 pFuncDesc->Entry = NULL;
8815 list_init(&pFuncDesc->custdata_list);
8816 pTIIface->typeattr.cFuncs++;
8817 ++pFuncDesc;
8820 dump_TypeInfo(pTIIface);
8822 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
8823 pTIClass->pTypeLib = pTypeLibImpl;
8824 pTIClass->index = 1;
8825 pTIClass->Name = NULL;
8826 pTIClass->dwHelpContext = -1;
8827 pTIClass->guid = NULL;
8828 pTIClass->typeattr.lcid = lcid;
8829 pTIClass->typeattr.typekind = TKIND_COCLASS;
8830 pTIClass->typeattr.wMajorVerNum = 0;
8831 pTIClass->typeattr.wMinorVerNum = 0;
8832 pTIClass->typeattr.cbAlignment = 2;
8833 pTIClass->typeattr.cbSizeInstance = -1;
8834 pTIClass->typeattr.cbSizeVft = -1;
8835 pTIClass->typeattr.cFuncs = 0;
8836 pTIClass->typeattr.cImplTypes = 1;
8837 pTIClass->typeattr.cVars = 0;
8838 pTIClass->typeattr.wTypeFlags = 0;
8839 pTIClass->hreftype = sizeof(MSFT_TypeInfoBase);
8841 pTIClass->impltypes = TLBImplType_Alloc(1);
8843 ref = heap_alloc_zero(sizeof(*ref));
8844 ref->pImpTLInfo = TLB_REF_INTERNAL;
8845 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
8847 dump_TypeInfo(pTIClass);
8849 *pptinfo = (ITypeInfo *)&pTIClass->ITypeInfo2_iface;
8851 ITypeInfo_AddRef(*pptinfo);
8852 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
8854 return S_OK;
8858 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
8860 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8862 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, ppv);
8865 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
8867 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8869 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
8872 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
8874 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8876 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
8879 static HRESULT WINAPI ITypeComp_fnBind(
8880 ITypeComp * iface,
8881 OLECHAR * szName,
8882 ULONG lHash,
8883 WORD wFlags,
8884 ITypeInfo ** ppTInfo,
8885 DESCKIND * pDescKind,
8886 BINDPTR * pBindPtr)
8888 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8889 const TLBFuncDesc *pFDesc;
8890 const TLBVarDesc *pVDesc;
8891 HRESULT hr = DISP_E_MEMBERNOTFOUND;
8892 UINT fdc;
8894 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8896 *pDescKind = DESCKIND_NONE;
8897 pBindPtr->lpfuncdesc = NULL;
8898 *ppTInfo = NULL;
8900 for(fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
8901 pFDesc = &This->funcdescs[fdc];
8902 if (!lstrcmpiW(TLB_get_bstr(pFDesc->Name), szName)) {
8903 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
8904 break;
8905 else
8906 /* name found, but wrong flags */
8907 hr = TYPE_E_TYPEMISMATCH;
8911 if (fdc < This->typeattr.cFuncs)
8913 HRESULT hr = TLB_AllocAndInitFuncDesc(
8914 &pFDesc->funcdesc,
8915 &pBindPtr->lpfuncdesc,
8916 This->typeattr.typekind == TKIND_DISPATCH);
8917 if (FAILED(hr))
8918 return hr;
8919 *pDescKind = DESCKIND_FUNCDESC;
8920 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8921 ITypeInfo_AddRef(*ppTInfo);
8922 return S_OK;
8923 } else {
8924 pVDesc = TLB_get_vardesc_by_name(This, szName);
8925 if(pVDesc){
8926 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
8927 if (FAILED(hr))
8928 return hr;
8929 *pDescKind = DESCKIND_VARDESC;
8930 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8931 ITypeInfo_AddRef(*ppTInfo);
8932 return S_OK;
8936 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
8937 /* recursive search */
8938 ITypeInfo *pTInfo;
8939 ITypeComp *pTComp;
8940 HRESULT hr;
8941 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
8942 if (SUCCEEDED(hr))
8944 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
8945 ITypeInfo_Release(pTInfo);
8947 if (SUCCEEDED(hr))
8949 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8950 ITypeComp_Release(pTComp);
8951 if (SUCCEEDED(hr) && *pDescKind == DESCKIND_FUNCDESC &&
8952 This->typeattr.typekind == TKIND_DISPATCH)
8954 FUNCDESC *tmp = pBindPtr->lpfuncdesc;
8955 hr = TLB_AllocAndInitFuncDesc(tmp, &pBindPtr->lpfuncdesc, TRUE);
8956 SysFreeString((BSTR)tmp);
8958 return hr;
8960 WARN("Could not search inherited interface!\n");
8962 if (hr == DISP_E_MEMBERNOTFOUND)
8963 hr = S_OK;
8964 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
8965 return hr;
8968 static HRESULT WINAPI ITypeComp_fnBindType(
8969 ITypeComp * iface,
8970 OLECHAR * szName,
8971 ULONG lHash,
8972 ITypeInfo ** ppTInfo,
8973 ITypeComp ** ppTComp)
8975 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
8977 /* strange behaviour (does nothing) but like the
8978 * original */
8980 if (!ppTInfo || !ppTComp)
8981 return E_POINTER;
8983 *ppTInfo = NULL;
8984 *ppTComp = NULL;
8986 return S_OK;
8989 static const ITypeCompVtbl tcompvt =
8992 ITypeComp_fnQueryInterface,
8993 ITypeComp_fnAddRef,
8994 ITypeComp_fnRelease,
8996 ITypeComp_fnBind,
8997 ITypeComp_fnBindType
9000 HRESULT WINAPI CreateTypeLib2(SYSKIND syskind, LPCOLESTR szFile,
9001 ICreateTypeLib2** ppctlib)
9003 ITypeLibImpl *This;
9004 HRESULT hres;
9006 TRACE("(%d,%s,%p)\n", syskind, debugstr_w(szFile), ppctlib);
9008 if (!szFile) return E_INVALIDARG;
9010 This = TypeLibImpl_Constructor();
9011 if (!This)
9012 return E_OUTOFMEMORY;
9014 This->lcid = GetSystemDefaultLCID();
9015 This->syskind = syskind;
9016 This->ptr_size = get_ptr_size(syskind);
9018 This->path = heap_alloc((lstrlenW(szFile) + 1) * sizeof(WCHAR));
9019 if (!This->path) {
9020 ITypeLib2_Release(&This->ITypeLib2_iface);
9021 return E_OUTOFMEMORY;
9023 lstrcpyW(This->path, szFile);
9025 hres = ITypeLib2_QueryInterface(&This->ITypeLib2_iface, &IID_ICreateTypeLib2, (LPVOID*)ppctlib);
9026 ITypeLib2_Release(&This->ITypeLib2_iface);
9027 return hres;
9030 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
9031 REFIID riid, void **object)
9033 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9035 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, object);
9038 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
9040 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9042 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
9045 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
9047 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9049 return ITypeLib2_Release(&This->ITypeLib2_iface);
9052 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
9053 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
9055 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9056 ITypeInfoImpl *info;
9057 HRESULT hres;
9059 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo);
9061 if (!ctinfo || !name)
9062 return E_INVALIDARG;
9064 info = TLB_get_typeinfo_by_name(This, name);
9065 if (info)
9066 return TYPE_E_NAMECONFLICT;
9068 if (This->typeinfos)
9069 This->typeinfos = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->typeinfos,
9070 sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1));
9071 else
9072 This->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*));
9074 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor();
9076 info->pTypeLib = This;
9077 info->Name = TLB_append_str(&This->name_list, name);
9078 info->index = This->TypeInfoCount;
9079 info->typeattr.typekind = kind;
9080 info->typeattr.cbAlignment = 4;
9082 switch (info->typeattr.typekind) {
9083 case TKIND_ENUM:
9084 case TKIND_INTERFACE:
9085 case TKIND_DISPATCH:
9086 case TKIND_COCLASS:
9087 info->typeattr.cbSizeInstance = This->ptr_size;
9088 break;
9089 case TKIND_RECORD:
9090 case TKIND_UNION:
9091 info->typeattr.cbSizeInstance = 0;
9092 break;
9093 case TKIND_MODULE:
9094 info->typeattr.cbSizeInstance = 2;
9095 break;
9096 case TKIND_ALIAS:
9097 info->typeattr.cbSizeInstance = -0x75;
9098 break;
9099 default:
9100 FIXME("unrecognized typekind %d\n", info->typeattr.typekind);
9101 info->typeattr.cbSizeInstance = 0xdeadbeef;
9102 break;
9105 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface,
9106 &IID_ICreateTypeInfo, (void **)ctinfo);
9107 if (FAILED(hres)) {
9108 ITypeInfo2_Release(&info->ITypeInfo2_iface);
9109 return hres;
9112 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase);
9114 ++This->TypeInfoCount;
9116 return S_OK;
9119 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
9120 LPOLESTR name)
9122 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9124 TRACE("%p %s\n", This, wine_dbgstr_w(name));
9126 if (!name)
9127 return E_INVALIDARG;
9129 This->Name = TLB_append_str(&This->name_list, name);
9131 return S_OK;
9134 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
9135 WORD majorVerNum, WORD minorVerNum)
9137 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9139 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
9141 This->ver_major = majorVerNum;
9142 This->ver_minor = minorVerNum;
9144 return S_OK;
9147 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
9148 REFGUID guid)
9150 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9152 TRACE("%p %s\n", This, debugstr_guid(guid));
9154 This->guid = TLB_append_guid(&This->guid_list, guid, -2);
9156 return S_OK;
9159 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
9160 LPOLESTR doc)
9162 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9164 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
9166 if (!doc)
9167 return E_INVALIDARG;
9169 This->DocString = TLB_append_str(&This->string_list, doc);
9171 return S_OK;
9174 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
9175 LPOLESTR helpFileName)
9177 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9179 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
9181 if (!helpFileName)
9182 return E_INVALIDARG;
9184 This->HelpFile = TLB_append_str(&This->string_list, helpFileName);
9186 return S_OK;
9189 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
9190 DWORD helpContext)
9192 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9194 TRACE("%p %d\n", This, helpContext);
9196 This->dwHelpContext = helpContext;
9198 return S_OK;
9201 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
9202 LCID lcid)
9204 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9206 TRACE("%p %x\n", This, lcid);
9208 This->set_lcid = lcid;
9210 return S_OK;
9213 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
9214 UINT libFlags)
9216 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9218 TRACE("%p %x\n", This, libFlags);
9220 This->libflags = libFlags;
9222 return S_OK;
9225 typedef struct tagWMSFT_SegContents {
9226 DWORD len;
9227 void *data;
9228 } WMSFT_SegContents;
9230 typedef struct tagWMSFT_TLBFile {
9231 MSFT_Header header;
9232 WMSFT_SegContents typeinfo_seg;
9233 WMSFT_SegContents impfile_seg;
9234 WMSFT_SegContents impinfo_seg;
9235 WMSFT_SegContents ref_seg;
9236 WMSFT_SegContents guidhash_seg;
9237 WMSFT_SegContents guid_seg;
9238 WMSFT_SegContents namehash_seg;
9239 WMSFT_SegContents name_seg;
9240 WMSFT_SegContents string_seg;
9241 WMSFT_SegContents typdesc_seg;
9242 WMSFT_SegContents arraydesc_seg;
9243 WMSFT_SegContents custdata_seg;
9244 WMSFT_SegContents cdguids_seg;
9245 MSFT_SegDir segdir;
9246 WMSFT_SegContents aux_seg;
9247 } WMSFT_TLBFile;
9249 static HRESULT WMSFT_compile_strings(ITypeLibImpl *This,
9250 WMSFT_TLBFile *file)
9252 TLBString *str;
9253 UINT last_offs;
9254 char *data;
9256 file->string_seg.len = 0;
9257 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
9258 int size;
9260 size = WideCharToMultiByte(CP_ACP, 0, str->str, lstrlenW(str->str), NULL, 0, NULL, NULL);
9261 if (size == 0)
9262 return E_UNEXPECTED;
9264 size += sizeof(INT16);
9265 if (size % 4)
9266 size = (size + 4) & ~0x3;
9267 if (size < 8)
9268 size = 8;
9270 file->string_seg.len += size;
9272 /* temporarily use str->offset to store the length of the aligned,
9273 * converted string */
9274 str->offset = size;
9277 file->string_seg.data = data = heap_alloc(file->string_seg.len);
9279 last_offs = 0;
9280 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
9281 int size;
9283 size = WideCharToMultiByte(CP_ACP, 0, str->str, lstrlenW(str->str),
9284 data + sizeof(INT16), file->string_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9285 if (size == 0) {
9286 heap_free(file->string_seg.data);
9287 return E_UNEXPECTED;
9290 *((INT16*)data) = size;
9292 memset(data + sizeof(INT16) + size, 0x57, str->offset - size - sizeof(INT16));
9294 size = str->offset;
9295 data += size;
9296 str->offset = last_offs;
9297 last_offs += size;
9300 return S_OK;
9303 static HRESULT WMSFT_compile_names(ITypeLibImpl *This,
9304 WMSFT_TLBFile *file)
9306 TLBString *str;
9307 UINT last_offs;
9308 char *data;
9309 MSFT_NameIntro *last_intro = NULL;
9311 file->header.nametablecount = 0;
9312 file->header.nametablechars = 0;
9314 file->name_seg.len = 0;
9315 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
9316 int size;
9318 size = lstrlenW(str->str);
9319 file->header.nametablechars += size;
9320 file->header.nametablecount++;
9322 size = WideCharToMultiByte(CP_ACP, 0, str->str, size, NULL, 0, NULL, NULL);
9323 if (size == 0)
9324 return E_UNEXPECTED;
9326 size += sizeof(MSFT_NameIntro);
9327 if (size % 4)
9328 size = (size + 4) & ~0x3;
9329 if (size < 8)
9330 size = 8;
9332 file->name_seg.len += size;
9334 /* temporarily use str->offset to store the length of the aligned,
9335 * converted string */
9336 str->offset = size;
9339 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
9340 file->name_seg.data = data = heap_alloc(file->name_seg.len+1);
9342 last_offs = 0;
9343 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
9344 int size, hash;
9345 MSFT_NameIntro *intro = (MSFT_NameIntro*)data;
9347 size = WideCharToMultiByte(CP_ACP, 0, str->str, lstrlenW(str->str),
9348 data + sizeof(MSFT_NameIntro),
9349 file->name_seg.len - last_offs - sizeof(MSFT_NameIntro), NULL, NULL);
9350 if (size == 0) {
9351 heap_free(file->name_seg.data);
9352 return E_UNEXPECTED;
9354 data[sizeof(MSFT_NameIntro) + size] = '\0';
9356 intro->hreftype = -1; /* TODO? */
9357 intro->namelen = size & 0xFF;
9358 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9359 hash = LHashValOfNameSysA(This->syskind, This->lcid, data + sizeof(MSFT_NameIntro));
9360 intro->namelen |= hash << 16;
9361 intro->next_hash = ((DWORD*)file->namehash_seg.data)[hash & 0x7f];
9362 ((DWORD*)file->namehash_seg.data)[hash & 0x7f] = last_offs;
9364 memset(data + sizeof(MSFT_NameIntro) + size, 0x57,
9365 str->offset - size - sizeof(MSFT_NameIntro));
9367 /* update str->offset to actual value to use in other
9368 * compilation functions that require positions within
9369 * the string table */
9370 last_intro = intro;
9371 size = str->offset;
9372 data += size;
9373 str->offset = last_offs;
9374 last_offs += size;
9377 if(last_intro)
9378 last_intro->hreftype = 0; /* last one is 0? */
9380 return S_OK;
9383 static inline int hash_guid(GUID *guid)
9385 int i, hash = 0;
9387 for (i = 0; i < 8; i ++)
9388 hash ^= ((const short *)guid)[i];
9390 return hash & 0x1f;
9393 static HRESULT WMSFT_compile_guids(ITypeLibImpl *This, WMSFT_TLBFile *file)
9395 TLBGuid *guid;
9396 MSFT_GuidEntry *entry;
9397 DWORD offs;
9398 int hash_key, *guidhashtab;
9400 file->guid_seg.len = sizeof(MSFT_GuidEntry) * list_count(&This->guid_list);
9401 file->guid_seg.data = heap_alloc(file->guid_seg.len);
9403 entry = file->guid_seg.data;
9404 offs = 0;
9405 guidhashtab = file->guidhash_seg.data;
9406 LIST_FOR_EACH_ENTRY(guid, &This->guid_list, TLBGuid, entry){
9407 memcpy(&entry->guid, &guid->guid, sizeof(GUID));
9408 entry->hreftype = guid->hreftype;
9410 hash_key = hash_guid(&guid->guid);
9411 entry->next_hash = guidhashtab[hash_key];
9412 guidhashtab[hash_key] = offs;
9414 guid->offset = offs;
9415 offs += sizeof(MSFT_GuidEntry);
9416 ++entry;
9419 return S_OK;
9422 static DWORD WMSFT_encode_variant(VARIANT *value, WMSFT_TLBFile *file)
9424 VARIANT v = *value;
9425 VARTYPE arg_type = V_VT(value);
9426 int mask = 0;
9427 HRESULT hres;
9428 DWORD ret = file->custdata_seg.len;
9430 if(arg_type == VT_INT)
9431 arg_type = VT_I4;
9432 if(arg_type == VT_UINT)
9433 arg_type = VT_UI4;
9435 v = *value;
9436 if(V_VT(value) != arg_type) {
9437 hres = VariantChangeType(&v, value, 0, arg_type);
9438 if(FAILED(hres)){
9439 ERR("VariantChangeType failed: %08x\n", hres);
9440 return -1;
9444 /* Check if default value can be stored in-place */
9445 switch(arg_type){
9446 case VT_I4:
9447 case VT_UI4:
9448 mask = 0x3ffffff;
9449 if(V_UI4(&v) > 0x3ffffff)
9450 break;
9451 /* fall through */
9452 case VT_I1:
9453 case VT_UI1:
9454 case VT_BOOL:
9455 if(!mask)
9456 mask = 0xff;
9457 /* fall through */
9458 case VT_I2:
9459 case VT_UI2:
9460 if(!mask)
9461 mask = 0xffff;
9462 return ((0x80 + 0x4 * V_VT(value)) << 24) | (V_UI4(&v) & mask);
9465 /* have to allocate space in custdata_seg */
9466 switch(arg_type) {
9467 case VT_I4:
9468 case VT_R4:
9469 case VT_UI4:
9470 case VT_INT:
9471 case VT_UINT:
9472 case VT_HRESULT:
9473 case VT_PTR: {
9474 /* Construct the data to be allocated */
9475 int *data;
9477 if(file->custdata_seg.data){
9478 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + sizeof(int) * 2);
9479 data = (int *)(((char *)file->custdata_seg.data) + file->custdata_seg.len);
9480 file->custdata_seg.len += sizeof(int) * 2;
9481 }else{
9482 file->custdata_seg.len = sizeof(int) * 2;
9483 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9486 data[0] = V_VT(value) + (V_UI4(&v) << 16);
9487 data[1] = (V_UI4(&v) >> 16) + 0x57570000;
9489 /* TODO: Check if the encoded data is already present in custdata_seg */
9491 return ret;
9494 case VT_BSTR: {
9495 int i, len = (6+SysStringLen(V_BSTR(&v))+3) & ~0x3;
9496 char *data;
9498 if(file->custdata_seg.data){
9499 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + len);
9500 data = ((char *)file->custdata_seg.data) + file->custdata_seg.len;
9501 file->custdata_seg.len += len;
9502 }else{
9503 file->custdata_seg.len = len;
9504 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9507 *((unsigned short *)data) = V_VT(value);
9508 *((unsigned int *)(data+2)) = SysStringLen(V_BSTR(&v));
9509 for(i=0; i<SysStringLen(V_BSTR(&v)); i++) {
9510 if(V_BSTR(&v)[i] <= 0x7f)
9511 data[i+6] = V_BSTR(&v)[i];
9512 else
9513 data[i+6] = '?';
9515 WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], len-6, NULL, NULL);
9516 for(i=6+SysStringLen(V_BSTR(&v)); i<len; i++)
9517 data[i] = 0x57;
9519 /* TODO: Check if the encoded data is already present in custdata_seg */
9521 return ret;
9523 default:
9524 FIXME("Argument type not yet handled\n");
9525 return -1;
9529 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size);
9531 static DWORD WMSFT_append_arraydesc(ARRAYDESC *desc, WMSFT_TLBFile *file)
9533 DWORD offs = file->arraydesc_seg.len;
9534 DWORD *encoded;
9535 USHORT i;
9537 /* TODO: we should check for duplicates, but that's harder because each
9538 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9539 * at the library-level) */
9541 file->arraydesc_seg.len += (2 + desc->cDims * 2) * sizeof(DWORD);
9542 if(!file->arraydesc_seg.data)
9543 file->arraydesc_seg.data = heap_alloc(file->arraydesc_seg.len);
9544 else
9545 file->arraydesc_seg.data = heap_realloc(file->arraydesc_seg.data, file->arraydesc_seg.len);
9546 encoded = (DWORD*)((char *)file->arraydesc_seg.data + offs);
9548 encoded[0] = WMSFT_append_typedesc(&desc->tdescElem, file, NULL, NULL);
9549 encoded[1] = desc->cDims | ((desc->cDims * 2 * sizeof(DWORD)) << 16);
9550 for(i = 0; i < desc->cDims; ++i){
9551 encoded[2 + i * 2] = desc->rgbounds[i].cElements;
9552 encoded[2 + i * 2 + 1] = desc->rgbounds[i].lLbound;
9555 return offs;
9558 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size)
9560 DWORD junk;
9561 INT16 junk2;
9562 DWORD offs = 0;
9563 DWORD encoded[2];
9564 VARTYPE vt, subtype;
9565 char *data;
9567 if(!desc)
9568 return -1;
9570 if(!out_mix)
9571 out_mix = &junk;
9572 if(!out_size)
9573 out_size = &junk2;
9575 vt = desc->vt & VT_TYPEMASK;
9577 if(vt == VT_PTR || vt == VT_SAFEARRAY){
9578 DWORD mix;
9579 encoded[1] = WMSFT_append_typedesc(desc->u.lptdesc, file, &mix, out_size);
9580 encoded[0] = desc->vt | ((mix | VT_BYREF) << 16);
9581 *out_mix = 0x7FFF;
9582 *out_size += 2 * sizeof(DWORD);
9583 }else if(vt == VT_CARRAY){
9584 encoded[0] = desc->vt | (0x7FFE << 16);
9585 encoded[1] = WMSFT_append_arraydesc(desc->u.lpadesc, file);
9586 *out_mix = 0x7FFE;
9587 }else if(vt == VT_USERDEFINED){
9588 encoded[0] = desc->vt | (0x7FFF << 16);
9589 encoded[1] = desc->u.hreftype;
9590 *out_mix = 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9591 }else{
9592 TRACE("Mixing in-place, VT: 0x%x\n", desc->vt);
9594 switch(vt){
9595 case VT_INT:
9596 subtype = VT_I4;
9597 break;
9598 case VT_UINT:
9599 subtype = VT_UI4;
9600 break;
9601 case VT_VOID:
9602 subtype = VT_EMPTY;
9603 break;
9604 default:
9605 subtype = vt;
9606 break;
9609 *out_mix = subtype;
9610 return 0x80000000 | (subtype << 16) | desc->vt;
9613 data = file->typdesc_seg.data;
9614 while(offs < file->typdesc_seg.len){
9615 if(!memcmp(&data[offs], encoded, sizeof(encoded)))
9616 return offs;
9617 offs += sizeof(encoded);
9620 file->typdesc_seg.len += sizeof(encoded);
9621 if(!file->typdesc_seg.data)
9622 data = file->typdesc_seg.data = heap_alloc(file->typdesc_seg.len);
9623 else
9624 data = file->typdesc_seg.data = heap_realloc(file->typdesc_seg.data, file->typdesc_seg.len);
9626 memcpy(&data[offs], encoded, sizeof(encoded));
9628 return offs;
9631 static DWORD WMSFT_compile_custdata(struct list *custdata_list, WMSFT_TLBFile *file)
9633 WMSFT_SegContents *cdguids_seg = &file->cdguids_seg;
9634 DWORD ret = cdguids_seg->len, offs;
9635 MSFT_CDGuid *cdguid;
9636 TLBCustData *cd;
9638 if(list_empty(custdata_list))
9639 return -1;
9641 cdguids_seg->len += sizeof(MSFT_CDGuid) * list_count(custdata_list);
9642 if(!cdguids_seg->data){
9643 cdguid = cdguids_seg->data = heap_alloc(cdguids_seg->len);
9644 }else {
9645 cdguids_seg->data = heap_realloc(cdguids_seg->data, cdguids_seg->len);
9646 cdguid = (MSFT_CDGuid*)((char*)cdguids_seg->data + ret);
9649 offs = ret + sizeof(MSFT_CDGuid);
9650 LIST_FOR_EACH_ENTRY(cd, custdata_list, TLBCustData, entry){
9651 cdguid->GuidOffset = cd->guid->offset;
9652 cdguid->DataOffset = WMSFT_encode_variant(&cd->data, file);
9653 cdguid->next = offs;
9654 offs += sizeof(MSFT_CDGuid);
9655 ++cdguid;
9658 --cdguid;
9659 cdguid->next = -1;
9661 return ret;
9664 static DWORD WMSFT_compile_typeinfo_aux(ITypeInfoImpl *info,
9665 WMSFT_TLBFile *file)
9667 WMSFT_SegContents *aux_seg = &file->aux_seg;
9668 DWORD ret = aux_seg->len, i, j, recorded_size = 0, extra_size = 0;
9669 MSFT_VarRecord *varrecord;
9670 MSFT_FuncRecord *funcrecord;
9671 MEMBERID *memid;
9672 DWORD *name, *offsets, offs;
9674 for(i = 0; i < info->typeattr.cFuncs; ++i){
9675 TLBFuncDesc *desc = &info->funcdescs[i];
9677 recorded_size += 6 * sizeof(INT); /* mandatory fields */
9679 /* optional fields */
9680 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9681 if(!list_empty(&desc->custdata_list))
9682 recorded_size += 7 * sizeof(INT);
9683 else if(desc->HelpStringContext != 0)
9684 recorded_size += 6 * sizeof(INT);
9685 /* res9? resA? */
9686 else if(desc->Entry)
9687 recorded_size += 3 * sizeof(INT);
9688 else if(desc->HelpString)
9689 recorded_size += 2 * sizeof(INT);
9690 else if(desc->helpcontext)
9691 recorded_size += sizeof(INT);
9693 recorded_size += desc->funcdesc.cParams * sizeof(MSFT_ParameterInfo);
9695 for(j = 0; j < desc->funcdesc.cParams; ++j){
9696 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9697 recorded_size += desc->funcdesc.cParams * sizeof(INT);
9698 break;
9702 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9705 for(i = 0; i < info->typeattr.cVars; ++i){
9706 TLBVarDesc *desc = &info->vardescs[i];
9708 recorded_size += 5 * sizeof(INT); /* mandatory fields */
9710 /* optional fields */
9711 if(desc->HelpStringContext != 0)
9712 recorded_size += 5 * sizeof(INT);
9713 else if(!list_empty(&desc->custdata_list))
9714 recorded_size += 4 * sizeof(INT);
9715 /* res9? */
9716 else if(desc->HelpString)
9717 recorded_size += 2 * sizeof(INT);
9718 else if(desc->HelpContext != 0)
9719 recorded_size += sizeof(INT);
9721 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9724 if(!recorded_size && !extra_size)
9725 return ret;
9727 extra_size += sizeof(INT); /* total aux size for this typeinfo */
9729 aux_seg->len += recorded_size + extra_size;
9731 aux_seg->len += sizeof(INT) * (info->typeattr.cVars + info->typeattr.cFuncs); /* offsets at the end */
9733 if(aux_seg->data)
9734 aux_seg->data = heap_realloc(aux_seg->data, aux_seg->len);
9735 else
9736 aux_seg->data = heap_alloc(aux_seg->len);
9738 *((DWORD*)((char *)aux_seg->data + ret)) = recorded_size;
9740 offsets = (DWORD*)((char *)aux_seg->data + ret + recorded_size + extra_size);
9741 offs = 0;
9743 funcrecord = (MSFT_FuncRecord*)(((char *)aux_seg->data) + ret + sizeof(INT));
9744 for(i = 0; i < info->typeattr.cFuncs; ++i){
9745 TLBFuncDesc *desc = &info->funcdescs[i];
9746 DWORD size = 6 * sizeof(INT), paramdefault_size = 0, *paramdefault;
9748 funcrecord->funcdescsize = sizeof(desc->funcdesc) + desc->funcdesc.cParams * sizeof(ELEMDESC);
9749 funcrecord->DataType = WMSFT_append_typedesc(&desc->funcdesc.elemdescFunc.tdesc, file, NULL, &funcrecord->funcdescsize);
9750 funcrecord->Flags = desc->funcdesc.wFuncFlags;
9751 funcrecord->VtableOffset = desc->funcdesc.oVft;
9753 /* FKCCIC:
9754 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9755 * ^^^funckind
9756 * ^^^ ^invkind
9757 * ^has_cust_data
9758 * ^^^^callconv
9759 * ^has_param_defaults
9760 * ^oEntry_is_intresource
9762 funcrecord->FKCCIC =
9763 desc->funcdesc.funckind |
9764 (desc->funcdesc.invkind << 3) |
9765 (list_empty(&desc->custdata_list) ? 0 : 0x80) |
9766 (desc->funcdesc.callconv << 8);
9768 if(desc->Entry && desc->Entry != (TLBString*)-1 && IS_INTRESOURCE(desc->Entry))
9769 funcrecord->FKCCIC |= 0x2000;
9771 for(j = 0; j < desc->funcdesc.cParams; ++j){
9772 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9773 paramdefault_size = sizeof(INT) * desc->funcdesc.cParams;
9774 funcrecord->funcdescsize += sizeof(PARAMDESCEX);
9777 if(paramdefault_size > 0)
9778 funcrecord->FKCCIC |= 0x1000;
9780 funcrecord->nrargs = desc->funcdesc.cParams;
9781 funcrecord->nroargs = desc->funcdesc.cParamsOpt;
9783 /* optional fields */
9784 /* res9? resA? */
9785 if(!list_empty(&desc->custdata_list)){
9786 size += 7 * sizeof(INT);
9787 funcrecord->HelpContext = desc->helpcontext;
9788 if(desc->HelpString)
9789 funcrecord->oHelpString = desc->HelpString->offset;
9790 else
9791 funcrecord->oHelpString = -1;
9792 if(!desc->Entry)
9793 funcrecord->oEntry = -1;
9794 else if(IS_INTRESOURCE(desc->Entry))
9795 funcrecord->oEntry = LOWORD(desc->Entry);
9796 else
9797 funcrecord->oEntry = desc->Entry->offset;
9798 funcrecord->res9 = -1;
9799 funcrecord->resA = -1;
9800 funcrecord->HelpStringContext = desc->HelpStringContext;
9801 funcrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9802 }else if(desc->HelpStringContext != 0){
9803 size += 6 * sizeof(INT);
9804 funcrecord->HelpContext = desc->helpcontext;
9805 if(desc->HelpString)
9806 funcrecord->oHelpString = desc->HelpString->offset;
9807 else
9808 funcrecord->oHelpString = -1;
9809 if(!desc->Entry)
9810 funcrecord->oEntry = -1;
9811 else if(IS_INTRESOURCE(desc->Entry))
9812 funcrecord->oEntry = LOWORD(desc->Entry);
9813 else
9814 funcrecord->oEntry = desc->Entry->offset;
9815 funcrecord->res9 = -1;
9816 funcrecord->resA = -1;
9817 funcrecord->HelpStringContext = desc->HelpStringContext;
9818 }else if(desc->Entry){
9819 size += 3 * sizeof(INT);
9820 funcrecord->HelpContext = desc->helpcontext;
9821 if(desc->HelpString)
9822 funcrecord->oHelpString = desc->HelpString->offset;
9823 else
9824 funcrecord->oHelpString = -1;
9825 if(!desc->Entry)
9826 funcrecord->oEntry = -1;
9827 else if(IS_INTRESOURCE(desc->Entry))
9828 funcrecord->oEntry = LOWORD(desc->Entry);
9829 else
9830 funcrecord->oEntry = desc->Entry->offset;
9831 }else if(desc->HelpString){
9832 size += 2 * sizeof(INT);
9833 funcrecord->HelpContext = desc->helpcontext;
9834 funcrecord->oHelpString = desc->HelpString->offset;
9835 }else if(desc->helpcontext){
9836 size += sizeof(INT);
9837 funcrecord->HelpContext = desc->helpcontext;
9840 paramdefault = (DWORD*)((char *)funcrecord + size);
9841 size += paramdefault_size;
9843 for(j = 0; j < desc->funcdesc.cParams; ++j){
9844 MSFT_ParameterInfo *info = (MSFT_ParameterInfo*)(((char *)funcrecord) + size);
9846 info->DataType = WMSFT_append_typedesc(&desc->funcdesc.lprgelemdescParam[j].tdesc, file, NULL, &funcrecord->funcdescsize);
9847 if(desc->pParamDesc[j].Name)
9848 info->oName = desc->pParamDesc[j].Name->offset;
9849 else
9850 info->oName = -1;
9851 info->Flags = desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags;
9853 if(paramdefault_size){
9854 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
9855 *paramdefault = WMSFT_encode_variant(&desc->funcdesc.lprgelemdescParam[j].u.paramdesc.pparamdescex->varDefaultValue, file);
9856 else if(paramdefault_size)
9857 *paramdefault = -1;
9858 ++paramdefault;
9861 size += sizeof(MSFT_ParameterInfo);
9864 funcrecord->Info = size | (i << 16); /* is it just the index? */
9866 *offsets = offs;
9867 offs += size;
9868 ++offsets;
9870 funcrecord = (MSFT_FuncRecord*)(((char*)funcrecord) + size);
9873 varrecord = (MSFT_VarRecord*)funcrecord;
9874 for(i = 0; i < info->typeattr.cVars; ++i){
9875 TLBVarDesc *desc = &info->vardescs[i];
9876 DWORD size = 5 * sizeof(INT);
9878 varrecord->vardescsize = sizeof(desc->vardesc);
9879 varrecord->DataType = WMSFT_append_typedesc(&desc->vardesc.elemdescVar.tdesc, file, NULL, &varrecord->vardescsize);
9880 varrecord->Flags = desc->vardesc.wVarFlags;
9881 varrecord->VarKind = desc->vardesc.varkind;
9883 if(desc->vardesc.varkind == VAR_CONST){
9884 varrecord->vardescsize += sizeof(VARIANT);
9885 varrecord->OffsValue = WMSFT_encode_variant(desc->vardesc.u.lpvarValue, file);
9886 }else
9887 varrecord->OffsValue = desc->vardesc.u.oInst;
9889 /* res9? */
9890 if(desc->HelpStringContext != 0){
9891 size += 5 * sizeof(INT);
9892 varrecord->HelpContext = desc->HelpContext;
9893 if(desc->HelpString)
9894 varrecord->HelpString = desc->HelpString->offset;
9895 else
9896 varrecord->HelpString = -1;
9897 varrecord->res9 = -1;
9898 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9899 varrecord->HelpStringContext = desc->HelpStringContext;
9900 }else if(!list_empty(&desc->custdata_list)){
9901 size += 4 * sizeof(INT);
9902 varrecord->HelpContext = desc->HelpContext;
9903 if(desc->HelpString)
9904 varrecord->HelpString = desc->HelpString->offset;
9905 else
9906 varrecord->HelpString = -1;
9907 varrecord->res9 = -1;
9908 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9909 }else if(desc->HelpString){
9910 size += 2 * sizeof(INT);
9911 varrecord->HelpContext = desc->HelpContext;
9912 if(desc->HelpString)
9913 varrecord->HelpString = desc->HelpString->offset;
9914 else
9915 varrecord->HelpString = -1;
9916 }else if(desc->HelpContext != 0){
9917 size += sizeof(INT);
9918 varrecord->HelpContext = desc->HelpContext;
9921 varrecord->Info = size | (i << 16);
9923 *offsets = offs;
9924 offs += size;
9925 ++offsets;
9927 varrecord = (MSFT_VarRecord*)(((char*)varrecord) + size);
9930 memid = (MEMBERID*)varrecord;
9931 for(i = 0; i < info->typeattr.cFuncs; ++i){
9932 TLBFuncDesc *desc = &info->funcdescs[i];
9933 *memid = desc->funcdesc.memid;
9934 ++memid;
9936 for(i = 0; i < info->typeattr.cVars; ++i){
9937 TLBVarDesc *desc = &info->vardescs[i];
9938 *memid = desc->vardesc.memid;
9939 ++memid;
9942 name = (UINT*)memid;
9943 for(i = 0; i < info->typeattr.cFuncs; ++i){
9944 TLBFuncDesc *desc = &info->funcdescs[i];
9945 if(desc->Name)
9946 *name = desc->Name->offset;
9947 else
9948 *name = -1;
9949 ++name;
9951 for(i = 0; i < info->typeattr.cVars; ++i){
9952 TLBVarDesc *desc = &info->vardescs[i];
9953 if(desc->Name)
9954 *name = desc->Name->offset;
9955 else
9956 *name = -1;
9957 ++name;
9960 return ret;
9963 typedef struct tagWMSFT_RefChunk {
9964 DWORD href;
9965 DWORD res04;
9966 DWORD res08;
9967 DWORD next;
9968 } WMSFT_RefChunk;
9970 static DWORD WMSFT_compile_typeinfo_ref(ITypeInfoImpl *info, WMSFT_TLBFile *file)
9972 DWORD offs = file->ref_seg.len, i;
9973 WMSFT_RefChunk *chunk;
9975 file->ref_seg.len += info->typeattr.cImplTypes * sizeof(WMSFT_RefChunk);
9976 if(!file->ref_seg.data)
9977 file->ref_seg.data = heap_alloc(file->ref_seg.len);
9978 else
9979 file->ref_seg.data = heap_realloc(file->ref_seg.data, file->ref_seg.len);
9981 chunk = (WMSFT_RefChunk*)((char*)file->ref_seg.data + offs);
9983 for(i = 0; i < info->typeattr.cImplTypes; ++i){
9984 chunk->href = info->impltypes[i].hRef;
9985 chunk->res04 = info->impltypes[i].implflags;
9986 chunk->res08 = -1;
9987 if(i < info->typeattr.cImplTypes - 1)
9988 chunk->next = offs + sizeof(WMSFT_RefChunk) * (i + 1);
9989 else
9990 chunk->next = -1;
9991 ++chunk;
9994 return offs;
9997 static DWORD WMSFT_compile_typeinfo(ITypeInfoImpl *info, INT16 index, WMSFT_TLBFile *file, char *data)
9999 DWORD size;
10001 size = sizeof(MSFT_TypeInfoBase);
10003 if(data){
10004 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase*)data;
10005 if(info->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
10006 base->typekind = TKIND_DISPATCH;
10007 else
10008 base->typekind = info->typeattr.typekind;
10009 base->typekind |= index << 16; /* TODO: There are some other flags here */
10010 base->typekind |= (info->typeattr.cbAlignment << 11) | (info->typeattr.cbAlignment << 6);
10011 base->memoffset = WMSFT_compile_typeinfo_aux(info, file);
10012 base->res2 = 0;
10013 base->res3 = 0;
10014 base->res4 = 3;
10015 base->res5 = 0;
10016 base->cElement = (info->typeattr.cVars << 16) | info->typeattr.cFuncs;
10017 base->res7 = 0;
10018 base->res8 = 0;
10019 base->res9 = 0;
10020 base->resA = 0;
10021 if(info->guid)
10022 base->posguid = info->guid->offset;
10023 else
10024 base->posguid = -1;
10025 base->flags = info->typeattr.wTypeFlags;
10026 if(info->Name) {
10027 base->NameOffset = info->Name->offset;
10029 ((unsigned char*)file->name_seg.data)[info->Name->offset+9] = 0x38;
10030 *(HREFTYPE*)((unsigned char*)file->name_seg.data+info->Name->offset) = info->hreftype;
10031 }else {
10032 base->NameOffset = -1;
10034 base->version = (info->typeattr.wMinorVerNum << 16) | info->typeattr.wMajorVerNum;
10035 if(info->DocString)
10036 base->docstringoffs = info->DocString->offset;
10037 else
10038 base->docstringoffs = -1;
10039 base->helpstringcontext = info->dwHelpStringContext;
10040 base->helpcontext = info->dwHelpContext;
10041 base->oCustData = WMSFT_compile_custdata(info->pcustdata_list, file);
10042 base->cImplTypes = info->typeattr.cImplTypes;
10043 base->cbSizeVft = info->typeattr.cbSizeVft;
10044 base->size = info->typeattr.cbSizeInstance;
10045 if(info->typeattr.typekind == TKIND_COCLASS){
10046 base->datatype1 = WMSFT_compile_typeinfo_ref(info, file);
10047 }else if(info->typeattr.typekind == TKIND_ALIAS){
10048 base->datatype1 = WMSFT_append_typedesc(info->tdescAlias, file, NULL, NULL);
10049 }else if(info->typeattr.typekind == TKIND_MODULE){
10050 if(info->DllName)
10051 base->datatype1 = info->DllName->offset;
10052 else
10053 base->datatype1 = -1;
10054 }else{
10055 if(info->typeattr.cImplTypes > 0)
10056 base->datatype1 = info->impltypes[0].hRef;
10057 else
10058 base->datatype1 = -1;
10060 base->datatype2 = index; /* FIXME: i think there's more here */
10061 base->res18 = 0;
10062 base->res19 = -1;
10065 return size;
10068 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl *This, WMSFT_TLBFile *file, DWORD *junk)
10070 UINT i;
10072 file->typeinfo_seg.len = 0;
10073 for(i = 0; i < This->TypeInfoCount; ++i){
10074 ITypeInfoImpl *info = This->typeinfos[i];
10075 *junk = file->typeinfo_seg.len;
10076 ++junk;
10077 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, NULL, NULL);
10080 file->typeinfo_seg.data = heap_alloc(file->typeinfo_seg.len);
10081 memset(file->typeinfo_seg.data, 0x96, file->typeinfo_seg.len);
10083 file->aux_seg.len = 0;
10084 file->aux_seg.data = NULL;
10086 file->typeinfo_seg.len = 0;
10087 for(i = 0; i < This->TypeInfoCount; ++i){
10088 ITypeInfoImpl *info = This->typeinfos[i];
10089 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, file,
10090 ((char *)file->typeinfo_seg.data) + file->typeinfo_seg.len);
10094 typedef struct tagWMSFT_ImpFile {
10095 INT guid_offs;
10096 LCID lcid;
10097 DWORD version;
10098 } WMSFT_ImpFile;
10100 static void WMSFT_compile_impfile(ITypeLibImpl *This, WMSFT_TLBFile *file)
10102 TLBImpLib *implib;
10103 WMSFT_ImpFile *impfile;
10104 char *data;
10105 DWORD last_offs = 0;
10107 file->impfile_seg.len = 0;
10108 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
10109 int size = 0;
10111 if(implib->name){
10112 WCHAR *path = wcsrchr(implib->name, '\\');
10113 if(path)
10114 ++path;
10115 else
10116 path = implib->name;
10117 size = WideCharToMultiByte(CP_ACP, 0, path, lstrlenW(path), NULL, 0, NULL, NULL);
10118 if (size == 0)
10119 ERR("failed to convert wide string: %s\n", debugstr_w(path));
10122 size += sizeof(INT16);
10123 if (size % 4)
10124 size = (size + 4) & ~0x3;
10125 if (size < 8)
10126 size = 8;
10128 file->impfile_seg.len += sizeof(WMSFT_ImpFile) + size;
10131 data = file->impfile_seg.data = heap_alloc(file->impfile_seg.len);
10133 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
10134 int strlen = 0, size;
10136 impfile = (WMSFT_ImpFile*)data;
10137 impfile->guid_offs = implib->guid->offset;
10138 impfile->lcid = implib->lcid;
10139 impfile->version = (implib->wVersionMinor << 16) | implib->wVersionMajor;
10141 data += sizeof(WMSFT_ImpFile);
10143 if(implib->name){
10144 WCHAR *path= wcsrchr(implib->name, '\\');
10145 if(path)
10146 ++path;
10147 else
10148 path = implib->name;
10149 strlen = WideCharToMultiByte(CP_ACP, 0, path, lstrlenW(path),
10150 data + sizeof(INT16), file->impfile_seg.len - last_offs - sizeof(INT16), NULL, NULL);
10151 if (strlen == 0)
10152 ERR("failed to convert wide string: %s\n", debugstr_w(path));
10155 *((INT16*)data) = (strlen << 2) | 1; /* FIXME: is that a flag, or what? */
10157 size = strlen + sizeof(INT16);
10158 if (size % 4)
10159 size = (size + 4) & ~0x3;
10160 if (size < 8)
10161 size = 8;
10162 memset(data + sizeof(INT16) + strlen, 0x57, size - strlen - sizeof(INT16));
10164 data += size;
10165 implib->offset = last_offs;
10166 last_offs += size + sizeof(WMSFT_ImpFile);
10170 static void WMSFT_compile_impinfo(ITypeLibImpl *This, WMSFT_TLBFile *file)
10172 MSFT_ImpInfo *info;
10173 TLBRefType *ref_type;
10174 UINT i = 0;
10176 WMSFT_compile_impfile(This, file);
10178 file->impinfo_seg.len = sizeof(MSFT_ImpInfo) * list_count(&This->ref_list);
10179 info = file->impinfo_seg.data = heap_alloc(file->impinfo_seg.len);
10181 LIST_FOR_EACH_ENTRY(ref_type, &This->ref_list, TLBRefType, entry){
10182 info->flags = i | ((ref_type->tkind & 0xFF) << 24);
10183 if(ref_type->index == TLB_REF_USE_GUID){
10184 info->flags |= MSFT_IMPINFO_OFFSET_IS_GUID;
10185 info->oGuid = ref_type->guid->offset;
10186 }else
10187 info->oGuid = ref_type->index;
10188 info->oImpFile = ref_type->pImpTLInfo->offset;
10189 ++i;
10190 ++info;
10194 static void WMSFT_compile_guidhash(ITypeLibImpl *This, WMSFT_TLBFile *file)
10196 file->guidhash_seg.len = 0x80;
10197 file->guidhash_seg.data = heap_alloc(file->guidhash_seg.len);
10198 memset(file->guidhash_seg.data, 0xFF, file->guidhash_seg.len);
10201 static void WMSFT_compile_namehash(ITypeLibImpl *This, WMSFT_TLBFile *file)
10203 file->namehash_seg.len = 0x200;
10204 file->namehash_seg.data = heap_alloc(file->namehash_seg.len);
10205 memset(file->namehash_seg.data, 0xFF, file->namehash_seg.len);
10208 static void tmp_fill_segdir_seg(MSFT_pSeg *segdir, WMSFT_SegContents *contents, DWORD *running_offset)
10210 if(contents && contents->len){
10211 segdir->offset = *running_offset;
10212 segdir->length = contents->len;
10213 *running_offset += segdir->length;
10214 }else{
10215 segdir->offset = -1;
10216 segdir->length = 0;
10219 /* TODO: do these ever change? */
10220 segdir->res08 = -1;
10221 segdir->res0c = 0xf;
10224 static void WMSFT_write_segment(HANDLE outfile, WMSFT_SegContents *segment)
10226 DWORD written;
10227 if(segment)
10228 WriteFile(outfile, segment->data, segment->len, &written, NULL);
10231 static HRESULT WMSFT_fixup_typeinfos(ITypeLibImpl *This, WMSFT_TLBFile *file,
10232 DWORD file_len)
10234 DWORD i;
10235 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase *)file->typeinfo_seg.data;
10237 for(i = 0; i < This->TypeInfoCount; ++i){
10238 base->memoffset += file_len;
10239 ++base;
10242 return S_OK;
10245 static void WMSFT_free_file(WMSFT_TLBFile *file)
10247 HeapFree(GetProcessHeap(), 0, file->typeinfo_seg.data);
10248 HeapFree(GetProcessHeap(), 0, file->guidhash_seg.data);
10249 HeapFree(GetProcessHeap(), 0, file->guid_seg.data);
10250 HeapFree(GetProcessHeap(), 0, file->ref_seg.data);
10251 HeapFree(GetProcessHeap(), 0, file->impinfo_seg.data);
10252 HeapFree(GetProcessHeap(), 0, file->impfile_seg.data);
10253 HeapFree(GetProcessHeap(), 0, file->namehash_seg.data);
10254 HeapFree(GetProcessHeap(), 0, file->name_seg.data);
10255 HeapFree(GetProcessHeap(), 0, file->string_seg.data);
10256 HeapFree(GetProcessHeap(), 0, file->typdesc_seg.data);
10257 HeapFree(GetProcessHeap(), 0, file->arraydesc_seg.data);
10258 HeapFree(GetProcessHeap(), 0, file->custdata_seg.data);
10259 HeapFree(GetProcessHeap(), 0, file->cdguids_seg.data);
10260 HeapFree(GetProcessHeap(), 0, file->aux_seg.data);
10263 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
10265 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10266 WMSFT_TLBFile file;
10267 DWORD written, junk_size, junk_offs, running_offset;
10268 BOOL br;
10269 HANDLE outfile;
10270 HRESULT hres;
10271 DWORD *junk;
10272 UINT i;
10274 TRACE("%p\n", This);
10276 for(i = 0; i < This->TypeInfoCount; ++i)
10277 if(This->typeinfos[i]->needs_layout)
10278 ICreateTypeInfo2_LayOut(&This->typeinfos[i]->ICreateTypeInfo2_iface);
10280 memset(&file, 0, sizeof(file));
10282 file.header.magic1 = 0x5446534D;
10283 file.header.magic2 = 0x00010002;
10284 file.header.lcid = This->set_lcid ? This->set_lcid : MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
10285 file.header.lcid2 = This->set_lcid;
10286 file.header.varflags = 0x40 | This->syskind;
10287 if (This->HelpFile)
10288 file.header.varflags |= 0x10;
10289 if (This->HelpStringDll)
10290 file.header.varflags |= HELPDLLFLAG;
10291 file.header.version = (This->ver_minor << 16) | This->ver_major;
10292 file.header.flags = This->libflags;
10293 file.header.helpstringcontext = 0; /* TODO - SetHelpStringContext not implemented yet */
10294 file.header.helpcontext = This->dwHelpContext;
10295 file.header.res44 = 0x20;
10296 file.header.res48 = 0x80;
10297 file.header.dispatchpos = This->dispatch_href;
10299 WMSFT_compile_namehash(This, &file);
10300 /* do name and string compilation to get offsets for other compilations */
10301 hres = WMSFT_compile_names(This, &file);
10302 if (FAILED(hres)){
10303 WMSFT_free_file(&file);
10304 return hres;
10307 hres = WMSFT_compile_strings(This, &file);
10308 if (FAILED(hres)){
10309 WMSFT_free_file(&file);
10310 return hres;
10313 WMSFT_compile_guidhash(This, &file);
10314 hres = WMSFT_compile_guids(This, &file);
10315 if (FAILED(hres)){
10316 WMSFT_free_file(&file);
10317 return hres;
10320 if(This->HelpFile)
10321 file.header.helpfile = This->HelpFile->offset;
10322 else
10323 file.header.helpfile = -1;
10325 if(This->DocString)
10326 file.header.helpstring = This->DocString->offset;
10327 else
10328 file.header.helpstring = -1;
10330 /* do some more segment compilation */
10331 file.header.nimpinfos = list_count(&This->ref_list);
10332 file.header.nrtypeinfos = This->TypeInfoCount;
10334 if(This->Name)
10335 file.header.NameOffset = This->Name->offset;
10336 else
10337 file.header.NameOffset = -1;
10339 file.header.CustomDataOffset = WMSFT_compile_custdata(&This->custdata_list, &file);
10341 if(This->guid)
10342 file.header.posguid = This->guid->offset;
10343 else
10344 file.header.posguid = -1;
10346 junk_size = file.header.nrtypeinfos * sizeof(DWORD);
10347 if(file.header.varflags & HELPDLLFLAG)
10348 junk_size += sizeof(DWORD);
10349 if(junk_size){
10350 junk = heap_alloc_zero(junk_size);
10351 if(file.header.varflags & HELPDLLFLAG){
10352 *junk = This->HelpStringDll->offset;
10353 junk_offs = 1;
10354 }else
10355 junk_offs = 0;
10356 }else{
10357 junk = NULL;
10358 junk_offs = 0;
10361 WMSFT_compile_typeinfo_seg(This, &file, junk + junk_offs);
10362 WMSFT_compile_impinfo(This, &file);
10364 running_offset = 0;
10366 TRACE("header at: 0x%x\n", running_offset);
10367 running_offset += sizeof(file.header);
10369 TRACE("junk at: 0x%x\n", running_offset);
10370 running_offset += junk_size;
10372 TRACE("segdir at: 0x%x\n", running_offset);
10373 running_offset += sizeof(file.segdir);
10375 TRACE("typeinfo at: 0x%x\n", running_offset);
10376 tmp_fill_segdir_seg(&file.segdir.pTypeInfoTab, &file.typeinfo_seg, &running_offset);
10378 TRACE("guidhashtab at: 0x%x\n", running_offset);
10379 tmp_fill_segdir_seg(&file.segdir.pGuidHashTab, &file.guidhash_seg, &running_offset);
10381 TRACE("guidtab at: 0x%x\n", running_offset);
10382 tmp_fill_segdir_seg(&file.segdir.pGuidTab, &file.guid_seg, &running_offset);
10384 TRACE("reftab at: 0x%x\n", running_offset);
10385 tmp_fill_segdir_seg(&file.segdir.pRefTab, &file.ref_seg, &running_offset);
10387 TRACE("impinfo at: 0x%x\n", running_offset);
10388 tmp_fill_segdir_seg(&file.segdir.pImpInfo, &file.impinfo_seg, &running_offset);
10390 TRACE("impfiles at: 0x%x\n", running_offset);
10391 tmp_fill_segdir_seg(&file.segdir.pImpFiles, &file.impfile_seg, &running_offset);
10393 TRACE("namehashtab at: 0x%x\n", running_offset);
10394 tmp_fill_segdir_seg(&file.segdir.pNameHashTab, &file.namehash_seg, &running_offset);
10396 TRACE("nametab at: 0x%x\n", running_offset);
10397 tmp_fill_segdir_seg(&file.segdir.pNametab, &file.name_seg, &running_offset);
10399 TRACE("stringtab at: 0x%x\n", running_offset);
10400 tmp_fill_segdir_seg(&file.segdir.pStringtab, &file.string_seg, &running_offset);
10402 TRACE("typdesc at: 0x%x\n", running_offset);
10403 tmp_fill_segdir_seg(&file.segdir.pTypdescTab, &file.typdesc_seg, &running_offset);
10405 TRACE("arraydescriptions at: 0x%x\n", running_offset);
10406 tmp_fill_segdir_seg(&file.segdir.pArrayDescriptions, &file.arraydesc_seg, &running_offset);
10408 TRACE("custdata at: 0x%x\n", running_offset);
10409 tmp_fill_segdir_seg(&file.segdir.pCustData, &file.custdata_seg, &running_offset);
10411 TRACE("cdguids at: 0x%x\n", running_offset);
10412 tmp_fill_segdir_seg(&file.segdir.pCDGuids, &file.cdguids_seg, &running_offset);
10414 TRACE("res0e at: 0x%x\n", running_offset);
10415 tmp_fill_segdir_seg(&file.segdir.res0e, NULL, &running_offset);
10417 TRACE("res0f at: 0x%x\n", running_offset);
10418 tmp_fill_segdir_seg(&file.segdir.res0f, NULL, &running_offset);
10420 TRACE("aux_seg at: 0x%x\n", running_offset);
10422 WMSFT_fixup_typeinfos(This, &file, running_offset);
10424 outfile = CreateFileW(This->path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
10425 FILE_ATTRIBUTE_NORMAL, 0);
10426 if (outfile == INVALID_HANDLE_VALUE){
10427 WMSFT_free_file(&file);
10428 heap_free(junk);
10429 return TYPE_E_IOERROR;
10432 br = WriteFile(outfile, &file.header, sizeof(file.header), &written, NULL);
10433 if (!br) {
10434 WMSFT_free_file(&file);
10435 CloseHandle(outfile);
10436 heap_free(junk);
10437 return TYPE_E_IOERROR;
10440 br = WriteFile(outfile, junk, junk_size, &written, NULL);
10441 heap_free(junk);
10442 if (!br) {
10443 WMSFT_free_file(&file);
10444 CloseHandle(outfile);
10445 return TYPE_E_IOERROR;
10448 br = WriteFile(outfile, &file.segdir, sizeof(file.segdir), &written, NULL);
10449 if (!br) {
10450 WMSFT_free_file(&file);
10451 CloseHandle(outfile);
10452 return TYPE_E_IOERROR;
10455 WMSFT_write_segment(outfile, &file.typeinfo_seg);
10456 WMSFT_write_segment(outfile, &file.guidhash_seg);
10457 WMSFT_write_segment(outfile, &file.guid_seg);
10458 WMSFT_write_segment(outfile, &file.ref_seg);
10459 WMSFT_write_segment(outfile, &file.impinfo_seg);
10460 WMSFT_write_segment(outfile, &file.impfile_seg);
10461 WMSFT_write_segment(outfile, &file.namehash_seg);
10462 WMSFT_write_segment(outfile, &file.name_seg);
10463 WMSFT_write_segment(outfile, &file.string_seg);
10464 WMSFT_write_segment(outfile, &file.typdesc_seg);
10465 WMSFT_write_segment(outfile, &file.arraydesc_seg);
10466 WMSFT_write_segment(outfile, &file.custdata_seg);
10467 WMSFT_write_segment(outfile, &file.cdguids_seg);
10468 WMSFT_write_segment(outfile, &file.aux_seg);
10470 WMSFT_free_file(&file);
10472 CloseHandle(outfile);
10474 return S_OK;
10477 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
10478 LPOLESTR name)
10480 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10481 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
10482 return E_NOTIMPL;
10485 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
10486 REFGUID guid, VARIANT *varVal)
10488 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10489 TLBGuid *tlbguid;
10491 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
10493 if (!guid || !varVal)
10494 return E_INVALIDARG;
10496 tlbguid = TLB_append_guid(&This->guid_list, guid, -1);
10498 return TLB_set_custdata(&This->custdata_list, tlbguid, varVal);
10501 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
10502 ULONG helpStringContext)
10504 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10505 FIXME("%p %u - stub\n", This, helpStringContext);
10506 return E_NOTIMPL;
10509 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
10510 LPOLESTR filename)
10512 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10513 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
10515 if (!filename)
10516 return E_INVALIDARG;
10518 This->HelpStringDll = TLB_append_str(&This->string_list, filename);
10520 return S_OK;
10523 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
10524 ICreateTypeLib2_fnQueryInterface,
10525 ICreateTypeLib2_fnAddRef,
10526 ICreateTypeLib2_fnRelease,
10527 ICreateTypeLib2_fnCreateTypeInfo,
10528 ICreateTypeLib2_fnSetName,
10529 ICreateTypeLib2_fnSetVersion,
10530 ICreateTypeLib2_fnSetGuid,
10531 ICreateTypeLib2_fnSetDocString,
10532 ICreateTypeLib2_fnSetHelpFileName,
10533 ICreateTypeLib2_fnSetHelpContext,
10534 ICreateTypeLib2_fnSetLcid,
10535 ICreateTypeLib2_fnSetLibFlags,
10536 ICreateTypeLib2_fnSaveAllChanges,
10537 ICreateTypeLib2_fnDeleteTypeInfo,
10538 ICreateTypeLib2_fnSetCustData,
10539 ICreateTypeLib2_fnSetHelpStringContext,
10540 ICreateTypeLib2_fnSetHelpStringDll
10543 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
10544 REFIID riid, void **object)
10546 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10548 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, object);
10551 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
10553 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10555 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
10558 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
10560 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10562 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
10565 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
10566 REFGUID guid)
10568 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10570 TRACE("%p %s\n", This, debugstr_guid(guid));
10572 This->guid = TLB_append_guid(&This->pTypeLib->guid_list, guid, This->hreftype);
10574 return S_OK;
10577 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
10578 UINT typeFlags)
10580 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10581 WORD old_flags;
10582 HRESULT hres;
10584 TRACE("%p %x\n", This, typeFlags);
10586 if (typeFlags & TYPEFLAG_FDUAL) {
10587 static const WCHAR stdole2tlb[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10588 ITypeLib *stdole;
10589 ITypeInfo *dispatch;
10590 HREFTYPE hreftype;
10591 HRESULT hres;
10593 hres = LoadTypeLib(stdole2tlb, &stdole);
10594 if(FAILED(hres))
10595 return hres;
10597 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
10598 ITypeLib_Release(stdole);
10599 if(FAILED(hres))
10600 return hres;
10602 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
10603 ITypeInfo_Release(dispatch);
10604 if(FAILED(hres))
10605 return hres;
10608 old_flags = This->typeattr.wTypeFlags;
10609 This->typeattr.wTypeFlags = typeFlags;
10611 hres = ICreateTypeInfo2_LayOut(iface);
10612 if (FAILED(hres)) {
10613 This->typeattr.wTypeFlags = old_flags;
10614 return hres;
10617 return S_OK;
10620 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
10621 LPOLESTR doc)
10623 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10625 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
10627 if (!doc)
10628 return E_INVALIDARG;
10630 This->DocString = TLB_append_str(&This->pTypeLib->string_list, doc);
10632 return S_OK;
10635 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
10636 DWORD helpContext)
10638 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10640 TRACE("%p %d\n", This, helpContext);
10642 This->dwHelpContext = helpContext;
10644 return S_OK;
10647 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
10648 WORD majorVerNum, WORD minorVerNum)
10650 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10652 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
10654 This->typeattr.wMajorVerNum = majorVerNum;
10655 This->typeattr.wMinorVerNum = minorVerNum;
10657 return S_OK;
10660 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
10661 ITypeInfo *typeInfo, HREFTYPE *refType)
10663 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10664 UINT index;
10665 ITypeLib *container;
10666 TLBRefType *ref_type;
10667 TLBImpLib *implib;
10668 TYPEATTR *typeattr;
10669 TLIBATTR *libattr;
10670 HRESULT hres;
10672 TRACE("%p %p %p\n", This, typeInfo, refType);
10674 if (!typeInfo || !refType)
10675 return E_INVALIDARG;
10677 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
10678 if (FAILED(hres))
10679 return hres;
10681 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
10682 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
10684 ITypeLib_Release(container);
10686 *refType = target->hreftype;
10688 return S_OK;
10691 hres = ITypeLib_GetLibAttr(container, &libattr);
10692 if (FAILED(hres)) {
10693 ITypeLib_Release(container);
10694 return hres;
10697 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
10698 if(IsEqualGUID(&implib->guid->guid, &libattr->guid) &&
10699 implib->lcid == libattr->lcid &&
10700 implib->wVersionMajor == libattr->wMajorVerNum &&
10701 implib->wVersionMinor == libattr->wMinorVerNum)
10702 break;
10705 if(&implib->entry == &This->pTypeLib->implib_list){
10706 implib = heap_alloc_zero(sizeof(TLBImpLib));
10708 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
10709 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
10710 implib->name = SysAllocString(our_container->path);
10711 }else{
10712 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
10713 libattr->wMinorVerNum, libattr->lcid, &implib->name);
10714 if(FAILED(hres)){
10715 implib->name = NULL;
10716 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres);
10720 implib->guid = TLB_append_guid(&This->pTypeLib->guid_list, &libattr->guid, 2);
10721 implib->lcid = libattr->lcid;
10722 implib->wVersionMajor = libattr->wMajorVerNum;
10723 implib->wVersionMinor = libattr->wMinorVerNum;
10725 list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
10728 ITypeLib_ReleaseTLibAttr(container, libattr);
10729 ITypeLib_Release(container);
10731 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
10732 if (FAILED(hres))
10733 return hres;
10735 index = 0;
10736 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
10737 if(ref_type->index == TLB_REF_USE_GUID &&
10738 IsEqualGUID(&ref_type->guid->guid, &typeattr->guid) &&
10739 ref_type->tkind == typeattr->typekind)
10740 break;
10741 ++index;
10744 if(&ref_type->entry == &This->pTypeLib->ref_list){
10745 ref_type = heap_alloc_zero(sizeof(TLBRefType));
10747 ref_type->tkind = typeattr->typekind;
10748 ref_type->pImpTLInfo = implib;
10749 ref_type->reference = index * sizeof(MSFT_ImpInfo);
10751 ref_type->index = TLB_REF_USE_GUID;
10753 ref_type->guid = TLB_append_guid(&This->pTypeLib->guid_list, &typeattr->guid, ref_type->reference+1);
10755 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
10758 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
10760 *refType = ref_type->reference | 0x1;
10762 if(IsEqualGUID(&ref_type->guid->guid, &IID_IDispatch))
10763 This->pTypeLib->dispatch_href = *refType;
10765 return S_OK;
10768 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
10769 UINT index, FUNCDESC *funcDesc)
10771 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10772 TLBFuncDesc tmp_func_desc, *func_desc;
10773 int buf_size, i;
10774 char *buffer;
10775 HRESULT hres;
10777 TRACE("%p %u %p\n", This, index, funcDesc);
10779 if (!funcDesc || funcDesc->oVft & 3)
10780 return E_INVALIDARG;
10782 switch (This->typeattr.typekind) {
10783 case TKIND_MODULE:
10784 if (funcDesc->funckind != FUNC_STATIC)
10785 return TYPE_E_BADMODULEKIND;
10786 break;
10787 case TKIND_DISPATCH:
10788 if (funcDesc->funckind != FUNC_DISPATCH)
10789 return TYPE_E_BADMODULEKIND;
10790 break;
10791 default:
10792 if (funcDesc->funckind != FUNC_PUREVIRTUAL)
10793 return TYPE_E_BADMODULEKIND;
10796 if (index > This->typeattr.cFuncs)
10797 return TYPE_E_ELEMENTNOTFOUND;
10799 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) &&
10800 !funcDesc->cParams)
10801 return TYPE_E_INCONSISTENTPROPFUNCS;
10803 #ifdef _WIN64
10804 if(This->pTypeLib->syskind == SYS_WIN64 &&
10805 funcDesc->oVft % 8 != 0)
10806 return E_INVALIDARG;
10807 #endif
10809 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc));
10810 TLBFuncDesc_Constructor(&tmp_func_desc);
10812 tmp_func_desc.funcdesc = *funcDesc;
10814 if (tmp_func_desc.funcdesc.oVft != 0)
10815 tmp_func_desc.funcdesc.oVft |= 1;
10817 if (funcDesc->cScodes && funcDesc->lprgscode) {
10818 tmp_func_desc.funcdesc.lprgscode = heap_alloc(sizeof(SCODE) * funcDesc->cScodes);
10819 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes);
10820 } else {
10821 tmp_func_desc.funcdesc.lprgscode = NULL;
10822 tmp_func_desc.funcdesc.cScodes = 0;
10825 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc);
10826 for (i = 0; i < funcDesc->cParams; ++i) {
10827 buf_size += sizeof(ELEMDESC);
10828 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i);
10830 tmp_func_desc.funcdesc.lprgelemdescParam = heap_alloc(buf_size);
10831 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams);
10833 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer);
10834 if (FAILED(hres)) {
10835 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10836 heap_free(tmp_func_desc.funcdesc.lprgscode);
10837 return hres;
10840 for (i = 0; i < funcDesc->cParams; ++i) {
10841 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i,
10842 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer);
10843 if (FAILED(hres)) {
10844 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10845 heap_free(tmp_func_desc.funcdesc.lprgscode);
10846 return hres;
10848 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT &&
10849 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT &&
10850 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){
10851 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
10852 if (FAILED(hres)) {
10853 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10854 heap_free(tmp_func_desc.funcdesc.lprgscode);
10855 return hres;
10860 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams);
10862 if (This->funcdescs) {
10863 This->funcdescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->funcdescs,
10864 sizeof(TLBFuncDesc) * (This->typeattr.cFuncs + 1));
10866 if (index < This->typeattr.cFuncs) {
10867 memmove(This->funcdescs + index + 1, This->funcdescs + index,
10868 (This->typeattr.cFuncs - index) * sizeof(TLBFuncDesc));
10869 func_desc = This->funcdescs + index;
10870 } else
10871 func_desc = This->funcdescs + This->typeattr.cFuncs;
10873 /* move custdata lists to the new memory location */
10874 for(i = 0; i < This->typeattr.cFuncs + 1; ++i){
10875 if(index != i)
10876 TLB_relink_custdata(&This->funcdescs[i].custdata_list);
10878 } else
10879 func_desc = This->funcdescs = heap_alloc(sizeof(TLBFuncDesc));
10881 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc));
10882 list_init(&func_desc->custdata_list);
10884 ++This->typeattr.cFuncs;
10886 This->needs_layout = TRUE;
10888 return S_OK;
10891 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
10892 UINT index, HREFTYPE refType)
10894 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10895 TLBImplType *impl_type;
10896 HRESULT hres;
10898 TRACE("%p %u %d\n", This, index, refType);
10900 switch(This->typeattr.typekind){
10901 case TKIND_COCLASS: {
10902 if (index == -1) {
10903 FIXME("Unhandled index: -1\n");
10904 return E_NOTIMPL;
10907 if(index != This->typeattr.cImplTypes)
10908 return TYPE_E_ELEMENTNOTFOUND;
10910 break;
10912 case TKIND_INTERFACE:
10913 case TKIND_DISPATCH:
10914 if (index != 0 || This->typeattr.cImplTypes)
10915 return TYPE_E_ELEMENTNOTFOUND;
10916 break;
10917 default:
10918 FIXME("Unimplemented typekind: %d\n", This->typeattr.typekind);
10919 return E_NOTIMPL;
10922 if (This->impltypes){
10923 UINT i;
10925 This->impltypes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->impltypes,
10926 sizeof(TLBImplType) * (This->typeattr.cImplTypes + 1));
10928 if (index < This->typeattr.cImplTypes) {
10929 memmove(This->impltypes + index + 1, This->impltypes + index,
10930 (This->typeattr.cImplTypes - index) * sizeof(TLBImplType));
10931 impl_type = This->impltypes + index;
10932 } else
10933 impl_type = This->impltypes + This->typeattr.cImplTypes;
10935 /* move custdata lists to the new memory location */
10936 for(i = 0; i < This->typeattr.cImplTypes + 1; ++i){
10937 if(index != i)
10938 TLB_relink_custdata(&This->impltypes[i].custdata_list);
10940 } else
10941 impl_type = This->impltypes = heap_alloc(sizeof(TLBImplType));
10943 memset(impl_type, 0, sizeof(TLBImplType));
10944 TLBImplType_Constructor(impl_type);
10945 impl_type->hRef = refType;
10947 ++This->typeattr.cImplTypes;
10949 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
10950 This->typeattr.wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
10952 hres = ICreateTypeInfo2_LayOut(iface);
10953 if (FAILED(hres))
10954 return hres;
10956 return S_OK;
10959 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
10960 UINT index, INT implTypeFlags)
10962 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10963 TLBImplType *impl_type = &This->impltypes[index];
10965 TRACE("%p %u %x\n", This, index, implTypeFlags);
10967 if (This->typeattr.typekind != TKIND_COCLASS)
10968 return TYPE_E_BADMODULEKIND;
10970 if (index >= This->typeattr.cImplTypes)
10971 return TYPE_E_ELEMENTNOTFOUND;
10973 impl_type->implflags = implTypeFlags;
10975 return S_OK;
10978 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
10979 WORD alignment)
10981 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10983 TRACE("%p %d\n", This, alignment);
10985 This->typeattr.cbAlignment = alignment;
10987 return S_OK;
10990 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
10991 LPOLESTR schema)
10993 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10995 TRACE("%p %s\n", This, wine_dbgstr_w(schema));
10997 if (!schema)
10998 return E_INVALIDARG;
11000 This->Schema = TLB_append_str(&This->pTypeLib->string_list, schema);
11002 This->typeattr.lpstrSchema = This->Schema->str;
11004 return S_OK;
11007 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
11008 UINT index, VARDESC *varDesc)
11010 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11011 TLBVarDesc *var_desc;
11013 TRACE("%p %u %p\n", This, index, varDesc);
11015 if (This->vardescs){
11016 UINT i;
11018 This->vardescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->vardescs,
11019 sizeof(TLBVarDesc) * (This->typeattr.cVars + 1));
11021 if (index < This->typeattr.cVars) {
11022 memmove(This->vardescs + index + 1, This->vardescs + index,
11023 (This->typeattr.cVars - index) * sizeof(TLBVarDesc));
11024 var_desc = This->vardescs + index;
11025 } else
11026 var_desc = This->vardescs + This->typeattr.cVars;
11028 /* move custdata lists to the new memory location */
11029 for(i = 0; i < This->typeattr.cVars + 1; ++i){
11030 if(index != i)
11031 TLB_relink_custdata(&This->vardescs[i].custdata_list);
11033 } else
11034 var_desc = This->vardescs = heap_alloc_zero(sizeof(TLBVarDesc));
11036 TLBVarDesc_Constructor(var_desc);
11037 TLB_AllocAndInitVarDesc(varDesc, &var_desc->vardesc_create);
11038 var_desc->vardesc = *var_desc->vardesc_create;
11040 ++This->typeattr.cVars;
11042 This->needs_layout = TRUE;
11044 return S_OK;
11047 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
11048 UINT index, LPOLESTR *names, UINT numNames)
11050 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11051 TLBFuncDesc *func_desc = &This->funcdescs[index];
11052 int i;
11054 TRACE("%p %u %p %u\n", This, index, names, numNames);
11056 if (!names)
11057 return E_INVALIDARG;
11059 if (index >= This->typeattr.cFuncs || numNames == 0)
11060 return TYPE_E_ELEMENTNOTFOUND;
11062 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){
11063 if(numNames > func_desc->funcdesc.cParams)
11064 return TYPE_E_ELEMENTNOTFOUND;
11065 } else
11066 if(numNames > func_desc->funcdesc.cParams + 1)
11067 return TYPE_E_ELEMENTNOTFOUND;
11069 for(i = 0; i < This->typeattr.cFuncs; ++i) {
11070 TLBFuncDesc *iter = &This->funcdescs[i];
11071 if (iter->Name && !wcscmp(TLB_get_bstr(iter->Name), *names)) {
11072 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
11073 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
11074 func_desc->funcdesc.invkind != iter->funcdesc.invkind)
11075 continue;
11076 return TYPE_E_AMBIGUOUSNAME;
11080 func_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *names);
11082 for (i = 1; i < numNames; ++i) {
11083 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1;
11084 par_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *(names + i));
11087 return S_OK;
11090 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
11091 UINT index, LPOLESTR name)
11093 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11095 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(name));
11097 if(!name)
11098 return E_INVALIDARG;
11100 if(index >= This->typeattr.cVars)
11101 return TYPE_E_ELEMENTNOTFOUND;
11103 This->vardescs[index].Name = TLB_append_str(&This->pTypeLib->name_list, name);
11104 return S_OK;
11107 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
11108 TYPEDESC *tdescAlias)
11110 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11111 HRESULT hr;
11113 TRACE("%p %p\n", This, tdescAlias);
11115 if(!tdescAlias)
11116 return E_INVALIDARG;
11118 if(This->typeattr.typekind != TKIND_ALIAS)
11119 return TYPE_E_BADMODULEKIND;
11121 hr = TLB_size_instance(This, This->pTypeLib->syskind, tdescAlias, &This->typeattr.cbSizeInstance, &This->typeattr.cbAlignment);
11122 if(FAILED(hr))
11123 return hr;
11125 heap_free(This->tdescAlias);
11126 This->tdescAlias = heap_alloc(TLB_SizeTypeDesc(tdescAlias, TRUE));
11127 TLB_CopyTypeDesc(NULL, tdescAlias, This->tdescAlias);
11129 return S_OK;
11132 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
11133 UINT index, LPOLESTR dllName, LPOLESTR procName)
11135 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11136 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
11137 return E_NOTIMPL;
11140 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
11141 UINT index, LPOLESTR docString)
11143 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11144 TLBFuncDesc *func_desc = &This->funcdescs[index];
11146 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
11148 if(!docString)
11149 return E_INVALIDARG;
11151 if(index >= This->typeattr.cFuncs)
11152 return TYPE_E_ELEMENTNOTFOUND;
11154 func_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
11156 return S_OK;
11159 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
11160 UINT index, LPOLESTR docString)
11162 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11163 TLBVarDesc *var_desc = &This->vardescs[index];
11165 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
11167 if(!docString)
11168 return E_INVALIDARG;
11170 if(index >= This->typeattr.cVars)
11171 return TYPE_E_ELEMENTNOTFOUND;
11173 var_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
11175 return S_OK;
11178 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
11179 UINT index, DWORD helpContext)
11181 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11182 TLBFuncDesc *func_desc = &This->funcdescs[index];
11184 TRACE("%p %u %d\n", This, index, helpContext);
11186 if(index >= This->typeattr.cFuncs)
11187 return TYPE_E_ELEMENTNOTFOUND;
11189 func_desc->helpcontext = helpContext;
11191 return S_OK;
11194 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
11195 UINT index, DWORD helpContext)
11197 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11198 TLBVarDesc *var_desc = &This->vardescs[index];
11200 TRACE("%p %u %d\n", This, index, helpContext);
11202 if(index >= This->typeattr.cVars)
11203 return TYPE_E_ELEMENTNOTFOUND;
11205 var_desc->HelpContext = helpContext;
11207 return S_OK;
11210 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
11211 UINT index, BSTR bstrMops)
11213 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11214 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
11215 return E_NOTIMPL;
11218 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
11219 IDLDESC *idlDesc)
11221 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11223 TRACE("%p %p\n", This, idlDesc);
11225 if (!idlDesc)
11226 return E_INVALIDARG;
11228 This->typeattr.idldescType.dwReserved = idlDesc->dwReserved;
11229 This->typeattr.idldescType.wIDLFlags = idlDesc->wIDLFlags;
11231 return S_OK;
11234 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
11236 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11237 ITypeInfo2 *tinfo = &This->ITypeInfo2_iface;
11238 TLBFuncDesc *func_desc;
11239 UINT user_vft = 0, i, depth = 0;
11240 HRESULT hres = S_OK;
11242 TRACE("%p\n", This);
11244 This->needs_layout = FALSE;
11246 if (This->typeattr.typekind == TKIND_INTERFACE) {
11247 ITypeInfo *inh;
11248 TYPEATTR *attr;
11249 HREFTYPE inh_href;
11251 hres = ITypeInfo2_GetRefTypeOfImplType(tinfo, 0, &inh_href);
11253 if (SUCCEEDED(hres)) {
11254 hres = ITypeInfo2_GetRefTypeInfo(tinfo, inh_href, &inh);
11256 if (SUCCEEDED(hres)) {
11257 hres = ITypeInfo_GetTypeAttr(inh, &attr);
11258 if (FAILED(hres)) {
11259 ITypeInfo_Release(inh);
11260 return hres;
11262 This->typeattr.cbSizeVft = attr->cbSizeVft;
11263 ITypeInfo_ReleaseTypeAttr(inh, attr);
11266 ++depth;
11267 hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href);
11268 if(SUCCEEDED(hres)){
11269 ITypeInfo *next;
11270 hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next);
11271 if(SUCCEEDED(hres)){
11272 ITypeInfo_Release(inh);
11273 inh = next;
11276 }while(SUCCEEDED(hres));
11277 hres = S_OK;
11279 ITypeInfo_Release(inh);
11280 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
11281 This->typeattr.cbSizeVft = 0;
11282 hres = S_OK;
11283 } else
11284 return hres;
11285 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
11286 This->typeattr.cbSizeVft = 0;
11287 hres = S_OK;
11288 } else
11289 return hres;
11290 } else if (This->typeattr.typekind == TKIND_DISPATCH)
11291 This->typeattr.cbSizeVft = 7 * This->pTypeLib->ptr_size;
11292 else
11293 This->typeattr.cbSizeVft = 0;
11295 func_desc = This->funcdescs;
11296 i = 0;
11297 while (i < This->typeattr.cFuncs) {
11298 if (!(func_desc->funcdesc.oVft & 0x1))
11299 func_desc->funcdesc.oVft = This->typeattr.cbSizeVft;
11301 if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft)
11302 user_vft = func_desc->funcdesc.oVft & 0xFFFC;
11304 This->typeattr.cbSizeVft += This->pTypeLib->ptr_size;
11306 if (func_desc->funcdesc.memid == MEMBERID_NIL) {
11307 TLBFuncDesc *iter;
11308 UINT j = 0;
11309 BOOL reset = FALSE;
11311 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i;
11313 iter = This->funcdescs;
11314 while (j < This->typeattr.cFuncs) {
11315 if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) {
11316 if (!reset) {
11317 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->typeattr.cFuncs;
11318 reset = TRUE;
11319 } else
11320 ++func_desc->funcdesc.memid;
11321 iter = This->funcdescs;
11322 j = 0;
11323 } else {
11324 ++iter;
11325 ++j;
11330 ++func_desc;
11331 ++i;
11334 if (user_vft > This->typeattr.cbSizeVft)
11335 This->typeattr.cbSizeVft = user_vft + This->pTypeLib->ptr_size;
11337 for(i = 0; i < This->typeattr.cVars; ++i){
11338 TLBVarDesc *var_desc = &This->vardescs[i];
11339 if(var_desc->vardesc.memid == MEMBERID_NIL){
11340 UINT j = 0;
11341 BOOL reset = FALSE;
11342 TLBVarDesc *iter;
11344 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + i;
11346 iter = This->vardescs;
11347 while (j < This->typeattr.cVars) {
11348 if (iter != var_desc && iter->vardesc.memid == var_desc->vardesc.memid) {
11349 if (!reset) {
11350 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + This->typeattr.cVars;
11351 reset = TRUE;
11352 } else
11353 ++var_desc->vardesc.memid;
11354 iter = This->vardescs;
11355 j = 0;
11356 } else {
11357 ++iter;
11358 ++j;
11364 return hres;
11367 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
11368 UINT index)
11370 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11371 FIXME("%p %u - stub\n", This, index);
11372 return E_NOTIMPL;
11375 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
11376 MEMBERID memid, INVOKEKIND invKind)
11378 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11379 FIXME("%p %x %d - stub\n", This, memid, invKind);
11380 return E_NOTIMPL;
11383 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
11384 UINT index)
11386 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11387 FIXME("%p %u - stub\n", This, index);
11388 return E_NOTIMPL;
11391 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
11392 MEMBERID memid)
11394 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11395 FIXME("%p %x - stub\n", This, memid);
11396 return E_NOTIMPL;
11399 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
11400 UINT index)
11402 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11403 int i;
11405 TRACE("%p %u\n", This, index);
11407 if (index >= This->typeattr.cImplTypes)
11408 return TYPE_E_ELEMENTNOTFOUND;
11410 TLB_FreeCustData(&This->impltypes[index].custdata_list);
11411 --This->typeattr.cImplTypes;
11413 if (index < This->typeattr.cImplTypes)
11415 memmove(This->impltypes + index, This->impltypes + index + 1, (This->typeattr.cImplTypes - index) *
11416 sizeof(*This->impltypes));
11417 for (i = index; i < This->typeattr.cImplTypes; ++i)
11418 TLB_relink_custdata(&This->impltypes[i].custdata_list);
11421 return S_OK;
11424 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
11425 REFGUID guid, VARIANT *varVal)
11427 TLBGuid *tlbguid;
11429 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11431 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
11433 if (!guid || !varVal)
11434 return E_INVALIDARG;
11436 tlbguid = TLB_append_guid(&This->pTypeLib->guid_list, guid, -1);
11438 return TLB_set_custdata(This->pcustdata_list, tlbguid, varVal);
11441 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
11442 UINT index, REFGUID guid, VARIANT *varVal)
11444 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11445 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11446 return E_NOTIMPL;
11449 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
11450 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
11452 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11453 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
11454 return E_NOTIMPL;
11457 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
11458 UINT index, REFGUID guid, VARIANT *varVal)
11460 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11461 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11462 return E_NOTIMPL;
11465 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
11466 UINT index, REFGUID guid, VARIANT *varVal)
11468 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11469 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11470 return E_NOTIMPL;
11473 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
11474 ULONG helpStringContext)
11476 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11478 TRACE("%p %u\n", This, helpStringContext);
11480 This->dwHelpStringContext = helpStringContext;
11482 return S_OK;
11485 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
11486 UINT index, ULONG helpStringContext)
11488 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11489 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11490 return E_NOTIMPL;
11493 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
11494 UINT index, ULONG helpStringContext)
11496 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11497 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11498 return E_NOTIMPL;
11501 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
11503 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11504 FIXME("%p - stub\n", This);
11505 return E_NOTIMPL;
11508 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
11509 LPOLESTR name)
11511 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11513 TRACE("%p %s\n", This, wine_dbgstr_w(name));
11515 if (!name)
11516 return E_INVALIDARG;
11518 This->Name = TLB_append_str(&This->pTypeLib->name_list, name);
11520 return S_OK;
11523 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
11524 ICreateTypeInfo2_fnQueryInterface,
11525 ICreateTypeInfo2_fnAddRef,
11526 ICreateTypeInfo2_fnRelease,
11527 ICreateTypeInfo2_fnSetGuid,
11528 ICreateTypeInfo2_fnSetTypeFlags,
11529 ICreateTypeInfo2_fnSetDocString,
11530 ICreateTypeInfo2_fnSetHelpContext,
11531 ICreateTypeInfo2_fnSetVersion,
11532 ICreateTypeInfo2_fnAddRefTypeInfo,
11533 ICreateTypeInfo2_fnAddFuncDesc,
11534 ICreateTypeInfo2_fnAddImplType,
11535 ICreateTypeInfo2_fnSetImplTypeFlags,
11536 ICreateTypeInfo2_fnSetAlignment,
11537 ICreateTypeInfo2_fnSetSchema,
11538 ICreateTypeInfo2_fnAddVarDesc,
11539 ICreateTypeInfo2_fnSetFuncAndParamNames,
11540 ICreateTypeInfo2_fnSetVarName,
11541 ICreateTypeInfo2_fnSetTypeDescAlias,
11542 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
11543 ICreateTypeInfo2_fnSetFuncDocString,
11544 ICreateTypeInfo2_fnSetVarDocString,
11545 ICreateTypeInfo2_fnSetFuncHelpContext,
11546 ICreateTypeInfo2_fnSetVarHelpContext,
11547 ICreateTypeInfo2_fnSetMops,
11548 ICreateTypeInfo2_fnSetTypeIdldesc,
11549 ICreateTypeInfo2_fnLayOut,
11550 ICreateTypeInfo2_fnDeleteFuncDesc,
11551 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
11552 ICreateTypeInfo2_fnDeleteVarDesc,
11553 ICreateTypeInfo2_fnDeleteVarDescByMemId,
11554 ICreateTypeInfo2_fnDeleteImplType,
11555 ICreateTypeInfo2_fnSetCustData,
11556 ICreateTypeInfo2_fnSetFuncCustData,
11557 ICreateTypeInfo2_fnSetParamCustData,
11558 ICreateTypeInfo2_fnSetVarCustData,
11559 ICreateTypeInfo2_fnSetImplTypeCustData,
11560 ICreateTypeInfo2_fnSetHelpStringContext,
11561 ICreateTypeInfo2_fnSetFuncHelpStringContext,
11562 ICreateTypeInfo2_fnSetVarHelpStringContext,
11563 ICreateTypeInfo2_fnInvalidate,
11564 ICreateTypeInfo2_fnSetName
11567 /******************************************************************************
11568 * ClearCustData (OLEAUT32.171)
11570 * Clear a custom data type's data.
11572 * PARAMS
11573 * lpCust [I] The custom data type instance
11575 * RETURNS
11576 * Nothing.
11578 void WINAPI ClearCustData(CUSTDATA *lpCust)
11580 if (lpCust && lpCust->cCustData)
11582 if (lpCust->prgCustData)
11584 DWORD i;
11586 for (i = 0; i < lpCust->cCustData; i++)
11587 VariantClear(&lpCust->prgCustData[i].varValue);
11589 CoTaskMemFree(lpCust->prgCustData);
11590 lpCust->prgCustData = NULL;
11592 lpCust->cCustData = 0;