makefiles: Don't use standard libs for programs that specify -nodefaultlibs.
[wine/zf.git] / dlls / oleaut32 / typelib.c
blobf8d713683459437bcdd1b553c533ba3ed6cfc7ed
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 TLBVarDesc *TLB_get_vardesc_by_memberid(ITypeInfoImpl *typeinfo, MEMBERID memid)
1706 int i;
1708 for (i = 0; i < typeinfo->typeattr.cVars; ++i)
1710 if (typeinfo->vardescs[i].vardesc.memid == memid)
1711 return &typeinfo->vardescs[i];
1714 return NULL;
1717 static inline TLBVarDesc *TLB_get_vardesc_by_name(ITypeInfoImpl *typeinfo, const OLECHAR *name)
1719 int i;
1721 for (i = 0; i < typeinfo->typeattr.cVars; ++i)
1723 if (!lstrcmpiW(TLB_get_bstr(typeinfo->vardescs[i].Name), name))
1724 return &typeinfo->vardescs[i];
1727 return NULL;
1730 static inline TLBCustData *TLB_get_custdata_by_guid(const struct list *custdata_list, REFGUID guid)
1732 TLBCustData *cust_data;
1733 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1734 if(IsEqualIID(TLB_get_guid_null(cust_data->guid), guid))
1735 return cust_data;
1736 return NULL;
1739 static inline ITypeInfoImpl *TLB_get_typeinfo_by_name(ITypeLibImpl *typelib, const OLECHAR *name)
1741 int i;
1743 for (i = 0; i < typelib->TypeInfoCount; ++i)
1745 if (!lstrcmpiW(TLB_get_bstr(typelib->typeinfos[i]->Name), name))
1746 return typelib->typeinfos[i];
1749 return NULL;
1752 static void TLBVarDesc_Constructor(TLBVarDesc *var_desc)
1754 list_init(&var_desc->custdata_list);
1757 static TLBVarDesc *TLBVarDesc_Alloc(UINT n)
1759 TLBVarDesc *ret;
1761 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1762 if(!ret)
1763 return NULL;
1765 while(n){
1766 TLBVarDesc_Constructor(&ret[n-1]);
1767 --n;
1770 return ret;
1773 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1775 TLBParDesc *ret;
1777 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1778 if(!ret)
1779 return NULL;
1781 while(n){
1782 list_init(&ret[n-1].custdata_list);
1783 --n;
1786 return ret;
1789 static void TLBFuncDesc_Constructor(TLBFuncDesc *func_desc)
1791 list_init(&func_desc->custdata_list);
1794 static TLBFuncDesc *TLBFuncDesc_Alloc(UINT n)
1796 TLBFuncDesc *ret;
1798 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1799 if(!ret)
1800 return NULL;
1802 while(n){
1803 TLBFuncDesc_Constructor(&ret[n-1]);
1804 --n;
1807 return ret;
1810 static void TLBImplType_Constructor(TLBImplType *impl)
1812 list_init(&impl->custdata_list);
1815 static TLBImplType *TLBImplType_Alloc(UINT n)
1817 TLBImplType *ret;
1819 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1820 if(!ret)
1821 return NULL;
1823 while(n){
1824 TLBImplType_Constructor(&ret[n-1]);
1825 --n;
1828 return ret;
1831 static TLBGuid *TLB_append_guid(struct list *guid_list,
1832 const GUID *new_guid, HREFTYPE hreftype)
1834 TLBGuid *guid;
1836 LIST_FOR_EACH_ENTRY(guid, guid_list, TLBGuid, entry) {
1837 if (IsEqualGUID(&guid->guid, new_guid))
1838 return guid;
1841 guid = heap_alloc(sizeof(TLBGuid));
1842 if (!guid)
1843 return NULL;
1845 memcpy(&guid->guid, new_guid, sizeof(GUID));
1846 guid->hreftype = hreftype;
1848 list_add_tail(guid_list, &guid->entry);
1850 return guid;
1853 static HRESULT TLB_set_custdata(struct list *custdata_list, TLBGuid *tlbguid, VARIANT *var)
1855 TLBCustData *cust_data;
1857 switch(V_VT(var)){
1858 case VT_I4:
1859 case VT_R4:
1860 case VT_UI4:
1861 case VT_INT:
1862 case VT_UINT:
1863 case VT_HRESULT:
1864 case VT_BSTR:
1865 break;
1866 default:
1867 return DISP_E_BADVARTYPE;
1870 cust_data = TLB_get_custdata_by_guid(custdata_list, TLB_get_guid_null(tlbguid));
1872 if (!cust_data) {
1873 cust_data = heap_alloc(sizeof(TLBCustData));
1874 if (!cust_data)
1875 return E_OUTOFMEMORY;
1877 cust_data->guid = tlbguid;
1878 VariantInit(&cust_data->data);
1880 list_add_tail(custdata_list, &cust_data->entry);
1881 }else
1882 VariantClear(&cust_data->data);
1884 return VariantCopy(&cust_data->data, var);
1887 /* Used to update list pointers after list itself was moved. */
1888 static void TLB_relink_custdata(struct list *custdata_list)
1890 if (custdata_list->prev == custdata_list->next)
1891 list_init(custdata_list);
1892 else
1894 custdata_list->prev->next = custdata_list;
1895 custdata_list->next->prev = custdata_list;
1899 static TLBString *TLB_append_str(struct list *string_list, BSTR new_str)
1901 TLBString *str;
1903 if(!new_str)
1904 return NULL;
1906 LIST_FOR_EACH_ENTRY(str, string_list, TLBString, entry) {
1907 if (wcscmp(str->str, new_str) == 0)
1908 return str;
1911 str = heap_alloc(sizeof(TLBString));
1912 if (!str)
1913 return NULL;
1915 str->str = SysAllocString(new_str);
1916 if (!str->str) {
1917 heap_free(str);
1918 return NULL;
1921 list_add_tail(string_list, &str->entry);
1923 return str;
1926 static HRESULT TLB_get_size_from_hreftype(ITypeInfoImpl *info, HREFTYPE href,
1927 ULONG *size, WORD *align)
1929 ITypeInfo *other;
1930 TYPEATTR *attr;
1931 HRESULT hr;
1933 hr = ITypeInfo2_GetRefTypeInfo(&info->ITypeInfo2_iface, href, &other);
1934 if(FAILED(hr))
1935 return hr;
1937 hr = ITypeInfo_GetTypeAttr(other, &attr);
1938 if(FAILED(hr)){
1939 ITypeInfo_Release(other);
1940 return hr;
1943 if(size)
1944 *size = attr->cbSizeInstance;
1945 if(align)
1946 *align = attr->cbAlignment;
1948 ITypeInfo_ReleaseTypeAttr(other, attr);
1949 ITypeInfo_Release(other);
1951 return S_OK;
1954 static HRESULT TLB_size_instance(ITypeInfoImpl *info, SYSKIND sys,
1955 TYPEDESC *tdesc, ULONG *size, WORD *align)
1957 ULONG i, sub, ptr_size;
1958 HRESULT hr;
1960 ptr_size = get_ptr_size(sys);
1962 switch(tdesc->vt){
1963 case VT_VOID:
1964 *size = 0;
1965 break;
1966 case VT_I1:
1967 case VT_UI1:
1968 *size = 1;
1969 break;
1970 case VT_I2:
1971 case VT_BOOL:
1972 case VT_UI2:
1973 *size = 2;
1974 break;
1975 case VT_I4:
1976 case VT_R4:
1977 case VT_ERROR:
1978 case VT_UI4:
1979 case VT_INT:
1980 case VT_UINT:
1981 case VT_HRESULT:
1982 *size = 4;
1983 break;
1984 case VT_R8:
1985 case VT_I8:
1986 case VT_UI8:
1987 *size = 8;
1988 break;
1989 case VT_BSTR:
1990 case VT_DISPATCH:
1991 case VT_UNKNOWN:
1992 case VT_PTR:
1993 case VT_SAFEARRAY:
1994 case VT_LPSTR:
1995 case VT_LPWSTR:
1996 *size = ptr_size;
1997 break;
1998 case VT_DATE:
1999 *size = sizeof(DATE);
2000 break;
2001 case VT_VARIANT:
2002 *size = sizeof(VARIANT);
2003 #ifdef _WIN64
2004 if(sys == SYS_WIN32)
2005 *size -= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
2006 #endif
2007 break;
2008 case VT_DECIMAL:
2009 *size = sizeof(DECIMAL);
2010 break;
2011 case VT_CY:
2012 *size = sizeof(CY);
2013 break;
2014 case VT_CARRAY:
2015 *size = 0;
2016 for(i = 0; i < tdesc->u.lpadesc->cDims; ++i)
2017 *size += tdesc->u.lpadesc->rgbounds[i].cElements;
2018 hr = TLB_size_instance(info, sys, &tdesc->u.lpadesc->tdescElem, &sub, align);
2019 if(FAILED(hr))
2020 return hr;
2021 *size *= sub;
2022 return S_OK;
2023 case VT_USERDEFINED:
2024 return TLB_get_size_from_hreftype(info, tdesc->u.hreftype, size, align);
2025 default:
2026 FIXME("Unsized VT: 0x%x\n", tdesc->vt);
2027 return E_FAIL;
2030 if(align){
2031 if(*size < 4)
2032 *align = *size;
2033 else
2034 *align = 4;
2037 return S_OK;
2040 /**********************************************************************
2042 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2045 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
2047 if (where != DO_NOT_SEEK)
2049 where += pcx->oStart;
2050 if (where > pcx->length)
2052 /* FIXME */
2053 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
2054 TLB_abort();
2056 pcx->pos = where;
2060 /* read function */
2061 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
2063 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2064 pcx->pos, count, pcx->oStart, pcx->length, where);
2066 MSFT_Seek(pcx, where);
2067 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
2068 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
2069 pcx->pos += count;
2070 return count;
2073 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
2074 LONG where )
2076 DWORD ret;
2078 ret = MSFT_Read(buffer, count, pcx, where);
2079 FromLEDWords(buffer, ret);
2081 return ret;
2084 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
2085 LONG where )
2087 DWORD ret;
2089 ret = MSFT_Read(buffer, count, pcx, where);
2090 FromLEWords(buffer, ret);
2092 return ret;
2095 static HRESULT MSFT_ReadAllGuids(TLBContext *pcx)
2097 TLBGuid *guid;
2098 MSFT_GuidEntry entry;
2099 int offs = 0;
2101 MSFT_Seek(pcx, pcx->pTblDir->pGuidTab.offset);
2102 while (1) {
2103 if (offs >= pcx->pTblDir->pGuidTab.length)
2104 return S_OK;
2106 MSFT_ReadLEWords(&entry, sizeof(MSFT_GuidEntry), pcx, DO_NOT_SEEK);
2108 guid = heap_alloc(sizeof(TLBGuid));
2110 guid->offset = offs;
2111 guid->guid = entry.guid;
2112 guid->hreftype = entry.hreftype;
2114 list_add_tail(&pcx->pLibInfo->guid_list, &guid->entry);
2116 offs += sizeof(MSFT_GuidEntry);
2120 static TLBGuid *MSFT_ReadGuid( int offset, TLBContext *pcx)
2122 TLBGuid *ret;
2124 LIST_FOR_EACH_ENTRY(ret, &pcx->pLibInfo->guid_list, TLBGuid, entry){
2125 if(ret->offset == offset){
2126 TRACE_(typelib)("%s\n", debugstr_guid(&ret->guid));
2127 return ret;
2131 return NULL;
2134 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
2136 MSFT_NameIntro niName;
2138 if (offset < 0)
2140 ERR_(typelib)("bad offset %d\n", offset);
2141 return -1;
2144 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
2145 pcx->pTblDir->pNametab.offset+offset);
2147 return niName.hreftype;
2150 static HRESULT MSFT_ReadAllNames(TLBContext *pcx)
2152 char *string;
2153 MSFT_NameIntro intro;
2154 INT16 len_piece;
2155 int offs = 0, lengthInChars;
2157 MSFT_Seek(pcx, pcx->pTblDir->pNametab.offset);
2158 while (1) {
2159 TLBString *tlbstr;
2161 if (offs >= pcx->pTblDir->pNametab.length)
2162 return S_OK;
2164 MSFT_ReadLEWords(&intro, sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2165 intro.namelen &= 0xFF;
2166 len_piece = intro.namelen + sizeof(MSFT_NameIntro);
2167 if(len_piece % 4)
2168 len_piece = (len_piece + 4) & ~0x3;
2169 if(len_piece < 8)
2170 len_piece = 8;
2172 string = heap_alloc(len_piece + 1);
2173 MSFT_Read(string, len_piece - sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2174 string[intro.namelen] = '\0';
2176 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2177 string, -1, NULL, 0);
2178 if (!lengthInChars) {
2179 heap_free(string);
2180 return E_UNEXPECTED;
2183 tlbstr = heap_alloc(sizeof(TLBString));
2185 tlbstr->offset = offs;
2186 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2187 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2189 heap_free(string);
2191 list_add_tail(&pcx->pLibInfo->name_list, &tlbstr->entry);
2193 offs += len_piece;
2197 static TLBString *MSFT_ReadName( TLBContext *pcx, int offset)
2199 TLBString *tlbstr;
2201 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->name_list, TLBString, entry) {
2202 if (tlbstr->offset == offset) {
2203 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2204 return tlbstr;
2208 return NULL;
2211 static TLBString *MSFT_ReadString( TLBContext *pcx, int offset)
2213 TLBString *tlbstr;
2215 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->string_list, TLBString, entry) {
2216 if (tlbstr->offset == offset) {
2217 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2218 return tlbstr;
2222 return NULL;
2226 * read a value and fill a VARIANT structure
2228 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
2230 int size;
2232 TRACE_(typelib)("\n");
2234 if(offset <0) { /* data are packed in here */
2235 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
2236 V_I4(pVar) = offset & 0x3ffffff;
2237 return;
2239 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
2240 pcx->pTblDir->pCustData.offset + offset );
2241 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
2242 switch (V_VT(pVar)){
2243 case VT_EMPTY: /* FIXME: is this right? */
2244 case VT_NULL: /* FIXME: is this right? */
2245 case VT_I2 : /* this should not happen */
2246 case VT_I4 :
2247 case VT_R4 :
2248 case VT_ERROR :
2249 case VT_BOOL :
2250 case VT_I1 :
2251 case VT_UI1 :
2252 case VT_UI2 :
2253 case VT_UI4 :
2254 case VT_INT :
2255 case VT_UINT :
2256 case VT_VOID : /* FIXME: is this right? */
2257 case VT_HRESULT :
2258 size=4; break;
2259 case VT_R8 :
2260 case VT_CY :
2261 case VT_DATE :
2262 case VT_I8 :
2263 case VT_UI8 :
2264 case VT_DECIMAL : /* FIXME: is this right? */
2265 case VT_FILETIME :
2266 size=8;break;
2267 /* pointer types with known behaviour */
2268 case VT_BSTR :{
2269 char * ptr;
2270 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
2271 if(size == -1){
2272 V_BSTR(pVar) = NULL;
2273 }else{
2274 ptr = heap_alloc_zero(size);
2275 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);
2276 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
2277 /* FIXME: do we need a AtoW conversion here? */
2278 V_UNION(pVar, bstrVal[size])='\0';
2279 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
2280 heap_free(ptr);
2283 size=-4; break;
2284 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2285 case VT_DISPATCH :
2286 case VT_VARIANT :
2287 case VT_UNKNOWN :
2288 case VT_PTR :
2289 case VT_SAFEARRAY :
2290 case VT_CARRAY :
2291 case VT_USERDEFINED :
2292 case VT_LPSTR :
2293 case VT_LPWSTR :
2294 case VT_BLOB :
2295 case VT_STREAM :
2296 case VT_STORAGE :
2297 case VT_STREAMED_OBJECT :
2298 case VT_STORED_OBJECT :
2299 case VT_BLOB_OBJECT :
2300 case VT_CF :
2301 case VT_CLSID :
2302 default:
2303 size=0;
2304 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2305 V_VT(pVar));
2308 if(size>0) /* (big|small) endian correct? */
2309 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
2310 return;
2313 * create a linked list with custom data
2315 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
2317 MSFT_CDGuid entry;
2318 TLBCustData* pNew;
2319 int count=0;
2321 TRACE_(typelib)("\n");
2323 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
2325 while(offset >=0){
2326 count++;
2327 pNew=heap_alloc_zero(sizeof(TLBCustData));
2328 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
2329 pNew->guid = MSFT_ReadGuid(entry.GuidOffset, pcx);
2330 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
2331 list_add_head(custdata_list, &pNew->entry);
2332 offset = entry.next;
2334 return count;
2337 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd)
2339 if(type <0)
2340 pTd->vt=type & VT_TYPEMASK;
2341 else
2342 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
2344 TRACE_(typelib)("vt type = %X\n", pTd->vt);
2347 static BOOL TLB_is_propgetput(INVOKEKIND invkind)
2349 return (invkind == INVOKE_PROPERTYGET ||
2350 invkind == INVOKE_PROPERTYPUT ||
2351 invkind == INVOKE_PROPERTYPUTREF);
2354 static void
2355 MSFT_DoFuncs(TLBContext* pcx,
2356 ITypeInfoImpl* pTI,
2357 int cFuncs,
2358 int cVars,
2359 int offset,
2360 TLBFuncDesc** pptfd)
2363 * member information is stored in a data structure at offset
2364 * indicated by the memoffset field of the typeinfo structure
2365 * There are several distinctive parts.
2366 * The first part starts with a field that holds the total length
2367 * of this (first) part excluding this field. Then follow the records,
2368 * for each member there is one record.
2370 * The first entry is always the length of the record (including this
2371 * length word).
2372 * The rest of the record depends on the type of the member. If there is
2373 * a field indicating the member type (function, variable, interface, etc)
2374 * I have not found it yet. At this time we depend on the information
2375 * in the type info and the usual order how things are stored.
2377 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2378 * for each member;
2380 * Third is an equal sized array with file offsets to the name entry
2381 * of each member.
2383 * The fourth and last (?) part is an array with offsets to the records
2384 * in the first part of this file segment.
2387 int infolen, nameoffset, reclength, i;
2388 int recoffset = offset + sizeof(INT);
2390 char *recbuf = heap_alloc(0xffff);
2391 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2392 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2394 TRACE_(typelib)("\n");
2396 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2398 *pptfd = TLBFuncDesc_Alloc(cFuncs);
2399 ptfd = *pptfd;
2400 for ( i = 0; i < cFuncs ; i++ )
2402 int optional;
2404 /* name, eventually add to a hash table */
2405 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2406 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2408 /* read the function information record */
2409 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2411 reclength &= 0xffff;
2413 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2415 /* size without argument data */
2416 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2417 if (pFuncRec->FKCCIC & 0x1000)
2418 optional -= pFuncRec->nrargs * sizeof(INT);
2420 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2421 ptfd->helpcontext = pFuncRec->HelpContext;
2423 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2424 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2426 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2428 if (pFuncRec->FKCCIC & 0x2000 )
2430 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2431 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2432 ptfd->Entry = (TLBString*)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2434 else
2435 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2437 else
2438 ptfd->Entry = (TLBString*)-1;
2440 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2441 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2443 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2444 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2446 /* fill the FuncDesc Structure */
2447 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2448 offset + infolen + ( i + 1) * sizeof(INT));
2450 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2451 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2452 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2453 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2454 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2455 ptfd->funcdesc.oVft = (pFuncRec->VtableOffset & ~1) * sizeof(void *) / pTI->pTypeLib->ptr_size;
2456 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2458 /* nameoffset is sometimes -1 on the second half of a propget/propput
2459 * pair of functions */
2460 if ((nameoffset == -1) && (i > 0) &&
2461 TLB_is_propgetput(ptfd_prev->funcdesc.invkind) &&
2462 TLB_is_propgetput(ptfd->funcdesc.invkind))
2463 ptfd->Name = ptfd_prev->Name;
2464 else
2465 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2467 MSFT_GetTdesc(pcx,
2468 pFuncRec->DataType,
2469 &ptfd->funcdesc.elemdescFunc.tdesc);
2471 /* do the parameters/arguments */
2472 if(pFuncRec->nrargs)
2474 int j = 0;
2475 MSFT_ParameterInfo paraminfo;
2477 ptfd->funcdesc.lprgelemdescParam =
2478 heap_alloc_zero(pFuncRec->nrargs * (sizeof(ELEMDESC) + sizeof(PARAMDESCEX)));
2480 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2482 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2483 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2485 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2487 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2489 MSFT_GetTdesc(pcx,
2490 paraminfo.DataType,
2491 &elemdesc->tdesc);
2493 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2495 /* name */
2496 if (paraminfo.oName != -1)
2497 ptfd->pParamDesc[j].Name =
2498 MSFT_ReadName( pcx, paraminfo.oName );
2499 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(TLB_get_bstr(ptfd->pParamDesc[j].Name)));
2501 /* default value */
2502 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2503 (pFuncRec->FKCCIC & 0x1000) )
2505 INT* pInt = (INT *)((char *)pFuncRec +
2506 reclength -
2507 (pFuncRec->nrargs * 4) * sizeof(INT) );
2509 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2511 pParamDesc->pparamdescex = (PARAMDESCEX*)(ptfd->funcdesc.lprgelemdescParam+pFuncRec->nrargs)+j;
2512 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2514 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2515 pInt[j], pcx);
2517 else
2518 elemdesc->u.paramdesc.pparamdescex = NULL;
2520 /* custom info */
2521 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2522 j*sizeof(pFuncRec->oArgCustData[0])) &&
2523 pFuncRec->FKCCIC & 0x80 )
2525 MSFT_CustData(pcx,
2526 pFuncRec->oArgCustData[j],
2527 &ptfd->pParamDesc[j].custdata_list);
2530 /* SEEK value = jump to offset,
2531 * from there jump to the end of record,
2532 * go back by (j-1) arguments
2534 MSFT_ReadLEDWords( &paraminfo ,
2535 sizeof(MSFT_ParameterInfo), pcx,
2536 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2537 * sizeof(MSFT_ParameterInfo)));
2541 /* scode is not used: archaic win16 stuff FIXME: right? */
2542 ptfd->funcdesc.cScodes = 0 ;
2543 ptfd->funcdesc.lprgscode = NULL ;
2545 ptfd_prev = ptfd;
2546 ++ptfd;
2547 recoffset += reclength;
2549 heap_free(recbuf);
2552 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2553 int cVars, int offset, TLBVarDesc ** pptvd)
2555 int infolen, nameoffset, reclength;
2556 char recbuf[256];
2557 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2558 TLBVarDesc *ptvd;
2559 int i;
2560 int recoffset;
2562 TRACE_(typelib)("\n");
2564 ptvd = *pptvd = TLBVarDesc_Alloc(cVars);
2565 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2566 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2567 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2568 recoffset += offset+sizeof(INT);
2569 for(i=0;i<cVars;i++, ++ptvd){
2570 /* name, eventually add to a hash table */
2571 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2572 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2573 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2574 /* read the variable information record */
2575 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2576 reclength &= 0xff;
2577 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2579 /* optional data */
2580 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2581 ptvd->HelpContext = pVarRec->HelpContext;
2583 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2584 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2586 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2587 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2589 /* fill the VarDesc Structure */
2590 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2591 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2592 ptvd->vardesc.varkind = pVarRec->VarKind;
2593 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2594 MSFT_GetTdesc(pcx, pVarRec->DataType,
2595 &ptvd->vardesc.elemdescVar.tdesc);
2596 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2597 if(pVarRec->VarKind == VAR_CONST ){
2598 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2599 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2600 pVarRec->OffsValue, pcx);
2601 } else
2602 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2603 recoffset += reclength;
2607 /* process Implemented Interfaces of a com class */
2608 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2609 int offset)
2611 int i;
2612 MSFT_RefRecord refrec;
2613 TLBImplType *pImpl;
2615 TRACE_(typelib)("\n");
2617 pTI->impltypes = TLBImplType_Alloc(count);
2618 pImpl = pTI->impltypes;
2619 for(i=0;i<count;i++){
2620 if(offset<0) break; /* paranoia */
2621 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2622 pImpl->hRef = refrec.reftype;
2623 pImpl->implflags=refrec.flags;
2624 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2625 offset=refrec.onext;
2626 ++pImpl;
2630 #ifdef _WIN64
2631 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2632 * and some structures, and fix the alignment */
2633 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl *info)
2635 if(info->typeattr.typekind == TKIND_ALIAS){
2636 switch(info->tdescAlias->vt){
2637 case VT_BSTR:
2638 case VT_DISPATCH:
2639 case VT_UNKNOWN:
2640 case VT_PTR:
2641 case VT_SAFEARRAY:
2642 case VT_LPSTR:
2643 case VT_LPWSTR:
2644 info->typeattr.cbSizeInstance = sizeof(void*);
2645 info->typeattr.cbAlignment = sizeof(void*);
2646 break;
2647 case VT_CARRAY:
2648 case VT_USERDEFINED:
2649 TLB_size_instance(info, SYS_WIN64, info->tdescAlias, &info->typeattr.cbSizeInstance, &info->typeattr.cbAlignment);
2650 break;
2651 case VT_VARIANT:
2652 info->typeattr.cbSizeInstance = sizeof(VARIANT);
2653 info->typeattr.cbAlignment = 8;
2654 default:
2655 if(info->typeattr.cbSizeInstance < sizeof(void*))
2656 info->typeattr.cbAlignment = info->typeattr.cbSizeInstance;
2657 else
2658 info->typeattr.cbAlignment = sizeof(void*);
2659 break;
2661 }else if(info->typeattr.typekind == TKIND_INTERFACE ||
2662 info->typeattr.typekind == TKIND_DISPATCH ||
2663 info->typeattr.typekind == TKIND_COCLASS){
2664 info->typeattr.cbSizeInstance = sizeof(void*);
2665 info->typeattr.cbAlignment = sizeof(void*);
2668 #endif
2671 * process a typeinfo record
2673 static ITypeInfoImpl * MSFT_DoTypeInfo(
2674 TLBContext *pcx,
2675 int count,
2676 ITypeLibImpl * pLibInfo)
2678 MSFT_TypeInfoBase tiBase;
2679 ITypeInfoImpl *ptiRet;
2681 TRACE_(typelib)("count=%u\n", count);
2683 ptiRet = ITypeInfoImpl_Constructor();
2684 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2685 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2687 /* this is where we are coming from */
2688 ptiRet->pTypeLib = pLibInfo;
2689 ptiRet->index=count;
2691 ptiRet->guid = MSFT_ReadGuid(tiBase.posguid, pcx);
2692 ptiRet->typeattr.lcid = pLibInfo->set_lcid; /* FIXME: correct? */
2693 ptiRet->typeattr.lpstrSchema = NULL; /* reserved */
2694 ptiRet->typeattr.cbSizeInstance = tiBase.size;
2695 ptiRet->typeattr.typekind = tiBase.typekind & 0xF;
2696 ptiRet->typeattr.cFuncs = LOWORD(tiBase.cElement);
2697 ptiRet->typeattr.cVars = HIWORD(tiBase.cElement);
2698 ptiRet->typeattr.cbAlignment = (tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2699 ptiRet->typeattr.wTypeFlags = tiBase.flags;
2700 ptiRet->typeattr.wMajorVerNum = LOWORD(tiBase.version);
2701 ptiRet->typeattr.wMinorVerNum = HIWORD(tiBase.version);
2702 ptiRet->typeattr.cImplTypes = tiBase.cImplTypes;
2703 ptiRet->typeattr.cbSizeVft = tiBase.cbSizeVft;
2704 if (ptiRet->typeattr.typekind == TKIND_ALIAS) {
2705 TYPEDESC tmp;
2706 MSFT_GetTdesc(pcx, tiBase.datatype1, &tmp);
2707 ptiRet->tdescAlias = heap_alloc(TLB_SizeTypeDesc(&tmp, TRUE));
2708 TLB_CopyTypeDesc(NULL, &tmp, ptiRet->tdescAlias);
2711 /* FIXME: */
2712 /* IDLDESC idldescType; *//* never saw this one != zero */
2714 /* name, eventually add to a hash table */
2715 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2716 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2717 TRACE_(typelib)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet->Name)));
2718 /* help info */
2719 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2720 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2721 ptiRet->dwHelpContext=tiBase.helpcontext;
2723 if (ptiRet->typeattr.typekind == TKIND_MODULE)
2724 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2726 /* note: InfoType's Help file and HelpStringDll come from the containing
2727 * library. Further HelpString and Docstring appear to be the same thing :(
2729 /* functions */
2730 if(ptiRet->typeattr.cFuncs >0 )
2731 MSFT_DoFuncs(pcx, ptiRet, ptiRet->typeattr.cFuncs,
2732 ptiRet->typeattr.cVars,
2733 tiBase.memoffset, &ptiRet->funcdescs);
2734 /* variables */
2735 if(ptiRet->typeattr.cVars >0 )
2736 MSFT_DoVars(pcx, ptiRet, ptiRet->typeattr.cFuncs,
2737 ptiRet->typeattr.cVars,
2738 tiBase.memoffset, &ptiRet->vardescs);
2739 if(ptiRet->typeattr.cImplTypes >0 ) {
2740 switch(ptiRet->typeattr.typekind)
2742 case TKIND_COCLASS:
2743 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->typeattr.cImplTypes,
2744 tiBase.datatype1);
2745 break;
2746 case TKIND_DISPATCH:
2747 /* This is not -1 when the interface is a non-base dual interface or
2748 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2749 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2750 not this interface.
2753 if (tiBase.datatype1 != -1)
2755 ptiRet->impltypes = TLBImplType_Alloc(1);
2756 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2758 break;
2759 default:
2760 ptiRet->impltypes = TLBImplType_Alloc(1);
2761 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2762 break;
2765 MSFT_CustData(pcx, tiBase.oCustData, ptiRet->pcustdata_list);
2767 TRACE_(typelib)("%s guid: %s kind:%s\n",
2768 debugstr_w(TLB_get_bstr(ptiRet->Name)),
2769 debugstr_guid(TLB_get_guidref(ptiRet->guid)),
2770 typekind_desc[ptiRet->typeattr.typekind]);
2771 if (TRACE_ON(typelib))
2772 dump_TypeInfo(ptiRet);
2774 return ptiRet;
2777 static HRESULT MSFT_ReadAllStrings(TLBContext *pcx)
2779 char *string;
2780 INT16 len_str, len_piece;
2781 int offs = 0, lengthInChars;
2783 MSFT_Seek(pcx, pcx->pTblDir->pStringtab.offset);
2784 while (1) {
2785 TLBString *tlbstr;
2787 if (offs >= pcx->pTblDir->pStringtab.length)
2788 return S_OK;
2790 MSFT_ReadLEWords(&len_str, sizeof(INT16), pcx, DO_NOT_SEEK);
2791 len_piece = len_str + sizeof(INT16);
2792 if(len_piece % 4)
2793 len_piece = (len_piece + 4) & ~0x3;
2794 if(len_piece < 8)
2795 len_piece = 8;
2797 string = heap_alloc(len_piece + 1);
2798 MSFT_Read(string, len_piece - sizeof(INT16), pcx, DO_NOT_SEEK);
2799 string[len_str] = '\0';
2801 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2802 string, -1, NULL, 0);
2803 if (!lengthInChars) {
2804 heap_free(string);
2805 return E_UNEXPECTED;
2808 tlbstr = heap_alloc(sizeof(TLBString));
2810 tlbstr->offset = offs;
2811 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2812 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2814 heap_free(string);
2816 list_add_tail(&pcx->pLibInfo->string_list, &tlbstr->entry);
2818 offs += len_piece;
2822 static HRESULT MSFT_ReadAllRefs(TLBContext *pcx)
2824 TLBRefType *ref;
2825 int offs = 0;
2827 MSFT_Seek(pcx, pcx->pTblDir->pImpInfo.offset);
2828 while (offs < pcx->pTblDir->pImpInfo.length) {
2829 MSFT_ImpInfo impinfo;
2830 TLBImpLib *pImpLib;
2832 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx, DO_NOT_SEEK);
2834 ref = heap_alloc_zero(sizeof(TLBRefType));
2835 list_add_tail(&pcx->pLibInfo->ref_list, &ref->entry);
2837 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2838 if(pImpLib->offset==impinfo.oImpFile)
2839 break;
2841 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2842 ref->reference = offs;
2843 ref->pImpTLInfo = pImpLib;
2844 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2845 ref->guid = MSFT_ReadGuid(impinfo.oGuid, pcx);
2846 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
2847 ref->index = TLB_REF_USE_GUID;
2848 } else
2849 ref->index = impinfo.oGuid;
2850 }else{
2851 ERR("Cannot find a reference\n");
2852 ref->reference = -1;
2853 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2856 offs += sizeof(impinfo);
2859 return S_OK;
2862 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2863 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2864 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2865 * tradeoff here.
2867 static struct list tlb_cache = LIST_INIT(tlb_cache);
2868 static CRITICAL_SECTION cache_section;
2869 static CRITICAL_SECTION_DEBUG cache_section_debug =
2871 0, 0, &cache_section,
2872 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2873 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2875 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2878 typedef struct TLB_PEFile
2880 IUnknown IUnknown_iface;
2881 LONG refs;
2882 HMODULE dll;
2883 HRSRC typelib_resource;
2884 HGLOBAL typelib_global;
2885 LPVOID typelib_base;
2886 } TLB_PEFile;
2888 static inline TLB_PEFile *pefile_impl_from_IUnknown(IUnknown *iface)
2890 return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2893 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2895 if (IsEqualIID(riid, &IID_IUnknown))
2897 *ppv = iface;
2898 IUnknown_AddRef(iface);
2899 return S_OK;
2901 *ppv = NULL;
2902 return E_NOINTERFACE;
2905 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2907 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2908 return InterlockedIncrement(&This->refs);
2911 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2913 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2914 ULONG refs = InterlockedDecrement(&This->refs);
2915 if (!refs)
2917 if (This->typelib_global)
2918 FreeResource(This->typelib_global);
2919 if (This->dll)
2920 FreeLibrary(This->dll);
2921 heap_free(This);
2923 return refs;
2926 static const IUnknownVtbl TLB_PEFile_Vtable =
2928 TLB_PEFile_QueryInterface,
2929 TLB_PEFile_AddRef,
2930 TLB_PEFile_Release
2933 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2935 TLB_PEFile *This;
2936 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2938 This = heap_alloc(sizeof(TLB_PEFile));
2939 if (!This)
2940 return E_OUTOFMEMORY;
2942 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
2943 This->refs = 1;
2944 This->dll = NULL;
2945 This->typelib_resource = NULL;
2946 This->typelib_global = NULL;
2947 This->typelib_base = NULL;
2949 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2950 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2952 if (This->dll)
2954 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2955 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2956 if (This->typelib_resource)
2958 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2959 if (This->typelib_global)
2961 This->typelib_base = LockResource(This->typelib_global);
2963 if (This->typelib_base)
2965 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2966 *ppBase = This->typelib_base;
2967 *ppFile = &This->IUnknown_iface;
2968 return S_OK;
2973 TRACE("No TYPELIB resource found\n");
2974 hr = E_FAIL;
2977 TLB_PEFile_Release(&This->IUnknown_iface);
2978 return hr;
2981 typedef struct TLB_NEFile
2983 IUnknown IUnknown_iface;
2984 LONG refs;
2985 LPVOID typelib_base;
2986 } TLB_NEFile;
2988 static inline TLB_NEFile *nefile_impl_from_IUnknown(IUnknown *iface)
2990 return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
2993 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2995 if (IsEqualIID(riid, &IID_IUnknown))
2997 *ppv = iface;
2998 IUnknown_AddRef(iface);
2999 return S_OK;
3001 *ppv = NULL;
3002 return E_NOINTERFACE;
3005 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
3007 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
3008 return InterlockedIncrement(&This->refs);
3011 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
3013 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
3014 ULONG refs = InterlockedDecrement(&This->refs);
3015 if (!refs)
3017 heap_free(This->typelib_base);
3018 heap_free(This);
3020 return refs;
3023 static const IUnknownVtbl TLB_NEFile_Vtable =
3025 TLB_NEFile_QueryInterface,
3026 TLB_NEFile_AddRef,
3027 TLB_NEFile_Release
3030 /***********************************************************************
3031 * read_xx_header [internal]
3033 static int read_xx_header( HFILE lzfd )
3035 IMAGE_DOS_HEADER mzh;
3036 char magic[3];
3038 LZSeek( lzfd, 0, SEEK_SET );
3039 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
3040 return 0;
3041 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
3042 return 0;
3044 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3045 if ( 2 != LZRead( lzfd, magic, 2 ) )
3046 return 0;
3048 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3050 if ( magic[0] == 'N' && magic[1] == 'E' )
3051 return IMAGE_OS2_SIGNATURE;
3052 if ( magic[0] == 'P' && magic[1] == 'E' )
3053 return IMAGE_NT_SIGNATURE;
3055 magic[2] = '\0';
3056 WARN("Can't handle %s files.\n", magic );
3057 return 0;
3061 /***********************************************************************
3062 * find_ne_resource [internal]
3064 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
3065 DWORD *resLen, DWORD *resOff )
3067 IMAGE_OS2_HEADER nehd;
3068 NE_TYPEINFO *typeInfo;
3069 NE_NAMEINFO *nameInfo;
3070 DWORD nehdoffset;
3071 LPBYTE resTab;
3072 DWORD resTabSize;
3073 int count;
3075 /* Read in NE header */
3076 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
3077 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return FALSE;
3079 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
3080 if ( !resTabSize )
3082 TRACE("No resources in NE dll\n" );
3083 return FALSE;
3086 /* Read in resource table */
3087 resTab = heap_alloc( resTabSize );
3088 if ( !resTab ) return FALSE;
3090 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
3091 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
3093 heap_free( resTab );
3094 return FALSE;
3097 /* Find resource */
3098 typeInfo = (NE_TYPEINFO *)(resTab + 2);
3100 if (!IS_INTRESOURCE(typeid)) /* named type */
3102 BYTE len = strlen( typeid );
3103 while (typeInfo->type_id)
3105 if (!(typeInfo->type_id & 0x8000))
3107 BYTE *p = resTab + typeInfo->type_id;
3108 if ((*p == len) && !_strnicmp( (char*)p+1, typeid, len )) goto found_type;
3110 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3111 typeInfo->count * sizeof(NE_NAMEINFO));
3114 else /* numeric type id */
3116 WORD id = LOWORD(typeid) | 0x8000;
3117 while (typeInfo->type_id)
3119 if (typeInfo->type_id == id) goto found_type;
3120 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3121 typeInfo->count * sizeof(NE_NAMEINFO));
3124 TRACE("No typeid entry found for %p\n", typeid );
3125 heap_free( resTab );
3126 return FALSE;
3128 found_type:
3129 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
3131 if (!IS_INTRESOURCE(resid)) /* named resource */
3133 BYTE len = strlen( resid );
3134 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3136 BYTE *p = resTab + nameInfo->id;
3137 if (nameInfo->id & 0x8000) continue;
3138 if ((*p == len) && !_strnicmp( (char*)p+1, resid, len )) goto found_name;
3141 else /* numeric resource id */
3143 WORD id = LOWORD(resid) | 0x8000;
3144 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3145 if (nameInfo->id == id) goto found_name;
3147 TRACE("No resid entry found for %p\n", typeid );
3148 heap_free( resTab );
3149 return FALSE;
3151 found_name:
3152 /* Return resource data */
3153 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
3154 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
3156 heap_free( resTab );
3157 return TRUE;
3160 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
3162 HFILE lzfd = -1;
3163 OFSTRUCT ofs;
3164 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
3165 TLB_NEFile *This;
3167 This = heap_alloc(sizeof(TLB_NEFile));
3168 if (!This) return E_OUTOFMEMORY;
3170 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
3171 This->refs = 1;
3172 This->typelib_base = NULL;
3174 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
3175 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
3177 DWORD reslen, offset;
3178 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
3180 This->typelib_base = heap_alloc(reslen);
3181 if( !This->typelib_base )
3182 hr = E_OUTOFMEMORY;
3183 else
3185 LZSeek( lzfd, offset, SEEK_SET );
3186 reslen = LZRead( lzfd, This->typelib_base, reslen );
3187 LZClose( lzfd );
3188 *ppBase = This->typelib_base;
3189 *pdwTLBLength = reslen;
3190 *ppFile = &This->IUnknown_iface;
3191 return S_OK;
3196 if( lzfd >= 0) LZClose( lzfd );
3197 TLB_NEFile_Release(&This->IUnknown_iface);
3198 return hr;
3201 typedef struct TLB_Mapping
3203 IUnknown IUnknown_iface;
3204 LONG refs;
3205 HANDLE file;
3206 HANDLE mapping;
3207 LPVOID typelib_base;
3208 } TLB_Mapping;
3210 static inline TLB_Mapping *mapping_impl_from_IUnknown(IUnknown *iface)
3212 return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
3215 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3217 if (IsEqualIID(riid, &IID_IUnknown))
3219 *ppv = iface;
3220 IUnknown_AddRef(iface);
3221 return S_OK;
3223 *ppv = NULL;
3224 return E_NOINTERFACE;
3227 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
3229 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3230 return InterlockedIncrement(&This->refs);
3233 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
3235 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3236 ULONG refs = InterlockedDecrement(&This->refs);
3237 if (!refs)
3239 if (This->typelib_base)
3240 UnmapViewOfFile(This->typelib_base);
3241 if (This->mapping)
3242 CloseHandle(This->mapping);
3243 if (This->file != INVALID_HANDLE_VALUE)
3244 CloseHandle(This->file);
3245 heap_free(This);
3247 return refs;
3250 static const IUnknownVtbl TLB_Mapping_Vtable =
3252 TLB_Mapping_QueryInterface,
3253 TLB_Mapping_AddRef,
3254 TLB_Mapping_Release
3257 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
3259 TLB_Mapping *This;
3261 This = heap_alloc(sizeof(TLB_Mapping));
3262 if (!This)
3263 return E_OUTOFMEMORY;
3265 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
3266 This->refs = 1;
3267 This->file = INVALID_HANDLE_VALUE;
3268 This->mapping = NULL;
3269 This->typelib_base = NULL;
3271 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3272 if (INVALID_HANDLE_VALUE != This->file)
3274 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
3275 if (This->mapping)
3277 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
3278 if(This->typelib_base)
3280 /* retrieve file size */
3281 *pdwTLBLength = GetFileSize(This->file, NULL);
3282 *ppBase = This->typelib_base;
3283 *ppFile = &This->IUnknown_iface;
3284 return S_OK;
3289 IUnknown_Release(&This->IUnknown_iface);
3290 return TYPE_E_CANTLOADLIBRARY;
3293 /****************************************************************************
3294 * TLB_ReadTypeLib
3296 * find the type of the typelib file and map the typelib resource into
3297 * the memory
3300 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3301 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
3303 ITypeLibImpl *entry;
3304 HRESULT ret;
3305 INT index = 1;
3306 LPWSTR index_str, file = (LPWSTR)pszFileName;
3307 LPVOID pBase = NULL;
3308 DWORD dwTLBLength = 0;
3309 IUnknown *pFile = NULL;
3310 HANDLE h;
3312 *ppTypeLib = NULL;
3314 index_str = wcsrchr(pszFileName, '\\');
3315 if(index_str && *++index_str != '\0')
3317 LPWSTR end_ptr;
3318 LONG idx = wcstol(index_str, &end_ptr, 10);
3319 if(*end_ptr == '\0')
3321 int str_len = index_str - pszFileName - 1;
3322 index = idx;
3323 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
3324 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
3325 file[str_len] = 0;
3329 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
3331 if(wcschr(file, '\\'))
3333 lstrcpyW(pszPath, file);
3335 else
3337 int len = GetSystemDirectoryW(pszPath, cchPath);
3338 pszPath[len] = '\\';
3339 memcpy(pszPath + len + 1, file, (lstrlenW(file) + 1) * sizeof(WCHAR));
3343 if(file != pszFileName) heap_free(file);
3345 h = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
3346 if(h != INVALID_HANDLE_VALUE){
3347 GetFinalPathNameByHandleW(h, pszPath, cchPath, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
3348 CloseHandle(h);
3351 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
3353 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3354 EnterCriticalSection(&cache_section);
3355 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
3357 if (!wcsicmp(entry->path, pszPath) && entry->index == index)
3359 TRACE("cache hit\n");
3360 *ppTypeLib = &entry->ITypeLib2_iface;
3361 ITypeLib2_AddRef(*ppTypeLib);
3362 LeaveCriticalSection(&cache_section);
3363 return S_OK;
3366 LeaveCriticalSection(&cache_section);
3368 /* now actually load and parse the typelib */
3370 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3371 if (ret == TYPE_E_CANTLOADLIBRARY)
3372 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3373 if (ret == TYPE_E_CANTLOADLIBRARY)
3374 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
3375 if (SUCCEEDED(ret))
3377 if (dwTLBLength >= 4)
3379 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
3380 if (dwSignature == MSFT_SIGNATURE)
3381 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
3382 else if (dwSignature == SLTG_SIGNATURE)
3383 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
3384 else
3386 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
3387 ret = TYPE_E_CANTLOADLIBRARY;
3390 else
3391 ret = TYPE_E_CANTLOADLIBRARY;
3392 IUnknown_Release(pFile);
3395 if(*ppTypeLib) {
3396 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
3398 TRACE("adding to cache\n");
3399 impl->path = heap_alloc((lstrlenW(pszPath)+1) * sizeof(WCHAR));
3400 lstrcpyW(impl->path, pszPath);
3401 /* We should really canonicalise the path here. */
3402 impl->index = index;
3404 /* FIXME: check if it has added already in the meantime */
3405 EnterCriticalSection(&cache_section);
3406 list_add_head(&tlb_cache, &impl->entry);
3407 LeaveCriticalSection(&cache_section);
3408 ret = S_OK;
3410 else
3412 if(ret != E_FAIL)
3413 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
3415 ret = TYPE_E_CANTLOADLIBRARY;
3419 return ret;
3422 /*================== ITypeLib(2) Methods ===================================*/
3424 static ITypeLibImpl* TypeLibImpl_Constructor(void)
3426 ITypeLibImpl* pTypeLibImpl;
3428 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
3429 if (!pTypeLibImpl) return NULL;
3431 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3432 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3433 pTypeLibImpl->ICreateTypeLib2_iface.lpVtbl = &CreateTypeLib2Vtbl;
3434 pTypeLibImpl->ref = 1;
3436 list_init(&pTypeLibImpl->implib_list);
3437 list_init(&pTypeLibImpl->custdata_list);
3438 list_init(&pTypeLibImpl->name_list);
3439 list_init(&pTypeLibImpl->string_list);
3440 list_init(&pTypeLibImpl->guid_list);
3441 list_init(&pTypeLibImpl->ref_list);
3442 pTypeLibImpl->dispatch_href = -1;
3444 return pTypeLibImpl;
3447 /****************************************************************************
3448 * ITypeLib2_Constructor_MSFT
3450 * loading an MSFT typelib from an in-memory image
3452 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3454 TLBContext cx;
3455 LONG lPSegDir;
3456 MSFT_Header tlbHeader;
3457 MSFT_SegDir tlbSegDir;
3458 ITypeLibImpl * pTypeLibImpl;
3459 int i;
3461 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3463 pTypeLibImpl = TypeLibImpl_Constructor();
3464 if (!pTypeLibImpl) return NULL;
3466 /* get pointer to beginning of typelib data */
3467 cx.pos = 0;
3468 cx.oStart=0;
3469 cx.mapping = pLib;
3470 cx.pLibInfo = pTypeLibImpl;
3471 cx.length = dwTLBLength;
3473 /* read header */
3474 MSFT_ReadLEDWords(&tlbHeader, sizeof(tlbHeader), &cx, 0);
3475 TRACE_(typelib)("header:\n");
3476 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3477 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3478 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3479 return NULL;
3481 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3483 /* there is a small amount of information here until the next important
3484 * part:
3485 * the segment directory . Try to calculate the amount of data */
3486 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3488 /* now read the segment directory */
3489 TRACE("read segment directory (at %d)\n",lPSegDir);
3490 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3491 cx.pTblDir = &tlbSegDir;
3493 /* just check two entries */
3494 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3496 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3497 heap_free(pTypeLibImpl);
3498 return NULL;
3501 MSFT_ReadAllNames(&cx);
3502 MSFT_ReadAllStrings(&cx);
3503 MSFT_ReadAllGuids(&cx);
3505 /* now fill our internal data */
3506 /* TLIBATTR fields */
3507 pTypeLibImpl->guid = MSFT_ReadGuid(tlbHeader.posguid, &cx);
3509 pTypeLibImpl->syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3510 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3511 pTypeLibImpl->ver_major = LOWORD(tlbHeader.version);
3512 pTypeLibImpl->ver_minor = HIWORD(tlbHeader.version);
3513 pTypeLibImpl->libflags = ((WORD) tlbHeader.flags & 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE;
3515 pTypeLibImpl->set_lcid = tlbHeader.lcid2;
3516 pTypeLibImpl->lcid = tlbHeader.lcid;
3518 /* name, eventually add to a hash table */
3519 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3521 /* help info */
3522 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3523 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3525 if( tlbHeader.varflags & HELPDLLFLAG)
3527 int offset;
3528 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3529 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3532 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3534 /* custom data */
3535 if(tlbHeader.CustomDataOffset >= 0)
3537 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3540 /* fill in type descriptions */
3541 if(tlbSegDir.pTypdescTab.length > 0)
3543 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3544 INT16 td[4];
3545 pTypeLibImpl->ctTypeDesc = cTD;
3546 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3547 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3548 for(i=0; i<cTD; )
3550 /* FIXME: add several sanity checks here */
3551 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3552 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3554 /* FIXME: check safearray */
3555 if(td[3] < 0)
3556 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3557 else
3558 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3560 else if(td[0] == VT_CARRAY)
3562 /* array descr table here */
3563 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3565 else if(td[0] == VT_USERDEFINED)
3567 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3569 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3572 /* second time around to fill the array subscript info */
3573 for(i=0;i<cTD;i++)
3575 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3576 if(tlbSegDir.pArrayDescriptions.offset>0)
3578 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3579 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3581 if(td[1]<0)
3582 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3583 else
3584 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3586 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3588 for(j = 0; j<td[2]; j++)
3590 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3591 sizeof(INT), &cx, DO_NOT_SEEK);
3592 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3593 sizeof(INT), &cx, DO_NOT_SEEK);
3596 else
3598 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3599 ERR("didn't find array description data\n");
3604 /* imported type libs */
3605 if(tlbSegDir.pImpFiles.offset>0)
3607 TLBImpLib *pImpLib;
3608 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3609 UINT16 size;
3611 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3613 char *name;
3615 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3616 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3617 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3619 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3620 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3621 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3622 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3624 size >>= 2;
3625 name = heap_alloc_zero(size+1);
3626 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3627 pImpLib->name = TLB_MultiByteToBSTR(name);
3628 heap_free(name);
3630 pImpLib->guid = MSFT_ReadGuid(oGuid, &cx);
3631 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3633 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3637 MSFT_ReadAllRefs(&cx);
3639 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3641 /* type infos */
3642 if(tlbHeader.nrtypeinfos >= 0 )
3644 ITypeInfoImpl **ppTI;
3646 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3648 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3650 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3652 ++ppTI;
3653 (pTypeLibImpl->TypeInfoCount)++;
3657 #ifdef _WIN64
3658 if(pTypeLibImpl->syskind == SYS_WIN32){
3659 for(i = 0; i < pTypeLibImpl->TypeInfoCount; ++i)
3660 TLB_fix_32on64_typeinfo(pTypeLibImpl->typeinfos[i]);
3662 #endif
3664 TRACE("(%p)\n", pTypeLibImpl);
3665 return &pTypeLibImpl->ITypeLib2_iface;
3669 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3671 char b[3];
3672 int i;
3673 short s;
3675 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3676 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3677 return FALSE;
3680 guid->Data4[0] = s >> 8;
3681 guid->Data4[1] = s & 0xff;
3683 b[2] = '\0';
3684 for(i = 0; i < 6; i++) {
3685 memcpy(b, str + 24 + 2 * i, 2);
3686 guid->Data4[i + 2] = strtol(b, NULL, 16);
3688 return TRUE;
3691 static WORD SLTG_ReadString(const char *ptr, const TLBString **pStr, ITypeLibImpl *lib)
3693 WORD bytelen;
3694 DWORD len;
3695 BSTR tmp_str;
3697 *pStr = NULL;
3698 bytelen = *(const WORD*)ptr;
3699 if(bytelen == 0xffff) return 2;
3701 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3702 tmp_str = SysAllocStringLen(NULL, len);
3703 if (tmp_str) {
3704 MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, tmp_str, len);
3705 *pStr = TLB_append_str(&lib->string_list, tmp_str);
3706 SysFreeString(tmp_str);
3708 return bytelen + 2;
3711 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3713 WORD bytelen;
3715 *str = NULL;
3716 bytelen = *(const WORD*)ptr;
3717 if(bytelen == 0xffff) return 2;
3718 *str = heap_alloc(bytelen + 1);
3719 memcpy(*str, ptr + 2, bytelen);
3720 (*str)[bytelen] = '\0';
3721 return bytelen + 2;
3724 static TLBString *SLTG_ReadName(const char *pNameTable, int offset, ITypeLibImpl *lib)
3726 BSTR tmp_str;
3727 TLBString *tlbstr;
3729 LIST_FOR_EACH_ENTRY(tlbstr, &lib->name_list, TLBString, entry) {
3730 if (tlbstr->offset == offset)
3731 return tlbstr;
3734 tmp_str = TLB_MultiByteToBSTR(pNameTable + offset);
3735 tlbstr = TLB_append_str(&lib->name_list, tmp_str);
3736 SysFreeString(tmp_str);
3738 return tlbstr;
3741 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3743 char *ptr = pLibBlk;
3744 WORD w;
3746 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3747 FIXME("libblk magic = %04x\n", w);
3748 return 0;
3751 ptr += 6;
3752 if((w = *(WORD*)ptr) != 0xffff) {
3753 FIXME("LibBlk.res06 = %04x. Assuming string and skipping\n", w);
3754 ptr += w;
3756 ptr += 2;
3758 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString, pTypeLibImpl);
3760 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile, pTypeLibImpl);
3762 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3763 ptr += 4;
3765 pTypeLibImpl->syskind = *(WORD*)ptr;
3766 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3767 ptr += 2;
3769 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3770 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3771 else
3772 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = 0;
3773 ptr += 2;
3775 ptr += 4; /* skip res12 */
3777 pTypeLibImpl->libflags = *(WORD*)ptr;
3778 ptr += 2;
3780 pTypeLibImpl->ver_major = *(WORD*)ptr;
3781 ptr += 2;
3783 pTypeLibImpl->ver_minor = *(WORD*)ptr;
3784 ptr += 2;
3786 pTypeLibImpl->guid = TLB_append_guid(&pTypeLibImpl->guid_list, (GUID*)ptr, -2);
3787 ptr += sizeof(GUID);
3789 return ptr - (char*)pLibBlk;
3792 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3793 typedef struct
3795 unsigned int num;
3796 HREFTYPE refs[1];
3797 } sltg_ref_lookup_t;
3799 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3800 HREFTYPE *typelib_ref)
3802 if(table && typeinfo_ref < table->num)
3804 *typelib_ref = table->refs[typeinfo_ref];
3805 return S_OK;
3808 ERR_(typelib)("Unable to find reference\n");
3809 *typelib_ref = -1;
3810 return E_FAIL;
3813 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3815 BOOL done = FALSE;
3817 while(!done) {
3818 if((*pType & 0xe00) == 0xe00) {
3819 pTD->vt = VT_PTR;
3820 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3821 pTD = pTD->u.lptdesc;
3823 switch(*pType & 0x3f) {
3824 case VT_PTR:
3825 pTD->vt = VT_PTR;
3826 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3827 pTD = pTD->u.lptdesc;
3828 break;
3830 case VT_USERDEFINED:
3831 pTD->vt = VT_USERDEFINED;
3832 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3833 done = TRUE;
3834 break;
3836 case VT_CARRAY:
3838 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3839 array */
3841 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3843 pTD->vt = VT_CARRAY;
3844 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3845 pTD->u.lpadesc->cDims = pSA->cDims;
3846 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3847 pSA->cDims * sizeof(SAFEARRAYBOUND));
3849 pTD = &pTD->u.lpadesc->tdescElem;
3850 break;
3853 case VT_SAFEARRAY:
3855 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3856 useful? */
3858 pType++;
3859 pTD->vt = VT_SAFEARRAY;
3860 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3861 pTD = pTD->u.lptdesc;
3862 break;
3864 default:
3865 pTD->vt = *pType & 0x3f;
3866 done = TRUE;
3867 break;
3869 pType++;
3871 return pType;
3874 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3875 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3877 /* Handle [in/out] first */
3878 if((*pType & 0xc000) == 0xc000)
3879 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3880 else if(*pType & 0x8000)
3881 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3882 else if(*pType & 0x4000)
3883 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3884 else
3885 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3887 if(*pType & 0x2000)
3888 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3890 if(*pType & 0x80)
3891 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3893 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3897 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3898 char *pNameTable)
3900 unsigned int ref;
3901 char *name;
3902 TLBRefType *ref_type;
3903 sltg_ref_lookup_t *table;
3904 HREFTYPE typelib_ref;
3906 if(pRef->magic != SLTG_REF_MAGIC) {
3907 FIXME("Ref magic = %x\n", pRef->magic);
3908 return NULL;
3910 name = ( (char*)pRef->names + pRef->number);
3912 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3913 table->num = pRef->number >> 3;
3915 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3917 /* We don't want the first href to be 0 */
3918 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3920 for(ref = 0; ref < pRef->number >> 3; ref++) {
3921 char *refname;
3922 unsigned int lib_offs, type_num;
3924 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3926 name += SLTG_ReadStringA(name, &refname);
3927 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3928 FIXME_(typelib)("Can't sscanf ref\n");
3929 if(lib_offs != 0xffff) {
3930 TLBImpLib *import;
3932 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
3933 if(import->offset == lib_offs)
3934 break;
3936 if(&import->entry == &pTL->implib_list) {
3937 char fname[MAX_PATH+1];
3938 int len;
3939 GUID tmpguid;
3941 import = heap_alloc_zero(sizeof(*import));
3942 import->offset = lib_offs;
3943 TLB_GUIDFromString( pNameTable + lib_offs + 4, &tmpguid);
3944 import->guid = TLB_append_guid(&pTL->guid_list, &tmpguid, 2);
3945 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3946 &import->wVersionMajor,
3947 &import->wVersionMinor,
3948 &import->lcid, fname) != 4) {
3949 FIXME_(typelib)("can't sscanf ref %s\n",
3950 pNameTable + lib_offs + 40);
3952 len = strlen(fname);
3953 if(fname[len-1] != '#')
3954 FIXME("fname = %s\n", fname);
3955 fname[len-1] = '\0';
3956 import->name = TLB_MultiByteToBSTR(fname);
3957 list_add_tail(&pTL->implib_list, &import->entry);
3959 ref_type->pImpTLInfo = import;
3961 /* Store a reference to IDispatch */
3962 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid->guid, &IID_StdOle) && type_num == 4)
3963 pTL->dispatch_href = typelib_ref;
3965 } else { /* internal ref */
3966 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3968 ref_type->reference = typelib_ref;
3969 ref_type->index = type_num;
3971 heap_free(refname);
3972 list_add_tail(&pTL->ref_list, &ref_type->entry);
3974 table->refs[ref] = typelib_ref;
3975 typelib_ref += 4;
3977 if((BYTE)*name != SLTG_REF_MAGIC)
3978 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3979 dump_TLBRefType(pTL);
3980 return table;
3983 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3984 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3986 SLTG_ImplInfo *info;
3987 TLBImplType *pImplType;
3988 /* I don't really get this structure, usually it's 0x16 bytes
3989 long, but iuser.tlb contains some that are 0x18 bytes long.
3990 That's ok because we can use the next ptr to jump to the next
3991 one. But how do we know the length of the last one? The WORD
3992 at offs 0x8 might be the clue. For now I'm just assuming that
3993 the last one is the regular 0x16 bytes. */
3995 info = (SLTG_ImplInfo*)pBlk;
3996 while(1){
3997 pTI->typeattr.cImplTypes++;
3998 if(info->next == 0xffff)
3999 break;
4000 info = (SLTG_ImplInfo*)(pBlk + info->next);
4003 info = (SLTG_ImplInfo*)pBlk;
4004 pTI->impltypes = TLBImplType_Alloc(pTI->typeattr.cImplTypes);
4005 pImplType = pTI->impltypes;
4006 while(1) {
4007 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
4008 pImplType->implflags = info->impltypeflags;
4009 ++pImplType;
4011 if(info->next == 0xffff)
4012 break;
4013 if(OneOnly)
4014 FIXME_(typelib)("Interface inheriting more than one interface\n");
4015 info = (SLTG_ImplInfo*)(pBlk + info->next);
4017 info++; /* see comment at top of function */
4018 return (char*)info;
4021 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
4022 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4024 TLBVarDesc *pVarDesc;
4025 const TLBString *prevName = NULL;
4026 SLTG_Variable *pItem;
4027 unsigned short i;
4028 WORD *pType;
4030 pVarDesc = pTI->vardescs = TLBVarDesc_Alloc(cVars);
4032 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
4033 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
4035 pVarDesc->vardesc.memid = pItem->memid;
4037 if (pItem->magic != SLTG_VAR_MAGIC &&
4038 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
4039 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
4040 return;
4043 if (pItem->name == 0xfffe)
4044 pVarDesc->Name = prevName;
4045 else
4046 pVarDesc->Name = SLTG_ReadName(pNameTable, pItem->name, pTI->pTypeLib);
4048 TRACE_(typelib)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc->Name)));
4049 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
4050 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
4052 if(pItem->flags & 0x02)
4053 pType = &pItem->type;
4054 else
4055 pType = (WORD*)(pBlk + pItem->type);
4057 if (pItem->flags & ~0xda)
4058 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
4060 SLTG_DoElem(pType, pBlk,
4061 &pVarDesc->vardesc.elemdescVar, ref_lookup);
4063 if (TRACE_ON(typelib)) {
4064 char buf[300];
4065 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
4066 TRACE_(typelib)("elemdescVar: %s\n", buf);
4069 if (pItem->flags & 0x40) {
4070 TRACE_(typelib)("VAR_DISPATCH\n");
4071 pVarDesc->vardesc.varkind = VAR_DISPATCH;
4073 else if (pItem->flags & 0x10) {
4074 TRACE_(typelib)("VAR_CONST\n");
4075 pVarDesc->vardesc.varkind = VAR_CONST;
4076 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
4077 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
4078 if (pItem->flags & 0x08)
4079 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
4080 else {
4081 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
4083 case VT_LPSTR:
4084 case VT_LPWSTR:
4085 case VT_BSTR:
4087 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
4088 BSTR str;
4089 TRACE_(typelib)("len = %u\n", len);
4090 if (len == 0xffff) {
4091 str = NULL;
4092 } else {
4093 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
4094 str = SysAllocStringLen(NULL, alloc_len);
4095 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
4097 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
4098 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
4099 break;
4101 case VT_I2:
4102 case VT_UI2:
4103 case VT_I4:
4104 case VT_UI4:
4105 case VT_INT:
4106 case VT_UINT:
4107 V_INT(pVarDesc->vardesc.u.lpvarValue) =
4108 *(INT*)(pBlk + pItem->byte_offs);
4109 break;
4110 default:
4111 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
4115 else {
4116 TRACE_(typelib)("VAR_PERINSTANCE\n");
4117 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
4118 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
4121 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
4122 pVarDesc->vardesc.wVarFlags = pItem->varflags;
4124 if (pItem->flags & 0x80)
4125 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
4127 prevName = pVarDesc->Name;
4129 pTI->typeattr.cVars = cVars;
4132 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
4133 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4135 SLTG_Function *pFunc;
4136 unsigned short i;
4137 TLBFuncDesc *pFuncDesc;
4139 pTI->funcdescs = TLBFuncDesc_Alloc(cFuncs);
4141 pFuncDesc = pTI->funcdescs;
4142 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
4143 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
4145 int param;
4146 WORD *pType, *pArg;
4148 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
4149 case SLTG_FUNCTION_MAGIC:
4150 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
4151 break;
4152 case SLTG_DISPATCH_FUNCTION_MAGIC:
4153 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
4154 break;
4155 case SLTG_STATIC_FUNCTION_MAGIC:
4156 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
4157 break;
4158 default:
4159 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
4160 continue;
4162 pFuncDesc->Name = SLTG_ReadName(pNameTable, pFunc->name, pTI->pTypeLib);
4164 pFuncDesc->funcdesc.memid = pFunc->dispid;
4165 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
4166 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
4167 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
4168 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
4169 pFuncDesc->funcdesc.oVft = (pFunc->vtblpos & ~1) * sizeof(void *) / pTI->pTypeLib->ptr_size;
4171 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
4172 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
4174 if(pFunc->retnextopt & 0x80)
4175 pType = &pFunc->rettype;
4176 else
4177 pType = (WORD*)(pBlk + pFunc->rettype);
4179 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
4181 pFuncDesc->funcdesc.lprgelemdescParam =
4182 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
4183 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
4185 pArg = (WORD*)(pBlk + pFunc->arg_off);
4187 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
4188 char *paramName = pNameTable + *pArg;
4189 BOOL HaveOffs;
4190 /* If arg type follows then paramName points to the 2nd
4191 letter of the name, else the next WORD is an offset to
4192 the arg type and paramName points to the first letter.
4193 So let's take one char off paramName and see if we're
4194 pointing at an alphanumeric char. However if *pArg is
4195 0xffff or 0xfffe then the param has no name, the former
4196 meaning that the next WORD is the type, the latter
4197 meaning that the next WORD is an offset to the type. */
4199 HaveOffs = FALSE;
4200 if(*pArg == 0xffff)
4201 paramName = NULL;
4202 else if(*pArg == 0xfffe) {
4203 paramName = NULL;
4204 HaveOffs = TRUE;
4206 else if(paramName[-1] && !isalnum(paramName[-1]))
4207 HaveOffs = TRUE;
4209 pArg++;
4211 if(HaveOffs) { /* the next word is an offset to type */
4212 pType = (WORD*)(pBlk + *pArg);
4213 SLTG_DoElem(pType, pBlk,
4214 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4215 pArg++;
4216 } else {
4217 if(paramName)
4218 paramName--;
4219 pArg = SLTG_DoElem(pArg, pBlk,
4220 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4223 /* Are we an optional param ? */
4224 if(pFuncDesc->funcdesc.cParams - param <=
4225 pFuncDesc->funcdesc.cParamsOpt)
4226 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
4228 if(paramName) {
4229 pFuncDesc->pParamDesc[param].Name = SLTG_ReadName(pNameTable,
4230 paramName - pNameTable, pTI->pTypeLib);
4231 } else {
4232 pFuncDesc->pParamDesc[param].Name = pFuncDesc->Name;
4236 pTI->typeattr.cFuncs = cFuncs;
4239 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
4240 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4241 SLTG_TypeInfoTail *pTITail)
4243 char *pFirstItem;
4244 sltg_ref_lookup_t *ref_lookup = NULL;
4246 if(pTIHeader->href_table != 0xffffffff) {
4247 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4248 pNameTable);
4251 pFirstItem = pBlk;
4253 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4254 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
4256 heap_free(ref_lookup);
4260 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
4261 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4262 const SLTG_TypeInfoTail *pTITail)
4264 char *pFirstItem;
4265 sltg_ref_lookup_t *ref_lookup = NULL;
4267 if(pTIHeader->href_table != 0xffffffff) {
4268 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4269 pNameTable);
4272 pFirstItem = pBlk;
4274 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4275 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
4278 if (pTITail->funcs_off != 0xffff)
4279 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4281 heap_free(ref_lookup);
4283 if (TRACE_ON(typelib))
4284 dump_TLBFuncDesc(pTI->funcdescs, pTI->typeattr.cFuncs);
4287 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
4288 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4289 const SLTG_TypeInfoTail *pTITail)
4291 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4294 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
4295 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4296 const SLTG_TypeInfoTail *pTITail)
4298 WORD *pType;
4299 sltg_ref_lookup_t *ref_lookup = NULL;
4301 if (pTITail->simple_alias) {
4302 /* if simple alias, no more processing required */
4303 pTI->tdescAlias = heap_alloc_zero(sizeof(TYPEDESC));
4304 pTI->tdescAlias->vt = pTITail->tdescalias_vt;
4305 return;
4308 if(pTIHeader->href_table != 0xffffffff) {
4309 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4310 pNameTable);
4313 /* otherwise it is an offset to a type */
4314 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
4316 pTI->tdescAlias = heap_alloc(sizeof(TYPEDESC));
4317 SLTG_DoType(pType, pBlk, pTI->tdescAlias, ref_lookup);
4319 heap_free(ref_lookup);
4322 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
4323 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4324 const SLTG_TypeInfoTail *pTITail)
4326 sltg_ref_lookup_t *ref_lookup = NULL;
4327 if (pTIHeader->href_table != 0xffffffff)
4328 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4329 pNameTable);
4331 if (pTITail->vars_off != 0xffff)
4332 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4334 if (pTITail->funcs_off != 0xffff)
4335 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4337 if (pTITail->impls_off != 0xffff)
4338 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
4340 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4341 * of dispinterface functions including the IDispatch ones, so
4342 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4343 pTI->typeattr.cbSizeVft = pTI->typeattr.cFuncs * pTI->pTypeLib->ptr_size;
4345 heap_free(ref_lookup);
4346 if (TRACE_ON(typelib))
4347 dump_TLBFuncDesc(pTI->funcdescs, pTI->typeattr.cFuncs);
4350 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
4351 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4352 const SLTG_TypeInfoTail *pTITail)
4354 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4357 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
4358 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4359 const SLTG_TypeInfoTail *pTITail)
4361 sltg_ref_lookup_t *ref_lookup = NULL;
4362 if (pTIHeader->href_table != 0xffffffff)
4363 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4364 pNameTable);
4366 if (pTITail->vars_off != 0xffff)
4367 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4369 if (pTITail->funcs_off != 0xffff)
4370 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4371 heap_free(ref_lookup);
4372 if (TRACE_ON(typelib))
4373 dump_TypeInfo(pTI);
4376 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4377 manageable copy of it into this */
4378 typedef struct {
4379 WORD small_no;
4380 char *index_name;
4381 char *other_name;
4382 WORD res1a;
4383 WORD name_offs;
4384 WORD more_bytes;
4385 char *extra;
4386 WORD res20;
4387 DWORD helpcontext;
4388 WORD res26;
4389 GUID uuid;
4390 } SLTG_InternalOtherTypeInfo;
4392 /****************************************************************************
4393 * ITypeLib2_Constructor_SLTG
4395 * loading a SLTG typelib from an in-memory image
4397 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
4399 ITypeLibImpl *pTypeLibImpl;
4400 SLTG_Header *pHeader;
4401 SLTG_BlkEntry *pBlkEntry;
4402 SLTG_Magic *pMagic;
4403 SLTG_Index *pIndex;
4404 SLTG_Pad9 *pPad9;
4405 LPVOID pBlk, pFirstBlk;
4406 SLTG_LibBlk *pLibBlk;
4407 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
4408 char *pAfterOTIBlks = NULL;
4409 char *pNameTable, *ptr;
4410 int i;
4411 DWORD len, order;
4412 ITypeInfoImpl **ppTypeInfoImpl;
4414 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
4417 pTypeLibImpl = TypeLibImpl_Constructor();
4418 if (!pTypeLibImpl) return NULL;
4420 pHeader = pLib;
4422 TRACE_(typelib)("header:\n");
4423 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
4424 pHeader->nrOfFileBlks );
4425 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
4426 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
4427 pHeader->SLTG_magic);
4428 return NULL;
4431 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4432 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
4434 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4435 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
4437 /* Next we have a magic block */
4438 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
4440 /* Let's see if we're still in sync */
4441 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
4442 sizeof(SLTG_COMPOBJ_MAGIC))) {
4443 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
4444 return NULL;
4446 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
4447 sizeof(SLTG_DIR_MAGIC))) {
4448 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
4449 return NULL;
4452 pIndex = (SLTG_Index*)(pMagic+1);
4454 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
4456 pFirstBlk = pPad9 + 1;
4458 /* We'll set up a ptr to the main library block, which is the last one. */
4460 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1;
4461 pBlkEntry[order].next != 0;
4462 order = pBlkEntry[order].next - 1) {
4463 pBlk = (char*)pBlk + pBlkEntry[order].len;
4465 pLibBlk = pBlk;
4467 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
4469 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4470 interspersed */
4472 len += 0x40;
4474 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4476 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
4479 ptr = (char*)pLibBlk + len;
4481 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4482 WORD w, extra;
4483 len = 0;
4485 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
4487 w = *(WORD*)(ptr + 2);
4488 if(w != 0xffff) {
4489 len += w;
4490 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
4491 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4492 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4494 w = *(WORD*)(ptr + 4 + len);
4495 if(w != 0xffff) {
4496 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4497 len += w;
4498 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4499 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4500 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4502 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4503 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4504 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4505 if(extra) {
4506 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4507 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4508 len += extra;
4510 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4511 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4512 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4513 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4514 len += sizeof(SLTG_OtherTypeInfo);
4515 ptr += len;
4518 pAfterOTIBlks = ptr;
4520 /* Skip this WORD and get the next DWORD */
4521 len = *(DWORD*)(pAfterOTIBlks + 2);
4523 /* Now add this to pLibBLk look at what we're pointing at and
4524 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4525 dust and we should be pointing at the beginning of the name
4526 table */
4528 pNameTable = (char*)pLibBlk + len;
4530 switch(*(WORD*)pNameTable) {
4531 case 0xffff:
4532 break;
4533 case 0x0200:
4534 pNameTable += 0x20;
4535 break;
4536 default:
4537 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4538 break;
4541 pNameTable += 0x216;
4543 pNameTable += 2;
4545 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4547 pTypeLibImpl->Name = SLTG_ReadName(pNameTable, pLibBlk->name, pTypeLibImpl);
4550 /* Hopefully we now have enough ptrs set up to actually read in
4551 some TypeInfos. It's not clear which order to do them in, so
4552 I'll just follow the links along the BlkEntry chain and read
4553 them in the order in which they are in the file */
4555 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4556 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4558 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4559 pBlkEntry[order].next != 0;
4560 order = pBlkEntry[order].next - 1, i++) {
4562 SLTG_TypeInfoHeader *pTIHeader;
4563 SLTG_TypeInfoTail *pTITail;
4564 SLTG_MemberHeader *pMemHeader;
4566 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4567 FIXME_(typelib)("Index strings don't match\n");
4568 heap_free(pOtherTypeInfoBlks);
4569 return NULL;
4572 pTIHeader = pBlk;
4573 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4574 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4575 heap_free(pOtherTypeInfoBlks);
4576 return NULL;
4578 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4579 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4580 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4582 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4583 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4584 (*ppTypeInfoImpl)->index = i;
4585 (*ppTypeInfoImpl)->Name = SLTG_ReadName(pNameTable, pOtherTypeInfoBlks[i].name_offs, pTypeLibImpl);
4586 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4587 (*ppTypeInfoImpl)->guid = TLB_append_guid(&pTypeLibImpl->guid_list, &pOtherTypeInfoBlks[i].uuid, 2);
4588 (*ppTypeInfoImpl)->typeattr.typekind = pTIHeader->typekind;
4589 (*ppTypeInfoImpl)->typeattr.wMajorVerNum = pTIHeader->major_version;
4590 (*ppTypeInfoImpl)->typeattr.wMinorVerNum = pTIHeader->minor_version;
4591 (*ppTypeInfoImpl)->typeattr.wTypeFlags =
4592 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4594 if((*ppTypeInfoImpl)->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
4595 (*ppTypeInfoImpl)->typeattr.typekind = TKIND_DISPATCH;
4597 if((pTIHeader->typeflags1 & 7) != 2)
4598 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4599 if(pTIHeader->typeflags3 != 2)
4600 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4602 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4603 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl)->Name)),
4604 typekind_desc[pTIHeader->typekind],
4605 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl)->guid)),
4606 (*ppTypeInfoImpl)->typeattr.wTypeFlags);
4608 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4610 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4612 (*ppTypeInfoImpl)->typeattr.cbAlignment = pTITail->cbAlignment;
4613 (*ppTypeInfoImpl)->typeattr.cbSizeInstance = pTITail->cbSizeInstance;
4614 (*ppTypeInfoImpl)->typeattr.cbSizeVft = pTITail->cbSizeVft;
4616 switch(pTIHeader->typekind) {
4617 case TKIND_ENUM:
4618 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4619 pTIHeader, pTITail);
4620 break;
4622 case TKIND_RECORD:
4623 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4624 pTIHeader, pTITail);
4625 break;
4627 case TKIND_INTERFACE:
4628 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4629 pTIHeader, pTITail);
4630 break;
4632 case TKIND_COCLASS:
4633 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4634 pTIHeader, pTITail);
4635 break;
4637 case TKIND_ALIAS:
4638 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4639 pTIHeader, pTITail);
4640 break;
4642 case TKIND_DISPATCH:
4643 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4644 pTIHeader, pTITail);
4645 break;
4647 case TKIND_MODULE:
4648 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4649 pTIHeader, pTITail);
4650 break;
4652 default:
4653 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4654 break;
4658 /* could get cFuncs, cVars and cImplTypes from here
4659 but we've already set those */
4660 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4661 X(06);
4662 X(16);
4663 X(18);
4664 X(1a);
4665 X(1e);
4666 X(24);
4667 X(26);
4668 X(2a);
4669 X(2c);
4670 X(2e);
4671 X(30);
4672 X(32);
4673 X(34);
4674 #undef X
4675 ++ppTypeInfoImpl;
4676 pBlk = (char*)pBlk + pBlkEntry[order].len;
4679 if(i != pTypeLibImpl->TypeInfoCount) {
4680 FIXME("Somehow processed %d TypeInfos\n", i);
4681 heap_free(pOtherTypeInfoBlks);
4682 return NULL;
4685 heap_free(pOtherTypeInfoBlks);
4686 return &pTypeLibImpl->ITypeLib2_iface;
4689 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4691 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4693 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4695 if(IsEqualIID(riid, &IID_IUnknown) ||
4696 IsEqualIID(riid,&IID_ITypeLib)||
4697 IsEqualIID(riid,&IID_ITypeLib2))
4699 *ppv = &This->ITypeLib2_iface;
4701 else if(IsEqualIID(riid, &IID_ICreateTypeLib) ||
4702 IsEqualIID(riid, &IID_ICreateTypeLib2))
4704 *ppv = &This->ICreateTypeLib2_iface;
4706 else
4708 *ppv = NULL;
4709 TRACE("-- Interface: E_NOINTERFACE\n");
4710 return E_NOINTERFACE;
4713 IUnknown_AddRef((IUnknown*)*ppv);
4714 return S_OK;
4717 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4719 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4720 ULONG ref = InterlockedIncrement(&This->ref);
4722 TRACE("(%p) ref=%u\n", This, ref);
4724 return ref;
4727 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4729 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4730 ULONG ref = InterlockedDecrement(&This->ref);
4732 TRACE("(%p) ref=%u\n",This, ref);
4734 if (!ref)
4736 TLBImpLib *pImpLib, *pImpLibNext;
4737 TLBRefType *ref_type, *ref_type_next;
4738 TLBString *tlbstr, *tlbstr_next;
4739 TLBGuid *tlbguid, *tlbguid_next;
4740 int i;
4742 /* remove cache entry */
4743 if(This->path)
4745 TRACE("removing from cache list\n");
4746 EnterCriticalSection(&cache_section);
4747 if(This->entry.next)
4748 list_remove(&This->entry);
4749 LeaveCriticalSection(&cache_section);
4750 heap_free(This->path);
4752 TRACE(" destroying ITypeLib(%p)\n",This);
4754 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->string_list, TLBString, entry) {
4755 list_remove(&tlbstr->entry);
4756 SysFreeString(tlbstr->str);
4757 heap_free(tlbstr);
4760 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->name_list, TLBString, entry) {
4761 list_remove(&tlbstr->entry);
4762 SysFreeString(tlbstr->str);
4763 heap_free(tlbstr);
4766 LIST_FOR_EACH_ENTRY_SAFE(tlbguid, tlbguid_next, &This->guid_list, TLBGuid, entry) {
4767 list_remove(&tlbguid->entry);
4768 heap_free(tlbguid);
4771 TLB_FreeCustData(&This->custdata_list);
4773 for (i = 0; i < This->ctTypeDesc; i++)
4774 if (This->pTypeDesc[i].vt == VT_CARRAY)
4775 heap_free(This->pTypeDesc[i].u.lpadesc);
4777 heap_free(This->pTypeDesc);
4779 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4781 if (pImpLib->pImpTypeLib)
4782 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4783 SysFreeString(pImpLib->name);
4785 list_remove(&pImpLib->entry);
4786 heap_free(pImpLib);
4789 LIST_FOR_EACH_ENTRY_SAFE(ref_type, ref_type_next, &This->ref_list, TLBRefType, entry)
4791 list_remove(&ref_type->entry);
4792 heap_free(ref_type);
4795 for (i = 0; i < This->TypeInfoCount; ++i){
4796 heap_free(This->typeinfos[i]->tdescAlias);
4797 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4799 heap_free(This->typeinfos);
4800 heap_free(This);
4801 return 0;
4804 return ref;
4807 /* ITypeLib::GetTypeInfoCount
4809 * Returns the number of type descriptions in the type library
4811 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4813 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4814 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4815 return This->TypeInfoCount;
4818 /* ITypeLib::GetTypeInfo
4820 * retrieves the specified type description in the library.
4822 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4823 ITypeLib2 *iface,
4824 UINT index,
4825 ITypeInfo **ppTInfo)
4827 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4829 TRACE("%p %u %p\n", This, index, ppTInfo);
4831 if(!ppTInfo)
4832 return E_INVALIDARG;
4834 if(index >= This->TypeInfoCount)
4835 return TYPE_E_ELEMENTNOTFOUND;
4837 *ppTInfo = (ITypeInfo *)&This->typeinfos[index]->ITypeInfo2_iface;
4838 ITypeInfo_AddRef(*ppTInfo);
4840 return S_OK;
4844 /* ITypeLibs::GetTypeInfoType
4846 * Retrieves the type of a type description.
4848 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4849 ITypeLib2 *iface,
4850 UINT index,
4851 TYPEKIND *pTKind)
4853 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4855 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4857 if(!pTKind)
4858 return E_INVALIDARG;
4860 if(index >= This->TypeInfoCount)
4861 return TYPE_E_ELEMENTNOTFOUND;
4863 *pTKind = This->typeinfos[index]->typeattr.typekind;
4865 return S_OK;
4868 /* ITypeLib::GetTypeInfoOfGuid
4870 * Retrieves the type description that corresponds to the specified GUID.
4873 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4874 ITypeLib2 *iface,
4875 REFGUID guid,
4876 ITypeInfo **ppTInfo)
4878 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4879 int i;
4881 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4883 for(i = 0; i < This->TypeInfoCount; ++i){
4884 if(IsEqualIID(TLB_get_guid_null(This->typeinfos[i]->guid), guid)){
4885 *ppTInfo = (ITypeInfo *)&This->typeinfos[i]->ITypeInfo2_iface;
4886 ITypeInfo_AddRef(*ppTInfo);
4887 return S_OK;
4891 return TYPE_E_ELEMENTNOTFOUND;
4894 /* ITypeLib::GetLibAttr
4896 * Retrieves the structure that contains the library's attributes.
4899 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4900 ITypeLib2 *iface,
4901 LPTLIBATTR *attr)
4903 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4905 TRACE("(%p, %p)\n", This, attr);
4907 if (!attr) return E_INVALIDARG;
4909 *attr = heap_alloc(sizeof(**attr));
4910 if (!*attr) return E_OUTOFMEMORY;
4912 (*attr)->guid = *TLB_get_guid_null(This->guid);
4913 (*attr)->lcid = This->set_lcid;
4914 (*attr)->syskind = This->syskind;
4915 (*attr)->wMajorVerNum = This->ver_major;
4916 (*attr)->wMinorVerNum = This->ver_minor;
4917 (*attr)->wLibFlags = This->libflags;
4919 return S_OK;
4922 /* ITypeLib::GetTypeComp
4924 * Enables a client compiler to bind to a library's types, variables,
4925 * constants, and global functions.
4928 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4929 ITypeLib2 *iface,
4930 ITypeComp **ppTComp)
4932 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4934 TRACE("(%p)->(%p)\n",This,ppTComp);
4935 *ppTComp = &This->ITypeComp_iface;
4936 ITypeComp_AddRef(*ppTComp);
4938 return S_OK;
4941 /* ITypeLib::GetDocumentation
4943 * Retrieves the library's documentation string, the complete Help file name
4944 * and path, and the context identifier for the library Help topic in the Help
4945 * file.
4947 * On a successful return all non-null BSTR pointers will have been set,
4948 * possibly to NULL.
4950 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4951 ITypeLib2 *iface,
4952 INT index,
4953 BSTR *pBstrName,
4954 BSTR *pBstrDocString,
4955 DWORD *pdwHelpContext,
4956 BSTR *pBstrHelpFile)
4958 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4959 HRESULT result = E_INVALIDARG;
4960 ITypeInfo *pTInfo;
4962 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4963 This, index,
4964 pBstrName, pBstrDocString,
4965 pdwHelpContext, pBstrHelpFile);
4967 if(index<0)
4969 /* documentation for the typelib */
4970 if(pBstrName)
4972 if (This->Name)
4974 if(!(*pBstrName = SysAllocString(TLB_get_bstr(This->Name))))
4975 goto memerr1;
4977 else
4978 *pBstrName = NULL;
4980 if(pBstrDocString)
4982 if (This->DocString)
4984 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->DocString))))
4985 goto memerr2;
4987 else
4988 *pBstrDocString = NULL;
4990 if(pdwHelpContext)
4992 *pdwHelpContext = This->dwHelpContext;
4994 if(pBstrHelpFile)
4996 if (This->HelpFile)
4998 if(!(*pBstrHelpFile = SysAllocString(TLB_get_bstr(This->HelpFile))))
4999 goto memerr3;
5001 else
5002 *pBstrHelpFile = NULL;
5005 result = S_OK;
5007 else
5009 /* for a typeinfo */
5010 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
5012 if(SUCCEEDED(result))
5014 result = ITypeInfo_GetDocumentation(pTInfo,
5015 MEMBERID_NIL,
5016 pBstrName,
5017 pBstrDocString,
5018 pdwHelpContext, pBstrHelpFile);
5020 ITypeInfo_Release(pTInfo);
5023 return result;
5024 memerr3:
5025 if (pBstrDocString) SysFreeString (*pBstrDocString);
5026 memerr2:
5027 if (pBstrName) SysFreeString (*pBstrName);
5028 memerr1:
5029 return STG_E_INSUFFICIENTMEMORY;
5032 /* ITypeLib::IsName
5034 * Indicates whether a passed-in string contains the name of a type or member
5035 * described in the library.
5038 static HRESULT WINAPI ITypeLib2_fnIsName(
5039 ITypeLib2 *iface,
5040 LPOLESTR szNameBuf,
5041 ULONG lHashVal,
5042 BOOL *pfName)
5044 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5045 int tic;
5046 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
5048 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
5049 pfName);
5051 *pfName=TRUE;
5052 for(tic = 0; tic < This->TypeInfoCount; ++tic){
5053 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5054 if(!TLB_str_memcmp(szNameBuf, pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5055 for(fdc = 0; fdc < pTInfo->typeattr.cFuncs; ++fdc) {
5056 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
5057 int pc;
5058 if(!TLB_str_memcmp(szNameBuf, pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5059 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++){
5060 if(!TLB_str_memcmp(szNameBuf, pFInfo->pParamDesc[pc].Name, nNameBufLen))
5061 goto ITypeLib2_fnIsName_exit;
5064 for(vrc = 0; vrc < pTInfo->typeattr.cVars; ++vrc){
5065 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
5066 if(!TLB_str_memcmp(szNameBuf, pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5070 *pfName=FALSE;
5072 ITypeLib2_fnIsName_exit:
5073 TRACE("(%p)slow! search for %s: %sfound!\n", This,
5074 debugstr_w(szNameBuf), *pfName ? "" : "NOT ");
5076 return S_OK;
5079 /* ITypeLib::FindName
5081 * Finds occurrences of a type description in a type library. This may be used
5082 * to quickly verify that a name exists in a type library.
5085 static HRESULT WINAPI ITypeLib2_fnFindName(
5086 ITypeLib2 *iface,
5087 LPOLESTR name,
5088 ULONG hash,
5089 ITypeInfo **ppTInfo,
5090 MEMBERID *memid,
5091 UINT16 *found)
5093 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5094 int tic;
5095 UINT count = 0;
5096 UINT len;
5098 TRACE("(%p)->(%s %u %p %p %p)\n", This, debugstr_w(name), hash, ppTInfo, memid, found);
5100 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
5101 return E_INVALIDARG;
5103 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
5104 for(tic = 0; count < *found && tic < This->TypeInfoCount; ++tic) {
5105 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5106 TLBVarDesc *var;
5107 UINT fdc;
5109 if(!TLB_str_memcmp(name, pTInfo->Name, len)) {
5110 memid[count] = MEMBERID_NIL;
5111 goto ITypeLib2_fnFindName_exit;
5114 for(fdc = 0; fdc < pTInfo->typeattr.cFuncs; ++fdc) {
5115 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
5117 if(!TLB_str_memcmp(name, func->Name, len)) {
5118 memid[count] = func->funcdesc.memid;
5119 goto ITypeLib2_fnFindName_exit;
5123 var = TLB_get_vardesc_by_name(pTInfo, name);
5124 if (var) {
5125 memid[count] = var->vardesc.memid;
5126 goto ITypeLib2_fnFindName_exit;
5129 continue;
5130 ITypeLib2_fnFindName_exit:
5131 ITypeInfo2_AddRef(&pTInfo->ITypeInfo2_iface);
5132 ppTInfo[count] = (ITypeInfo *)&pTInfo->ITypeInfo2_iface;
5133 count++;
5135 TRACE("found %d typeinfos\n", count);
5137 *found = count;
5139 return S_OK;
5142 /* ITypeLib::ReleaseTLibAttr
5144 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5147 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
5148 ITypeLib2 *iface,
5149 TLIBATTR *pTLibAttr)
5151 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5152 TRACE("(%p)->(%p)\n", This, pTLibAttr);
5153 heap_free(pTLibAttr);
5156 /* ITypeLib2::GetCustData
5158 * gets the custom data
5160 static HRESULT WINAPI ITypeLib2_fnGetCustData(
5161 ITypeLib2 * iface,
5162 REFGUID guid,
5163 VARIANT *pVarVal)
5165 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5166 TLBCustData *pCData;
5168 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
5170 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
5171 if(!pCData)
5172 return TYPE_E_ELEMENTNOTFOUND;
5174 VariantInit(pVarVal);
5175 VariantCopy(pVarVal, &pCData->data);
5177 return S_OK;
5180 /* ITypeLib2::GetLibStatistics
5182 * Returns statistics about a type library that are required for efficient
5183 * sizing of hash tables.
5186 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
5187 ITypeLib2 * iface,
5188 ULONG *pcUniqueNames,
5189 ULONG *pcchUniqueNames)
5191 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5193 FIXME("(%p): stub!\n", This);
5195 if(pcUniqueNames) *pcUniqueNames=1;
5196 if(pcchUniqueNames) *pcchUniqueNames=1;
5197 return S_OK;
5200 /* ITypeLib2::GetDocumentation2
5202 * Retrieves the library's documentation string, the complete Help file name
5203 * and path, the localization context to use, and the context ID for the
5204 * library Help topic in the Help file.
5207 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
5208 ITypeLib2 * iface,
5209 INT index,
5210 LCID lcid,
5211 BSTR *pbstrHelpString,
5212 DWORD *pdwHelpStringContext,
5213 BSTR *pbstrHelpStringDll)
5215 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5216 HRESULT result;
5217 ITypeInfo *pTInfo;
5219 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
5221 /* the help string should be obtained from the helpstringdll,
5222 * using the _DLLGetDocumentation function, based on the supplied
5223 * lcid. Nice to do sometime...
5225 if(index<0)
5227 /* documentation for the typelib */
5228 if(pbstrHelpString)
5229 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->DocString));
5230 if(pdwHelpStringContext)
5231 *pdwHelpStringContext=This->dwHelpContext;
5232 if(pbstrHelpStringDll)
5233 *pbstrHelpStringDll=SysAllocString(TLB_get_bstr(This->HelpStringDll));
5235 result = S_OK;
5237 else
5239 /* for a typeinfo */
5240 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
5242 if(SUCCEEDED(result))
5244 ITypeInfo2 * pTInfo2;
5245 result = ITypeInfo_QueryInterface(pTInfo,
5246 &IID_ITypeInfo2,
5247 (LPVOID*) &pTInfo2);
5249 if(SUCCEEDED(result))
5251 result = ITypeInfo2_GetDocumentation2(pTInfo2,
5252 MEMBERID_NIL,
5253 lcid,
5254 pbstrHelpString,
5255 pdwHelpStringContext,
5256 pbstrHelpStringDll);
5258 ITypeInfo2_Release(pTInfo2);
5261 ITypeInfo_Release(pTInfo);
5264 return result;
5267 static HRESULT TLB_copy_all_custdata(const struct list *custdata_list, CUSTDATA *pCustData)
5269 TLBCustData *pCData;
5270 unsigned int ct;
5271 CUSTDATAITEM *cdi;
5273 ct = list_count(custdata_list);
5275 pCustData->prgCustData = CoTaskMemAlloc(ct * sizeof(CUSTDATAITEM));
5276 if(!pCustData->prgCustData)
5277 return E_OUTOFMEMORY;
5279 pCustData->cCustData = ct;
5281 cdi = pCustData->prgCustData;
5282 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
5283 cdi->guid = *TLB_get_guid_null(pCData->guid);
5284 VariantCopy(&cdi->varValue, &pCData->data);
5285 ++cdi;
5288 return S_OK;
5292 /* ITypeLib2::GetAllCustData
5294 * Gets all custom data items for the library.
5297 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
5298 ITypeLib2 * iface,
5299 CUSTDATA *pCustData)
5301 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5302 TRACE("(%p)->(%p)\n", This, pCustData);
5303 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
5306 static const ITypeLib2Vtbl tlbvt = {
5307 ITypeLib2_fnQueryInterface,
5308 ITypeLib2_fnAddRef,
5309 ITypeLib2_fnRelease,
5310 ITypeLib2_fnGetTypeInfoCount,
5311 ITypeLib2_fnGetTypeInfo,
5312 ITypeLib2_fnGetTypeInfoType,
5313 ITypeLib2_fnGetTypeInfoOfGuid,
5314 ITypeLib2_fnGetLibAttr,
5315 ITypeLib2_fnGetTypeComp,
5316 ITypeLib2_fnGetDocumentation,
5317 ITypeLib2_fnIsName,
5318 ITypeLib2_fnFindName,
5319 ITypeLib2_fnReleaseTLibAttr,
5321 ITypeLib2_fnGetCustData,
5322 ITypeLib2_fnGetLibStatistics,
5323 ITypeLib2_fnGetDocumentation2,
5324 ITypeLib2_fnGetAllCustData
5328 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5330 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5332 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
5335 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
5337 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5339 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
5342 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
5344 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5346 return ITypeLib2_Release(&This->ITypeLib2_iface);
5349 static HRESULT WINAPI ITypeLibComp_fnBind(
5350 ITypeComp * iface,
5351 OLECHAR * szName,
5352 ULONG lHash,
5353 WORD wFlags,
5354 ITypeInfo ** ppTInfo,
5355 DESCKIND * pDescKind,
5356 BINDPTR * pBindPtr)
5358 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5359 BOOL typemismatch = FALSE;
5360 int i;
5362 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5364 *pDescKind = DESCKIND_NONE;
5365 pBindPtr->lptcomp = NULL;
5366 *ppTInfo = NULL;
5368 for(i = 0; i < This->TypeInfoCount; ++i){
5369 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5370 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo->Name)));
5372 /* FIXME: check wFlags here? */
5373 /* FIXME: we should use a hash table to look this info up using lHash
5374 * instead of an O(n) search */
5375 if ((pTypeInfo->typeattr.typekind == TKIND_ENUM) ||
5376 (pTypeInfo->typeattr.typekind == TKIND_MODULE))
5378 if (pTypeInfo->Name && !wcscmp(pTypeInfo->Name->str, szName))
5380 *pDescKind = DESCKIND_TYPECOMP;
5381 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
5382 ITypeComp_AddRef(pBindPtr->lptcomp);
5383 TRACE("module or enum: %s\n", debugstr_w(szName));
5384 return S_OK;
5388 if ((pTypeInfo->typeattr.typekind == TKIND_MODULE) ||
5389 (pTypeInfo->typeattr.typekind == TKIND_ENUM))
5391 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5392 HRESULT hr;
5394 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5395 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
5397 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
5398 return S_OK;
5400 else if (hr == TYPE_E_TYPEMISMATCH)
5401 typemismatch = TRUE;
5404 if ((pTypeInfo->typeattr.typekind == TKIND_COCLASS) &&
5405 (pTypeInfo->typeattr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
5407 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5408 HRESULT hr;
5409 ITypeInfo *subtypeinfo;
5410 BINDPTR subbindptr;
5411 DESCKIND subdesckind;
5413 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
5414 &subtypeinfo, &subdesckind, &subbindptr);
5415 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
5417 TYPEDESC tdesc_appobject;
5418 const VARDESC vardesc_appobject =
5420 -2, /* memid */
5421 NULL, /* lpstrSchema */
5423 0 /* oInst */
5426 /* ELEMDESC */
5428 /* TYPEDESC */
5430 &tdesc_appobject
5432 VT_PTR
5435 0, /* wVarFlags */
5436 VAR_STATIC /* varkind */
5439 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
5440 tdesc_appobject.vt = VT_USERDEFINED;
5442 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
5444 /* cleanup things filled in by Bind call so we can put our
5445 * application object data in there instead */
5446 switch (subdesckind)
5448 case DESCKIND_FUNCDESC:
5449 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
5450 break;
5451 case DESCKIND_VARDESC:
5452 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
5453 break;
5454 default:
5455 break;
5457 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
5459 if (pTypeInfo->hreftype == -1)
5460 FIXME("no hreftype for interface %p\n", pTypeInfo);
5462 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
5463 if (FAILED(hr))
5464 return hr;
5466 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5467 *ppTInfo = (ITypeInfo *)&pTypeInfo->ITypeInfo2_iface;
5468 ITypeInfo_AddRef(*ppTInfo);
5469 return S_OK;
5471 else if (hr == TYPE_E_TYPEMISMATCH)
5472 typemismatch = TRUE;
5476 if (typemismatch)
5478 TRACE("type mismatch %s\n", debugstr_w(szName));
5479 return TYPE_E_TYPEMISMATCH;
5481 else
5483 TRACE("name not found %s\n", debugstr_w(szName));
5484 return S_OK;
5488 static HRESULT WINAPI ITypeLibComp_fnBindType(
5489 ITypeComp * iface,
5490 OLECHAR * szName,
5491 ULONG lHash,
5492 ITypeInfo ** ppTInfo,
5493 ITypeComp ** ppTComp)
5495 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5496 ITypeInfoImpl *info;
5498 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5500 if(!szName || !ppTInfo || !ppTComp)
5501 return E_INVALIDARG;
5503 info = TLB_get_typeinfo_by_name(This, szName);
5504 if(!info){
5505 *ppTInfo = NULL;
5506 *ppTComp = NULL;
5507 return S_OK;
5510 *ppTInfo = (ITypeInfo *)&info->ITypeInfo2_iface;
5511 ITypeInfo_AddRef(*ppTInfo);
5512 *ppTComp = &info->ITypeComp_iface;
5513 ITypeComp_AddRef(*ppTComp);
5515 return S_OK;
5518 static const ITypeCompVtbl tlbtcvt =
5521 ITypeLibComp_fnQueryInterface,
5522 ITypeLibComp_fnAddRef,
5523 ITypeLibComp_fnRelease,
5525 ITypeLibComp_fnBind,
5526 ITypeLibComp_fnBindType
5529 /*================== ITypeInfo(2) Methods ===================================*/
5530 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5532 ITypeInfoImpl *pTypeInfoImpl;
5534 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5535 if (pTypeInfoImpl)
5537 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5538 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5539 pTypeInfoImpl->ICreateTypeInfo2_iface.lpVtbl = &CreateTypeInfo2Vtbl;
5540 pTypeInfoImpl->ref = 0;
5541 pTypeInfoImpl->hreftype = -1;
5542 pTypeInfoImpl->typeattr.memidConstructor = MEMBERID_NIL;
5543 pTypeInfoImpl->typeattr.memidDestructor = MEMBERID_NIL;
5544 pTypeInfoImpl->pcustdata_list = &pTypeInfoImpl->custdata_list;
5545 list_init(pTypeInfoImpl->pcustdata_list);
5547 TRACE("(%p)\n", pTypeInfoImpl);
5548 return pTypeInfoImpl;
5551 /* ITypeInfo::QueryInterface
5553 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5554 ITypeInfo2 *iface,
5555 REFIID riid,
5556 VOID **ppvObject)
5558 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5560 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5562 *ppvObject=NULL;
5563 if(IsEqualIID(riid, &IID_IUnknown) ||
5564 IsEqualIID(riid,&IID_ITypeInfo)||
5565 IsEqualIID(riid,&IID_ITypeInfo2))
5566 *ppvObject = &This->ITypeInfo2_iface;
5567 else if(IsEqualIID(riid, &IID_ICreateTypeInfo) ||
5568 IsEqualIID(riid, &IID_ICreateTypeInfo2))
5569 *ppvObject = &This->ICreateTypeInfo2_iface;
5570 else if(IsEqualIID(riid, &IID_ITypeComp))
5571 *ppvObject = &This->ITypeComp_iface;
5573 if(*ppvObject){
5574 IUnknown_AddRef((IUnknown*)*ppvObject);
5575 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5576 return S_OK;
5578 TRACE("-- Interface: E_NOINTERFACE\n");
5579 return E_NOINTERFACE;
5582 /* ITypeInfo::AddRef
5584 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5586 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5587 ULONG ref = InterlockedIncrement(&This->ref);
5589 TRACE("(%p)->ref is %u\n",This, ref);
5591 if (ref == 1 /* incremented from 0 */)
5592 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5594 return ref;
5597 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5599 UINT i;
5601 TRACE("destroying ITypeInfo(%p)\n",This);
5603 for (i = 0; i < This->typeattr.cFuncs; ++i)
5605 int j;
5606 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5607 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5609 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5610 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5611 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5612 TLB_FreeCustData(&pFInfo->pParamDesc[j].custdata_list);
5614 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5615 heap_free(pFInfo->pParamDesc);
5616 TLB_FreeCustData(&pFInfo->custdata_list);
5618 heap_free(This->funcdescs);
5620 for(i = 0; i < This->typeattr.cVars; ++i)
5622 TLBVarDesc *pVInfo = &This->vardescs[i];
5623 if (pVInfo->vardesc_create) {
5624 TLB_FreeVarDesc(pVInfo->vardesc_create);
5625 } else if (pVInfo->vardesc.varkind == VAR_CONST) {
5626 VariantClear(pVInfo->vardesc.u.lpvarValue);
5627 heap_free(pVInfo->vardesc.u.lpvarValue);
5629 TLB_FreeCustData(&pVInfo->custdata_list);
5631 heap_free(This->vardescs);
5633 if(This->impltypes){
5634 for (i = 0; i < This->typeattr.cImplTypes; ++i){
5635 TLBImplType *pImpl = &This->impltypes[i];
5636 TLB_FreeCustData(&pImpl->custdata_list);
5638 heap_free(This->impltypes);
5641 TLB_FreeCustData(&This->custdata_list);
5643 heap_free(This);
5646 /* ITypeInfo::Release
5648 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5650 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5651 ULONG ref = InterlockedDecrement(&This->ref);
5653 TRACE("(%p)->(%u)\n",This, ref);
5655 if (!ref)
5657 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5658 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5659 if (not_attached_to_typelib)
5660 heap_free(This);
5661 /* otherwise This will be freed when typelib is freed */
5664 return ref;
5667 /* ITypeInfo::GetTypeAttr
5669 * Retrieves a TYPEATTR structure that contains the attributes of the type
5670 * description.
5673 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5674 LPTYPEATTR *ppTypeAttr)
5676 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5677 SIZE_T size;
5679 TRACE("(%p)\n",This);
5681 size = sizeof(**ppTypeAttr);
5682 if (This->typeattr.typekind == TKIND_ALIAS && This->tdescAlias)
5683 size += TLB_SizeTypeDesc(This->tdescAlias, FALSE);
5685 *ppTypeAttr = heap_alloc(size);
5686 if (!*ppTypeAttr)
5687 return E_OUTOFMEMORY;
5689 **ppTypeAttr = This->typeattr;
5690 (*ppTypeAttr)->guid = *TLB_get_guid_null(This->guid);
5692 if (This->tdescAlias)
5693 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias, This->tdescAlias, *ppTypeAttr + 1);
5695 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5696 /* This should include all the inherited funcs */
5697 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / This->pTypeLib->ptr_size;
5698 /* This is always the size of IDispatch's vtbl */
5699 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5700 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5702 return S_OK;
5705 /* ITypeInfo::GetTypeComp
5707 * Retrieves the ITypeComp interface for the type description, which enables a
5708 * client compiler to bind to the type description's members.
5711 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5712 ITypeComp * *ppTComp)
5714 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5716 TRACE("(%p)->(%p)\n", This, ppTComp);
5718 *ppTComp = &This->ITypeComp_iface;
5719 ITypeComp_AddRef(*ppTComp);
5720 return S_OK;
5723 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5725 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5726 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5727 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5728 return size;
5731 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5733 *dest = *src;
5734 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5735 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5737 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5738 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5739 *buffer += sizeof(PARAMDESCEX);
5740 *pparamdescex_dest = *pparamdescex_src;
5741 pparamdescex_dest->cBytes = sizeof(PARAMDESCEX);
5742 VariantInit(&pparamdescex_dest->varDefaultValue);
5743 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5744 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5746 else
5747 dest->u.paramdesc.pparamdescex = NULL;
5748 return S_OK;
5751 static HRESULT TLB_SanitizeBSTR(BSTR str)
5753 UINT len = SysStringLen(str), i;
5754 for (i = 0; i < len; ++i)
5755 if (str[i] > 0x7f)
5756 str[i] = '?';
5757 return S_OK;
5760 static HRESULT TLB_SanitizeVariant(VARIANT *var)
5762 if (V_VT(var) == VT_INT)
5763 return VariantChangeType(var, var, 0, VT_I4);
5764 else if (V_VT(var) == VT_UINT)
5765 return VariantChangeType(var, var, 0, VT_UI4);
5766 else if (V_VT(var) == VT_BSTR)
5767 return TLB_SanitizeBSTR(V_BSTR(var));
5769 return S_OK;
5772 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5774 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5775 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5778 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5780 FUNCDESC *dest;
5781 char *buffer;
5782 SIZE_T size = sizeof(*src);
5783 SHORT i;
5784 HRESULT hr;
5786 size += sizeof(*src->lprgscode) * src->cScodes;
5787 size += TLB_SizeElemDesc(&src->elemdescFunc);
5788 for (i = 0; i < src->cParams; i++)
5790 size += sizeof(ELEMDESC);
5791 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5794 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5795 if (!dest) return E_OUTOFMEMORY;
5797 *dest = *src;
5798 if (dispinterface) /* overwrite funckind */
5799 dest->funckind = FUNC_DISPATCH;
5800 buffer = (char *)(dest + 1);
5802 dest->oVft = dest->oVft & 0xFFFC;
5804 if (dest->cScodes) {
5805 dest->lprgscode = (SCODE *)buffer;
5806 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5807 buffer += sizeof(*src->lprgscode) * src->cScodes;
5808 } else
5809 dest->lprgscode = NULL;
5811 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5812 if (FAILED(hr))
5814 SysFreeString((BSTR)dest);
5815 return hr;
5818 if (dest->cParams) {
5819 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5820 buffer += sizeof(ELEMDESC) * src->cParams;
5821 for (i = 0; i < src->cParams; i++)
5823 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5824 if (FAILED(hr))
5825 break;
5827 if (FAILED(hr))
5829 /* undo the above actions */
5830 for (i = i - 1; i >= 0; i--)
5831 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5832 TLB_FreeElemDesc(&dest->elemdescFunc);
5833 SysFreeString((BSTR)dest);
5834 return hr;
5836 } else
5837 dest->lprgelemdescParam = NULL;
5839 /* special treatment for dispinterfaces: this makes functions appear
5840 * to return their [retval] value when it is really returning an
5841 * HRESULT */
5842 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5844 if (dest->cParams &&
5845 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5847 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5848 if (elemdesc->tdesc.vt != VT_PTR)
5850 ERR("elemdesc should have started with VT_PTR instead of:\n");
5851 if (ERR_ON(ole))
5852 dump_ELEMDESC(elemdesc);
5853 return E_UNEXPECTED;
5856 /* copy last parameter to the return value. we are using a flat
5857 * buffer so there is no danger of leaking memory in
5858 * elemdescFunc */
5859 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5861 /* remove the last parameter */
5862 dest->cParams--;
5864 else
5865 /* otherwise this function is made to appear to have no return
5866 * value */
5867 dest->elemdescFunc.tdesc.vt = VT_VOID;
5871 *dest_ptr = dest;
5872 return S_OK;
5875 static void TLB_FreeVarDesc(VARDESC *var_desc)
5877 TLB_FreeElemDesc(&var_desc->elemdescVar);
5878 if (var_desc->varkind == VAR_CONST)
5879 VariantClear(var_desc->u.lpvarValue);
5880 SysFreeString((BSTR)var_desc);
5883 /* internal function to make the inherited interfaces' methods appear
5884 * part of the interface */
5885 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5886 UINT index, const TLBFuncDesc **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5888 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5889 HRESULT hr;
5890 UINT implemented_funcs = 0;
5892 if (funcs)
5893 *funcs = 0;
5894 else
5895 *hrefoffset = DISPATCH_HREF_OFFSET;
5897 if(This->impltypes)
5899 ITypeInfo *pSubTypeInfo;
5900 UINT sub_funcs;
5902 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5903 if (FAILED(hr))
5904 return hr;
5906 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5907 index,
5908 ppFuncDesc,
5909 &sub_funcs, hrefoffset);
5910 implemented_funcs += sub_funcs;
5911 ITypeInfo_Release(pSubTypeInfo);
5912 if (SUCCEEDED(hr))
5913 return hr;
5914 *hrefoffset += DISPATCH_HREF_OFFSET;
5917 if (funcs)
5918 *funcs = implemented_funcs + This->typeattr.cFuncs;
5919 else
5920 *hrefoffset = 0;
5922 if (index < implemented_funcs)
5923 return E_INVALIDARG;
5924 index -= implemented_funcs;
5926 if (index >= This->typeattr.cFuncs)
5927 return TYPE_E_ELEMENTNOTFOUND;
5929 *ppFuncDesc = &This->funcdescs[index];
5930 return S_OK;
5933 static HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const TLBFuncDesc **func_desc, UINT *hrefoffset )
5935 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5937 if (This->typeattr.typekind == TKIND_DISPATCH)
5938 return ITypeInfoImpl_GetInternalDispatchFuncDesc(iface, index, func_desc, NULL, hrefoffset);
5940 if (index >= This->typeattr.cFuncs)
5941 return TYPE_E_ELEMENTNOTFOUND;
5943 *func_desc = &This->funcdescs[index];
5944 return S_OK;
5947 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5949 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5950 while (TRUE)
5952 switch (pTypeDesc->vt)
5954 case VT_USERDEFINED:
5955 pTypeDesc->u.hreftype += hrefoffset;
5956 return;
5957 case VT_PTR:
5958 case VT_SAFEARRAY:
5959 pTypeDesc = pTypeDesc->u.lptdesc;
5960 break;
5961 case VT_CARRAY:
5962 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5963 break;
5964 default:
5965 return;
5970 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5972 SHORT i;
5973 for (i = 0; i < pFuncDesc->cParams; i++)
5974 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5975 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5978 /* ITypeInfo::GetFuncDesc
5980 * Retrieves the FUNCDESC structure that contains information about a
5981 * specified function.
5984 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5985 LPFUNCDESC *ppFuncDesc)
5987 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5988 const TLBFuncDesc *internal_funcdesc;
5989 HRESULT hr;
5990 UINT hrefoffset = 0;
5992 TRACE("(%p) index %d\n", This, index);
5994 if (!ppFuncDesc)
5995 return E_INVALIDARG;
5997 if (This->needs_layout)
5998 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6000 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
6001 &internal_funcdesc, &hrefoffset);
6002 if (FAILED(hr))
6004 WARN("description for function %d not found\n", index);
6005 return hr;
6008 hr = TLB_AllocAndInitFuncDesc(
6009 &internal_funcdesc->funcdesc,
6010 ppFuncDesc,
6011 This->typeattr.typekind == TKIND_DISPATCH);
6013 if ((This->typeattr.typekind == TKIND_DISPATCH) && hrefoffset)
6014 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
6016 TRACE("-- 0x%08x\n", hr);
6017 return hr;
6020 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
6022 VARDESC *dest;
6023 char *buffer;
6024 SIZE_T size = sizeof(*src);
6025 HRESULT hr;
6027 if (src->lpstrSchema) size += (lstrlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
6028 if (src->varkind == VAR_CONST)
6029 size += sizeof(VARIANT);
6030 size += TLB_SizeElemDesc(&src->elemdescVar);
6032 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
6033 if (!dest) return E_OUTOFMEMORY;
6035 *dest = *src;
6036 buffer = (char *)(dest + 1);
6037 if (src->lpstrSchema)
6039 int len;
6040 dest->lpstrSchema = (LPOLESTR)buffer;
6041 len = lstrlenW(src->lpstrSchema);
6042 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
6043 buffer += (len + 1) * sizeof(WCHAR);
6046 if (src->varkind == VAR_CONST)
6048 HRESULT hr;
6050 dest->u.lpvarValue = (VARIANT *)buffer;
6051 *dest->u.lpvarValue = *src->u.lpvarValue;
6052 buffer += sizeof(VARIANT);
6053 VariantInit(dest->u.lpvarValue);
6054 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
6055 if (FAILED(hr))
6057 SysFreeString((BSTR)dest);
6058 return hr;
6061 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
6062 if (FAILED(hr))
6064 if (src->varkind == VAR_CONST)
6065 VariantClear(dest->u.lpvarValue);
6066 SysFreeString((BSTR)dest);
6067 return hr;
6069 *dest_ptr = dest;
6070 return S_OK;
6073 /* ITypeInfo::GetVarDesc
6075 * Retrieves a VARDESC structure that describes the specified variable.
6078 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
6079 LPVARDESC *ppVarDesc)
6081 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6082 const TLBVarDesc *pVDesc = &This->vardescs[index];
6084 TRACE("(%p) index %d\n", This, index);
6086 if(index >= This->typeattr.cVars)
6087 return TYPE_E_ELEMENTNOTFOUND;
6089 if (This->needs_layout)
6090 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6092 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
6095 /* ITypeInfo_GetNames
6097 * Retrieves the variable with the specified member ID (or the name of the
6098 * property or method and its parameters) that correspond to the specified
6099 * function ID.
6101 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
6102 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
6104 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6105 const TLBFuncDesc *pFDesc;
6106 const TLBVarDesc *pVDesc;
6107 int i;
6108 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
6110 if(!rgBstrNames)
6111 return E_INVALIDARG;
6113 *pcNames = 0;
6115 pFDesc = TLB_get_funcdesc_by_memberid(This, memid);
6116 if(pFDesc)
6118 if(!cMaxNames || !pFDesc->Name)
6119 return S_OK;
6121 *rgBstrNames = SysAllocString(TLB_get_bstr(pFDesc->Name));
6122 ++(*pcNames);
6124 for(i = 0; i < pFDesc->funcdesc.cParams; ++i){
6125 if(*pcNames >= cMaxNames || !pFDesc->pParamDesc[i].Name)
6126 return S_OK;
6127 rgBstrNames[*pcNames] = SysAllocString(TLB_get_bstr(pFDesc->pParamDesc[i].Name));
6128 ++(*pcNames);
6130 return S_OK;
6133 pVDesc = TLB_get_vardesc_by_memberid(This, memid);
6134 if(pVDesc)
6136 *rgBstrNames=SysAllocString(TLB_get_bstr(pVDesc->Name));
6137 *pcNames=1;
6139 else
6141 if(This->impltypes &&
6142 (This->typeattr.typekind == TKIND_INTERFACE || This->typeattr.typekind == TKIND_DISPATCH)) {
6143 /* recursive search */
6144 ITypeInfo *pTInfo;
6145 HRESULT result;
6146 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6147 if(SUCCEEDED(result))
6149 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
6150 ITypeInfo_Release(pTInfo);
6151 return result;
6153 WARN("Could not search inherited interface!\n");
6155 else
6157 WARN("no names found\n");
6159 *pcNames=0;
6160 return TYPE_E_ELEMENTNOTFOUND;
6162 return S_OK;
6166 /* ITypeInfo::GetRefTypeOfImplType
6168 * If a type description describes a COM class, it retrieves the type
6169 * description of the implemented interface types. For an interface,
6170 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6171 * if any exist.
6174 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
6175 ITypeInfo2 *iface,
6176 UINT index,
6177 HREFTYPE *pRefType)
6179 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6180 HRESULT hr = S_OK;
6182 TRACE("(%p) index %d\n", This, index);
6183 if (TRACE_ON(ole)) dump_TypeInfo(This);
6185 if(index==(UINT)-1)
6187 /* only valid on dual interfaces;
6188 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6191 if (This->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
6193 *pRefType = -2;
6195 else
6197 hr = TYPE_E_ELEMENTNOTFOUND;
6200 else if(index == 0 && This->typeattr.typekind == TKIND_DISPATCH)
6202 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6203 *pRefType = This->pTypeLib->dispatch_href;
6205 else
6207 if(index >= This->typeattr.cImplTypes)
6208 hr = TYPE_E_ELEMENTNOTFOUND;
6209 else{
6210 *pRefType = This->impltypes[index].hRef;
6211 if (This->typeattr.typekind == TKIND_INTERFACE)
6212 *pRefType |= 0x2;
6216 if(TRACE_ON(ole))
6218 if(SUCCEEDED(hr))
6219 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
6220 else
6221 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
6224 return hr;
6227 /* ITypeInfo::GetImplTypeFlags
6229 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6230 * or base interface in a type description.
6232 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
6233 UINT index, INT *pImplTypeFlags)
6235 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6237 TRACE("(%p) index %d\n", This, index);
6239 if(!pImplTypeFlags)
6240 return E_INVALIDARG;
6242 if(This->typeattr.typekind == TKIND_DISPATCH && index == 0){
6243 *pImplTypeFlags = 0;
6244 return S_OK;
6247 if(index >= This->typeattr.cImplTypes)
6248 return TYPE_E_ELEMENTNOTFOUND;
6250 *pImplTypeFlags = This->impltypes[index].implflags;
6252 return S_OK;
6255 /* GetIDsOfNames
6256 * Maps between member names and member IDs, and parameter names and
6257 * parameter IDs.
6259 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
6260 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
6262 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6263 const TLBVarDesc *pVDesc;
6264 HRESULT ret=S_OK;
6265 UINT i, fdc;
6267 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
6268 cNames);
6270 /* init out parameters in case of failure */
6271 for (i = 0; i < cNames; i++)
6272 pMemId[i] = MEMBERID_NIL;
6274 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc) {
6275 int j;
6276 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
6277 if(!lstrcmpiW(*rgszNames, TLB_get_bstr(pFDesc->Name))) {
6278 if(cNames) *pMemId=pFDesc->funcdesc.memid;
6279 for(i=1; i < cNames; i++){
6280 for(j=0; j<pFDesc->funcdesc.cParams; j++)
6281 if(!lstrcmpiW(rgszNames[i],TLB_get_bstr(pFDesc->pParamDesc[j].Name)))
6282 break;
6283 if( j<pFDesc->funcdesc.cParams)
6284 pMemId[i]=j;
6285 else
6286 ret=DISP_E_UNKNOWNNAME;
6288 TRACE("-- 0x%08x\n", ret);
6289 return ret;
6292 pVDesc = TLB_get_vardesc_by_name(This, *rgszNames);
6293 if(pVDesc){
6294 if(cNames)
6295 *pMemId = pVDesc->vardesc.memid;
6296 return ret;
6298 /* not found, see if it can be found in an inherited interface */
6299 if(This->impltypes) {
6300 /* recursive search */
6301 ITypeInfo *pTInfo;
6302 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6303 if(SUCCEEDED(ret)){
6304 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
6305 ITypeInfo_Release(pTInfo);
6306 return ret;
6308 WARN("Could not search inherited interface!\n");
6309 } else
6310 WARN("no names found\n");
6311 return DISP_E_UNKNOWNNAME;
6315 #ifdef __i386__
6317 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6318 extern double call_double_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6319 __ASM_GLOBAL_FUNC( call_method,
6320 "pushl %ebp\n\t"
6321 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6322 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6323 "movl %esp,%ebp\n\t"
6324 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6325 "pushl %esi\n\t"
6326 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6327 "pushl %edi\n\t"
6328 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6329 "movl 12(%ebp),%edx\n\t"
6330 "movl %esp,%edi\n\t"
6331 "shll $2,%edx\n\t"
6332 "jz 1f\n\t"
6333 "subl %edx,%edi\n\t"
6334 "andl $~15,%edi\n\t"
6335 "movl %edi,%esp\n\t"
6336 "movl 12(%ebp),%ecx\n\t"
6337 "movl 16(%ebp),%esi\n\t"
6338 "cld\n\t"
6339 "rep; movsl\n"
6340 "1:\tcall *8(%ebp)\n\t"
6341 "subl %esp,%edi\n\t"
6342 "movl 20(%ebp),%ecx\n\t"
6343 "movl %edi,(%ecx)\n\t"
6344 "leal -8(%ebp),%esp\n\t"
6345 "popl %edi\n\t"
6346 __ASM_CFI(".cfi_same_value %edi\n\t")
6347 "popl %esi\n\t"
6348 __ASM_CFI(".cfi_same_value %esi\n\t")
6349 "popl %ebp\n\t"
6350 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6351 __ASM_CFI(".cfi_same_value %ebp\n\t")
6352 "ret" )
6353 __ASM_GLOBAL_FUNC( call_double_method,
6354 "jmp " __ASM_NAME("call_method") )
6356 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
6357 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
6359 int argspos = 0, stack_offset;
6360 void *func;
6361 UINT i;
6362 DWORD *args;
6364 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6365 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6366 pvargResult, V_VT(pvargResult));
6368 if (cc != CC_STDCALL && cc != CC_CDECL)
6370 FIXME("unsupported calling convention %d\n",cc);
6371 return E_INVALIDARG;
6374 /* maximum size for an argument is sizeof(VARIANT) */
6375 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6377 if (pvInstance)
6379 const FARPROC *vtable = *(FARPROC **)pvInstance;
6380 func = vtable[oVft/sizeof(void *)];
6381 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6383 else func = (void *)oVft;
6385 switch (vtReturn)
6387 case VT_DECIMAL:
6388 case VT_VARIANT:
6389 args[argspos++] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6390 break;
6391 case VT_HRESULT:
6392 WARN("invalid return type %u\n", vtReturn);
6393 heap_free( args );
6394 return E_INVALIDARG;
6395 default:
6396 break;
6399 for (i = 0; i < cActuals; i++)
6401 VARIANT *arg = prgpvarg[i];
6403 switch (prgvt[i])
6405 case VT_EMPTY:
6406 break;
6407 case VT_I8:
6408 case VT_UI8:
6409 case VT_R8:
6410 case VT_DATE:
6411 case VT_CY:
6412 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6413 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6414 break;
6415 case VT_DECIMAL:
6416 case VT_VARIANT:
6417 memcpy( &args[argspos], arg, sizeof(*arg) );
6418 argspos += sizeof(*arg) / sizeof(DWORD);
6419 break;
6420 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6421 args[argspos++] = V_BOOL(arg);
6422 break;
6423 default:
6424 args[argspos++] = V_UI4(arg);
6425 break;
6427 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6430 switch (vtReturn)
6432 case VT_EMPTY:
6433 case VT_DECIMAL:
6434 case VT_VARIANT:
6435 call_method( func, argspos, args, &stack_offset );
6436 break;
6437 case VT_R4:
6438 V_R4(pvargResult) = call_double_method( func, argspos, args, &stack_offset );
6439 break;
6440 case VT_R8:
6441 case VT_DATE:
6442 V_R8(pvargResult) = call_double_method( func, argspos, args, &stack_offset );
6443 break;
6444 case VT_I8:
6445 case VT_UI8:
6446 case VT_CY:
6447 V_UI8(pvargResult) = call_method( func, argspos, args, &stack_offset );
6448 break;
6449 default:
6450 V_UI4(pvargResult) = call_method( func, argspos, args, &stack_offset );
6451 break;
6453 heap_free( args );
6454 if (stack_offset && cc == CC_STDCALL)
6456 WARN( "stack pointer off by %d\n", stack_offset );
6457 return DISP_E_BADCALLEE;
6459 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6460 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6461 return S_OK;
6464 #elif defined(__x86_64__)
6466 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
6467 extern double CDECL call_double_method( void *func, int nb_args, const DWORD_PTR *args );
6468 __ASM_GLOBAL_FUNC( call_method,
6469 "pushq %rbp\n\t"
6470 __ASM_SEH(".seh_pushreg %rbp\n\t")
6471 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6472 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6473 "movq %rsp,%rbp\n\t"
6474 __ASM_SEH(".seh_setframe %rbp,0\n\t")
6475 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6476 "pushq %rsi\n\t"
6477 __ASM_SEH(".seh_pushreg %rsi\n\t")
6478 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6479 "pushq %rdi\n\t"
6480 __ASM_SEH(".seh_pushreg %rdi\n\t")
6481 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6482 __ASM_SEH(".seh_endprologue\n\t")
6483 "movq %rcx,%rax\n\t"
6484 "movq $4,%rcx\n\t"
6485 "cmp %rcx,%rdx\n\t"
6486 "cmovgq %rdx,%rcx\n\t"
6487 "leaq 0(,%rcx,8),%rdx\n\t"
6488 "subq %rdx,%rsp\n\t"
6489 "andq $~15,%rsp\n\t"
6490 "movq %rsp,%rdi\n\t"
6491 "movq %r8,%rsi\n\t"
6492 "rep; movsq\n\t"
6493 "movq 0(%rsp),%rcx\n\t"
6494 "movq 8(%rsp),%rdx\n\t"
6495 "movq 16(%rsp),%r8\n\t"
6496 "movq 24(%rsp),%r9\n\t"
6497 "movq 0(%rsp),%xmm0\n\t"
6498 "movq 8(%rsp),%xmm1\n\t"
6499 "movq 16(%rsp),%xmm2\n\t"
6500 "movq 24(%rsp),%xmm3\n\t"
6501 "callq *%rax\n\t"
6502 "leaq -16(%rbp),%rsp\n\t"
6503 "popq %rdi\n\t"
6504 __ASM_CFI(".cfi_same_value %rdi\n\t")
6505 "popq %rsi\n\t"
6506 __ASM_CFI(".cfi_same_value %rsi\n\t")
6507 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6508 "popq %rbp\n\t"
6509 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6510 __ASM_CFI(".cfi_same_value %rbp\n\t")
6511 "ret")
6512 __ASM_GLOBAL_FUNC( call_double_method,
6513 "jmp " __ASM_NAME("call_method") )
6515 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
6516 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
6518 int argspos = 0;
6519 UINT i;
6520 DWORD_PTR *args;
6521 void *func;
6523 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6524 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6525 pvargResult, V_VT(pvargResult));
6527 if (cc != CC_STDCALL && cc != CC_CDECL)
6529 FIXME("unsupported calling convention %d\n",cc);
6530 return E_INVALIDARG;
6533 /* maximum size for an argument is sizeof(DWORD_PTR) */
6534 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6536 if (pvInstance)
6538 const FARPROC *vtable = *(FARPROC **)pvInstance;
6539 func = vtable[oVft/sizeof(void *)];
6540 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6542 else func = (void *)oVft;
6544 switch (vtReturn)
6546 case VT_DECIMAL:
6547 case VT_VARIANT:
6548 args[argspos++] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6549 break;
6550 case VT_HRESULT:
6551 WARN("invalid return type %u\n", vtReturn);
6552 heap_free( args );
6553 return E_INVALIDARG;
6554 default:
6555 break;
6558 for (i = 0; i < cActuals; i++)
6560 VARIANT *arg = prgpvarg[i];
6562 switch (prgvt[i])
6564 case VT_DECIMAL:
6565 case VT_VARIANT:
6566 args[argspos++] = (ULONG_PTR)arg;
6567 break;
6568 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6569 args[argspos++] = V_BOOL(arg);
6570 break;
6571 default:
6572 args[argspos++] = V_UI8(arg);
6573 break;
6575 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6578 switch (vtReturn)
6580 case VT_R4:
6581 V_R4(pvargResult) = call_double_method( func, argspos, args );
6582 break;
6583 case VT_R8:
6584 case VT_DATE:
6585 V_R8(pvargResult) = call_double_method( func, argspos, args );
6586 break;
6587 case VT_DECIMAL:
6588 case VT_VARIANT:
6589 call_method( func, argspos, args );
6590 break;
6591 default:
6592 V_UI8(pvargResult) = call_method( func, argspos, args );
6593 break;
6595 heap_free( args );
6596 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6597 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6598 return S_OK;
6601 #elif defined(__arm__)
6603 extern LONGLONG CDECL call_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6604 extern float CDECL call_float_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6605 extern double CDECL call_double_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6606 __ASM_GLOBAL_FUNC( call_method,
6607 /* r0 = *func
6608 * r1 = nb_stk_args
6609 * r2 = *stk_args (pointer to 'nb_stk_args' DWORD values to push on stack)
6610 * 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)
6613 "push {fp, lr}\n\t" /* Save frame pointer and return address (stack still aligned to 8 bytes) */
6614 "mov fp, sp\n\t" /* Save stack pointer as our frame for cleaning the stack on return */
6616 "lsls r1, r1, #2\n\t" /* r1 = nb_stk_args * sizeof(DWORD) */
6617 "beq 1f\n\t" /* Skip allocation if no stack args */
6618 "add r2, r2, r1\n" /* Calculate ending address of incoming stack data */
6619 "2:\tldr ip, [r2, #-4]!\n\t" /* Get next value */
6620 "str ip, [sp, #-4]!\n\t" /* Push it on the stack */
6621 "subs r1, r1, #4\n\t" /* Decrement count */
6622 "bgt 2b\n\t" /* Loop till done */
6624 "1:\n\t"
6625 #ifndef __SOFTFP__
6626 "vldm r3!, {s0-s15}\n\t" /* Load the s0-s15/d0-d7 arguments */
6627 #endif
6628 "mov ip, r0\n\t" /* Save the function call address to ip before we nuke r0 with arguments to pass */
6629 "ldm r3, {r0-r3}\n\t" /* Load the r0-r3 arguments */
6631 "blx ip\n\t" /* Call the target function */
6633 "mov sp, fp\n\t" /* Clean the stack using fp */
6634 "pop {fp, pc}\n\t" /* Restore fp and return */
6636 __ASM_GLOBAL_FUNC( call_float_method,
6637 "b " __ASM_NAME("call_method") )
6638 __ASM_GLOBAL_FUNC( call_double_method,
6639 "b " __ASM_NAME("call_method") )
6641 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
6642 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
6644 int argspos;
6645 void *func;
6646 UINT i;
6647 DWORD *args;
6648 struct {
6649 #ifndef __SOFTFP__
6650 union {
6651 float s[16];
6652 double d[8];
6653 } sd;
6654 #endif
6655 DWORD r[4];
6656 } regs;
6657 int rcount; /* 32-bit register index count */
6658 #ifndef __SOFTFP__
6659 int scount = 0; /* single-precision float register index count */
6660 int dcount = 0; /* double-precision float register index count */
6661 #endif
6663 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6664 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6666 if (cc != CC_STDCALL && cc != CC_CDECL)
6668 FIXME("unsupported calling convention %d\n",cc);
6669 return E_INVALIDARG;
6672 argspos = 0;
6673 rcount = 0;
6675 if (pvInstance)
6677 const FARPROC *vtable = *(FARPROC **)pvInstance;
6678 func = vtable[oVft/sizeof(void *)];
6679 regs.r[rcount++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6681 else func = (void *)oVft;
6683 /* Determine if we need to pass a pointer for the return value as arg 0. If so, do that */
6684 /* first as it will need to be in the 'r' registers: */
6685 switch (vtReturn)
6687 case VT_DECIMAL:
6688 case VT_VARIANT:
6689 regs.r[rcount++] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6690 break;
6691 case VT_HRESULT:
6692 WARN("invalid return type %u\n", vtReturn);
6693 return E_INVALIDARG;
6694 default: /* And all others are in 'r', 's', or 'd' registers or have no return value */
6695 break;
6698 /* maximum size for an argument is sizeof(VARIANT). Also allow for return pointer and stack alignment. */
6699 args = heap_alloc( sizeof(VARIANT) * cActuals + sizeof(DWORD) * 4 );
6701 for (i = 0; i < cActuals; i++)
6703 VARIANT *arg = prgpvarg[i];
6704 DWORD *pdwarg = (DWORD *)(arg); /* a reinterpret_cast of the variant, used for copying structures when they are split between registers and stack */
6705 int ntemp; /* Used for counting words split between registers and stack */
6707 switch (prgvt[i])
6709 case VT_EMPTY:
6710 break;
6711 case VT_R8: /* these must be 8-byte aligned, and put in 'd' regs or stack, as they are double-floats */
6712 case VT_DATE:
6713 #ifndef __SOFTFP__
6714 dcount = max( (scount + 1) / 2, dcount );
6715 if (dcount < 8)
6717 regs.sd.d[dcount++] = V_R8(arg);
6719 else
6721 argspos += (argspos % 2); /* align argspos to 8-bytes */
6722 memcpy( &args[argspos], &V_R8(arg), sizeof(V_R8(arg)) );
6723 argspos += sizeof(V_R8(arg)) / sizeof(DWORD);
6725 break;
6726 #endif
6727 case VT_I8: /* these must be 8-byte aligned, and put in 'r' regs or stack, as they are long-longs */
6728 case VT_UI8:
6729 case VT_CY:
6730 if (rcount < 3)
6732 rcount += (rcount % 2); /* align rcount to 8-byte register pair */
6733 memcpy( &regs.r[rcount], &V_UI8(arg), sizeof(V_UI8(arg)) );
6734 rcount += sizeof(V_UI8(arg)) / sizeof(DWORD);
6736 else
6738 rcount = 4; /* Make sure we flag that all 'r' regs are full */
6739 argspos += (argspos % 2); /* align argspos to 8-bytes */
6740 memcpy( &args[argspos], &V_UI8(arg), sizeof(V_UI8(arg)) );
6741 argspos += sizeof(V_UI8(arg)) / sizeof(DWORD);
6743 break;
6744 case VT_DECIMAL: /* these structures are 8-byte aligned, and put in 'r' regs or stack, can be split between the two */
6745 case VT_VARIANT:
6746 /* 8-byte align 'r' and/or stack: */
6747 if (rcount < 3)
6748 rcount += (rcount % 2);
6749 else
6751 rcount = 4;
6752 argspos += (argspos % 2);
6754 ntemp = sizeof(*arg) / sizeof(DWORD);
6755 while (ntemp > 0)
6757 if (rcount < 4)
6758 regs.r[rcount++] = *pdwarg++;
6759 else
6760 args[argspos++] = *pdwarg++;
6761 --ntemp;
6763 break;
6764 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6765 if (rcount < 4)
6766 regs.r[rcount++] = V_BOOL(arg);
6767 else
6768 args[argspos++] = V_BOOL(arg);
6769 break;
6770 case VT_R4: /* these must be 4-byte aligned, and put in 's' regs or stack, as they are single-floats */
6771 #ifndef __SOFTFP__
6772 if (!(scount % 2)) scount = max( scount, dcount * 2 );
6773 if (scount < 16)
6774 regs.sd.s[scount++] = V_R4(arg);
6775 else
6776 args[argspos++] = V_UI4(arg);
6777 break;
6778 #endif
6779 default:
6780 if (rcount < 4)
6781 regs.r[rcount++] = V_UI4(arg);
6782 else
6783 args[argspos++] = V_UI4(arg);
6784 break;
6786 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6789 argspos += (argspos % 2); /* Make sure stack function alignment is 8-byte */
6791 switch (vtReturn)
6793 case VT_EMPTY: /* EMPTY = no return value */
6794 case VT_DECIMAL: /* DECIMAL and VARIANT already have a pointer argument passed (see above) */
6795 case VT_VARIANT:
6796 call_method( func, argspos, args, (DWORD*)&regs );
6797 break;
6798 case VT_R4:
6799 V_R4(pvargResult) = call_float_method( func, argspos, args, (DWORD*)&regs );
6800 break;
6801 case VT_R8:
6802 case VT_DATE:
6803 V_R8(pvargResult) = call_double_method( func, argspos, args, (DWORD*)&regs );
6804 break;
6805 case VT_I8:
6806 case VT_UI8:
6807 case VT_CY:
6808 V_UI8(pvargResult) = call_method( func, argspos, args, (DWORD*)&regs );
6809 break;
6810 default:
6811 V_UI4(pvargResult) = call_method( func, argspos, args, (DWORD*)&regs );
6812 break;
6814 heap_free( args );
6815 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6816 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6817 return S_OK;
6820 #elif defined(__aarch64__)
6822 extern DWORD_PTR CDECL call_method( void *func, int nb_stk_args, const DWORD_PTR *stk_args, const DWORD_PTR *reg_args );
6823 extern float CDECL call_float_method( void *func, int nb_stk_args, const DWORD_PTR *stk_args, const DWORD_PTR *reg_args );
6824 extern double CDECL call_double_method( void *func, int nb_stk_args, const DWORD_PTR *stk_args, const DWORD_PTR *reg_args );
6825 __ASM_GLOBAL_FUNC( call_method,
6826 "stp x29, x30, [sp, #-16]!\n\t"
6827 "mov x29, sp\n\t"
6828 "sub sp, sp, x1, lsl #3\n\t"
6829 "cbz x1, 2f\n"
6830 "1:\tsub x1, x1, #1\n\t"
6831 "ldr x4, [x2, x1, lsl #3]\n\t"
6832 "str x4, [sp, x1, lsl #3]\n\t"
6833 "cbnz x1, 1b\n"
6834 "2:\tmov x16, x0\n\t"
6835 "mov x9, x3\n\t"
6836 "ldp d0, d1, [x9]\n\t"
6837 "ldp d2, d3, [x9, #0x10]\n\t"
6838 "ldp d4, d5, [x9, #0x20]\n\t"
6839 "ldp d6, d7, [x9, #0x30]\n\t"
6840 "ldp x0, x1, [x9, #0x40]\n\t"
6841 "ldp x2, x3, [x9, #0x50]\n\t"
6842 "ldp x4, x5, [x9, #0x60]\n\t"
6843 "ldp x6, x7, [x9, #0x70]\n\t"
6844 "ldr x8, [x9, #0x80]\n\t"
6845 "blr x16\n\t"
6846 "mov sp, x29\n\t"
6847 "ldp x29, x30, [sp], #16\n\t"
6848 "ret" )
6849 __ASM_GLOBAL_FUNC( call_float_method,
6850 "b " __ASM_NAME("call_method") )
6851 __ASM_GLOBAL_FUNC( call_double_method,
6852 "b " __ASM_NAME("call_method") )
6854 HRESULT WINAPI DispCallFunc( void *instance, ULONG_PTR offset, CALLCONV cc, VARTYPE ret_type, UINT count,
6855 VARTYPE *types, VARIANTARG **vargs, VARIANT *result )
6857 int argspos;
6858 void *func;
6859 UINT i;
6860 DWORD_PTR *args;
6861 struct
6863 union
6865 float f;
6866 double d;
6867 } fp[8];
6868 DWORD_PTR x[9];
6869 } regs;
6870 int rcount; /* 64-bit register index count */
6871 int fpcount = 0; /* float register index count */
6873 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6874 instance, offset, cc, ret_type, count, types, vargs, result, V_VT(result));
6876 if (cc != CC_STDCALL && cc != CC_CDECL)
6878 FIXME("unsupported calling convention %d\n",cc);
6879 return E_INVALIDARG;
6882 argspos = 0;
6883 rcount = 0;
6885 if (instance)
6887 const FARPROC *vtable = *(FARPROC **)instance;
6888 func = vtable[offset/sizeof(void *)];
6889 regs.x[rcount++] = (DWORD_PTR)instance; /* the This pointer is always the first parameter */
6891 else func = (void *)offset;
6893 /* maximum size for an argument is 16 */
6894 args = heap_alloc( 16 * count );
6896 for (i = 0; i < count; i++)
6898 VARIANT *arg = vargs[i];
6900 switch (types[i])
6902 case VT_R4:
6903 if (fpcount < 8) regs.fp[fpcount++].f = V_R4(arg);
6904 else *(float *)&args[argspos++] = V_R4(arg);
6905 break;
6906 case VT_R8:
6907 case VT_DATE:
6908 if (fpcount < 8) regs.fp[fpcount++].d = V_R8(arg);
6909 else *(double *)&args[argspos++] = V_R8(arg);
6910 break;
6911 case VT_DECIMAL:
6912 if (rcount < 7)
6914 memcpy( &regs.x[rcount], arg, sizeof(*arg) );
6915 rcount += 2;
6917 else
6919 memcpy( &args[argspos], arg, sizeof(*arg) );
6920 argspos += 2;
6922 break;
6923 case VT_VARIANT:
6924 if (rcount < 8) regs.x[rcount++] = (DWORD_PTR)arg;
6925 else args[argspos++] = (DWORD_PTR)arg;
6926 break;
6927 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6928 if (rcount < 8) regs.x[rcount++] = V_BOOL(arg);
6929 else args[argspos++] = V_BOOL(arg);
6930 break;
6931 default:
6932 if (rcount < 8) regs.x[rcount++] = V_UI8(arg);
6933 else args[argspos++] = V_UI8(arg);
6934 break;
6936 TRACE("arg %u: type %s %s\n", i, debugstr_vt(types[i]), debugstr_variant(arg));
6939 argspos += (argspos % 2); /* Make sure stack function alignment is 16-byte */
6941 switch (ret_type)
6943 case VT_HRESULT:
6944 heap_free( args );
6945 return E_INVALIDARG;
6946 case VT_DECIMAL:
6947 case VT_VARIANT:
6948 regs.x[8] = (DWORD_PTR)result; /* x8 is a pointer to the result */
6949 call_method( func, argspos, args, (DWORD_PTR *)&regs );
6950 break;
6951 case VT_R4:
6952 V_R4(result) = call_float_method( func, argspos, args, (DWORD_PTR *)&regs );
6953 break;
6954 case VT_R8:
6955 case VT_DATE:
6956 V_R8(result) = call_double_method( func, argspos, args, (DWORD_PTR *)&regs );
6957 break;
6958 default:
6959 V_UI8(result) = call_method( func, argspos, args, (DWORD_PTR *)&regs );
6960 break;
6962 heap_free( args );
6963 if (ret_type != VT_VARIANT) V_VT(result) = ret_type;
6964 TRACE("retval: %s\n", debugstr_variant(result));
6965 return S_OK;
6968 #else /* __aarch64__ */
6970 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
6971 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
6973 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6974 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6975 return E_NOTIMPL;
6978 #endif
6980 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6982 HRESULT hr = S_OK;
6983 ITypeInfo *tinfo2 = NULL;
6984 TYPEATTR *tattr = NULL;
6986 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6987 if (hr)
6989 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6990 "hr = 0x%08x\n",
6991 tdesc->u.hreftype, hr);
6992 return hr;
6994 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6995 if (hr)
6997 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
6998 ITypeInfo_Release(tinfo2);
6999 return hr;
7002 switch (tattr->typekind)
7004 case TKIND_ENUM:
7005 *vt |= VT_I4;
7006 break;
7008 case TKIND_ALIAS:
7009 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
7010 break;
7012 case TKIND_INTERFACE:
7013 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
7014 *vt |= VT_DISPATCH;
7015 else
7016 *vt |= VT_UNKNOWN;
7017 break;
7019 case TKIND_DISPATCH:
7020 *vt |= VT_DISPATCH;
7021 break;
7023 case TKIND_COCLASS:
7024 *vt |= VT_DISPATCH;
7025 break;
7027 case TKIND_RECORD:
7028 FIXME("TKIND_RECORD unhandled.\n");
7029 hr = E_NOTIMPL;
7030 break;
7032 case TKIND_UNION:
7033 FIXME("TKIND_UNION unhandled.\n");
7034 hr = E_NOTIMPL;
7035 break;
7037 default:
7038 FIXME("TKIND %d unhandled.\n",tattr->typekind);
7039 hr = E_NOTIMPL;
7040 break;
7042 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
7043 ITypeInfo_Release(tinfo2);
7044 return hr;
7047 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
7049 HRESULT hr = S_OK;
7051 /* enforce only one level of pointer indirection */
7052 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
7054 tdesc = tdesc->u.lptdesc;
7056 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
7057 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
7058 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
7059 if ((tdesc->vt == VT_USERDEFINED) ||
7060 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
7062 VARTYPE vt_userdefined = 0;
7063 const TYPEDESC *tdesc_userdefined = tdesc;
7064 if (tdesc->vt == VT_PTR)
7066 vt_userdefined = VT_BYREF;
7067 tdesc_userdefined = tdesc->u.lptdesc;
7069 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
7070 if ((hr == S_OK) &&
7071 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
7072 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
7074 *vt |= vt_userdefined;
7075 return S_OK;
7078 *vt = VT_BYREF;
7081 switch (tdesc->vt)
7083 case VT_HRESULT:
7084 *vt |= VT_ERROR;
7085 break;
7086 case VT_USERDEFINED:
7087 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
7088 break;
7089 case VT_VOID:
7090 case VT_CARRAY:
7091 case VT_PTR:
7092 case VT_LPSTR:
7093 case VT_LPWSTR:
7094 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
7095 hr = DISP_E_BADVARTYPE;
7096 break;
7097 case VT_SAFEARRAY:
7098 *vt |= VT_ARRAY;
7099 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
7100 break;
7101 case VT_INT:
7102 *vt |= VT_I4;
7103 break;
7104 case VT_UINT:
7105 *vt |= VT_UI4;
7106 break;
7107 default:
7108 *vt |= tdesc->vt;
7109 break;
7111 return hr;
7114 static HRESULT get_iface_guid(ITypeInfo *tinfo, HREFTYPE href, GUID *guid)
7116 ITypeInfo *tinfo2;
7117 TYPEATTR *tattr;
7118 HRESULT hres;
7119 int flags, i;
7121 hres = ITypeInfo_GetRefTypeInfo(tinfo, href, &tinfo2);
7122 if(FAILED(hres))
7123 return hres;
7125 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
7126 if(FAILED(hres)) {
7127 ITypeInfo_Release(tinfo2);
7128 return hres;
7131 switch(tattr->typekind) {
7132 case TKIND_ALIAS:
7133 hres = get_iface_guid(tinfo2, tattr->tdescAlias.u.hreftype, guid);
7134 break;
7136 case TKIND_INTERFACE:
7137 case TKIND_DISPATCH:
7138 *guid = tattr->guid;
7139 break;
7141 case TKIND_COCLASS:
7142 for (i = 0; i < tattr->cImplTypes; i++)
7144 ITypeInfo_GetImplTypeFlags(tinfo2, i, &flags);
7145 if (flags & IMPLTYPEFLAG_FDEFAULT)
7146 break;
7149 if (i == tattr->cImplTypes)
7150 i = 0;
7152 hres = ITypeInfo_GetRefTypeOfImplType(tinfo2, i, &href);
7153 if (SUCCEEDED(hres))
7154 hres = get_iface_guid(tinfo2, href, guid);
7155 break;
7157 default:
7158 ERR("Unexpected typekind %d\n", tattr->typekind);
7159 hres = E_UNEXPECTED;
7162 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
7163 ITypeInfo_Release(tinfo2);
7164 return hres;
7167 static inline BOOL func_restricted( const FUNCDESC *desc )
7169 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
7172 #define INVBUF_ELEMENT_SIZE \
7173 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
7174 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
7175 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
7176 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
7177 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
7178 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
7179 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
7180 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
7182 static HRESULT WINAPI ITypeInfo_fnInvoke(
7183 ITypeInfo2 *iface,
7184 VOID *pIUnk,
7185 MEMBERID memid,
7186 UINT16 wFlags,
7187 DISPPARAMS *pDispParams,
7188 VARIANT *pVarResult,
7189 EXCEPINFO *pExcepInfo,
7190 UINT *pArgErr)
7192 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7193 int i;
7194 unsigned int var_index;
7195 TYPEKIND type_kind;
7196 HRESULT hres;
7197 const TLBFuncDesc *pFuncInfo;
7198 UINT fdc;
7200 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
7201 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
7204 if( This->typeattr.wTypeFlags & TYPEFLAG_FRESTRICTED )
7205 return DISP_E_MEMBERNOTFOUND;
7207 if (!pDispParams)
7209 ERR("NULL pDispParams not allowed\n");
7210 return E_INVALIDARG;
7213 dump_DispParms(pDispParams);
7215 if (pDispParams->cNamedArgs > pDispParams->cArgs)
7217 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
7218 pDispParams->cNamedArgs, pDispParams->cArgs);
7219 return E_INVALIDARG;
7222 /* we do this instead of using GetFuncDesc since it will return a fake
7223 * FUNCDESC for dispinterfaces and we want the real function description */
7224 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
7225 pFuncInfo = &This->funcdescs[fdc];
7226 if ((memid == pFuncInfo->funcdesc.memid) &&
7227 (wFlags & pFuncInfo->funcdesc.invkind) &&
7228 !func_restricted( &pFuncInfo->funcdesc ))
7229 break;
7232 if (fdc < This->typeattr.cFuncs) {
7233 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
7235 if (TRACE_ON(ole))
7237 TRACE("invoking:\n");
7238 dump_TLBFuncDescOne(pFuncInfo);
7241 switch (func_desc->funckind) {
7242 case FUNC_PUREVIRTUAL:
7243 case FUNC_VIRTUAL: {
7244 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
7245 VARIANT varresult;
7246 VARIANT retval; /* pointer for storing byref retvals in */
7247 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
7248 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
7249 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
7250 UINT cNamedArgs = pDispParams->cNamedArgs;
7251 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
7252 UINT vargs_converted=0;
7253 SAFEARRAY *a;
7255 hres = S_OK;
7257 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
7259 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
7261 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
7262 hres = DISP_E_PARAMNOTFOUND;
7263 goto func_fail;
7267 if (func_desc->cParamsOpt < 0 && cNamedArgs)
7269 ERR("functions with the vararg attribute do not support named arguments\n");
7270 hres = DISP_E_NONAMEDARGS;
7271 goto func_fail;
7274 for (i = 0; i < func_desc->cParams; i++)
7276 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7277 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
7278 if (FAILED(hres))
7279 goto func_fail;
7282 TRACE("changing args\n");
7283 for (i = 0; i < func_desc->cParams; i++)
7285 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7286 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7287 VARIANTARG *src_arg;
7289 if (wParamFlags & PARAMFLAG_FLCID)
7291 VARIANTARG *arg;
7292 arg = prgpvarg[i] = &rgvarg[i];
7293 V_VT(arg) = VT_I4;
7294 V_I4(arg) = This->pTypeLib->lcid;
7295 continue;
7298 src_arg = NULL;
7300 if (cNamedArgs)
7302 USHORT j;
7303 for (j = 0; j < cNamedArgs; j++)
7304 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
7306 src_arg = &pDispParams->rgvarg[j];
7307 break;
7311 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
7313 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7314 vargs_converted++;
7317 if (wParamFlags & PARAMFLAG_FRETVAL)
7319 /* under most conditions the caller is not allowed to
7320 * pass in a dispparam arg in the index of what would be
7321 * the retval parameter. however, there is an exception
7322 * where the extra parameter is used in an extra
7323 * IDispatch::Invoke below */
7324 if ((i < pDispParams->cArgs) &&
7325 ((func_desc->cParams != 1) || !pVarResult ||
7326 !(func_desc->invkind & INVOKE_PROPERTYGET)))
7328 hres = DISP_E_BADPARAMCOUNT;
7329 break;
7332 /* note: this check is placed so that if the caller passes
7333 * in a VARIANTARG for the retval we just ignore it, like
7334 * native does */
7335 if (i == func_desc->cParams - 1)
7337 VARIANTARG *arg;
7338 arg = prgpvarg[i] = &rgvarg[i];
7339 memset(arg, 0, sizeof(*arg));
7340 V_VT(arg) = rgvt[i];
7341 memset(&retval, 0, sizeof(retval));
7342 V_BYREF(arg) = &retval;
7344 else
7346 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
7347 hres = E_UNEXPECTED;
7348 break;
7351 else if (src_arg && !((wParamFlags & PARAMFLAG_FOPT) &&
7352 V_VT(src_arg) == VT_ERROR && V_ERROR(src_arg) == DISP_E_PARAMNOTFOUND))
7354 TRACE("%s\n", debugstr_variant(src_arg));
7356 if(rgvt[i]!=V_VT(src_arg))
7358 if (rgvt[i] == VT_VARIANT)
7359 hres = VariantCopy(&rgvarg[i], src_arg);
7360 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
7362 if (rgvt[i] == V_VT(src_arg))
7363 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
7364 else
7366 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7367 if (wParamFlags & PARAMFLAG_FIN)
7368 hres = VariantCopy(&missing_arg[i], src_arg);
7369 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
7371 V_VT(&rgvarg[i]) = rgvt[i];
7373 else if ((rgvt[i] == (VT_VARIANT | VT_ARRAY) || rgvt[i] == (VT_VARIANT | VT_ARRAY | VT_BYREF)) && func_desc->cParamsOpt < 0)
7375 SAFEARRAYBOUND bound;
7376 VARIANT *v;
7377 LONG j;
7378 bound.lLbound = 0;
7379 bound.cElements = pDispParams->cArgs-i;
7380 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
7382 ERR("SafeArrayCreate failed\n");
7383 break;
7385 hres = SafeArrayAccessData(a, (LPVOID)&v);
7386 if (hres != S_OK)
7388 ERR("SafeArrayAccessData failed with %x\n", hres);
7389 SafeArrayDestroy(a);
7390 break;
7392 for (j = 0; j < bound.cElements; j++)
7393 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
7394 hres = SafeArrayUnaccessData(a);
7395 if (hres != S_OK)
7397 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7398 SafeArrayDestroy(a);
7399 break;
7401 if (rgvt[i] & VT_BYREF)
7402 V_BYREF(&rgvarg[i]) = &a;
7403 else
7404 V_ARRAY(&rgvarg[i]) = a;
7405 V_VT(&rgvarg[i]) = rgvt[i];
7407 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
7409 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7410 if (wParamFlags & PARAMFLAG_FIN)
7411 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
7412 else
7413 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
7414 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
7415 V_VT(&rgvarg[i]) = rgvt[i];
7417 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
7419 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
7420 V_VT(&rgvarg[i]) = rgvt[i];
7422 else
7424 /* FIXME: this doesn't work for VT_BYREF arguments if
7425 * they are not the same type as in the paramdesc */
7426 V_VT(&rgvarg[i]) = V_VT(src_arg);
7427 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
7428 V_VT(&rgvarg[i]) = rgvt[i];
7431 if (FAILED(hres))
7433 ERR("failed to convert param %d to %s from %s\n", i,
7434 debugstr_vt(rgvt[i]), debugstr_variant(src_arg));
7435 break;
7437 prgpvarg[i] = &rgvarg[i];
7439 else
7441 prgpvarg[i] = src_arg;
7444 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
7445 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
7446 && V_UNKNOWN(prgpvarg[i])) {
7447 IUnknown *userdefined_iface;
7448 GUID guid;
7450 if (tdesc->vt == VT_PTR)
7451 tdesc = tdesc->u.lptdesc;
7453 hres = get_iface_guid((ITypeInfo*)iface, tdesc->u.hreftype, &guid);
7454 if(FAILED(hres))
7455 break;
7457 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
7458 if(FAILED(hres)) {
7459 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
7460 break;
7463 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
7464 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
7467 else if (wParamFlags & PARAMFLAG_FOPT)
7469 VARIANTARG *arg;
7470 arg = prgpvarg[i] = &rgvarg[i];
7471 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7473 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
7474 if (FAILED(hres))
7475 break;
7477 else
7479 VARIANTARG *missing_arg;
7480 /* if the function wants a pointer to a variant then
7481 * set that up, otherwise just pass the VT_ERROR in
7482 * the argument by value */
7483 if (rgvt[i] & VT_BYREF)
7485 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
7486 V_VT(arg) = VT_VARIANT | VT_BYREF;
7487 V_VARIANTREF(arg) = missing_arg;
7489 else
7490 missing_arg = arg;
7491 V_VT(missing_arg) = VT_ERROR;
7492 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
7495 else
7497 hres = DISP_E_BADPARAMCOUNT;
7498 break;
7501 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7503 /* VT_VOID is a special case for return types, so it is not
7504 * handled in the general function */
7505 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
7506 V_VT(&varresult) = VT_EMPTY;
7507 else
7509 V_VT(&varresult) = 0;
7510 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
7511 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7514 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv,
7515 V_VT(&varresult), func_desc->cParams, rgvt,
7516 prgpvarg, &varresult);
7518 vargs_converted = 0;
7520 for (i = 0; i < func_desc->cParams; i++)
7522 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7523 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7525 if (wParamFlags & PARAMFLAG_FLCID)
7526 continue;
7527 else if (wParamFlags & PARAMFLAG_FRETVAL)
7529 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg[i]));
7531 if (pVarResult)
7533 VariantInit(pVarResult);
7534 /* deref return value */
7535 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
7538 VARIANT_ClearInd(prgpvarg[i]);
7540 else if (vargs_converted < pDispParams->cArgs)
7542 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7543 if (wParamFlags & PARAMFLAG_FOUT)
7545 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
7547 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
7549 if (FAILED(hres))
7551 ERR("failed to convert param %d to vt %d\n", i,
7552 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
7553 break;
7557 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
7558 func_desc->cParamsOpt < 0 &&
7559 i == func_desc->cParams-1)
7561 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
7562 LONG j, ubound;
7563 VARIANT *v;
7564 hres = SafeArrayGetUBound(a, 1, &ubound);
7565 if (hres != S_OK)
7567 ERR("SafeArrayGetUBound failed with %x\n", hres);
7568 break;
7570 hres = SafeArrayAccessData(a, (LPVOID)&v);
7571 if (hres != S_OK)
7573 ERR("SafeArrayAccessData failed with %x\n", hres);
7574 break;
7576 for (j = 0; j <= ubound; j++)
7577 VariantClear(&v[j]);
7578 hres = SafeArrayUnaccessData(a);
7579 if (hres != S_OK)
7581 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7582 break;
7585 VariantClear(&rgvarg[i]);
7586 vargs_converted++;
7588 else if (wParamFlags & PARAMFLAG_FOPT)
7590 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7591 VariantClear(&rgvarg[i]);
7594 VariantClear(&missing_arg[i]);
7597 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
7599 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
7600 hres = DISP_E_EXCEPTION;
7601 if (pExcepInfo)
7603 IErrorInfo *pErrorInfo;
7604 pExcepInfo->scode = V_ERROR(&varresult);
7605 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
7607 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
7608 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
7609 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
7610 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
7612 IErrorInfo_Release(pErrorInfo);
7616 if (V_VT(&varresult) != VT_ERROR)
7618 TRACE("varresult value: %s\n", debugstr_variant(&varresult));
7620 if (pVarResult)
7622 VariantClear(pVarResult);
7623 *pVarResult = varresult;
7625 else
7626 VariantClear(&varresult);
7629 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
7630 (func_desc->invkind & INVOKE_PROPERTYGET) &&
7631 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
7632 (pDispParams->cArgs != 0))
7634 if (V_VT(pVarResult) == VT_DISPATCH)
7636 IDispatch *pDispatch = V_DISPATCH(pVarResult);
7637 /* Note: not VariantClear; we still need the dispatch
7638 * pointer to be valid */
7639 VariantInit(pVarResult);
7640 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
7641 GetSystemDefaultLCID(), wFlags,
7642 pDispParams, pVarResult, pExcepInfo, pArgErr);
7643 IDispatch_Release(pDispatch);
7645 else
7647 VariantClear(pVarResult);
7648 hres = DISP_E_NOTACOLLECTION;
7652 func_fail:
7653 heap_free(buffer);
7654 break;
7656 case FUNC_DISPATCH: {
7657 IDispatch *disp;
7659 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
7660 if (SUCCEEDED(hres)) {
7661 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7662 hres = IDispatch_Invoke(
7663 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
7664 pVarResult,pExcepInfo,pArgErr
7666 if (FAILED(hres))
7667 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
7668 IDispatch_Release(disp);
7669 } else
7670 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7671 break;
7673 default:
7674 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
7675 hres = E_FAIL;
7676 break;
7679 TRACE("-- 0x%08x\n", hres);
7680 return hres;
7682 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
7683 VARDESC *var_desc;
7685 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
7686 if(FAILED(hres)) return hres;
7688 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7689 dump_VARDESC(var_desc);
7690 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
7691 return E_NOTIMPL;
7694 /* not found, look for it in inherited interfaces */
7695 ITypeInfo2_GetTypeKind(iface, &type_kind);
7696 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
7697 if(This->impltypes) {
7698 /* recursive search */
7699 ITypeInfo *pTInfo;
7700 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7701 if(SUCCEEDED(hres)){
7702 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
7703 ITypeInfo_Release(pTInfo);
7704 return hres;
7706 WARN("Could not search inherited interface!\n");
7709 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
7710 return DISP_E_MEMBERNOTFOUND;
7713 /* ITypeInfo::GetDocumentation
7715 * Retrieves the documentation string, the complete Help file name and path,
7716 * and the context ID for the Help topic for a specified type description.
7718 * (Can be tested by the Visual Basic Editor in Word for instance.)
7720 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
7721 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
7722 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
7724 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7725 const TLBFuncDesc *pFDesc;
7726 const TLBVarDesc *pVDesc;
7727 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7728 " HelpContext(%p) HelpFile(%p)\n",
7729 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
7730 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7731 if(pBstrName)
7732 *pBstrName=SysAllocString(TLB_get_bstr(This->Name));
7733 if(pBstrDocString)
7734 *pBstrDocString=SysAllocString(TLB_get_bstr(This->DocString));
7735 if(pdwHelpContext)
7736 *pdwHelpContext=This->dwHelpContext;
7737 if(pBstrHelpFile)
7738 *pBstrHelpFile=SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7739 return S_OK;
7740 }else {/* for a member */
7741 pFDesc = TLB_get_funcdesc_by_memberid(This, memid);
7742 if(pFDesc){
7743 if(pBstrName)
7744 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Name));
7745 if(pBstrDocString)
7746 *pBstrDocString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7747 if(pdwHelpContext)
7748 *pdwHelpContext=pFDesc->helpcontext;
7749 if(pBstrHelpFile)
7750 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7751 return S_OK;
7753 pVDesc = TLB_get_vardesc_by_memberid(This, memid);
7754 if(pVDesc){
7755 if(pBstrName)
7756 *pBstrName = SysAllocString(TLB_get_bstr(pVDesc->Name));
7757 if(pBstrDocString)
7758 *pBstrDocString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7759 if(pdwHelpContext)
7760 *pdwHelpContext=pVDesc->HelpContext;
7761 if(pBstrHelpFile)
7762 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7763 return S_OK;
7767 if(This->impltypes &&
7768 (This->typeattr.typekind == TKIND_INTERFACE || This->typeattr.typekind == TKIND_DISPATCH)) {
7769 /* recursive search */
7770 ITypeInfo *pTInfo;
7771 HRESULT result;
7772 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7773 if(SUCCEEDED(result)) {
7774 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
7775 pBstrDocString, pdwHelpContext, pBstrHelpFile);
7776 ITypeInfo_Release(pTInfo);
7777 return result;
7779 WARN("Could not search inherited interface!\n");
7782 WARN("member %d not found\n", memid);
7783 return TYPE_E_ELEMENTNOTFOUND;
7786 /* ITypeInfo::GetDllEntry
7788 * Retrieves a description or specification of an entry point for a function
7789 * in a DLL.
7791 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
7792 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
7793 WORD *pwOrdinal)
7795 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7796 const TLBFuncDesc *pFDesc;
7798 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
7800 if (pBstrDllName) *pBstrDllName = NULL;
7801 if (pBstrName) *pBstrName = NULL;
7802 if (pwOrdinal) *pwOrdinal = 0;
7804 if (This->typeattr.typekind != TKIND_MODULE)
7805 return TYPE_E_BADMODULEKIND;
7807 pFDesc = TLB_get_funcdesc_by_memberid(This, memid);
7808 if(pFDesc){
7809 dump_TypeInfo(This);
7810 if (TRACE_ON(ole))
7811 dump_TLBFuncDescOne(pFDesc);
7813 if (pBstrDllName)
7814 *pBstrDllName = SysAllocString(TLB_get_bstr(This->DllName));
7816 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
7817 if (pBstrName)
7818 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Entry));
7819 if (pwOrdinal)
7820 *pwOrdinal = -1;
7821 return S_OK;
7823 if (pBstrName)
7824 *pBstrName = NULL;
7825 if (pwOrdinal)
7826 *pwOrdinal = LOWORD(pFDesc->Entry);
7827 return S_OK;
7829 return TYPE_E_ELEMENTNOTFOUND;
7832 /* internal function to make the inherited interfaces' methods appear
7833 * part of the interface */
7834 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7835 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7837 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7838 HRESULT hr;
7840 TRACE("%p, 0x%x\n", iface, *hRefType);
7842 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7844 ITypeInfo *pSubTypeInfo;
7846 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7847 if (FAILED(hr))
7848 return hr;
7850 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7851 hRefType, ppTInfo);
7852 ITypeInfo_Release(pSubTypeInfo);
7853 if (SUCCEEDED(hr))
7854 return hr;
7856 *hRefType -= DISPATCH_HREF_OFFSET;
7858 if (!(*hRefType & DISPATCH_HREF_MASK))
7859 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7860 else
7861 return E_FAIL;
7864 struct search_res_tlb_params
7866 const GUID *guid;
7867 ITypeLib *pTLib;
7870 static BOOL CALLBACK search_res_tlb(HMODULE hModule, LPCWSTR lpszType, LPWSTR lpszName, LONG_PTR lParam)
7872 struct search_res_tlb_params *params = (LPVOID)lParam;
7873 static const WCHAR formatW[] = {'\\','%','d',0};
7874 WCHAR szPath[MAX_PATH+1];
7875 ITypeLib *pTLib = NULL;
7876 HRESULT ret;
7877 DWORD len;
7879 if (IS_INTRESOURCE(lpszName) == FALSE)
7880 return TRUE;
7882 if (!(len = GetModuleFileNameW(hModule, szPath, MAX_PATH)))
7883 return TRUE;
7885 if (swprintf(szPath + len, ARRAY_SIZE(szPath) - len, formatW, LOWORD(lpszName)) < 0)
7886 return TRUE;
7888 ret = LoadTypeLibEx(szPath, REGKIND_NONE, &pTLib);
7889 if (SUCCEEDED(ret))
7891 ITypeLibImpl *impl = impl_from_ITypeLib(pTLib);
7892 if (IsEqualGUID(params->guid, impl->guid))
7894 params->pTLib = pTLib;
7895 return FALSE; /* stop enumeration */
7897 ITypeLib_Release(pTLib);
7900 return TRUE;
7903 /* ITypeInfo::GetRefTypeInfo
7905 * If a type description references other type descriptions, it retrieves
7906 * the referenced type descriptions.
7908 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7909 ITypeInfo2 *iface,
7910 HREFTYPE hRefType,
7911 ITypeInfo **ppTInfo)
7913 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7914 ITypeInfo *type_info = NULL;
7915 HRESULT result = E_FAIL;
7916 TLBRefType *ref_type;
7917 UINT i;
7919 if(!ppTInfo)
7920 return E_INVALIDARG;
7922 if ((INT)hRefType < 0) {
7923 ITypeInfoImpl *pTypeInfoImpl;
7925 if (!(This->typeattr.wTypeFlags & TYPEFLAG_FDUAL) ||
7926 !(This->typeattr.typekind == TKIND_INTERFACE ||
7927 This->typeattr.typekind == TKIND_DISPATCH))
7928 return TYPE_E_ELEMENTNOTFOUND;
7930 /* when we meet a DUAL typeinfo, we must create the alternate
7931 * version of it.
7933 pTypeInfoImpl = ITypeInfoImpl_Constructor();
7935 *pTypeInfoImpl = *This;
7936 pTypeInfoImpl->ref = 0;
7937 list_init(&pTypeInfoImpl->custdata_list);
7939 if (This->typeattr.typekind == TKIND_INTERFACE)
7940 pTypeInfoImpl->typeattr.typekind = TKIND_DISPATCH;
7941 else
7942 pTypeInfoImpl->typeattr.typekind = TKIND_INTERFACE;
7944 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface;
7945 /* the AddRef implicitly adds a reference to the parent typelib, which
7946 * stops the copied data from being destroyed until the new typeinfo's
7947 * refcount goes to zero, but we need to signal to the new instance to
7948 * not free its data structures when it is destroyed */
7949 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7950 ITypeInfo_AddRef(*ppTInfo);
7952 TRACE("got dual interface %p\n", *ppTInfo);
7953 return S_OK;
7956 if ((hRefType & DISPATCH_HREF_MASK) && (This->typeattr.typekind == TKIND_DISPATCH))
7957 return ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &hRefType, ppTInfo);
7959 if(!(hRefType & 0x1))
7961 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
7963 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
7965 result = S_OK;
7966 type_info = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
7967 ITypeInfo_AddRef(type_info);
7968 break;
7973 if (!type_info)
7975 ITypeLib *pTLib = NULL;
7977 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7979 if(ref_type->reference == (hRefType & (~0x3)))
7980 break;
7982 if(&ref_type->entry == &This->pTypeLib->ref_list)
7984 FIXME("Can't find pRefType for ref %x\n", hRefType);
7985 return E_FAIL;
7988 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7989 UINT Index;
7990 TRACE("internal reference\n");
7991 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7992 } else {
7993 if(ref_type->pImpTLInfo->pImpTypeLib) {
7994 TRACE("typeinfo in imported typelib that is already loaded\n");
7995 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
7996 ITypeLib_AddRef(pTLib);
7997 result = S_OK;
7998 } else {
7999 /* Search in cached typelibs */
8000 ITypeLibImpl *entry;
8002 EnterCriticalSection(&cache_section);
8003 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
8005 if (entry->guid
8006 && IsEqualIID(&entry->guid->guid, TLB_get_guid_null(ref_type->pImpTLInfo->guid))
8007 && entry->ver_major == ref_type->pImpTLInfo->wVersionMajor
8008 && entry->ver_minor == ref_type->pImpTLInfo->wVersionMinor
8009 && entry->set_lcid == ref_type->pImpTLInfo->lcid)
8011 TRACE("got cached %p\n", entry);
8012 pTLib = (ITypeLib*)&entry->ITypeLib2_iface;
8013 ITypeLib_AddRef(pTLib);
8014 result = S_OK;
8015 break;
8018 LeaveCriticalSection(&cache_section);
8020 if (!pTLib)
8022 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
8023 struct search_res_tlb_params params;
8025 TRACE("typeinfo in imported typelib that isn't already loaded\n");
8027 /* Search in resource table */
8028 params.guid = TLB_get_guid_null(ref_type->pImpTLInfo->guid);
8029 params.pTLib = NULL;
8030 EnumResourceNamesW(NULL, TYPELIBW, search_res_tlb, (LONG_PTR)&params);
8031 if(params.pTLib)
8033 pTLib = params.pTLib;
8034 result = S_OK;
8038 if (!pTLib)
8040 BSTR libnam;
8042 /* Search on disk */
8043 result = query_typelib_path(TLB_get_guid_null(ref_type->pImpTLInfo->guid),
8044 ref_type->pImpTLInfo->wVersionMajor,
8045 ref_type->pImpTLInfo->wVersionMinor,
8046 This->pTypeLib->syskind,
8047 ref_type->pImpTLInfo->lcid, &libnam, TRUE);
8048 if (FAILED(result))
8049 libnam = SysAllocString(ref_type->pImpTLInfo->name);
8051 result = LoadTypeLib(libnam, &pTLib);
8052 SysFreeString(libnam);
8055 if(SUCCEEDED(result)) {
8056 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
8057 ITypeLib_AddRef(pTLib);
8061 if(SUCCEEDED(result)) {
8062 if(ref_type->index == TLB_REF_USE_GUID)
8063 result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), &type_info);
8064 else
8065 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, &type_info);
8067 if (pTLib != NULL)
8068 ITypeLib_Release(pTLib);
8069 if (FAILED(result))
8071 WARN("(%p) failed hreftype 0x%04x\n", This, hRefType);
8072 return result;
8076 if ((hRefType & 0x2) && SUCCEEDED(ITypeInfo_GetRefTypeInfo(type_info, -2, ppTInfo)))
8077 ITypeInfo_Release(type_info);
8078 else *ppTInfo = type_info;
8080 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
8081 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
8082 return result;
8085 /* ITypeInfo::AddressOfMember
8087 * Retrieves the addresses of static functions or variables, such as those
8088 * defined in a DLL.
8090 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
8091 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
8093 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8094 HRESULT hr;
8095 BSTR dll, entry;
8096 WORD ordinal;
8097 HMODULE module;
8099 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
8101 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
8102 if (FAILED(hr))
8103 return hr;
8105 module = LoadLibraryW(dll);
8106 if (!module)
8108 ERR("couldn't load %s\n", debugstr_w(dll));
8109 SysFreeString(dll);
8110 SysFreeString(entry);
8111 return STG_E_FILENOTFOUND;
8113 /* FIXME: store library somewhere where we can free it */
8115 if (entry)
8117 LPSTR entryA;
8118 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
8119 entryA = heap_alloc(len);
8120 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
8122 *ppv = GetProcAddress(module, entryA);
8123 if (!*ppv)
8124 ERR("function not found %s\n", debugstr_a(entryA));
8126 heap_free(entryA);
8128 else
8130 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
8131 if (!*ppv)
8132 ERR("function not found %d\n", ordinal);
8135 SysFreeString(dll);
8136 SysFreeString(entry);
8138 if (!*ppv)
8139 return TYPE_E_DLLFUNCTIONNOTFOUND;
8141 return S_OK;
8144 /* ITypeInfo::CreateInstance
8146 * Creates a new instance of a type that describes a component object class
8147 * (coclass).
8149 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
8150 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
8152 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8153 HRESULT hr;
8154 TYPEATTR *pTA;
8156 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
8158 *ppvObj = NULL;
8160 if(pOuterUnk)
8162 WARN("Not able to aggregate\n");
8163 return CLASS_E_NOAGGREGATION;
8166 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
8167 if(FAILED(hr)) return hr;
8169 if(pTA->typekind != TKIND_COCLASS)
8171 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
8172 hr = E_INVALIDARG;
8173 goto end;
8176 hr = S_FALSE;
8177 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
8179 IUnknown *pUnk;
8180 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
8181 TRACE("GetActiveObject rets %08x\n", hr);
8182 if(hr == S_OK)
8184 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
8185 IUnknown_Release(pUnk);
8189 if(hr != S_OK)
8190 hr = CoCreateInstance(&pTA->guid, NULL,
8191 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
8192 riid, ppvObj);
8194 end:
8195 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
8196 return hr;
8199 /* ITypeInfo::GetMops
8201 * Retrieves marshalling information.
8203 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
8204 BSTR *pBstrMops)
8206 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8207 FIXME("(%p %d) stub!\n", This, memid);
8208 *pBstrMops = NULL;
8209 return S_OK;
8212 /* ITypeInfo::GetContainingTypeLib
8214 * Retrieves the containing type library and the index of the type description
8215 * within that type library.
8217 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
8218 ITypeLib * *ppTLib, UINT *pIndex)
8220 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8222 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
8223 if (pIndex) {
8224 *pIndex=This->index;
8225 TRACE("returning pIndex=%d\n", *pIndex);
8228 if (ppTLib) {
8229 *ppTLib = (ITypeLib *)&This->pTypeLib->ITypeLib2_iface;
8230 ITypeLib_AddRef(*ppTLib);
8231 TRACE("returning ppTLib=%p\n", *ppTLib);
8234 return S_OK;
8237 /* ITypeInfo::ReleaseTypeAttr
8239 * Releases a TYPEATTR previously returned by Get
8242 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
8243 TYPEATTR* pTypeAttr)
8245 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8246 TRACE("(%p)->(%p)\n", This, pTypeAttr);
8247 heap_free(pTypeAttr);
8250 /* ITypeInfo::ReleaseFuncDesc
8252 * Releases a FUNCDESC previously returned by GetFuncDesc. *
8254 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
8255 ITypeInfo2 *iface,
8256 FUNCDESC *pFuncDesc)
8258 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8259 SHORT i;
8261 TRACE("(%p)->(%p)\n", This, pFuncDesc);
8263 for (i = 0; i < pFuncDesc->cParams; i++)
8264 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
8265 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
8267 SysFreeString((BSTR)pFuncDesc);
8270 /* ITypeInfo::ReleaseVarDesc
8272 * Releases a VARDESC previously returned by GetVarDesc.
8274 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
8275 VARDESC *pVarDesc)
8277 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8278 TRACE("(%p)->(%p)\n", This, pVarDesc);
8280 TLB_FreeVarDesc(pVarDesc);
8283 /* ITypeInfo2::GetTypeKind
8285 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
8288 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
8289 TYPEKIND *pTypeKind)
8291 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8292 *pTypeKind = This->typeattr.typekind;
8293 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
8294 return S_OK;
8297 /* ITypeInfo2::GetTypeFlags
8299 * Returns the type flags without any allocations. This returns a DWORD type
8300 * flag, which expands the type flags without growing the TYPEATTR (type
8301 * attribute).
8304 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
8306 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8307 *pTypeFlags=This->typeattr.wTypeFlags;
8308 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
8309 return S_OK;
8312 /* ITypeInfo2::GetFuncIndexOfMemId
8313 * Binds to a specific member based on a known DISPID, where the member name
8314 * is not known (for example, when binding to a default member).
8317 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
8318 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
8320 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8321 UINT fdc;
8322 HRESULT result;
8324 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
8325 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
8326 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
8327 break;
8329 if(fdc < This->typeattr.cFuncs) {
8330 *pFuncIndex = fdc;
8331 result = S_OK;
8332 } else
8333 result = TYPE_E_ELEMENTNOTFOUND;
8335 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
8336 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
8337 return result;
8340 /* TypeInfo2::GetVarIndexOfMemId
8342 * Binds to a specific member based on a known DISPID, where the member name
8343 * is not known (for example, when binding to a default member).
8346 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
8347 MEMBERID memid, UINT *pVarIndex)
8349 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8350 TLBVarDesc *pVarInfo;
8352 TRACE("%p %d %p\n", iface, memid, pVarIndex);
8354 pVarInfo = TLB_get_vardesc_by_memberid(This, memid);
8355 if(!pVarInfo)
8356 return TYPE_E_ELEMENTNOTFOUND;
8358 *pVarIndex = (pVarInfo - This->vardescs);
8360 return S_OK;
8363 /* ITypeInfo2::GetCustData
8365 * Gets the custom data
8367 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
8368 ITypeInfo2 * iface,
8369 REFGUID guid,
8370 VARIANT *pVarVal)
8372 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8373 TLBCustData *pCData;
8375 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8377 if(!guid || !pVarVal)
8378 return E_INVALIDARG;
8380 pCData = TLB_get_custdata_by_guid(This->pcustdata_list, guid);
8382 VariantInit( pVarVal);
8383 if (pCData)
8384 VariantCopy( pVarVal, &pCData->data);
8385 else
8386 VariantClear( pVarVal );
8387 return S_OK;
8390 /* ITypeInfo2::GetFuncCustData
8392 * Gets the custom data
8394 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
8395 ITypeInfo2 * iface,
8396 UINT index,
8397 REFGUID guid,
8398 VARIANT *pVarVal)
8400 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8401 const TLBFuncDesc *desc;
8402 TLBCustData *data;
8403 UINT hrefoffset;
8404 HRESULT hr;
8406 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8408 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index, &desc, &hrefoffset);
8409 if (FAILED(hr))
8411 WARN("description for function %d not found\n", index);
8412 return hr;
8415 VariantInit(pVarVal);
8416 data = TLB_get_custdata_by_guid(&desc->custdata_list, guid);
8417 return data ? VariantCopy(pVarVal, &data->data) : S_OK;
8420 /* ITypeInfo2::GetParamCustData
8422 * Gets the custom data
8424 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
8425 ITypeInfo2 * iface,
8426 UINT indexFunc,
8427 UINT indexParam,
8428 REFGUID guid,
8429 VARIANT *pVarVal)
8431 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8432 const TLBFuncDesc *pFDesc;
8433 TLBCustData *pCData;
8434 UINT hrefoffset;
8435 HRESULT hr;
8437 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
8438 debugstr_guid(guid), pVarVal);
8440 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, indexFunc, &pFDesc, &hrefoffset);
8441 if (FAILED(hr))
8442 return hr;
8444 if(indexParam >= pFDesc->funcdesc.cParams)
8445 return TYPE_E_ELEMENTNOTFOUND;
8447 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
8448 if(!pCData)
8449 return TYPE_E_ELEMENTNOTFOUND;
8451 VariantInit(pVarVal);
8452 VariantCopy(pVarVal, &pCData->data);
8454 return S_OK;
8457 /* ITypeInfo2::GetVarCustData
8459 * Gets the custom data
8461 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
8462 ITypeInfo2 * iface,
8463 UINT index,
8464 REFGUID guid,
8465 VARIANT *pVarVal)
8467 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8468 TLBCustData *pCData;
8469 TLBVarDesc *pVDesc = &This->vardescs[index];
8471 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8473 if(index >= This->typeattr.cVars)
8474 return TYPE_E_ELEMENTNOTFOUND;
8476 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
8477 if(!pCData)
8478 return TYPE_E_ELEMENTNOTFOUND;
8480 VariantInit(pVarVal);
8481 VariantCopy(pVarVal, &pCData->data);
8483 return S_OK;
8486 /* ITypeInfo2::GetImplCustData
8488 * Gets the custom data
8490 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
8491 ITypeInfo2 * iface,
8492 UINT index,
8493 REFGUID guid,
8494 VARIANT *pVarVal)
8496 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8497 TLBCustData *pCData;
8498 TLBImplType *pRDesc = &This->impltypes[index];
8500 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8502 if(index >= This->typeattr.cImplTypes)
8503 return TYPE_E_ELEMENTNOTFOUND;
8505 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
8506 if(!pCData)
8507 return TYPE_E_ELEMENTNOTFOUND;
8509 VariantInit(pVarVal);
8510 VariantCopy(pVarVal, &pCData->data);
8512 return S_OK;
8515 /* ITypeInfo2::GetDocumentation2
8517 * Retrieves the documentation string, the complete Help file name and path,
8518 * the localization context to use, and the context ID for the library Help
8519 * topic in the Help file.
8522 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
8523 ITypeInfo2 * iface,
8524 MEMBERID memid,
8525 LCID lcid,
8526 BSTR *pbstrHelpString,
8527 DWORD *pdwHelpStringContext,
8528 BSTR *pbstrHelpStringDll)
8530 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8531 const TLBFuncDesc *pFDesc;
8532 const TLBVarDesc *pVDesc;
8533 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8534 "HelpStringContext(%p) HelpStringDll(%p)\n",
8535 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
8536 pbstrHelpStringDll );
8537 /* the help string should be obtained from the helpstringdll,
8538 * using the _DLLGetDocumentation function, based on the supplied
8539 * lcid. Nice to do sometime...
8541 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
8542 if(pbstrHelpString)
8543 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->Name));
8544 if(pdwHelpStringContext)
8545 *pdwHelpStringContext=This->dwHelpStringContext;
8546 if(pbstrHelpStringDll)
8547 *pbstrHelpStringDll=
8548 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8549 return S_OK;
8550 }else {/* for a member */
8551 pFDesc = TLB_get_funcdesc_by_memberid(This, memid);
8552 if(pFDesc){
8553 if(pbstrHelpString)
8554 *pbstrHelpString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
8555 if(pdwHelpStringContext)
8556 *pdwHelpStringContext=pFDesc->HelpStringContext;
8557 if(pbstrHelpStringDll)
8558 *pbstrHelpStringDll=
8559 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8560 return S_OK;
8562 pVDesc = TLB_get_vardesc_by_memberid(This, memid);
8563 if(pVDesc){
8564 if(pbstrHelpString)
8565 *pbstrHelpString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
8566 if(pdwHelpStringContext)
8567 *pdwHelpStringContext=pVDesc->HelpStringContext;
8568 if(pbstrHelpStringDll)
8569 *pbstrHelpStringDll=
8570 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8571 return S_OK;
8574 return TYPE_E_ELEMENTNOTFOUND;
8577 /* ITypeInfo2::GetAllCustData
8579 * Gets all custom data items for the Type info.
8582 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
8583 ITypeInfo2 * iface,
8584 CUSTDATA *pCustData)
8586 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8588 TRACE("%p %p\n", This, pCustData);
8590 return TLB_copy_all_custdata(This->pcustdata_list, pCustData);
8593 /* ITypeInfo2::GetAllFuncCustData
8595 * Gets all custom data items for the specified Function
8598 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
8599 ITypeInfo2 * iface,
8600 UINT index,
8601 CUSTDATA *pCustData)
8603 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8604 const TLBFuncDesc *pFDesc;
8605 UINT hrefoffset;
8606 HRESULT hr;
8608 TRACE("%p %u %p\n", This, index, pCustData);
8610 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index, &pFDesc, &hrefoffset);
8611 if (FAILED(hr))
8612 return hr;
8614 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
8617 /* ITypeInfo2::GetAllParamCustData
8619 * Gets all custom data items for the Functions
8622 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
8623 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
8625 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8626 const TLBFuncDesc *pFDesc;
8627 UINT hrefoffset;
8628 HRESULT hr;
8630 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
8632 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, indexFunc, &pFDesc, &hrefoffset);
8633 if (FAILED(hr))
8634 return hr;
8636 if(indexParam >= pFDesc->funcdesc.cParams)
8637 return TYPE_E_ELEMENTNOTFOUND;
8639 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
8642 /* ITypeInfo2::GetAllVarCustData
8644 * Gets all custom data items for the specified Variable
8647 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
8648 UINT index, CUSTDATA *pCustData)
8650 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8651 TLBVarDesc * pVDesc = &This->vardescs[index];
8653 TRACE("%p %u %p\n", This, index, pCustData);
8655 if(index >= This->typeattr.cVars)
8656 return TYPE_E_ELEMENTNOTFOUND;
8658 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
8661 /* ITypeInfo2::GetAllImplCustData
8663 * Gets all custom data items for the specified implementation type
8666 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
8667 ITypeInfo2 * iface,
8668 UINT index,
8669 CUSTDATA *pCustData)
8671 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8672 TLBImplType *pRDesc = &This->impltypes[index];
8674 TRACE("%p %u %p\n", This, index, pCustData);
8676 if(index >= This->typeattr.cImplTypes)
8677 return TYPE_E_ELEMENTNOTFOUND;
8679 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
8682 static const ITypeInfo2Vtbl tinfvt =
8685 ITypeInfo_fnQueryInterface,
8686 ITypeInfo_fnAddRef,
8687 ITypeInfo_fnRelease,
8689 ITypeInfo_fnGetTypeAttr,
8690 ITypeInfo_fnGetTypeComp,
8691 ITypeInfo_fnGetFuncDesc,
8692 ITypeInfo_fnGetVarDesc,
8693 ITypeInfo_fnGetNames,
8694 ITypeInfo_fnGetRefTypeOfImplType,
8695 ITypeInfo_fnGetImplTypeFlags,
8696 ITypeInfo_fnGetIDsOfNames,
8697 ITypeInfo_fnInvoke,
8698 ITypeInfo_fnGetDocumentation,
8699 ITypeInfo_fnGetDllEntry,
8700 ITypeInfo_fnGetRefTypeInfo,
8701 ITypeInfo_fnAddressOfMember,
8702 ITypeInfo_fnCreateInstance,
8703 ITypeInfo_fnGetMops,
8704 ITypeInfo_fnGetContainingTypeLib,
8705 ITypeInfo_fnReleaseTypeAttr,
8706 ITypeInfo_fnReleaseFuncDesc,
8707 ITypeInfo_fnReleaseVarDesc,
8709 ITypeInfo2_fnGetTypeKind,
8710 ITypeInfo2_fnGetTypeFlags,
8711 ITypeInfo2_fnGetFuncIndexOfMemId,
8712 ITypeInfo2_fnGetVarIndexOfMemId,
8713 ITypeInfo2_fnGetCustData,
8714 ITypeInfo2_fnGetFuncCustData,
8715 ITypeInfo2_fnGetParamCustData,
8716 ITypeInfo2_fnGetVarCustData,
8717 ITypeInfo2_fnGetImplTypeCustData,
8718 ITypeInfo2_fnGetDocumentation2,
8719 ITypeInfo2_fnGetAllCustData,
8720 ITypeInfo2_fnGetAllFuncCustData,
8721 ITypeInfo2_fnGetAllParamCustData,
8722 ITypeInfo2_fnGetAllVarCustData,
8723 ITypeInfo2_fnGetAllImplTypeCustData,
8726 /******************************************************************************
8727 * CreateDispTypeInfo [OLEAUT32.31]
8729 * Build type information for an object so it can be called through an
8730 * IDispatch interface.
8732 * RETURNS
8733 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8734 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8736 * NOTES
8737 * This call allows an objects methods to be accessed through IDispatch, by
8738 * building an ITypeInfo object that IDispatch can use to call through.
8740 HRESULT WINAPI CreateDispTypeInfo(
8741 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
8742 LCID lcid, /* [I] Locale Id */
8743 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
8745 ITypeInfoImpl *pTIClass, *pTIIface;
8746 ITypeLibImpl *pTypeLibImpl;
8747 unsigned int param, func;
8748 TLBFuncDesc *pFuncDesc;
8749 TLBRefType *ref;
8751 TRACE("\n");
8752 pTypeLibImpl = TypeLibImpl_Constructor();
8753 if (!pTypeLibImpl) return E_FAIL;
8755 pTypeLibImpl->TypeInfoCount = 2;
8756 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
8758 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
8759 pTIIface->pTypeLib = pTypeLibImpl;
8760 pTIIface->index = 0;
8761 pTIIface->Name = NULL;
8762 pTIIface->dwHelpContext = -1;
8763 pTIIface->guid = NULL;
8764 pTIIface->typeattr.lcid = lcid;
8765 pTIIface->typeattr.typekind = TKIND_INTERFACE;
8766 pTIIface->typeattr.wMajorVerNum = 0;
8767 pTIIface->typeattr.wMinorVerNum = 0;
8768 pTIIface->typeattr.cbAlignment = 2;
8769 pTIIface->typeattr.cbSizeInstance = -1;
8770 pTIIface->typeattr.cbSizeVft = -1;
8771 pTIIface->typeattr.cFuncs = 0;
8772 pTIIface->typeattr.cImplTypes = 0;
8773 pTIIface->typeattr.cVars = 0;
8774 pTIIface->typeattr.wTypeFlags = 0;
8775 pTIIface->hreftype = 0;
8777 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers);
8778 pFuncDesc = pTIIface->funcdescs;
8779 for(func = 0; func < pidata->cMembers; func++) {
8780 METHODDATA *md = pidata->pmethdata + func;
8781 pFuncDesc->Name = TLB_append_str(&pTypeLibImpl->name_list, md->szName);
8782 pFuncDesc->funcdesc.memid = md->dispid;
8783 pFuncDesc->funcdesc.lprgscode = NULL;
8784 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
8785 pFuncDesc->funcdesc.invkind = md->wFlags;
8786 pFuncDesc->funcdesc.callconv = md->cc;
8787 pFuncDesc->funcdesc.cParams = md->cArgs;
8788 pFuncDesc->funcdesc.cParamsOpt = 0;
8789 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
8790 pFuncDesc->funcdesc.cScodes = 0;
8791 pFuncDesc->funcdesc.wFuncFlags = 0;
8792 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
8793 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
8794 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
8795 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8796 md->cArgs * sizeof(ELEMDESC));
8797 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
8798 for(param = 0; param < md->cArgs; param++) {
8799 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
8800 pFuncDesc->pParamDesc[param].Name = TLB_append_str(&pTypeLibImpl->name_list, md->ppdata[param].szName);
8802 pFuncDesc->helpcontext = 0;
8803 pFuncDesc->HelpStringContext = 0;
8804 pFuncDesc->HelpString = NULL;
8805 pFuncDesc->Entry = NULL;
8806 list_init(&pFuncDesc->custdata_list);
8807 pTIIface->typeattr.cFuncs++;
8808 ++pFuncDesc;
8811 dump_TypeInfo(pTIIface);
8813 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
8814 pTIClass->pTypeLib = pTypeLibImpl;
8815 pTIClass->index = 1;
8816 pTIClass->Name = NULL;
8817 pTIClass->dwHelpContext = -1;
8818 pTIClass->guid = NULL;
8819 pTIClass->typeattr.lcid = lcid;
8820 pTIClass->typeattr.typekind = TKIND_COCLASS;
8821 pTIClass->typeattr.wMajorVerNum = 0;
8822 pTIClass->typeattr.wMinorVerNum = 0;
8823 pTIClass->typeattr.cbAlignment = 2;
8824 pTIClass->typeattr.cbSizeInstance = -1;
8825 pTIClass->typeattr.cbSizeVft = -1;
8826 pTIClass->typeattr.cFuncs = 0;
8827 pTIClass->typeattr.cImplTypes = 1;
8828 pTIClass->typeattr.cVars = 0;
8829 pTIClass->typeattr.wTypeFlags = 0;
8830 pTIClass->hreftype = sizeof(MSFT_TypeInfoBase);
8832 pTIClass->impltypes = TLBImplType_Alloc(1);
8834 ref = heap_alloc_zero(sizeof(*ref));
8835 ref->pImpTLInfo = TLB_REF_INTERNAL;
8836 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
8838 dump_TypeInfo(pTIClass);
8840 *pptinfo = (ITypeInfo *)&pTIClass->ITypeInfo2_iface;
8842 ITypeInfo_AddRef(*pptinfo);
8843 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
8845 return S_OK;
8849 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
8851 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8853 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, ppv);
8856 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
8858 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8860 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
8863 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
8865 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8867 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
8870 static HRESULT WINAPI ITypeComp_fnBind(
8871 ITypeComp * iface,
8872 OLECHAR * szName,
8873 ULONG lHash,
8874 WORD wFlags,
8875 ITypeInfo ** ppTInfo,
8876 DESCKIND * pDescKind,
8877 BINDPTR * pBindPtr)
8879 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8880 const TLBFuncDesc *pFDesc;
8881 const TLBVarDesc *pVDesc;
8882 HRESULT hr = DISP_E_MEMBERNOTFOUND;
8883 UINT fdc;
8885 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8887 *pDescKind = DESCKIND_NONE;
8888 pBindPtr->lpfuncdesc = NULL;
8889 *ppTInfo = NULL;
8891 for(fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
8892 pFDesc = &This->funcdescs[fdc];
8893 if (!lstrcmpiW(TLB_get_bstr(pFDesc->Name), szName)) {
8894 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
8895 break;
8896 else
8897 /* name found, but wrong flags */
8898 hr = TYPE_E_TYPEMISMATCH;
8902 if (fdc < This->typeattr.cFuncs)
8904 HRESULT hr = TLB_AllocAndInitFuncDesc(
8905 &pFDesc->funcdesc,
8906 &pBindPtr->lpfuncdesc,
8907 This->typeattr.typekind == TKIND_DISPATCH);
8908 if (FAILED(hr))
8909 return hr;
8910 *pDescKind = DESCKIND_FUNCDESC;
8911 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8912 ITypeInfo_AddRef(*ppTInfo);
8913 return S_OK;
8914 } else {
8915 pVDesc = TLB_get_vardesc_by_name(This, szName);
8916 if(pVDesc){
8917 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
8918 if (FAILED(hr))
8919 return hr;
8920 *pDescKind = DESCKIND_VARDESC;
8921 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8922 ITypeInfo_AddRef(*ppTInfo);
8923 return S_OK;
8927 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
8928 /* recursive search */
8929 ITypeInfo *pTInfo;
8930 ITypeComp *pTComp;
8931 HRESULT hr;
8932 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
8933 if (SUCCEEDED(hr))
8935 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
8936 ITypeInfo_Release(pTInfo);
8938 if (SUCCEEDED(hr))
8940 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8941 ITypeComp_Release(pTComp);
8942 if (SUCCEEDED(hr) && *pDescKind == DESCKIND_FUNCDESC &&
8943 This->typeattr.typekind == TKIND_DISPATCH)
8945 FUNCDESC *tmp = pBindPtr->lpfuncdesc;
8946 hr = TLB_AllocAndInitFuncDesc(tmp, &pBindPtr->lpfuncdesc, TRUE);
8947 SysFreeString((BSTR)tmp);
8949 return hr;
8951 WARN("Could not search inherited interface!\n");
8953 if (hr == DISP_E_MEMBERNOTFOUND)
8954 hr = S_OK;
8955 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
8956 return hr;
8959 static HRESULT WINAPI ITypeComp_fnBindType(
8960 ITypeComp * iface,
8961 OLECHAR * szName,
8962 ULONG lHash,
8963 ITypeInfo ** ppTInfo,
8964 ITypeComp ** ppTComp)
8966 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
8968 /* strange behaviour (does nothing) but like the
8969 * original */
8971 if (!ppTInfo || !ppTComp)
8972 return E_POINTER;
8974 *ppTInfo = NULL;
8975 *ppTComp = NULL;
8977 return S_OK;
8980 static const ITypeCompVtbl tcompvt =
8983 ITypeComp_fnQueryInterface,
8984 ITypeComp_fnAddRef,
8985 ITypeComp_fnRelease,
8987 ITypeComp_fnBind,
8988 ITypeComp_fnBindType
8991 HRESULT WINAPI CreateTypeLib2(SYSKIND syskind, LPCOLESTR szFile,
8992 ICreateTypeLib2** ppctlib)
8994 ITypeLibImpl *This;
8995 HRESULT hres;
8997 TRACE("(%d,%s,%p)\n", syskind, debugstr_w(szFile), ppctlib);
8999 if (!szFile) return E_INVALIDARG;
9001 This = TypeLibImpl_Constructor();
9002 if (!This)
9003 return E_OUTOFMEMORY;
9005 This->lcid = GetSystemDefaultLCID();
9006 This->syskind = syskind;
9007 This->ptr_size = get_ptr_size(syskind);
9009 This->path = heap_alloc((lstrlenW(szFile) + 1) * sizeof(WCHAR));
9010 if (!This->path) {
9011 ITypeLib2_Release(&This->ITypeLib2_iface);
9012 return E_OUTOFMEMORY;
9014 lstrcpyW(This->path, szFile);
9016 hres = ITypeLib2_QueryInterface(&This->ITypeLib2_iface, &IID_ICreateTypeLib2, (LPVOID*)ppctlib);
9017 ITypeLib2_Release(&This->ITypeLib2_iface);
9018 return hres;
9021 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
9022 REFIID riid, void **object)
9024 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9026 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, object);
9029 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
9031 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9033 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
9036 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
9038 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9040 return ITypeLib2_Release(&This->ITypeLib2_iface);
9043 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
9044 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
9046 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9047 ITypeInfoImpl *info;
9048 HRESULT hres;
9050 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo);
9052 if (!ctinfo || !name)
9053 return E_INVALIDARG;
9055 info = TLB_get_typeinfo_by_name(This, name);
9056 if (info)
9057 return TYPE_E_NAMECONFLICT;
9059 if (This->typeinfos)
9060 This->typeinfos = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->typeinfos,
9061 sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1));
9062 else
9063 This->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*));
9065 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor();
9067 info->pTypeLib = This;
9068 info->Name = TLB_append_str(&This->name_list, name);
9069 info->index = This->TypeInfoCount;
9070 info->typeattr.typekind = kind;
9071 info->typeattr.cbAlignment = 4;
9073 switch (info->typeattr.typekind) {
9074 case TKIND_ENUM:
9075 case TKIND_INTERFACE:
9076 case TKIND_DISPATCH:
9077 case TKIND_COCLASS:
9078 info->typeattr.cbSizeInstance = This->ptr_size;
9079 break;
9080 case TKIND_RECORD:
9081 case TKIND_UNION:
9082 info->typeattr.cbSizeInstance = 0;
9083 break;
9084 case TKIND_MODULE:
9085 info->typeattr.cbSizeInstance = 2;
9086 break;
9087 case TKIND_ALIAS:
9088 info->typeattr.cbSizeInstance = -0x75;
9089 break;
9090 default:
9091 FIXME("unrecognized typekind %d\n", info->typeattr.typekind);
9092 info->typeattr.cbSizeInstance = 0xdeadbeef;
9093 break;
9096 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface,
9097 &IID_ICreateTypeInfo, (void **)ctinfo);
9098 if (FAILED(hres)) {
9099 ITypeInfo2_Release(&info->ITypeInfo2_iface);
9100 return hres;
9103 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase);
9105 ++This->TypeInfoCount;
9107 return S_OK;
9110 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
9111 LPOLESTR name)
9113 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9115 TRACE("%p %s\n", This, wine_dbgstr_w(name));
9117 if (!name)
9118 return E_INVALIDARG;
9120 This->Name = TLB_append_str(&This->name_list, name);
9122 return S_OK;
9125 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
9126 WORD majorVerNum, WORD minorVerNum)
9128 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9130 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
9132 This->ver_major = majorVerNum;
9133 This->ver_minor = minorVerNum;
9135 return S_OK;
9138 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
9139 REFGUID guid)
9141 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9143 TRACE("%p %s\n", This, debugstr_guid(guid));
9145 This->guid = TLB_append_guid(&This->guid_list, guid, -2);
9147 return S_OK;
9150 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
9151 LPOLESTR doc)
9153 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9155 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
9157 if (!doc)
9158 return E_INVALIDARG;
9160 This->DocString = TLB_append_str(&This->string_list, doc);
9162 return S_OK;
9165 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
9166 LPOLESTR helpFileName)
9168 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9170 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
9172 if (!helpFileName)
9173 return E_INVALIDARG;
9175 This->HelpFile = TLB_append_str(&This->string_list, helpFileName);
9177 return S_OK;
9180 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
9181 DWORD helpContext)
9183 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9185 TRACE("%p %d\n", This, helpContext);
9187 This->dwHelpContext = helpContext;
9189 return S_OK;
9192 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
9193 LCID lcid)
9195 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9197 TRACE("%p %x\n", This, lcid);
9199 This->set_lcid = lcid;
9201 return S_OK;
9204 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
9205 UINT libFlags)
9207 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9209 TRACE("%p %x\n", This, libFlags);
9211 This->libflags = libFlags;
9213 return S_OK;
9216 typedef struct tagWMSFT_SegContents {
9217 DWORD len;
9218 void *data;
9219 } WMSFT_SegContents;
9221 typedef struct tagWMSFT_TLBFile {
9222 MSFT_Header header;
9223 WMSFT_SegContents typeinfo_seg;
9224 WMSFT_SegContents impfile_seg;
9225 WMSFT_SegContents impinfo_seg;
9226 WMSFT_SegContents ref_seg;
9227 WMSFT_SegContents guidhash_seg;
9228 WMSFT_SegContents guid_seg;
9229 WMSFT_SegContents namehash_seg;
9230 WMSFT_SegContents name_seg;
9231 WMSFT_SegContents string_seg;
9232 WMSFT_SegContents typdesc_seg;
9233 WMSFT_SegContents arraydesc_seg;
9234 WMSFT_SegContents custdata_seg;
9235 WMSFT_SegContents cdguids_seg;
9236 MSFT_SegDir segdir;
9237 WMSFT_SegContents aux_seg;
9238 } WMSFT_TLBFile;
9240 static HRESULT WMSFT_compile_strings(ITypeLibImpl *This,
9241 WMSFT_TLBFile *file)
9243 TLBString *str;
9244 UINT last_offs;
9245 char *data;
9247 file->string_seg.len = 0;
9248 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
9249 int size;
9251 size = WideCharToMultiByte(CP_ACP, 0, str->str, lstrlenW(str->str), NULL, 0, NULL, NULL);
9252 if (size == 0)
9253 return E_UNEXPECTED;
9255 size += sizeof(INT16);
9256 if (size % 4)
9257 size = (size + 4) & ~0x3;
9258 if (size < 8)
9259 size = 8;
9261 file->string_seg.len += size;
9263 /* temporarily use str->offset to store the length of the aligned,
9264 * converted string */
9265 str->offset = size;
9268 file->string_seg.data = data = heap_alloc(file->string_seg.len);
9270 last_offs = 0;
9271 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
9272 int size;
9274 size = WideCharToMultiByte(CP_ACP, 0, str->str, lstrlenW(str->str),
9275 data + sizeof(INT16), file->string_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9276 if (size == 0) {
9277 heap_free(file->string_seg.data);
9278 return E_UNEXPECTED;
9281 *((INT16*)data) = size;
9283 memset(data + sizeof(INT16) + size, 0x57, str->offset - size - sizeof(INT16));
9285 size = str->offset;
9286 data += size;
9287 str->offset = last_offs;
9288 last_offs += size;
9291 return S_OK;
9294 static HRESULT WMSFT_compile_names(ITypeLibImpl *This,
9295 WMSFT_TLBFile *file)
9297 TLBString *str;
9298 UINT last_offs;
9299 char *data;
9300 MSFT_NameIntro *last_intro = NULL;
9302 file->header.nametablecount = 0;
9303 file->header.nametablechars = 0;
9305 file->name_seg.len = 0;
9306 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
9307 int size;
9309 size = lstrlenW(str->str);
9310 file->header.nametablechars += size;
9311 file->header.nametablecount++;
9313 size = WideCharToMultiByte(CP_ACP, 0, str->str, size, NULL, 0, NULL, NULL);
9314 if (size == 0)
9315 return E_UNEXPECTED;
9317 size += sizeof(MSFT_NameIntro);
9318 if (size % 4)
9319 size = (size + 4) & ~0x3;
9320 if (size < 8)
9321 size = 8;
9323 file->name_seg.len += size;
9325 /* temporarily use str->offset to store the length of the aligned,
9326 * converted string */
9327 str->offset = size;
9330 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
9331 file->name_seg.data = data = heap_alloc(file->name_seg.len+1);
9333 last_offs = 0;
9334 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
9335 int size, hash;
9336 MSFT_NameIntro *intro = (MSFT_NameIntro*)data;
9338 size = WideCharToMultiByte(CP_ACP, 0, str->str, lstrlenW(str->str),
9339 data + sizeof(MSFT_NameIntro),
9340 file->name_seg.len - last_offs - sizeof(MSFT_NameIntro), NULL, NULL);
9341 if (size == 0) {
9342 heap_free(file->name_seg.data);
9343 return E_UNEXPECTED;
9345 data[sizeof(MSFT_NameIntro) + size] = '\0';
9347 intro->hreftype = -1; /* TODO? */
9348 intro->namelen = size & 0xFF;
9349 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9350 hash = LHashValOfNameSysA(This->syskind, This->lcid, data + sizeof(MSFT_NameIntro));
9351 intro->namelen |= hash << 16;
9352 intro->next_hash = ((DWORD*)file->namehash_seg.data)[hash & 0x7f];
9353 ((DWORD*)file->namehash_seg.data)[hash & 0x7f] = last_offs;
9355 memset(data + sizeof(MSFT_NameIntro) + size, 0x57,
9356 str->offset - size - sizeof(MSFT_NameIntro));
9358 /* update str->offset to actual value to use in other
9359 * compilation functions that require positions within
9360 * the string table */
9361 last_intro = intro;
9362 size = str->offset;
9363 data += size;
9364 str->offset = last_offs;
9365 last_offs += size;
9368 if(last_intro)
9369 last_intro->hreftype = 0; /* last one is 0? */
9371 return S_OK;
9374 static inline int hash_guid(GUID *guid)
9376 int i, hash = 0;
9378 for (i = 0; i < 8; i ++)
9379 hash ^= ((const short *)guid)[i];
9381 return hash & 0x1f;
9384 static HRESULT WMSFT_compile_guids(ITypeLibImpl *This, WMSFT_TLBFile *file)
9386 TLBGuid *guid;
9387 MSFT_GuidEntry *entry;
9388 DWORD offs;
9389 int hash_key, *guidhashtab;
9391 file->guid_seg.len = sizeof(MSFT_GuidEntry) * list_count(&This->guid_list);
9392 file->guid_seg.data = heap_alloc(file->guid_seg.len);
9394 entry = file->guid_seg.data;
9395 offs = 0;
9396 guidhashtab = file->guidhash_seg.data;
9397 LIST_FOR_EACH_ENTRY(guid, &This->guid_list, TLBGuid, entry){
9398 memcpy(&entry->guid, &guid->guid, sizeof(GUID));
9399 entry->hreftype = guid->hreftype;
9401 hash_key = hash_guid(&guid->guid);
9402 entry->next_hash = guidhashtab[hash_key];
9403 guidhashtab[hash_key] = offs;
9405 guid->offset = offs;
9406 offs += sizeof(MSFT_GuidEntry);
9407 ++entry;
9410 return S_OK;
9413 static DWORD WMSFT_encode_variant(VARIANT *value, WMSFT_TLBFile *file)
9415 VARIANT v = *value;
9416 VARTYPE arg_type = V_VT(value);
9417 int mask = 0;
9418 HRESULT hres;
9419 DWORD ret = file->custdata_seg.len;
9421 if(arg_type == VT_INT)
9422 arg_type = VT_I4;
9423 if(arg_type == VT_UINT)
9424 arg_type = VT_UI4;
9426 v = *value;
9427 if(V_VT(value) != arg_type) {
9428 hres = VariantChangeType(&v, value, 0, arg_type);
9429 if(FAILED(hres)){
9430 ERR("VariantChangeType failed: %08x\n", hres);
9431 return -1;
9435 /* Check if default value can be stored in-place */
9436 switch(arg_type){
9437 case VT_I4:
9438 case VT_UI4:
9439 mask = 0x3ffffff;
9440 if(V_UI4(&v) > 0x3ffffff)
9441 break;
9442 /* fall through */
9443 case VT_I1:
9444 case VT_UI1:
9445 case VT_BOOL:
9446 if(!mask)
9447 mask = 0xff;
9448 /* fall through */
9449 case VT_I2:
9450 case VT_UI2:
9451 if(!mask)
9452 mask = 0xffff;
9453 return ((0x80 + 0x4 * V_VT(value)) << 24) | (V_UI4(&v) & mask);
9456 /* have to allocate space in custdata_seg */
9457 switch(arg_type) {
9458 case VT_I4:
9459 case VT_R4:
9460 case VT_UI4:
9461 case VT_INT:
9462 case VT_UINT:
9463 case VT_HRESULT:
9464 case VT_PTR: {
9465 /* Construct the data to be allocated */
9466 int *data;
9468 if(file->custdata_seg.data){
9469 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + sizeof(int) * 2);
9470 data = (int *)(((char *)file->custdata_seg.data) + file->custdata_seg.len);
9471 file->custdata_seg.len += sizeof(int) * 2;
9472 }else{
9473 file->custdata_seg.len = sizeof(int) * 2;
9474 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9477 data[0] = V_VT(value) + (V_UI4(&v) << 16);
9478 data[1] = (V_UI4(&v) >> 16) + 0x57570000;
9480 /* TODO: Check if the encoded data is already present in custdata_seg */
9482 return ret;
9485 case VT_BSTR: {
9486 int i, len = (6+SysStringLen(V_BSTR(&v))+3) & ~0x3;
9487 char *data;
9489 if(file->custdata_seg.data){
9490 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + len);
9491 data = ((char *)file->custdata_seg.data) + file->custdata_seg.len;
9492 file->custdata_seg.len += len;
9493 }else{
9494 file->custdata_seg.len = len;
9495 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9498 *((unsigned short *)data) = V_VT(value);
9499 *((unsigned int *)(data+2)) = SysStringLen(V_BSTR(&v));
9500 for(i=0; i<SysStringLen(V_BSTR(&v)); i++) {
9501 if(V_BSTR(&v)[i] <= 0x7f)
9502 data[i+6] = V_BSTR(&v)[i];
9503 else
9504 data[i+6] = '?';
9506 WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], len-6, NULL, NULL);
9507 for(i=6+SysStringLen(V_BSTR(&v)); i<len; i++)
9508 data[i] = 0x57;
9510 /* TODO: Check if the encoded data is already present in custdata_seg */
9512 return ret;
9514 default:
9515 FIXME("Argument type not yet handled\n");
9516 return -1;
9520 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size);
9522 static DWORD WMSFT_append_arraydesc(ARRAYDESC *desc, WMSFT_TLBFile *file)
9524 DWORD offs = file->arraydesc_seg.len;
9525 DWORD *encoded;
9526 USHORT i;
9528 /* TODO: we should check for duplicates, but that's harder because each
9529 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9530 * at the library-level) */
9532 file->arraydesc_seg.len += (2 + desc->cDims * 2) * sizeof(DWORD);
9533 if(!file->arraydesc_seg.data)
9534 file->arraydesc_seg.data = heap_alloc(file->arraydesc_seg.len);
9535 else
9536 file->arraydesc_seg.data = heap_realloc(file->arraydesc_seg.data, file->arraydesc_seg.len);
9537 encoded = (DWORD*)((char *)file->arraydesc_seg.data + offs);
9539 encoded[0] = WMSFT_append_typedesc(&desc->tdescElem, file, NULL, NULL);
9540 encoded[1] = desc->cDims | ((desc->cDims * 2 * sizeof(DWORD)) << 16);
9541 for(i = 0; i < desc->cDims; ++i){
9542 encoded[2 + i * 2] = desc->rgbounds[i].cElements;
9543 encoded[2 + i * 2 + 1] = desc->rgbounds[i].lLbound;
9546 return offs;
9549 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size)
9551 DWORD junk;
9552 INT16 junk2;
9553 DWORD offs = 0;
9554 DWORD encoded[2];
9555 VARTYPE vt, subtype;
9556 char *data;
9558 if(!desc)
9559 return -1;
9561 if(!out_mix)
9562 out_mix = &junk;
9563 if(!out_size)
9564 out_size = &junk2;
9566 vt = desc->vt & VT_TYPEMASK;
9568 if(vt == VT_PTR || vt == VT_SAFEARRAY){
9569 DWORD mix;
9570 encoded[1] = WMSFT_append_typedesc(desc->u.lptdesc, file, &mix, out_size);
9571 encoded[0] = desc->vt | ((mix | VT_BYREF) << 16);
9572 *out_mix = 0x7FFF;
9573 *out_size += 2 * sizeof(DWORD);
9574 }else if(vt == VT_CARRAY){
9575 encoded[0] = desc->vt | (0x7FFE << 16);
9576 encoded[1] = WMSFT_append_arraydesc(desc->u.lpadesc, file);
9577 *out_mix = 0x7FFE;
9578 }else if(vt == VT_USERDEFINED){
9579 encoded[0] = desc->vt | (0x7FFF << 16);
9580 encoded[1] = desc->u.hreftype;
9581 *out_mix = 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9582 }else{
9583 TRACE("Mixing in-place, VT: 0x%x\n", desc->vt);
9585 switch(vt){
9586 case VT_INT:
9587 subtype = VT_I4;
9588 break;
9589 case VT_UINT:
9590 subtype = VT_UI4;
9591 break;
9592 case VT_VOID:
9593 subtype = VT_EMPTY;
9594 break;
9595 default:
9596 subtype = vt;
9597 break;
9600 *out_mix = subtype;
9601 return 0x80000000 | (subtype << 16) | desc->vt;
9604 data = file->typdesc_seg.data;
9605 while(offs < file->typdesc_seg.len){
9606 if(!memcmp(&data[offs], encoded, sizeof(encoded)))
9607 return offs;
9608 offs += sizeof(encoded);
9611 file->typdesc_seg.len += sizeof(encoded);
9612 if(!file->typdesc_seg.data)
9613 data = file->typdesc_seg.data = heap_alloc(file->typdesc_seg.len);
9614 else
9615 data = file->typdesc_seg.data = heap_realloc(file->typdesc_seg.data, file->typdesc_seg.len);
9617 memcpy(&data[offs], encoded, sizeof(encoded));
9619 return offs;
9622 static DWORD WMSFT_compile_custdata(struct list *custdata_list, WMSFT_TLBFile *file)
9624 WMSFT_SegContents *cdguids_seg = &file->cdguids_seg;
9625 DWORD ret = cdguids_seg->len, offs;
9626 MSFT_CDGuid *cdguid;
9627 TLBCustData *cd;
9629 if(list_empty(custdata_list))
9630 return -1;
9632 cdguids_seg->len += sizeof(MSFT_CDGuid) * list_count(custdata_list);
9633 if(!cdguids_seg->data){
9634 cdguid = cdguids_seg->data = heap_alloc(cdguids_seg->len);
9635 }else {
9636 cdguids_seg->data = heap_realloc(cdguids_seg->data, cdguids_seg->len);
9637 cdguid = (MSFT_CDGuid*)((char*)cdguids_seg->data + ret);
9640 offs = ret + sizeof(MSFT_CDGuid);
9641 LIST_FOR_EACH_ENTRY(cd, custdata_list, TLBCustData, entry){
9642 cdguid->GuidOffset = cd->guid->offset;
9643 cdguid->DataOffset = WMSFT_encode_variant(&cd->data, file);
9644 cdguid->next = offs;
9645 offs += sizeof(MSFT_CDGuid);
9646 ++cdguid;
9649 --cdguid;
9650 cdguid->next = -1;
9652 return ret;
9655 static DWORD WMSFT_compile_typeinfo_aux(ITypeInfoImpl *info,
9656 WMSFT_TLBFile *file)
9658 WMSFT_SegContents *aux_seg = &file->aux_seg;
9659 DWORD ret = aux_seg->len, i, j, recorded_size = 0, extra_size = 0;
9660 MSFT_VarRecord *varrecord;
9661 MSFT_FuncRecord *funcrecord;
9662 MEMBERID *memid;
9663 DWORD *name, *offsets, offs;
9665 for(i = 0; i < info->typeattr.cFuncs; ++i){
9666 TLBFuncDesc *desc = &info->funcdescs[i];
9668 recorded_size += 6 * sizeof(INT); /* mandatory fields */
9670 /* optional fields */
9671 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9672 if(!list_empty(&desc->custdata_list))
9673 recorded_size += 7 * sizeof(INT);
9674 else if(desc->HelpStringContext != 0)
9675 recorded_size += 6 * sizeof(INT);
9676 /* res9? resA? */
9677 else if(desc->Entry)
9678 recorded_size += 3 * sizeof(INT);
9679 else if(desc->HelpString)
9680 recorded_size += 2 * sizeof(INT);
9681 else if(desc->helpcontext)
9682 recorded_size += sizeof(INT);
9684 recorded_size += desc->funcdesc.cParams * sizeof(MSFT_ParameterInfo);
9686 for(j = 0; j < desc->funcdesc.cParams; ++j){
9687 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9688 recorded_size += desc->funcdesc.cParams * sizeof(INT);
9689 break;
9693 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9696 for(i = 0; i < info->typeattr.cVars; ++i){
9697 TLBVarDesc *desc = &info->vardescs[i];
9699 recorded_size += 5 * sizeof(INT); /* mandatory fields */
9701 /* optional fields */
9702 if(desc->HelpStringContext != 0)
9703 recorded_size += 5 * sizeof(INT);
9704 else if(!list_empty(&desc->custdata_list))
9705 recorded_size += 4 * sizeof(INT);
9706 /* res9? */
9707 else if(desc->HelpString)
9708 recorded_size += 2 * sizeof(INT);
9709 else if(desc->HelpContext != 0)
9710 recorded_size += sizeof(INT);
9712 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9715 if(!recorded_size && !extra_size)
9716 return ret;
9718 extra_size += sizeof(INT); /* total aux size for this typeinfo */
9720 aux_seg->len += recorded_size + extra_size;
9722 aux_seg->len += sizeof(INT) * (info->typeattr.cVars + info->typeattr.cFuncs); /* offsets at the end */
9724 if(aux_seg->data)
9725 aux_seg->data = heap_realloc(aux_seg->data, aux_seg->len);
9726 else
9727 aux_seg->data = heap_alloc(aux_seg->len);
9729 *((DWORD*)((char *)aux_seg->data + ret)) = recorded_size;
9731 offsets = (DWORD*)((char *)aux_seg->data + ret + recorded_size + extra_size);
9732 offs = 0;
9734 funcrecord = (MSFT_FuncRecord*)(((char *)aux_seg->data) + ret + sizeof(INT));
9735 for(i = 0; i < info->typeattr.cFuncs; ++i){
9736 TLBFuncDesc *desc = &info->funcdescs[i];
9737 DWORD size = 6 * sizeof(INT), paramdefault_size = 0, *paramdefault;
9739 funcrecord->funcdescsize = sizeof(desc->funcdesc) + desc->funcdesc.cParams * sizeof(ELEMDESC);
9740 funcrecord->DataType = WMSFT_append_typedesc(&desc->funcdesc.elemdescFunc.tdesc, file, NULL, &funcrecord->funcdescsize);
9741 funcrecord->Flags = desc->funcdesc.wFuncFlags;
9742 funcrecord->VtableOffset = desc->funcdesc.oVft;
9744 /* FKCCIC:
9745 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9746 * ^^^funckind
9747 * ^^^ ^invkind
9748 * ^has_cust_data
9749 * ^^^^callconv
9750 * ^has_param_defaults
9751 * ^oEntry_is_intresource
9753 funcrecord->FKCCIC =
9754 desc->funcdesc.funckind |
9755 (desc->funcdesc.invkind << 3) |
9756 (list_empty(&desc->custdata_list) ? 0 : 0x80) |
9757 (desc->funcdesc.callconv << 8);
9759 if(desc->Entry && desc->Entry != (TLBString*)-1 && IS_INTRESOURCE(desc->Entry))
9760 funcrecord->FKCCIC |= 0x2000;
9762 for(j = 0; j < desc->funcdesc.cParams; ++j){
9763 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9764 paramdefault_size = sizeof(INT) * desc->funcdesc.cParams;
9765 funcrecord->funcdescsize += sizeof(PARAMDESCEX);
9768 if(paramdefault_size > 0)
9769 funcrecord->FKCCIC |= 0x1000;
9771 funcrecord->nrargs = desc->funcdesc.cParams;
9772 funcrecord->nroargs = desc->funcdesc.cParamsOpt;
9774 /* optional fields */
9775 /* res9? resA? */
9776 if(!list_empty(&desc->custdata_list)){
9777 size += 7 * sizeof(INT);
9778 funcrecord->HelpContext = desc->helpcontext;
9779 if(desc->HelpString)
9780 funcrecord->oHelpString = desc->HelpString->offset;
9781 else
9782 funcrecord->oHelpString = -1;
9783 if(!desc->Entry)
9784 funcrecord->oEntry = -1;
9785 else if(IS_INTRESOURCE(desc->Entry))
9786 funcrecord->oEntry = LOWORD(desc->Entry);
9787 else
9788 funcrecord->oEntry = desc->Entry->offset;
9789 funcrecord->res9 = -1;
9790 funcrecord->resA = -1;
9791 funcrecord->HelpStringContext = desc->HelpStringContext;
9792 funcrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9793 }else if(desc->HelpStringContext != 0){
9794 size += 6 * sizeof(INT);
9795 funcrecord->HelpContext = desc->helpcontext;
9796 if(desc->HelpString)
9797 funcrecord->oHelpString = desc->HelpString->offset;
9798 else
9799 funcrecord->oHelpString = -1;
9800 if(!desc->Entry)
9801 funcrecord->oEntry = -1;
9802 else if(IS_INTRESOURCE(desc->Entry))
9803 funcrecord->oEntry = LOWORD(desc->Entry);
9804 else
9805 funcrecord->oEntry = desc->Entry->offset;
9806 funcrecord->res9 = -1;
9807 funcrecord->resA = -1;
9808 funcrecord->HelpStringContext = desc->HelpStringContext;
9809 }else if(desc->Entry){
9810 size += 3 * sizeof(INT);
9811 funcrecord->HelpContext = desc->helpcontext;
9812 if(desc->HelpString)
9813 funcrecord->oHelpString = desc->HelpString->offset;
9814 else
9815 funcrecord->oHelpString = -1;
9816 if(!desc->Entry)
9817 funcrecord->oEntry = -1;
9818 else if(IS_INTRESOURCE(desc->Entry))
9819 funcrecord->oEntry = LOWORD(desc->Entry);
9820 else
9821 funcrecord->oEntry = desc->Entry->offset;
9822 }else if(desc->HelpString){
9823 size += 2 * sizeof(INT);
9824 funcrecord->HelpContext = desc->helpcontext;
9825 funcrecord->oHelpString = desc->HelpString->offset;
9826 }else if(desc->helpcontext){
9827 size += sizeof(INT);
9828 funcrecord->HelpContext = desc->helpcontext;
9831 paramdefault = (DWORD*)((char *)funcrecord + size);
9832 size += paramdefault_size;
9834 for(j = 0; j < desc->funcdesc.cParams; ++j){
9835 MSFT_ParameterInfo *info = (MSFT_ParameterInfo*)(((char *)funcrecord) + size);
9837 info->DataType = WMSFT_append_typedesc(&desc->funcdesc.lprgelemdescParam[j].tdesc, file, NULL, &funcrecord->funcdescsize);
9838 if(desc->pParamDesc[j].Name)
9839 info->oName = desc->pParamDesc[j].Name->offset;
9840 else
9841 info->oName = -1;
9842 info->Flags = desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags;
9844 if(paramdefault_size){
9845 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
9846 *paramdefault = WMSFT_encode_variant(&desc->funcdesc.lprgelemdescParam[j].u.paramdesc.pparamdescex->varDefaultValue, file);
9847 else if(paramdefault_size)
9848 *paramdefault = -1;
9849 ++paramdefault;
9852 size += sizeof(MSFT_ParameterInfo);
9855 funcrecord->Info = size | (i << 16); /* is it just the index? */
9857 *offsets = offs;
9858 offs += size;
9859 ++offsets;
9861 funcrecord = (MSFT_FuncRecord*)(((char*)funcrecord) + size);
9864 varrecord = (MSFT_VarRecord*)funcrecord;
9865 for(i = 0; i < info->typeattr.cVars; ++i){
9866 TLBVarDesc *desc = &info->vardescs[i];
9867 DWORD size = 5 * sizeof(INT);
9869 varrecord->vardescsize = sizeof(desc->vardesc);
9870 varrecord->DataType = WMSFT_append_typedesc(&desc->vardesc.elemdescVar.tdesc, file, NULL, &varrecord->vardescsize);
9871 varrecord->Flags = desc->vardesc.wVarFlags;
9872 varrecord->VarKind = desc->vardesc.varkind;
9874 if(desc->vardesc.varkind == VAR_CONST){
9875 varrecord->vardescsize += sizeof(VARIANT);
9876 varrecord->OffsValue = WMSFT_encode_variant(desc->vardesc.u.lpvarValue, file);
9877 }else
9878 varrecord->OffsValue = desc->vardesc.u.oInst;
9880 /* res9? */
9881 if(desc->HelpStringContext != 0){
9882 size += 5 * sizeof(INT);
9883 varrecord->HelpContext = desc->HelpContext;
9884 if(desc->HelpString)
9885 varrecord->HelpString = desc->HelpString->offset;
9886 else
9887 varrecord->HelpString = -1;
9888 varrecord->res9 = -1;
9889 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9890 varrecord->HelpStringContext = desc->HelpStringContext;
9891 }else if(!list_empty(&desc->custdata_list)){
9892 size += 4 * sizeof(INT);
9893 varrecord->HelpContext = desc->HelpContext;
9894 if(desc->HelpString)
9895 varrecord->HelpString = desc->HelpString->offset;
9896 else
9897 varrecord->HelpString = -1;
9898 varrecord->res9 = -1;
9899 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9900 }else if(desc->HelpString){
9901 size += 2 * sizeof(INT);
9902 varrecord->HelpContext = desc->HelpContext;
9903 if(desc->HelpString)
9904 varrecord->HelpString = desc->HelpString->offset;
9905 else
9906 varrecord->HelpString = -1;
9907 }else if(desc->HelpContext != 0){
9908 size += sizeof(INT);
9909 varrecord->HelpContext = desc->HelpContext;
9912 varrecord->Info = size | (i << 16);
9914 *offsets = offs;
9915 offs += size;
9916 ++offsets;
9918 varrecord = (MSFT_VarRecord*)(((char*)varrecord) + size);
9921 memid = (MEMBERID*)varrecord;
9922 for(i = 0; i < info->typeattr.cFuncs; ++i){
9923 TLBFuncDesc *desc = &info->funcdescs[i];
9924 *memid = desc->funcdesc.memid;
9925 ++memid;
9927 for(i = 0; i < info->typeattr.cVars; ++i){
9928 TLBVarDesc *desc = &info->vardescs[i];
9929 *memid = desc->vardesc.memid;
9930 ++memid;
9933 name = (UINT*)memid;
9934 for(i = 0; i < info->typeattr.cFuncs; ++i){
9935 TLBFuncDesc *desc = &info->funcdescs[i];
9936 if(desc->Name)
9937 *name = desc->Name->offset;
9938 else
9939 *name = -1;
9940 ++name;
9942 for(i = 0; i < info->typeattr.cVars; ++i){
9943 TLBVarDesc *desc = &info->vardescs[i];
9944 if(desc->Name)
9945 *name = desc->Name->offset;
9946 else
9947 *name = -1;
9948 ++name;
9951 return ret;
9954 typedef struct tagWMSFT_RefChunk {
9955 DWORD href;
9956 DWORD res04;
9957 DWORD res08;
9958 DWORD next;
9959 } WMSFT_RefChunk;
9961 static DWORD WMSFT_compile_typeinfo_ref(ITypeInfoImpl *info, WMSFT_TLBFile *file)
9963 DWORD offs = file->ref_seg.len, i;
9964 WMSFT_RefChunk *chunk;
9966 file->ref_seg.len += info->typeattr.cImplTypes * sizeof(WMSFT_RefChunk);
9967 if(!file->ref_seg.data)
9968 file->ref_seg.data = heap_alloc(file->ref_seg.len);
9969 else
9970 file->ref_seg.data = heap_realloc(file->ref_seg.data, file->ref_seg.len);
9972 chunk = (WMSFT_RefChunk*)((char*)file->ref_seg.data + offs);
9974 for(i = 0; i < info->typeattr.cImplTypes; ++i){
9975 chunk->href = info->impltypes[i].hRef;
9976 chunk->res04 = info->impltypes[i].implflags;
9977 chunk->res08 = -1;
9978 if(i < info->typeattr.cImplTypes - 1)
9979 chunk->next = offs + sizeof(WMSFT_RefChunk) * (i + 1);
9980 else
9981 chunk->next = -1;
9982 ++chunk;
9985 return offs;
9988 static DWORD WMSFT_compile_typeinfo(ITypeInfoImpl *info, INT16 index, WMSFT_TLBFile *file, char *data)
9990 DWORD size;
9992 size = sizeof(MSFT_TypeInfoBase);
9994 if(data){
9995 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase*)data;
9996 if(info->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
9997 base->typekind = TKIND_DISPATCH;
9998 else
9999 base->typekind = info->typeattr.typekind;
10000 base->typekind |= index << 16; /* TODO: There are some other flags here */
10001 base->typekind |= (info->typeattr.cbAlignment << 11) | (info->typeattr.cbAlignment << 6);
10002 base->memoffset = WMSFT_compile_typeinfo_aux(info, file);
10003 base->res2 = 0;
10004 base->res3 = 0;
10005 base->res4 = 3;
10006 base->res5 = 0;
10007 base->cElement = (info->typeattr.cVars << 16) | info->typeattr.cFuncs;
10008 base->res7 = 0;
10009 base->res8 = 0;
10010 base->res9 = 0;
10011 base->resA = 0;
10012 if(info->guid)
10013 base->posguid = info->guid->offset;
10014 else
10015 base->posguid = -1;
10016 base->flags = info->typeattr.wTypeFlags;
10017 if(info->Name) {
10018 base->NameOffset = info->Name->offset;
10020 ((unsigned char*)file->name_seg.data)[info->Name->offset+9] = 0x38;
10021 *(HREFTYPE*)((unsigned char*)file->name_seg.data+info->Name->offset) = info->hreftype;
10022 }else {
10023 base->NameOffset = -1;
10025 base->version = (info->typeattr.wMinorVerNum << 16) | info->typeattr.wMajorVerNum;
10026 if(info->DocString)
10027 base->docstringoffs = info->DocString->offset;
10028 else
10029 base->docstringoffs = -1;
10030 base->helpstringcontext = info->dwHelpStringContext;
10031 base->helpcontext = info->dwHelpContext;
10032 base->oCustData = WMSFT_compile_custdata(info->pcustdata_list, file);
10033 base->cImplTypes = info->typeattr.cImplTypes;
10034 base->cbSizeVft = info->typeattr.cbSizeVft;
10035 base->size = info->typeattr.cbSizeInstance;
10036 if(info->typeattr.typekind == TKIND_COCLASS){
10037 base->datatype1 = WMSFT_compile_typeinfo_ref(info, file);
10038 }else if(info->typeattr.typekind == TKIND_ALIAS){
10039 base->datatype1 = WMSFT_append_typedesc(info->tdescAlias, file, NULL, NULL);
10040 }else if(info->typeattr.typekind == TKIND_MODULE){
10041 if(info->DllName)
10042 base->datatype1 = info->DllName->offset;
10043 else
10044 base->datatype1 = -1;
10045 }else{
10046 if(info->typeattr.cImplTypes > 0)
10047 base->datatype1 = info->impltypes[0].hRef;
10048 else
10049 base->datatype1 = -1;
10051 base->datatype2 = index; /* FIXME: i think there's more here */
10052 base->res18 = 0;
10053 base->res19 = -1;
10056 return size;
10059 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl *This, WMSFT_TLBFile *file, DWORD *junk)
10061 UINT i;
10063 file->typeinfo_seg.len = 0;
10064 for(i = 0; i < This->TypeInfoCount; ++i){
10065 ITypeInfoImpl *info = This->typeinfos[i];
10066 *junk = file->typeinfo_seg.len;
10067 ++junk;
10068 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, NULL, NULL);
10071 file->typeinfo_seg.data = heap_alloc(file->typeinfo_seg.len);
10072 memset(file->typeinfo_seg.data, 0x96, file->typeinfo_seg.len);
10074 file->aux_seg.len = 0;
10075 file->aux_seg.data = NULL;
10077 file->typeinfo_seg.len = 0;
10078 for(i = 0; i < This->TypeInfoCount; ++i){
10079 ITypeInfoImpl *info = This->typeinfos[i];
10080 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, file,
10081 ((char *)file->typeinfo_seg.data) + file->typeinfo_seg.len);
10085 typedef struct tagWMSFT_ImpFile {
10086 INT guid_offs;
10087 LCID lcid;
10088 DWORD version;
10089 } WMSFT_ImpFile;
10091 static void WMSFT_compile_impfile(ITypeLibImpl *This, WMSFT_TLBFile *file)
10093 TLBImpLib *implib;
10094 WMSFT_ImpFile *impfile;
10095 char *data;
10096 DWORD last_offs = 0;
10098 file->impfile_seg.len = 0;
10099 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
10100 int size = 0;
10102 if(implib->name){
10103 WCHAR *path = wcsrchr(implib->name, '\\');
10104 if(path)
10105 ++path;
10106 else
10107 path = implib->name;
10108 size = WideCharToMultiByte(CP_ACP, 0, path, lstrlenW(path), NULL, 0, NULL, NULL);
10109 if (size == 0)
10110 ERR("failed to convert wide string: %s\n", debugstr_w(path));
10113 size += sizeof(INT16);
10114 if (size % 4)
10115 size = (size + 4) & ~0x3;
10116 if (size < 8)
10117 size = 8;
10119 file->impfile_seg.len += sizeof(WMSFT_ImpFile) + size;
10122 data = file->impfile_seg.data = heap_alloc(file->impfile_seg.len);
10124 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
10125 int strlen = 0, size;
10127 impfile = (WMSFT_ImpFile*)data;
10128 impfile->guid_offs = implib->guid->offset;
10129 impfile->lcid = implib->lcid;
10130 impfile->version = (implib->wVersionMinor << 16) | implib->wVersionMajor;
10132 data += sizeof(WMSFT_ImpFile);
10134 if(implib->name){
10135 WCHAR *path= wcsrchr(implib->name, '\\');
10136 if(path)
10137 ++path;
10138 else
10139 path = implib->name;
10140 strlen = WideCharToMultiByte(CP_ACP, 0, path, lstrlenW(path),
10141 data + sizeof(INT16), file->impfile_seg.len - last_offs - sizeof(INT16), NULL, NULL);
10142 if (strlen == 0)
10143 ERR("failed to convert wide string: %s\n", debugstr_w(path));
10146 *((INT16*)data) = (strlen << 2) | 1; /* FIXME: is that a flag, or what? */
10148 size = strlen + sizeof(INT16);
10149 if (size % 4)
10150 size = (size + 4) & ~0x3;
10151 if (size < 8)
10152 size = 8;
10153 memset(data + sizeof(INT16) + strlen, 0x57, size - strlen - sizeof(INT16));
10155 data += size;
10156 implib->offset = last_offs;
10157 last_offs += size + sizeof(WMSFT_ImpFile);
10161 static void WMSFT_compile_impinfo(ITypeLibImpl *This, WMSFT_TLBFile *file)
10163 MSFT_ImpInfo *info;
10164 TLBRefType *ref_type;
10165 UINT i = 0;
10167 WMSFT_compile_impfile(This, file);
10169 file->impinfo_seg.len = sizeof(MSFT_ImpInfo) * list_count(&This->ref_list);
10170 info = file->impinfo_seg.data = heap_alloc(file->impinfo_seg.len);
10172 LIST_FOR_EACH_ENTRY(ref_type, &This->ref_list, TLBRefType, entry){
10173 info->flags = i | ((ref_type->tkind & 0xFF) << 24);
10174 if(ref_type->index == TLB_REF_USE_GUID){
10175 info->flags |= MSFT_IMPINFO_OFFSET_IS_GUID;
10176 info->oGuid = ref_type->guid->offset;
10177 }else
10178 info->oGuid = ref_type->index;
10179 info->oImpFile = ref_type->pImpTLInfo->offset;
10180 ++i;
10181 ++info;
10185 static void WMSFT_compile_guidhash(ITypeLibImpl *This, WMSFT_TLBFile *file)
10187 file->guidhash_seg.len = 0x80;
10188 file->guidhash_seg.data = heap_alloc(file->guidhash_seg.len);
10189 memset(file->guidhash_seg.data, 0xFF, file->guidhash_seg.len);
10192 static void WMSFT_compile_namehash(ITypeLibImpl *This, WMSFT_TLBFile *file)
10194 file->namehash_seg.len = 0x200;
10195 file->namehash_seg.data = heap_alloc(file->namehash_seg.len);
10196 memset(file->namehash_seg.data, 0xFF, file->namehash_seg.len);
10199 static void tmp_fill_segdir_seg(MSFT_pSeg *segdir, WMSFT_SegContents *contents, DWORD *running_offset)
10201 if(contents && contents->len){
10202 segdir->offset = *running_offset;
10203 segdir->length = contents->len;
10204 *running_offset += segdir->length;
10205 }else{
10206 segdir->offset = -1;
10207 segdir->length = 0;
10210 /* TODO: do these ever change? */
10211 segdir->res08 = -1;
10212 segdir->res0c = 0xf;
10215 static void WMSFT_write_segment(HANDLE outfile, WMSFT_SegContents *segment)
10217 DWORD written;
10218 if(segment)
10219 WriteFile(outfile, segment->data, segment->len, &written, NULL);
10222 static HRESULT WMSFT_fixup_typeinfos(ITypeLibImpl *This, WMSFT_TLBFile *file,
10223 DWORD file_len)
10225 DWORD i;
10226 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase *)file->typeinfo_seg.data;
10228 for(i = 0; i < This->TypeInfoCount; ++i){
10229 base->memoffset += file_len;
10230 ++base;
10233 return S_OK;
10236 static void WMSFT_free_file(WMSFT_TLBFile *file)
10238 HeapFree(GetProcessHeap(), 0, file->typeinfo_seg.data);
10239 HeapFree(GetProcessHeap(), 0, file->guidhash_seg.data);
10240 HeapFree(GetProcessHeap(), 0, file->guid_seg.data);
10241 HeapFree(GetProcessHeap(), 0, file->ref_seg.data);
10242 HeapFree(GetProcessHeap(), 0, file->impinfo_seg.data);
10243 HeapFree(GetProcessHeap(), 0, file->impfile_seg.data);
10244 HeapFree(GetProcessHeap(), 0, file->namehash_seg.data);
10245 HeapFree(GetProcessHeap(), 0, file->name_seg.data);
10246 HeapFree(GetProcessHeap(), 0, file->string_seg.data);
10247 HeapFree(GetProcessHeap(), 0, file->typdesc_seg.data);
10248 HeapFree(GetProcessHeap(), 0, file->arraydesc_seg.data);
10249 HeapFree(GetProcessHeap(), 0, file->custdata_seg.data);
10250 HeapFree(GetProcessHeap(), 0, file->cdguids_seg.data);
10251 HeapFree(GetProcessHeap(), 0, file->aux_seg.data);
10254 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
10256 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10257 WMSFT_TLBFile file;
10258 DWORD written, junk_size, junk_offs, running_offset;
10259 BOOL br;
10260 HANDLE outfile;
10261 HRESULT hres;
10262 DWORD *junk;
10263 UINT i;
10265 TRACE("%p\n", This);
10267 for(i = 0; i < This->TypeInfoCount; ++i)
10268 if(This->typeinfos[i]->needs_layout)
10269 ICreateTypeInfo2_LayOut(&This->typeinfos[i]->ICreateTypeInfo2_iface);
10271 memset(&file, 0, sizeof(file));
10273 file.header.magic1 = 0x5446534D;
10274 file.header.magic2 = 0x00010002;
10275 file.header.lcid = This->set_lcid ? This->set_lcid : MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
10276 file.header.lcid2 = This->set_lcid;
10277 file.header.varflags = 0x40 | This->syskind;
10278 if (This->HelpFile)
10279 file.header.varflags |= 0x10;
10280 if (This->HelpStringDll)
10281 file.header.varflags |= HELPDLLFLAG;
10282 file.header.version = (This->ver_minor << 16) | This->ver_major;
10283 file.header.flags = This->libflags;
10284 file.header.helpstringcontext = 0; /* TODO - SetHelpStringContext not implemented yet */
10285 file.header.helpcontext = This->dwHelpContext;
10286 file.header.res44 = 0x20;
10287 file.header.res48 = 0x80;
10288 file.header.dispatchpos = This->dispatch_href;
10290 WMSFT_compile_namehash(This, &file);
10291 /* do name and string compilation to get offsets for other compilations */
10292 hres = WMSFT_compile_names(This, &file);
10293 if (FAILED(hres)){
10294 WMSFT_free_file(&file);
10295 return hres;
10298 hres = WMSFT_compile_strings(This, &file);
10299 if (FAILED(hres)){
10300 WMSFT_free_file(&file);
10301 return hres;
10304 WMSFT_compile_guidhash(This, &file);
10305 hres = WMSFT_compile_guids(This, &file);
10306 if (FAILED(hres)){
10307 WMSFT_free_file(&file);
10308 return hres;
10311 if(This->HelpFile)
10312 file.header.helpfile = This->HelpFile->offset;
10313 else
10314 file.header.helpfile = -1;
10316 if(This->DocString)
10317 file.header.helpstring = This->DocString->offset;
10318 else
10319 file.header.helpstring = -1;
10321 /* do some more segment compilation */
10322 file.header.nimpinfos = list_count(&This->ref_list);
10323 file.header.nrtypeinfos = This->TypeInfoCount;
10325 if(This->Name)
10326 file.header.NameOffset = This->Name->offset;
10327 else
10328 file.header.NameOffset = -1;
10330 file.header.CustomDataOffset = WMSFT_compile_custdata(&This->custdata_list, &file);
10332 if(This->guid)
10333 file.header.posguid = This->guid->offset;
10334 else
10335 file.header.posguid = -1;
10337 junk_size = file.header.nrtypeinfos * sizeof(DWORD);
10338 if(file.header.varflags & HELPDLLFLAG)
10339 junk_size += sizeof(DWORD);
10340 if(junk_size){
10341 junk = heap_alloc_zero(junk_size);
10342 if(file.header.varflags & HELPDLLFLAG){
10343 *junk = This->HelpStringDll->offset;
10344 junk_offs = 1;
10345 }else
10346 junk_offs = 0;
10347 }else{
10348 junk = NULL;
10349 junk_offs = 0;
10352 WMSFT_compile_typeinfo_seg(This, &file, junk + junk_offs);
10353 WMSFT_compile_impinfo(This, &file);
10355 running_offset = 0;
10357 TRACE("header at: 0x%x\n", running_offset);
10358 running_offset += sizeof(file.header);
10360 TRACE("junk at: 0x%x\n", running_offset);
10361 running_offset += junk_size;
10363 TRACE("segdir at: 0x%x\n", running_offset);
10364 running_offset += sizeof(file.segdir);
10366 TRACE("typeinfo at: 0x%x\n", running_offset);
10367 tmp_fill_segdir_seg(&file.segdir.pTypeInfoTab, &file.typeinfo_seg, &running_offset);
10369 TRACE("guidhashtab at: 0x%x\n", running_offset);
10370 tmp_fill_segdir_seg(&file.segdir.pGuidHashTab, &file.guidhash_seg, &running_offset);
10372 TRACE("guidtab at: 0x%x\n", running_offset);
10373 tmp_fill_segdir_seg(&file.segdir.pGuidTab, &file.guid_seg, &running_offset);
10375 TRACE("reftab at: 0x%x\n", running_offset);
10376 tmp_fill_segdir_seg(&file.segdir.pRefTab, &file.ref_seg, &running_offset);
10378 TRACE("impinfo at: 0x%x\n", running_offset);
10379 tmp_fill_segdir_seg(&file.segdir.pImpInfo, &file.impinfo_seg, &running_offset);
10381 TRACE("impfiles at: 0x%x\n", running_offset);
10382 tmp_fill_segdir_seg(&file.segdir.pImpFiles, &file.impfile_seg, &running_offset);
10384 TRACE("namehashtab at: 0x%x\n", running_offset);
10385 tmp_fill_segdir_seg(&file.segdir.pNameHashTab, &file.namehash_seg, &running_offset);
10387 TRACE("nametab at: 0x%x\n", running_offset);
10388 tmp_fill_segdir_seg(&file.segdir.pNametab, &file.name_seg, &running_offset);
10390 TRACE("stringtab at: 0x%x\n", running_offset);
10391 tmp_fill_segdir_seg(&file.segdir.pStringtab, &file.string_seg, &running_offset);
10393 TRACE("typdesc at: 0x%x\n", running_offset);
10394 tmp_fill_segdir_seg(&file.segdir.pTypdescTab, &file.typdesc_seg, &running_offset);
10396 TRACE("arraydescriptions at: 0x%x\n", running_offset);
10397 tmp_fill_segdir_seg(&file.segdir.pArrayDescriptions, &file.arraydesc_seg, &running_offset);
10399 TRACE("custdata at: 0x%x\n", running_offset);
10400 tmp_fill_segdir_seg(&file.segdir.pCustData, &file.custdata_seg, &running_offset);
10402 TRACE("cdguids at: 0x%x\n", running_offset);
10403 tmp_fill_segdir_seg(&file.segdir.pCDGuids, &file.cdguids_seg, &running_offset);
10405 TRACE("res0e at: 0x%x\n", running_offset);
10406 tmp_fill_segdir_seg(&file.segdir.res0e, NULL, &running_offset);
10408 TRACE("res0f at: 0x%x\n", running_offset);
10409 tmp_fill_segdir_seg(&file.segdir.res0f, NULL, &running_offset);
10411 TRACE("aux_seg at: 0x%x\n", running_offset);
10413 WMSFT_fixup_typeinfos(This, &file, running_offset);
10415 outfile = CreateFileW(This->path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
10416 FILE_ATTRIBUTE_NORMAL, 0);
10417 if (outfile == INVALID_HANDLE_VALUE){
10418 WMSFT_free_file(&file);
10419 heap_free(junk);
10420 return TYPE_E_IOERROR;
10423 br = WriteFile(outfile, &file.header, sizeof(file.header), &written, NULL);
10424 if (!br) {
10425 WMSFT_free_file(&file);
10426 CloseHandle(outfile);
10427 heap_free(junk);
10428 return TYPE_E_IOERROR;
10431 br = WriteFile(outfile, junk, junk_size, &written, NULL);
10432 heap_free(junk);
10433 if (!br) {
10434 WMSFT_free_file(&file);
10435 CloseHandle(outfile);
10436 return TYPE_E_IOERROR;
10439 br = WriteFile(outfile, &file.segdir, sizeof(file.segdir), &written, NULL);
10440 if (!br) {
10441 WMSFT_free_file(&file);
10442 CloseHandle(outfile);
10443 return TYPE_E_IOERROR;
10446 WMSFT_write_segment(outfile, &file.typeinfo_seg);
10447 WMSFT_write_segment(outfile, &file.guidhash_seg);
10448 WMSFT_write_segment(outfile, &file.guid_seg);
10449 WMSFT_write_segment(outfile, &file.ref_seg);
10450 WMSFT_write_segment(outfile, &file.impinfo_seg);
10451 WMSFT_write_segment(outfile, &file.impfile_seg);
10452 WMSFT_write_segment(outfile, &file.namehash_seg);
10453 WMSFT_write_segment(outfile, &file.name_seg);
10454 WMSFT_write_segment(outfile, &file.string_seg);
10455 WMSFT_write_segment(outfile, &file.typdesc_seg);
10456 WMSFT_write_segment(outfile, &file.arraydesc_seg);
10457 WMSFT_write_segment(outfile, &file.custdata_seg);
10458 WMSFT_write_segment(outfile, &file.cdguids_seg);
10459 WMSFT_write_segment(outfile, &file.aux_seg);
10461 WMSFT_free_file(&file);
10463 CloseHandle(outfile);
10465 return S_OK;
10468 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
10469 LPOLESTR name)
10471 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10472 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
10473 return E_NOTIMPL;
10476 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
10477 REFGUID guid, VARIANT *varVal)
10479 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10480 TLBGuid *tlbguid;
10482 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
10484 if (!guid || !varVal)
10485 return E_INVALIDARG;
10487 tlbguid = TLB_append_guid(&This->guid_list, guid, -1);
10489 return TLB_set_custdata(&This->custdata_list, tlbguid, varVal);
10492 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
10493 ULONG helpStringContext)
10495 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10496 FIXME("%p %u - stub\n", This, helpStringContext);
10497 return E_NOTIMPL;
10500 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
10501 LPOLESTR filename)
10503 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10504 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
10506 if (!filename)
10507 return E_INVALIDARG;
10509 This->HelpStringDll = TLB_append_str(&This->string_list, filename);
10511 return S_OK;
10514 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
10515 ICreateTypeLib2_fnQueryInterface,
10516 ICreateTypeLib2_fnAddRef,
10517 ICreateTypeLib2_fnRelease,
10518 ICreateTypeLib2_fnCreateTypeInfo,
10519 ICreateTypeLib2_fnSetName,
10520 ICreateTypeLib2_fnSetVersion,
10521 ICreateTypeLib2_fnSetGuid,
10522 ICreateTypeLib2_fnSetDocString,
10523 ICreateTypeLib2_fnSetHelpFileName,
10524 ICreateTypeLib2_fnSetHelpContext,
10525 ICreateTypeLib2_fnSetLcid,
10526 ICreateTypeLib2_fnSetLibFlags,
10527 ICreateTypeLib2_fnSaveAllChanges,
10528 ICreateTypeLib2_fnDeleteTypeInfo,
10529 ICreateTypeLib2_fnSetCustData,
10530 ICreateTypeLib2_fnSetHelpStringContext,
10531 ICreateTypeLib2_fnSetHelpStringDll
10534 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
10535 REFIID riid, void **object)
10537 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10539 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, object);
10542 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
10544 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10546 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
10549 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
10551 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10553 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
10556 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
10557 REFGUID guid)
10559 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10561 TRACE("%p %s\n", This, debugstr_guid(guid));
10563 This->guid = TLB_append_guid(&This->pTypeLib->guid_list, guid, This->hreftype);
10565 return S_OK;
10568 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
10569 UINT typeFlags)
10571 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10572 WORD old_flags;
10573 HRESULT hres;
10575 TRACE("%p %x\n", This, typeFlags);
10577 if (typeFlags & TYPEFLAG_FDUAL) {
10578 static const WCHAR stdole2tlb[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10579 ITypeLib *stdole;
10580 ITypeInfo *dispatch;
10581 HREFTYPE hreftype;
10582 HRESULT hres;
10584 hres = LoadTypeLib(stdole2tlb, &stdole);
10585 if(FAILED(hres))
10586 return hres;
10588 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
10589 ITypeLib_Release(stdole);
10590 if(FAILED(hres))
10591 return hres;
10593 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
10594 ITypeInfo_Release(dispatch);
10595 if(FAILED(hres))
10596 return hres;
10599 old_flags = This->typeattr.wTypeFlags;
10600 This->typeattr.wTypeFlags = typeFlags;
10602 hres = ICreateTypeInfo2_LayOut(iface);
10603 if (FAILED(hres)) {
10604 This->typeattr.wTypeFlags = old_flags;
10605 return hres;
10608 return S_OK;
10611 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
10612 LPOLESTR doc)
10614 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10616 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
10618 if (!doc)
10619 return E_INVALIDARG;
10621 This->DocString = TLB_append_str(&This->pTypeLib->string_list, doc);
10623 return S_OK;
10626 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
10627 DWORD helpContext)
10629 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10631 TRACE("%p %d\n", This, helpContext);
10633 This->dwHelpContext = helpContext;
10635 return S_OK;
10638 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
10639 WORD majorVerNum, WORD minorVerNum)
10641 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10643 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
10645 This->typeattr.wMajorVerNum = majorVerNum;
10646 This->typeattr.wMinorVerNum = minorVerNum;
10648 return S_OK;
10651 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
10652 ITypeInfo *typeInfo, HREFTYPE *refType)
10654 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10655 UINT index;
10656 ITypeLib *container;
10657 TLBRefType *ref_type;
10658 TLBImpLib *implib;
10659 TYPEATTR *typeattr;
10660 TLIBATTR *libattr;
10661 HRESULT hres;
10663 TRACE("%p %p %p\n", This, typeInfo, refType);
10665 if (!typeInfo || !refType)
10666 return E_INVALIDARG;
10668 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
10669 if (FAILED(hres))
10670 return hres;
10672 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
10673 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
10675 ITypeLib_Release(container);
10677 *refType = target->hreftype;
10679 return S_OK;
10682 hres = ITypeLib_GetLibAttr(container, &libattr);
10683 if (FAILED(hres)) {
10684 ITypeLib_Release(container);
10685 return hres;
10688 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
10689 if(IsEqualGUID(&implib->guid->guid, &libattr->guid) &&
10690 implib->lcid == libattr->lcid &&
10691 implib->wVersionMajor == libattr->wMajorVerNum &&
10692 implib->wVersionMinor == libattr->wMinorVerNum)
10693 break;
10696 if(&implib->entry == &This->pTypeLib->implib_list){
10697 implib = heap_alloc_zero(sizeof(TLBImpLib));
10699 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
10700 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
10701 implib->name = SysAllocString(our_container->path);
10702 }else{
10703 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
10704 libattr->wMinorVerNum, libattr->lcid, &implib->name);
10705 if(FAILED(hres)){
10706 implib->name = NULL;
10707 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres);
10711 implib->guid = TLB_append_guid(&This->pTypeLib->guid_list, &libattr->guid, 2);
10712 implib->lcid = libattr->lcid;
10713 implib->wVersionMajor = libattr->wMajorVerNum;
10714 implib->wVersionMinor = libattr->wMinorVerNum;
10716 list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
10719 ITypeLib_ReleaseTLibAttr(container, libattr);
10720 ITypeLib_Release(container);
10722 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
10723 if (FAILED(hres))
10724 return hres;
10726 index = 0;
10727 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
10728 if(ref_type->index == TLB_REF_USE_GUID &&
10729 IsEqualGUID(&ref_type->guid->guid, &typeattr->guid) &&
10730 ref_type->tkind == typeattr->typekind)
10731 break;
10732 ++index;
10735 if(&ref_type->entry == &This->pTypeLib->ref_list){
10736 ref_type = heap_alloc_zero(sizeof(TLBRefType));
10738 ref_type->tkind = typeattr->typekind;
10739 ref_type->pImpTLInfo = implib;
10740 ref_type->reference = index * sizeof(MSFT_ImpInfo);
10742 ref_type->index = TLB_REF_USE_GUID;
10744 ref_type->guid = TLB_append_guid(&This->pTypeLib->guid_list, &typeattr->guid, ref_type->reference+1);
10746 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
10749 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
10751 *refType = ref_type->reference | 0x1;
10753 if(IsEqualGUID(&ref_type->guid->guid, &IID_IDispatch))
10754 This->pTypeLib->dispatch_href = *refType;
10756 return S_OK;
10759 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
10760 UINT index, FUNCDESC *funcDesc)
10762 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10763 TLBFuncDesc tmp_func_desc, *func_desc;
10764 int buf_size, i;
10765 char *buffer;
10766 HRESULT hres;
10768 TRACE("%p %u %p\n", This, index, funcDesc);
10770 if (!funcDesc || funcDesc->oVft & 3)
10771 return E_INVALIDARG;
10773 switch (This->typeattr.typekind) {
10774 case TKIND_MODULE:
10775 if (funcDesc->funckind != FUNC_STATIC)
10776 return TYPE_E_BADMODULEKIND;
10777 break;
10778 case TKIND_DISPATCH:
10779 if (funcDesc->funckind != FUNC_DISPATCH)
10780 return TYPE_E_BADMODULEKIND;
10781 break;
10782 default:
10783 if (funcDesc->funckind != FUNC_PUREVIRTUAL)
10784 return TYPE_E_BADMODULEKIND;
10787 if (index > This->typeattr.cFuncs)
10788 return TYPE_E_ELEMENTNOTFOUND;
10790 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) &&
10791 !funcDesc->cParams)
10792 return TYPE_E_INCONSISTENTPROPFUNCS;
10794 #ifdef _WIN64
10795 if(This->pTypeLib->syskind == SYS_WIN64 &&
10796 funcDesc->oVft % 8 != 0)
10797 return E_INVALIDARG;
10798 #endif
10800 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc));
10801 TLBFuncDesc_Constructor(&tmp_func_desc);
10803 tmp_func_desc.funcdesc = *funcDesc;
10805 if (tmp_func_desc.funcdesc.oVft != 0)
10806 tmp_func_desc.funcdesc.oVft |= 1;
10808 if (funcDesc->cScodes && funcDesc->lprgscode) {
10809 tmp_func_desc.funcdesc.lprgscode = heap_alloc(sizeof(SCODE) * funcDesc->cScodes);
10810 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes);
10811 } else {
10812 tmp_func_desc.funcdesc.lprgscode = NULL;
10813 tmp_func_desc.funcdesc.cScodes = 0;
10816 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc);
10817 for (i = 0; i < funcDesc->cParams; ++i) {
10818 buf_size += sizeof(ELEMDESC);
10819 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i);
10821 tmp_func_desc.funcdesc.lprgelemdescParam = heap_alloc(buf_size);
10822 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams);
10824 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer);
10825 if (FAILED(hres)) {
10826 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10827 heap_free(tmp_func_desc.funcdesc.lprgscode);
10828 return hres;
10831 for (i = 0; i < funcDesc->cParams; ++i) {
10832 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i,
10833 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer);
10834 if (FAILED(hres)) {
10835 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10836 heap_free(tmp_func_desc.funcdesc.lprgscode);
10837 return hres;
10839 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT &&
10840 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT &&
10841 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){
10842 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
10843 if (FAILED(hres)) {
10844 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10845 heap_free(tmp_func_desc.funcdesc.lprgscode);
10846 return hres;
10851 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams);
10853 if (This->funcdescs) {
10854 This->funcdescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->funcdescs,
10855 sizeof(TLBFuncDesc) * (This->typeattr.cFuncs + 1));
10857 if (index < This->typeattr.cFuncs) {
10858 memmove(This->funcdescs + index + 1, This->funcdescs + index,
10859 (This->typeattr.cFuncs - index) * sizeof(TLBFuncDesc));
10860 func_desc = This->funcdescs + index;
10861 } else
10862 func_desc = This->funcdescs + This->typeattr.cFuncs;
10864 /* move custdata lists to the new memory location */
10865 for(i = 0; i < This->typeattr.cFuncs + 1; ++i){
10866 if(index != i)
10867 TLB_relink_custdata(&This->funcdescs[i].custdata_list);
10869 } else
10870 func_desc = This->funcdescs = heap_alloc(sizeof(TLBFuncDesc));
10872 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc));
10873 list_init(&func_desc->custdata_list);
10875 ++This->typeattr.cFuncs;
10877 This->needs_layout = TRUE;
10879 return S_OK;
10882 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
10883 UINT index, HREFTYPE refType)
10885 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10886 TLBImplType *impl_type;
10887 HRESULT hres;
10889 TRACE("%p %u %d\n", This, index, refType);
10891 switch(This->typeattr.typekind){
10892 case TKIND_COCLASS: {
10893 if (index == -1) {
10894 FIXME("Unhandled index: -1\n");
10895 return E_NOTIMPL;
10898 if(index != This->typeattr.cImplTypes)
10899 return TYPE_E_ELEMENTNOTFOUND;
10901 break;
10903 case TKIND_INTERFACE:
10904 case TKIND_DISPATCH:
10905 if (index != 0 || This->typeattr.cImplTypes)
10906 return TYPE_E_ELEMENTNOTFOUND;
10907 break;
10908 default:
10909 FIXME("Unimplemented typekind: %d\n", This->typeattr.typekind);
10910 return E_NOTIMPL;
10913 if (This->impltypes){
10914 UINT i;
10916 This->impltypes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->impltypes,
10917 sizeof(TLBImplType) * (This->typeattr.cImplTypes + 1));
10919 if (index < This->typeattr.cImplTypes) {
10920 memmove(This->impltypes + index + 1, This->impltypes + index,
10921 (This->typeattr.cImplTypes - index) * sizeof(TLBImplType));
10922 impl_type = This->impltypes + index;
10923 } else
10924 impl_type = This->impltypes + This->typeattr.cImplTypes;
10926 /* move custdata lists to the new memory location */
10927 for(i = 0; i < This->typeattr.cImplTypes + 1; ++i){
10928 if(index != i)
10929 TLB_relink_custdata(&This->impltypes[i].custdata_list);
10931 } else
10932 impl_type = This->impltypes = heap_alloc(sizeof(TLBImplType));
10934 memset(impl_type, 0, sizeof(TLBImplType));
10935 TLBImplType_Constructor(impl_type);
10936 impl_type->hRef = refType;
10938 ++This->typeattr.cImplTypes;
10940 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
10941 This->typeattr.wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
10943 hres = ICreateTypeInfo2_LayOut(iface);
10944 if (FAILED(hres))
10945 return hres;
10947 return S_OK;
10950 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
10951 UINT index, INT implTypeFlags)
10953 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10954 TLBImplType *impl_type = &This->impltypes[index];
10956 TRACE("%p %u %x\n", This, index, implTypeFlags);
10958 if (This->typeattr.typekind != TKIND_COCLASS)
10959 return TYPE_E_BADMODULEKIND;
10961 if (index >= This->typeattr.cImplTypes)
10962 return TYPE_E_ELEMENTNOTFOUND;
10964 impl_type->implflags = implTypeFlags;
10966 return S_OK;
10969 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
10970 WORD alignment)
10972 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10974 TRACE("%p %d\n", This, alignment);
10976 This->typeattr.cbAlignment = alignment;
10978 return S_OK;
10981 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
10982 LPOLESTR schema)
10984 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10986 TRACE("%p %s\n", This, wine_dbgstr_w(schema));
10988 if (!schema)
10989 return E_INVALIDARG;
10991 This->Schema = TLB_append_str(&This->pTypeLib->string_list, schema);
10993 This->typeattr.lpstrSchema = This->Schema->str;
10995 return S_OK;
10998 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
10999 UINT index, VARDESC *varDesc)
11001 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11002 TLBVarDesc *var_desc;
11004 TRACE("%p %u %p\n", This, index, varDesc);
11006 if (This->vardescs){
11007 UINT i;
11009 This->vardescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->vardescs,
11010 sizeof(TLBVarDesc) * (This->typeattr.cVars + 1));
11012 if (index < This->typeattr.cVars) {
11013 memmove(This->vardescs + index + 1, This->vardescs + index,
11014 (This->typeattr.cVars - index) * sizeof(TLBVarDesc));
11015 var_desc = This->vardescs + index;
11016 } else
11017 var_desc = This->vardescs + This->typeattr.cVars;
11019 /* move custdata lists to the new memory location */
11020 for(i = 0; i < This->typeattr.cVars + 1; ++i){
11021 if(index != i)
11022 TLB_relink_custdata(&This->vardescs[i].custdata_list);
11024 } else
11025 var_desc = This->vardescs = heap_alloc_zero(sizeof(TLBVarDesc));
11027 TLBVarDesc_Constructor(var_desc);
11028 TLB_AllocAndInitVarDesc(varDesc, &var_desc->vardesc_create);
11029 var_desc->vardesc = *var_desc->vardesc_create;
11031 ++This->typeattr.cVars;
11033 This->needs_layout = TRUE;
11035 return S_OK;
11038 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
11039 UINT index, LPOLESTR *names, UINT numNames)
11041 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11042 TLBFuncDesc *func_desc = &This->funcdescs[index];
11043 int i;
11045 TRACE("%p %u %p %u\n", This, index, names, numNames);
11047 if (!names)
11048 return E_INVALIDARG;
11050 if (index >= This->typeattr.cFuncs || numNames == 0)
11051 return TYPE_E_ELEMENTNOTFOUND;
11053 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){
11054 if(numNames > func_desc->funcdesc.cParams)
11055 return TYPE_E_ELEMENTNOTFOUND;
11056 } else
11057 if(numNames > func_desc->funcdesc.cParams + 1)
11058 return TYPE_E_ELEMENTNOTFOUND;
11060 for(i = 0; i < This->typeattr.cFuncs; ++i) {
11061 TLBFuncDesc *iter = &This->funcdescs[i];
11062 if (iter->Name && !wcscmp(TLB_get_bstr(iter->Name), *names)) {
11063 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
11064 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
11065 func_desc->funcdesc.invkind != iter->funcdesc.invkind)
11066 continue;
11067 return TYPE_E_AMBIGUOUSNAME;
11071 func_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *names);
11073 for (i = 1; i < numNames; ++i) {
11074 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1;
11075 par_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *(names + i));
11078 return S_OK;
11081 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
11082 UINT index, LPOLESTR name)
11084 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11086 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(name));
11088 if(!name)
11089 return E_INVALIDARG;
11091 if(index >= This->typeattr.cVars)
11092 return TYPE_E_ELEMENTNOTFOUND;
11094 This->vardescs[index].Name = TLB_append_str(&This->pTypeLib->name_list, name);
11095 return S_OK;
11098 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
11099 TYPEDESC *tdescAlias)
11101 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11102 HRESULT hr;
11104 TRACE("%p %p\n", This, tdescAlias);
11106 if(!tdescAlias)
11107 return E_INVALIDARG;
11109 if(This->typeattr.typekind != TKIND_ALIAS)
11110 return TYPE_E_BADMODULEKIND;
11112 hr = TLB_size_instance(This, This->pTypeLib->syskind, tdescAlias, &This->typeattr.cbSizeInstance, &This->typeattr.cbAlignment);
11113 if(FAILED(hr))
11114 return hr;
11116 heap_free(This->tdescAlias);
11117 This->tdescAlias = heap_alloc(TLB_SizeTypeDesc(tdescAlias, TRUE));
11118 TLB_CopyTypeDesc(NULL, tdescAlias, This->tdescAlias);
11120 return S_OK;
11123 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
11124 UINT index, LPOLESTR dllName, LPOLESTR procName)
11126 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11127 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
11128 return E_NOTIMPL;
11131 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
11132 UINT index, LPOLESTR docString)
11134 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11135 TLBFuncDesc *func_desc = &This->funcdescs[index];
11137 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
11139 if(!docString)
11140 return E_INVALIDARG;
11142 if(index >= This->typeattr.cFuncs)
11143 return TYPE_E_ELEMENTNOTFOUND;
11145 func_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
11147 return S_OK;
11150 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
11151 UINT index, LPOLESTR docString)
11153 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11154 TLBVarDesc *var_desc = &This->vardescs[index];
11156 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
11158 if(!docString)
11159 return E_INVALIDARG;
11161 if(index >= This->typeattr.cVars)
11162 return TYPE_E_ELEMENTNOTFOUND;
11164 var_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
11166 return S_OK;
11169 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
11170 UINT index, DWORD helpContext)
11172 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11173 TLBFuncDesc *func_desc = &This->funcdescs[index];
11175 TRACE("%p %u %d\n", This, index, helpContext);
11177 if(index >= This->typeattr.cFuncs)
11178 return TYPE_E_ELEMENTNOTFOUND;
11180 func_desc->helpcontext = helpContext;
11182 return S_OK;
11185 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
11186 UINT index, DWORD helpContext)
11188 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11189 TLBVarDesc *var_desc = &This->vardescs[index];
11191 TRACE("%p %u %d\n", This, index, helpContext);
11193 if(index >= This->typeattr.cVars)
11194 return TYPE_E_ELEMENTNOTFOUND;
11196 var_desc->HelpContext = helpContext;
11198 return S_OK;
11201 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
11202 UINT index, BSTR bstrMops)
11204 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11205 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
11206 return E_NOTIMPL;
11209 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
11210 IDLDESC *idlDesc)
11212 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11214 TRACE("%p %p\n", This, idlDesc);
11216 if (!idlDesc)
11217 return E_INVALIDARG;
11219 This->typeattr.idldescType.dwReserved = idlDesc->dwReserved;
11220 This->typeattr.idldescType.wIDLFlags = idlDesc->wIDLFlags;
11222 return S_OK;
11225 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
11227 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11228 ITypeInfo2 *tinfo = &This->ITypeInfo2_iface;
11229 TLBFuncDesc *func_desc;
11230 UINT user_vft = 0, i, depth = 0;
11231 HRESULT hres = S_OK;
11233 TRACE("%p\n", This);
11235 This->needs_layout = FALSE;
11237 if (This->typeattr.typekind == TKIND_INTERFACE) {
11238 ITypeInfo *inh;
11239 TYPEATTR *attr;
11240 HREFTYPE inh_href;
11242 hres = ITypeInfo2_GetRefTypeOfImplType(tinfo, 0, &inh_href);
11244 if (SUCCEEDED(hres)) {
11245 hres = ITypeInfo2_GetRefTypeInfo(tinfo, inh_href, &inh);
11247 if (SUCCEEDED(hres)) {
11248 hres = ITypeInfo_GetTypeAttr(inh, &attr);
11249 if (FAILED(hres)) {
11250 ITypeInfo_Release(inh);
11251 return hres;
11253 This->typeattr.cbSizeVft = attr->cbSizeVft;
11254 ITypeInfo_ReleaseTypeAttr(inh, attr);
11257 ++depth;
11258 hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href);
11259 if(SUCCEEDED(hres)){
11260 ITypeInfo *next;
11261 hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next);
11262 if(SUCCEEDED(hres)){
11263 ITypeInfo_Release(inh);
11264 inh = next;
11267 }while(SUCCEEDED(hres));
11268 hres = S_OK;
11270 ITypeInfo_Release(inh);
11271 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
11272 This->typeattr.cbSizeVft = 0;
11273 hres = S_OK;
11274 } else
11275 return hres;
11276 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
11277 This->typeattr.cbSizeVft = 0;
11278 hres = S_OK;
11279 } else
11280 return hres;
11281 } else if (This->typeattr.typekind == TKIND_DISPATCH)
11282 This->typeattr.cbSizeVft = 7 * This->pTypeLib->ptr_size;
11283 else
11284 This->typeattr.cbSizeVft = 0;
11286 func_desc = This->funcdescs;
11287 i = 0;
11288 while (i < This->typeattr.cFuncs) {
11289 if (!(func_desc->funcdesc.oVft & 0x1))
11290 func_desc->funcdesc.oVft = This->typeattr.cbSizeVft;
11292 if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft)
11293 user_vft = func_desc->funcdesc.oVft & 0xFFFC;
11295 This->typeattr.cbSizeVft += This->pTypeLib->ptr_size;
11297 if (func_desc->funcdesc.memid == MEMBERID_NIL) {
11298 TLBFuncDesc *iter;
11299 UINT j = 0;
11300 BOOL reset = FALSE;
11302 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i;
11304 iter = This->funcdescs;
11305 while (j < This->typeattr.cFuncs) {
11306 if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) {
11307 if (!reset) {
11308 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->typeattr.cFuncs;
11309 reset = TRUE;
11310 } else
11311 ++func_desc->funcdesc.memid;
11312 iter = This->funcdescs;
11313 j = 0;
11314 } else {
11315 ++iter;
11316 ++j;
11321 ++func_desc;
11322 ++i;
11325 if (user_vft > This->typeattr.cbSizeVft)
11326 This->typeattr.cbSizeVft = user_vft + This->pTypeLib->ptr_size;
11328 for(i = 0; i < This->typeattr.cVars; ++i){
11329 TLBVarDesc *var_desc = &This->vardescs[i];
11330 if(var_desc->vardesc.memid == MEMBERID_NIL){
11331 UINT j = 0;
11332 BOOL reset = FALSE;
11333 TLBVarDesc *iter;
11335 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + i;
11337 iter = This->vardescs;
11338 while (j < This->typeattr.cVars) {
11339 if (iter != var_desc && iter->vardesc.memid == var_desc->vardesc.memid) {
11340 if (!reset) {
11341 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + This->typeattr.cVars;
11342 reset = TRUE;
11343 } else
11344 ++var_desc->vardesc.memid;
11345 iter = This->vardescs;
11346 j = 0;
11347 } else {
11348 ++iter;
11349 ++j;
11355 return hres;
11358 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
11359 UINT index)
11361 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11362 FIXME("%p %u - stub\n", This, index);
11363 return E_NOTIMPL;
11366 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
11367 MEMBERID memid, INVOKEKIND invKind)
11369 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11370 FIXME("%p %x %d - stub\n", This, memid, invKind);
11371 return E_NOTIMPL;
11374 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
11375 UINT index)
11377 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11378 FIXME("%p %u - stub\n", This, index);
11379 return E_NOTIMPL;
11382 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
11383 MEMBERID memid)
11385 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11386 FIXME("%p %x - stub\n", This, memid);
11387 return E_NOTIMPL;
11390 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
11391 UINT index)
11393 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11394 int i;
11396 TRACE("%p %u\n", This, index);
11398 if (index >= This->typeattr.cImplTypes)
11399 return TYPE_E_ELEMENTNOTFOUND;
11401 TLB_FreeCustData(&This->impltypes[index].custdata_list);
11402 --This->typeattr.cImplTypes;
11404 if (index < This->typeattr.cImplTypes)
11406 memmove(This->impltypes + index, This->impltypes + index + 1, (This->typeattr.cImplTypes - index) *
11407 sizeof(*This->impltypes));
11408 for (i = index; i < This->typeattr.cImplTypes; ++i)
11409 TLB_relink_custdata(&This->impltypes[i].custdata_list);
11412 return S_OK;
11415 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
11416 REFGUID guid, VARIANT *varVal)
11418 TLBGuid *tlbguid;
11420 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11422 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
11424 if (!guid || !varVal)
11425 return E_INVALIDARG;
11427 tlbguid = TLB_append_guid(&This->pTypeLib->guid_list, guid, -1);
11429 return TLB_set_custdata(This->pcustdata_list, tlbguid, varVal);
11432 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
11433 UINT index, REFGUID guid, VARIANT *varVal)
11435 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11436 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11437 return E_NOTIMPL;
11440 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
11441 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
11443 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11444 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
11445 return E_NOTIMPL;
11448 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
11449 UINT index, REFGUID guid, VARIANT *varVal)
11451 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11452 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11453 return E_NOTIMPL;
11456 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
11457 UINT index, REFGUID guid, VARIANT *varVal)
11459 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11460 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11461 return E_NOTIMPL;
11464 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
11465 ULONG helpStringContext)
11467 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11469 TRACE("%p %u\n", This, helpStringContext);
11471 This->dwHelpStringContext = helpStringContext;
11473 return S_OK;
11476 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
11477 UINT index, ULONG helpStringContext)
11479 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11480 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11481 return E_NOTIMPL;
11484 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
11485 UINT index, ULONG helpStringContext)
11487 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11488 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11489 return E_NOTIMPL;
11492 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
11494 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11495 FIXME("%p - stub\n", This);
11496 return E_NOTIMPL;
11499 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
11500 LPOLESTR name)
11502 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11504 TRACE("%p %s\n", This, wine_dbgstr_w(name));
11506 if (!name)
11507 return E_INVALIDARG;
11509 This->Name = TLB_append_str(&This->pTypeLib->name_list, name);
11511 return S_OK;
11514 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
11515 ICreateTypeInfo2_fnQueryInterface,
11516 ICreateTypeInfo2_fnAddRef,
11517 ICreateTypeInfo2_fnRelease,
11518 ICreateTypeInfo2_fnSetGuid,
11519 ICreateTypeInfo2_fnSetTypeFlags,
11520 ICreateTypeInfo2_fnSetDocString,
11521 ICreateTypeInfo2_fnSetHelpContext,
11522 ICreateTypeInfo2_fnSetVersion,
11523 ICreateTypeInfo2_fnAddRefTypeInfo,
11524 ICreateTypeInfo2_fnAddFuncDesc,
11525 ICreateTypeInfo2_fnAddImplType,
11526 ICreateTypeInfo2_fnSetImplTypeFlags,
11527 ICreateTypeInfo2_fnSetAlignment,
11528 ICreateTypeInfo2_fnSetSchema,
11529 ICreateTypeInfo2_fnAddVarDesc,
11530 ICreateTypeInfo2_fnSetFuncAndParamNames,
11531 ICreateTypeInfo2_fnSetVarName,
11532 ICreateTypeInfo2_fnSetTypeDescAlias,
11533 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
11534 ICreateTypeInfo2_fnSetFuncDocString,
11535 ICreateTypeInfo2_fnSetVarDocString,
11536 ICreateTypeInfo2_fnSetFuncHelpContext,
11537 ICreateTypeInfo2_fnSetVarHelpContext,
11538 ICreateTypeInfo2_fnSetMops,
11539 ICreateTypeInfo2_fnSetTypeIdldesc,
11540 ICreateTypeInfo2_fnLayOut,
11541 ICreateTypeInfo2_fnDeleteFuncDesc,
11542 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
11543 ICreateTypeInfo2_fnDeleteVarDesc,
11544 ICreateTypeInfo2_fnDeleteVarDescByMemId,
11545 ICreateTypeInfo2_fnDeleteImplType,
11546 ICreateTypeInfo2_fnSetCustData,
11547 ICreateTypeInfo2_fnSetFuncCustData,
11548 ICreateTypeInfo2_fnSetParamCustData,
11549 ICreateTypeInfo2_fnSetVarCustData,
11550 ICreateTypeInfo2_fnSetImplTypeCustData,
11551 ICreateTypeInfo2_fnSetHelpStringContext,
11552 ICreateTypeInfo2_fnSetFuncHelpStringContext,
11553 ICreateTypeInfo2_fnSetVarHelpStringContext,
11554 ICreateTypeInfo2_fnInvalidate,
11555 ICreateTypeInfo2_fnSetName
11558 /******************************************************************************
11559 * ClearCustData (OLEAUT32.171)
11561 * Clear a custom data type's data.
11563 * PARAMS
11564 * lpCust [I] The custom data type instance
11566 * RETURNS
11567 * Nothing.
11569 void WINAPI ClearCustData(CUSTDATA *lpCust)
11571 if (lpCust && lpCust->cCustData)
11573 if (lpCust->prgCustData)
11575 DWORD i;
11577 for (i = 0; i < lpCust->cCustData; i++)
11578 VariantClear(&lpCust->prgCustData[i].varValue);
11580 CoTaskMemFree(lpCust->prgCustData);
11581 lpCust->prgCustData = NULL;
11583 lpCust->cCustData = 0;