oleaut32: Fix automatic value getting in ITypeInfo::Invoke.
[wine.git] / dlls / oleaut32 / typelib.c
blob388f10846ae31bff7ce293bc77cedf0d07a0eb0e
1 /*
2 * TYPELIB
4 * Copyright 1997 Marcus Meissner
5 * 1999 Rein Klazes
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 2004 Alastair Bridgewater
9 * 2005 Robert Shearman, for CodeWeavers
10 * 2013 Andrew Eikum for CodeWeavers
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 * --------------------------------------------------------------------------------------
27 * Known problems (2000, Francois Jacques)
29 * - Tested using OLEVIEW (Platform SDK tool) only.
31 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
32 * creating by doing a straight copy of the dispinterface instance and just changing
33 * its typekind. Pointed structures aren't copied - only the address of the pointers.
35 * - locale stuff is partially implemented but hasn't been tested.
37 * - typelib file is still read in its entirety, but it is released now.
39 * --------------------------------------------------------------------------------------
40 * Known problems left from previous implementation (1999, Rein Klazes) :
42 * -. Data structures are straightforward, but slow for look-ups.
43 * -. (related) nothing is hashed
44 * -. Most error return values are just guessed not checked with windows
45 * behaviour.
46 * -. lousy fatal error handling
50 #include "config.h"
51 #include "wine/port.h"
53 #include <stdlib.h>
54 #include <string.h>
55 #include <stdarg.h>
56 #include <stdio.h>
57 #include <ctype.h>
59 #define COBJMACROS
60 #define NONAMELESSUNION
62 #include "winerror.h"
63 #include "windef.h"
64 #include "winbase.h"
65 #include "winnls.h"
66 #include "winreg.h"
67 #include "winuser.h"
68 #include "winternl.h"
69 #include "lzexpand.h"
71 #include "wine/unicode.h"
72 #include "objbase.h"
73 #include "typelib.h"
74 #include "wine/debug.h"
75 #include "variant.h"
76 #include "wine/list.h"
78 WINE_DEFAULT_DEBUG_CHANNEL(ole);
79 WINE_DECLARE_DEBUG_CHANNEL(typelib);
81 typedef struct
83 WORD offset;
84 WORD length;
85 WORD flags;
86 WORD id;
87 WORD handle;
88 WORD usage;
89 } NE_NAMEINFO;
91 typedef struct
93 WORD type_id; /* Type identifier */
94 WORD count; /* Number of resources of this type */
95 DWORD resloader; /* SetResourceHandler() */
97 * Name info array.
99 } NE_TYPEINFO;
101 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
102 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
103 static void TLB_FreeVarDesc(VARDESC*);
105 /****************************************************************************
106 * FromLExxx
108 * Takes p_iVal (which is in little endian) and returns it
109 * in the host machine's byte order.
111 #ifdef WORDS_BIGENDIAN
112 static WORD FromLEWord(WORD p_iVal)
114 return (((p_iVal & 0x00FF) << 8) |
115 ((p_iVal & 0xFF00) >> 8));
119 static DWORD FromLEDWord(DWORD p_iVal)
121 return (((p_iVal & 0x000000FF) << 24) |
122 ((p_iVal & 0x0000FF00) << 8) |
123 ((p_iVal & 0x00FF0000) >> 8) |
124 ((p_iVal & 0xFF000000) >> 24));
126 #else
127 #define FromLEWord(X) (X)
128 #define FromLEDWord(X) (X)
129 #endif
131 #define DISPATCH_HREF_OFFSET 0x01000000
132 #define DISPATCH_HREF_MASK 0xff000000
134 /****************************************************************************
135 * FromLExxx
137 * Fix byte order in any structure if necessary
139 #ifdef WORDS_BIGENDIAN
140 static void FromLEWords(void *p_Val, int p_iSize)
142 WORD *Val = p_Val;
144 p_iSize /= sizeof(WORD);
146 while (p_iSize) {
147 *Val = FromLEWord(*Val);
148 Val++;
149 p_iSize--;
154 static void FromLEDWords(void *p_Val, int p_iSize)
156 DWORD *Val = p_Val;
158 p_iSize /= sizeof(DWORD);
160 while (p_iSize) {
161 *Val = FromLEDWord(*Val);
162 Val++;
163 p_iSize--;
166 #else
167 #define FromLEWords(X,Y) /*nothing*/
168 #define FromLEDWords(X,Y) /*nothing*/
169 #endif
172 * Find a typelib key which matches a requested maj.min version.
174 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
176 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
177 WCHAR buffer[60];
178 char key_name[16];
179 DWORD len, i;
180 INT best_maj = -1, best_min = -1;
181 HKEY hkey;
183 memcpy( buffer, typelibW, sizeof(typelibW) );
184 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
186 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
187 return FALSE;
189 len = sizeof(key_name);
190 i = 0;
191 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
193 INT v_maj, v_min;
195 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
197 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
199 if (*wMaj == 0xffff && *wMin == 0xffff)
201 if (v_maj > best_maj) best_maj = v_maj;
202 if (v_min > best_min) best_min = v_min;
204 else if (*wMaj == v_maj)
206 best_maj = v_maj;
208 if (*wMin == v_min)
210 best_min = v_min;
211 break; /* exact match */
213 if (*wMin != 0xffff && v_min > best_min) best_min = v_min;
216 len = sizeof(key_name);
218 RegCloseKey( hkey );
220 TRACE("found best_maj %d, best_min %d\n", best_maj, best_min);
222 if (*wMaj == 0xffff && *wMin == 0xffff)
224 if (best_maj >= 0 && best_min >= 0)
226 *wMaj = best_maj;
227 *wMin = best_min;
228 return TRUE;
232 if (*wMaj == best_maj && best_min >= 0)
234 *wMin = best_min;
235 return TRUE;
237 return FALSE;
240 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
241 /* buffer must be at least 60 characters long */
242 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
244 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
245 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
247 memcpy( buffer, TypelibW, sizeof(TypelibW) );
248 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
249 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
250 return buffer;
253 /* get the path of an interface key, in the form "Interface\\<guid>" */
254 /* buffer must be at least 50 characters long */
255 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
257 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
259 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
260 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
261 return buffer;
264 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
265 /* buffer must be at least 16 characters long */
266 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
268 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
269 static const WCHAR win16W[] = {'w','i','n','1','6',0};
270 static const WCHAR win32W[] = {'w','i','n','3','2',0};
271 static const WCHAR win64W[] = {'w','i','n','6','4',0};
273 sprintfW( buffer, LcidFormatW, lcid );
274 switch(syskind)
276 case SYS_WIN16: strcatW( buffer, win16W ); break;
277 case SYS_WIN32: strcatW( buffer, win32W ); break;
278 case SYS_WIN64: strcatW( buffer, win64W ); break;
279 default:
280 TRACE("Typelib is for unsupported syskind %i\n", syskind);
281 return NULL;
283 return buffer;
286 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
288 struct tlibredirect_data
290 ULONG size;
291 DWORD res;
292 ULONG name_len;
293 ULONG name_offset;
294 LANGID langid;
295 WORD flags;
296 ULONG help_len;
297 ULONG help_offset;
298 WORD major_version;
299 WORD minor_version;
302 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
303 static HRESULT query_typelib_path( REFGUID guid, WORD wMaj, WORD wMin,
304 SYSKIND syskind, LCID lcid, BSTR *path, BOOL redir )
306 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
307 LCID myLCID = lcid;
308 HKEY hkey;
309 WCHAR buffer[60];
310 WCHAR Path[MAX_PATH];
311 LONG res;
313 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
315 if (redir)
317 ACTCTX_SECTION_KEYED_DATA data;
319 data.cbSize = sizeof(data);
320 if (FindActCtxSectionGuid( 0, NULL, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION, guid, &data ))
322 struct tlibredirect_data *tlib = (struct tlibredirect_data*)data.lpData;
323 WCHAR *nameW;
324 DWORD len;
326 if ((wMaj != 0xffff || wMin != 0xffff) && (tlib->major_version != wMaj || tlib->minor_version < wMin))
327 return TYPE_E_LIBNOTREGISTERED;
329 nameW = (WCHAR*)((BYTE*)data.lpSectionBase + tlib->name_offset);
330 len = SearchPathW( NULL, nameW, NULL, sizeof(Path)/sizeof(WCHAR), Path, NULL );
331 if (!len) return TYPE_E_LIBNOTREGISTERED;
333 TRACE_(typelib)("got path from context %s\n", debugstr_w(Path));
334 *path = SysAllocString( Path );
335 return S_OK;
339 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
340 get_typelib_key( guid, wMaj, wMin, buffer );
342 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
343 if (res == ERROR_FILE_NOT_FOUND)
345 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
346 return TYPE_E_LIBNOTREGISTERED;
348 else if (res != ERROR_SUCCESS)
350 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
351 return TYPE_E_REGISTRYACCESS;
354 while (hr != S_OK)
356 LONG dwPathLen = sizeof(Path);
358 get_lcid_subkey( myLCID, syskind, buffer );
360 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
362 if (!lcid)
363 break;
364 else if (myLCID == lcid)
366 /* try with sub-langid */
367 myLCID = SUBLANGID(lcid);
369 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
371 /* try with system langid */
372 myLCID = 0;
374 else
376 break;
379 else
381 *path = SysAllocString( Path );
382 hr = S_OK;
385 RegCloseKey( hkey );
386 TRACE_(typelib)("-- 0x%08x\n", hr);
387 return hr;
390 /****************************************************************************
391 * QueryPathOfRegTypeLib [OLEAUT32.164]
393 * Gets the path to a registered type library.
395 * PARAMS
396 * guid [I] referenced guid
397 * wMaj [I] major version
398 * wMin [I] minor version
399 * lcid [I] locale id
400 * path [O] path of typelib
402 * RETURNS
403 * Success: S_OK.
404 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
405 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
406 * opened.
408 HRESULT WINAPI QueryPathOfRegTypeLib( REFGUID guid, WORD wMaj, WORD wMin, LCID lcid, LPBSTR path )
410 BOOL redir = TRUE;
411 #ifdef _WIN64
412 HRESULT hres = query_typelib_path( guid, wMaj, wMin, SYS_WIN64, lcid, path, TRUE );
413 if(SUCCEEDED(hres))
414 return hres;
415 redir = FALSE;
416 #endif
417 return query_typelib_path( guid, wMaj, wMin, SYS_WIN32, lcid, path, redir );
420 /******************************************************************************
421 * CreateTypeLib [OLEAUT32.160] creates a typelib
423 * RETURNS
424 * Success: S_OK
425 * Failure: Status
427 HRESULT WINAPI CreateTypeLib(
428 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
430 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
431 return E_FAIL;
434 /******************************************************************************
435 * LoadTypeLib [OLEAUT32.161]
437 * Loads a type library
439 * PARAMS
440 * szFile [I] Name of file to load from.
441 * pptLib [O] Pointer that receives ITypeLib object on success.
443 * RETURNS
444 * Success: S_OK
445 * Failure: Status
447 * SEE
448 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
450 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
452 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
453 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
456 /******************************************************************************
457 * LoadTypeLibEx [OLEAUT32.183]
459 * Loads and optionally registers a type library
461 * RETURNS
462 * Success: S_OK
463 * Failure: Status
465 HRESULT WINAPI LoadTypeLibEx(
466 LPCOLESTR szFile, /* [in] Name of file to load from */
467 REGKIND regkind, /* [in] Specify kind of registration */
468 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
470 WCHAR szPath[MAX_PATH+1];
471 HRESULT res;
473 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
475 if (!szFile || !pptLib)
476 return E_INVALIDARG;
478 *pptLib = NULL;
480 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
482 if (SUCCEEDED(res))
483 switch(regkind)
485 case REGKIND_DEFAULT:
486 /* don't register typelibs supplied with full path. Experimentation confirms the following */
487 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
488 (szFile[0] && (szFile[1] == ':'))) break;
489 /* else fall-through */
491 case REGKIND_REGISTER:
492 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
494 ITypeLib_Release(*pptLib);
495 *pptLib = 0;
497 break;
498 case REGKIND_NONE:
499 break;
502 TRACE(" returns %08x\n",res);
503 return res;
506 /******************************************************************************
507 * LoadRegTypeLib [OLEAUT32.162]
509 * Loads a registered type library.
511 * PARAMS
512 * rguid [I] GUID of the registered type library.
513 * wVerMajor [I] major version.
514 * wVerMinor [I] minor version.
515 * lcid [I] locale ID.
516 * ppTLib [O] pointer that receives an ITypeLib object on success.
518 * RETURNS
519 * Success: S_OK.
520 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
521 * LoadTypeLib.
523 HRESULT WINAPI LoadRegTypeLib(
524 REFGUID rguid,
525 WORD wVerMajor,
526 WORD wVerMinor,
527 LCID lcid,
528 ITypeLib **ppTLib)
530 BSTR bstr=NULL;
531 HRESULT res;
533 *ppTLib = NULL;
535 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
537 if(SUCCEEDED(res))
539 res= LoadTypeLib(bstr, ppTLib);
540 SysFreeString(bstr);
542 if ((wVerMajor!=0xffff || wVerMinor!=0xffff) && *ppTLib)
544 TLIBATTR *attr;
546 res = ITypeLib_GetLibAttr(*ppTLib, &attr);
547 if (res == S_OK)
549 BOOL mismatch = attr->wMajorVerNum != wVerMajor || attr->wMinorVerNum < wVerMinor;
550 ITypeLib_ReleaseTLibAttr(*ppTLib, attr);
552 if (mismatch)
554 ITypeLib_Release(*ppTLib);
555 *ppTLib = NULL;
556 res = TYPE_E_LIBNOTREGISTERED;
562 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
564 return res;
568 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
569 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
570 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
571 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
572 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
573 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
575 static void TLB_register_interface(TLIBATTR *libattr, LPOLESTR name, TYPEATTR *tattr, DWORD flag)
577 WCHAR keyName[60];
578 HKEY key, subKey;
580 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
581 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
582 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
584 get_interface_key( &tattr->guid, keyName );
585 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
586 KEY_WRITE | flag, NULL, &key, NULL) == ERROR_SUCCESS)
588 if (name)
589 RegSetValueExW(key, NULL, 0, REG_SZ,
590 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
592 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
593 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS) {
594 RegSetValueExW(subKey, NULL, 0, REG_SZ,
595 (const BYTE *)PSOA, sizeof PSOA);
596 RegCloseKey(subKey);
599 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
600 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS) {
601 RegSetValueExW(subKey, NULL, 0, REG_SZ,
602 (const BYTE *)PSOA, sizeof PSOA);
603 RegCloseKey(subKey);
606 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
607 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS)
609 WCHAR buffer[40];
610 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
611 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
613 StringFromGUID2(&libattr->guid, buffer, 40);
614 RegSetValueExW(subKey, NULL, 0, REG_SZ,
615 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
616 sprintfW(buffer, fmtver, libattr->wMajorVerNum, libattr->wMinorVerNum);
617 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
618 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
619 RegCloseKey(subKey);
622 RegCloseKey(key);
626 /******************************************************************************
627 * RegisterTypeLib [OLEAUT32.163]
628 * Adds information about a type library to the System Registry
629 * NOTES
630 * Docs: ITypeLib FAR * ptlib
631 * Docs: OLECHAR FAR* szFullPath
632 * Docs: OLECHAR FAR* szHelpDir
634 * RETURNS
635 * Success: S_OK
636 * Failure: Status
638 HRESULT WINAPI RegisterTypeLib(
639 ITypeLib * ptlib, /* [in] Pointer to the library*/
640 OLECHAR * szFullPath, /* [in] full Path of the library*/
641 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
642 may be NULL*/
644 HRESULT res;
645 TLIBATTR *attr;
646 WCHAR keyName[60];
647 WCHAR tmp[16];
648 HKEY key, subKey;
649 UINT types, tidx;
650 TYPEKIND kind;
651 DWORD disposition;
653 if (ptlib == NULL || szFullPath == NULL)
654 return E_INVALIDARG;
656 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
657 return E_FAIL;
659 #ifndef _WIN64
660 if (attr->syskind == SYS_WIN64) return TYPE_E_BADMODULEKIND;
661 #endif
663 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
665 res = S_OK;
666 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
667 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
669 LPOLESTR doc;
671 /* Set the human-readable name of the typelib */
672 if (FAILED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
673 res = E_FAIL;
674 else if (doc)
676 if (RegSetValueExW(key, NULL, 0, REG_SZ,
677 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
678 res = E_FAIL;
680 SysFreeString(doc);
683 /* Make up the name of the typelib path subkey */
684 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
686 /* Create the typelib path subkey */
687 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
688 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
690 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
691 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
692 res = E_FAIL;
694 RegCloseKey(subKey);
696 else
697 res = E_FAIL;
699 /* Create the flags subkey */
700 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
701 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
703 /* FIXME: is %u correct? */
704 static const WCHAR formatW[] = {'%','u',0};
705 WCHAR buf[20];
706 sprintfW(buf, formatW, attr->wLibFlags);
707 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
708 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
709 res = E_FAIL;
711 RegCloseKey(subKey);
713 else
714 res = E_FAIL;
716 /* create the helpdir subkey */
717 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
718 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
720 BOOL freeHelpDir = FALSE;
721 OLECHAR* pIndexStr;
723 /* if we created a new key, and helpDir was null, set the helpdir
724 to the directory which contains the typelib. However,
725 if we just opened an existing key, we leave the helpdir alone */
726 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
727 szHelpDir = SysAllocString(szFullPath);
728 pIndexStr = strrchrW(szHelpDir, '\\');
729 if (pIndexStr) {
730 *pIndexStr = 0;
732 freeHelpDir = TRUE;
735 /* if we have an szHelpDir, set it! */
736 if (szHelpDir != NULL) {
737 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
738 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
739 res = E_FAIL;
743 /* tidy up */
744 if (freeHelpDir) SysFreeString(szHelpDir);
745 RegCloseKey(subKey);
747 } else {
748 res = E_FAIL;
751 RegCloseKey(key);
753 else
754 res = E_FAIL;
756 /* register OLE Automation-compatible interfaces for this typelib */
757 types = ITypeLib_GetTypeInfoCount(ptlib);
758 for (tidx=0; tidx<types; tidx++) {
759 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
760 LPOLESTR name = NULL;
761 ITypeInfo *tinfo = NULL;
763 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
765 switch (kind) {
766 case TKIND_INTERFACE:
767 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
768 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
769 break;
771 case TKIND_DISPATCH:
772 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
773 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
774 break;
776 default:
777 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
778 break;
781 if (tinfo) {
782 TYPEATTR *tattr = NULL;
783 ITypeInfo_GetTypeAttr(tinfo, &tattr);
785 if (tattr) {
786 TRACE_(typelib)("guid=%s, flags=%04x (",
787 debugstr_guid(&tattr->guid),
788 tattr->wTypeFlags);
790 if (TRACE_ON(typelib)) {
791 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
792 XX(FAPPOBJECT);
793 XX(FCANCREATE);
794 XX(FLICENSED);
795 XX(FPREDECLID);
796 XX(FHIDDEN);
797 XX(FCONTROL);
798 XX(FDUAL);
799 XX(FNONEXTENSIBLE);
800 XX(FOLEAUTOMATION);
801 XX(FRESTRICTED);
802 XX(FAGGREGATABLE);
803 XX(FREPLACEABLE);
804 XX(FDISPATCHABLE);
805 XX(FREVERSEBIND);
806 XX(FPROXY);
807 #undef XX
808 MESSAGE("\n");
811 /* Register all dispinterfaces (which includes dual interfaces) and
812 oleautomation interfaces */
813 if ((kind == TKIND_INTERFACE && (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
814 kind == TKIND_DISPATCH)
816 BOOL is_wow64;
817 DWORD opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
819 /* register interface<->typelib coupling */
820 TLB_register_interface(attr, name, tattr, 0);
822 /* register TLBs into the opposite registry view, too */
823 if(opposite == KEY_WOW64_32KEY ||
824 (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64))
825 TLB_register_interface(attr, name, tattr, opposite);
828 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
831 ITypeInfo_Release(tinfo);
834 SysFreeString(name);
838 ITypeLib_ReleaseTLibAttr(ptlib, attr);
840 return res;
843 static void TLB_unregister_interface(GUID *guid, REGSAM flag)
845 WCHAR subKeyName[50];
846 HKEY subKey;
848 /* the path to the type */
849 get_interface_key( guid, subKeyName );
851 /* Delete its bits */
852 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE | flag, &subKey) != ERROR_SUCCESS)
853 return;
855 RegDeleteKeyW(subKey, ProxyStubClsidW);
856 RegDeleteKeyW(subKey, ProxyStubClsid32W);
857 RegDeleteKeyW(subKey, TypeLibW);
858 RegCloseKey(subKey);
859 RegDeleteKeyExW(HKEY_CLASSES_ROOT, subKeyName, flag, 0);
862 /******************************************************************************
863 * UnRegisterTypeLib [OLEAUT32.186]
864 * Removes information about a type library from the System Registry
865 * NOTES
867 * RETURNS
868 * Success: S_OK
869 * Failure: Status
871 HRESULT WINAPI UnRegisterTypeLib(
872 REFGUID libid, /* [in] Guid of the library */
873 WORD wVerMajor, /* [in] major version */
874 WORD wVerMinor, /* [in] minor version */
875 LCID lcid, /* [in] locale id */
876 SYSKIND syskind)
878 BSTR tlibPath = NULL;
879 DWORD tmpLength;
880 WCHAR keyName[60];
881 WCHAR subKeyName[50];
882 int result = S_OK;
883 DWORD i = 0;
884 BOOL deleteOtherStuff;
885 HKEY key = NULL;
886 TYPEATTR* typeAttr = NULL;
887 TYPEKIND kind;
888 ITypeInfo* typeInfo = NULL;
889 ITypeLib* typeLib = NULL;
890 int numTypes;
892 TRACE("(IID: %s)\n",debugstr_guid(libid));
894 /* Create the path to the key */
895 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
897 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
899 TRACE("Unsupported syskind %i\n", syskind);
900 result = E_INVALIDARG;
901 goto end;
904 /* get the path to the typelib on disk */
905 if (query_typelib_path(libid, wVerMajor, wVerMinor, syskind, lcid, &tlibPath, FALSE) != S_OK) {
906 result = E_INVALIDARG;
907 goto end;
910 /* Try and open the key to the type library. */
911 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
912 result = E_INVALIDARG;
913 goto end;
916 /* Try and load the type library */
917 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib) != S_OK) {
918 result = TYPE_E_INVALIDSTATE;
919 goto end;
922 /* remove any types registered with this typelib */
923 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
924 for (i=0; i<numTypes; i++) {
925 /* get the kind of type */
926 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
927 goto enddeleteloop;
930 /* skip non-interfaces, and get type info for the type */
931 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
932 goto enddeleteloop;
934 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
935 goto enddeleteloop;
937 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
938 goto enddeleteloop;
941 if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
942 kind == TKIND_DISPATCH)
944 BOOL is_wow64;
945 REGSAM opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
947 TLB_unregister_interface(&typeAttr->guid, 0);
949 /* unregister TLBs into the opposite registry view, too */
950 if(opposite == KEY_WOW64_32KEY ||
951 (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64)) {
952 TLB_unregister_interface(&typeAttr->guid, opposite);
956 enddeleteloop:
957 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
958 typeAttr = NULL;
959 if (typeInfo) ITypeInfo_Release(typeInfo);
960 typeInfo = NULL;
963 /* Now, delete the type library path subkey */
964 get_lcid_subkey( lcid, syskind, subKeyName );
965 RegDeleteKeyW(key, subKeyName);
966 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
967 RegDeleteKeyW(key, subKeyName);
969 /* check if there is anything besides the FLAGS/HELPDIR keys.
970 If there is, we don't delete them */
971 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
972 deleteOtherStuff = TRUE;
973 i = 0;
974 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
975 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
977 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
978 if (!strcmpW(subKeyName, FLAGSW)) continue;
979 if (!strcmpW(subKeyName, HELPDIRW)) continue;
980 deleteOtherStuff = FALSE;
981 break;
984 /* only delete the other parts of the key if we're absolutely sure */
985 if (deleteOtherStuff) {
986 RegDeleteKeyW(key, FLAGSW);
987 RegDeleteKeyW(key, HELPDIRW);
988 RegCloseKey(key);
989 key = NULL;
991 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
992 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
993 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
996 end:
997 SysFreeString(tlibPath);
998 if (typeLib) ITypeLib_Release(typeLib);
999 if (key) RegCloseKey(key);
1000 return result;
1003 /******************************************************************************
1004 * RegisterTypeLibForUser [OLEAUT32.442]
1005 * Adds information about a type library to the user registry
1006 * NOTES
1007 * Docs: ITypeLib FAR * ptlib
1008 * Docs: OLECHAR FAR* szFullPath
1009 * Docs: OLECHAR FAR* szHelpDir
1011 * RETURNS
1012 * Success: S_OK
1013 * Failure: Status
1015 HRESULT WINAPI RegisterTypeLibForUser(
1016 ITypeLib * ptlib, /* [in] Pointer to the library*/
1017 OLECHAR * szFullPath, /* [in] full Path of the library*/
1018 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
1019 may be NULL*/
1021 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib,
1022 debugstr_w(szFullPath), debugstr_w(szHelpDir));
1023 return RegisterTypeLib(ptlib, szFullPath, szHelpDir);
1026 /******************************************************************************
1027 * UnRegisterTypeLibForUser [OLEAUT32.443]
1028 * Removes information about a type library from the user registry
1030 * RETURNS
1031 * Success: S_OK
1032 * Failure: Status
1034 HRESULT WINAPI UnRegisterTypeLibForUser(
1035 REFGUID libid, /* [in] GUID of the library */
1036 WORD wVerMajor, /* [in] major version */
1037 WORD wVerMinor, /* [in] minor version */
1038 LCID lcid, /* [in] locale id */
1039 SYSKIND syskind)
1041 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
1042 debugstr_guid(libid), wVerMajor, wVerMinor, lcid, syskind);
1043 return UnRegisterTypeLib(libid, wVerMajor, wVerMinor, lcid, syskind);
1046 /*======================= ITypeLib implementation =======================*/
1048 typedef struct tagTLBGuid {
1049 GUID guid;
1050 INT hreftype;
1051 UINT offset;
1052 struct list entry;
1053 } TLBGuid;
1055 typedef struct tagTLBCustData
1057 TLBGuid *guid;
1058 VARIANT data;
1059 struct list entry;
1060 } TLBCustData;
1062 /* data structure for import typelibs */
1063 typedef struct tagTLBImpLib
1065 int offset; /* offset in the file (MSFT)
1066 offset in nametable (SLTG)
1067 just used to identify library while reading
1068 data from file */
1069 TLBGuid *guid; /* libid */
1070 BSTR name; /* name */
1072 LCID lcid; /* lcid of imported typelib */
1074 WORD wVersionMajor; /* major version number */
1075 WORD wVersionMinor; /* minor version number */
1077 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
1078 NULL if not yet loaded */
1079 struct list entry;
1080 } TLBImpLib;
1082 typedef struct tagTLBString {
1083 BSTR str;
1084 UINT offset;
1085 struct list entry;
1086 } TLBString;
1088 /* internal ITypeLib data */
1089 typedef struct tagITypeLibImpl
1091 ITypeLib2 ITypeLib2_iface;
1092 ITypeComp ITypeComp_iface;
1093 ICreateTypeLib2 ICreateTypeLib2_iface;
1094 LONG ref;
1095 TLBGuid *guid;
1096 LCID lcid;
1097 SYSKIND syskind;
1098 int ptr_size;
1099 WORD ver_major;
1100 WORD ver_minor;
1101 WORD libflags;
1102 LCID set_lcid;
1104 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1105 * exported to the application as a UNICODE string.
1107 struct list string_list;
1108 struct list name_list;
1109 struct list guid_list;
1111 const TLBString *Name;
1112 const TLBString *DocString;
1113 const TLBString *HelpFile;
1114 const TLBString *HelpStringDll;
1115 DWORD dwHelpContext;
1116 int TypeInfoCount; /* nr of typeinfo's in librarry */
1117 struct tagITypeInfoImpl **typeinfos;
1118 struct list custdata_list;
1119 struct list implib_list;
1120 int ctTypeDesc; /* number of items in type desc array */
1121 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1122 library. Only used while reading MSFT
1123 typelibs */
1124 struct list ref_list; /* list of ref types in this typelib */
1125 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1128 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1129 struct list entry;
1130 WCHAR *path;
1131 INT index;
1132 } ITypeLibImpl;
1134 static const ITypeLib2Vtbl tlbvt;
1135 static const ITypeCompVtbl tlbtcvt;
1136 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl;
1138 static inline ITypeLibImpl *impl_from_ITypeLib2(ITypeLib2 *iface)
1140 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeLib2_iface);
1143 static inline ITypeLibImpl *impl_from_ITypeLib(ITypeLib *iface)
1145 return impl_from_ITypeLib2((ITypeLib2*)iface);
1148 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1150 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeComp_iface);
1153 static inline ITypeLibImpl *impl_from_ICreateTypeLib2( ICreateTypeLib2 *iface )
1155 return CONTAINING_RECORD(iface, ITypeLibImpl, ICreateTypeLib2_iface);
1158 /* ITypeLib methods */
1159 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1160 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1162 /*======================= ITypeInfo implementation =======================*/
1164 /* data for referenced types */
1165 typedef struct tagTLBRefType
1167 INT index; /* Type index for internal ref or for external ref
1168 it the format is SLTG. -2 indicates to
1169 use guid */
1171 TYPEKIND tkind;
1172 TLBGuid *guid; /* guid of the referenced type */
1173 /* if index == TLB_REF_USE_GUID */
1175 HREFTYPE reference; /* The href of this ref */
1176 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1177 TLB_REF_INTERNAL for internal refs
1178 TLB_REF_NOT_FOUND for broken refs */
1180 struct list entry;
1181 } TLBRefType;
1183 #define TLB_REF_USE_GUID -2
1185 #define TLB_REF_INTERNAL (void*)-2
1186 #define TLB_REF_NOT_FOUND (void*)-1
1188 /* internal Parameter data */
1189 typedef struct tagTLBParDesc
1191 const TLBString *Name;
1192 struct list custdata_list;
1193 } TLBParDesc;
1195 /* internal Function data */
1196 typedef struct tagTLBFuncDesc
1198 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1199 const TLBString *Name; /* the name of this function */
1200 TLBParDesc *pParamDesc; /* array with param names and custom data */
1201 int helpcontext;
1202 int HelpStringContext;
1203 const TLBString *HelpString;
1204 const TLBString *Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1205 struct list custdata_list;
1206 } TLBFuncDesc;
1208 /* internal Variable data */
1209 typedef struct tagTLBVarDesc
1211 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1212 VARDESC *vardesc_create; /* additional data needed for storing VARDESC */
1213 const TLBString *Name; /* the name of this variable */
1214 int HelpContext;
1215 int HelpStringContext;
1216 const TLBString *HelpString;
1217 struct list custdata_list;
1218 } TLBVarDesc;
1220 /* internal implemented interface data */
1221 typedef struct tagTLBImplType
1223 HREFTYPE hRef; /* hRef of interface */
1224 int implflags; /* IMPLFLAG_*s */
1225 struct list custdata_list;
1226 } TLBImplType;
1228 /* internal TypeInfo data */
1229 typedef struct tagITypeInfoImpl
1231 ITypeInfo2 ITypeInfo2_iface;
1232 ITypeComp ITypeComp_iface;
1233 ICreateTypeInfo2 ICreateTypeInfo2_iface;
1234 LONG ref;
1235 BOOL not_attached_to_typelib;
1236 BOOL needs_layout;
1238 TLBGuid *guid;
1239 TYPEATTR typeattr;
1240 TYPEDESC *tdescAlias;
1242 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1243 int index; /* index in this typelib; */
1244 HREFTYPE hreftype; /* hreftype for app object binding */
1245 /* type libs seem to store the doc strings in ascii
1246 * so why should we do it in unicode?
1248 const TLBString *Name;
1249 const TLBString *DocString;
1250 const TLBString *DllName;
1251 const TLBString *Schema;
1252 DWORD dwHelpContext;
1253 DWORD dwHelpStringContext;
1255 /* functions */
1256 TLBFuncDesc *funcdescs;
1258 /* variables */
1259 TLBVarDesc *vardescs;
1261 /* Implemented Interfaces */
1262 TLBImplType *impltypes;
1264 struct list *pcustdata_list;
1265 struct list custdata_list;
1266 } ITypeInfoImpl;
1268 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1270 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeComp_iface);
1273 static inline ITypeInfoImpl *impl_from_ITypeInfo2( ITypeInfo2 *iface )
1275 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeInfo2_iface);
1278 static inline ITypeInfoImpl *impl_from_ITypeInfo( ITypeInfo *iface )
1280 return impl_from_ITypeInfo2((ITypeInfo2*)iface);
1283 static inline ITypeInfoImpl *info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2 *iface )
1285 return CONTAINING_RECORD(iface, ITypeInfoImpl, ICreateTypeInfo2_iface);
1288 static const ITypeInfo2Vtbl tinfvt;
1289 static const ITypeCompVtbl tcompvt;
1290 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl;
1292 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1293 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1295 typedef struct tagTLBContext
1297 unsigned int oStart; /* start of TLB in file */
1298 unsigned int pos; /* current pos */
1299 unsigned int length; /* total length */
1300 void *mapping; /* memory mapping */
1301 MSFT_SegDir * pTblDir;
1302 ITypeLibImpl* pLibInfo;
1303 } TLBContext;
1306 static inline BSTR TLB_get_bstr(const TLBString *str)
1308 return str != NULL ? str->str : NULL;
1311 static inline int TLB_str_memcmp(void *left, const TLBString *str, DWORD len)
1313 if(!str)
1314 return 1;
1315 return memcmp(left, str->str, len);
1318 static inline const GUID *TLB_get_guidref(const TLBGuid *guid)
1320 return guid != NULL ? &guid->guid : NULL;
1323 static inline const GUID *TLB_get_guid_null(const TLBGuid *guid)
1325 return guid != NULL ? &guid->guid : &GUID_NULL;
1328 static int get_ptr_size(SYSKIND syskind)
1330 switch(syskind){
1331 case SYS_WIN64:
1332 return 8;
1333 case SYS_WIN32:
1334 case SYS_MAC:
1335 case SYS_WIN16:
1336 return 4;
1338 WARN("Unhandled syskind: 0x%x\n", syskind);
1339 return 4;
1343 debug
1345 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1346 if (pTD->vt & VT_RESERVED)
1347 szVarType += strlen(strcpy(szVarType, "reserved | "));
1348 if (pTD->vt & VT_BYREF)
1349 szVarType += strlen(strcpy(szVarType, "ref to "));
1350 if (pTD->vt & VT_ARRAY)
1351 szVarType += strlen(strcpy(szVarType, "array of "));
1352 if (pTD->vt & VT_VECTOR)
1353 szVarType += strlen(strcpy(szVarType, "vector of "));
1354 switch(pTD->vt & VT_TYPEMASK) {
1355 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1356 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1357 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1358 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1359 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1360 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1361 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1362 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1363 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1364 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1365 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1366 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1367 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1368 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1369 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1370 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1371 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1372 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1373 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1374 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1375 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1376 pTD->u.hreftype); break;
1377 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1378 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1379 case VT_PTR: sprintf(szVarType, "ptr to ");
1380 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1381 break;
1382 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1383 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1384 break;
1385 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1386 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1387 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1388 break;
1390 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1394 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1395 char buf[200];
1396 USHORT flags = edesc->u.paramdesc.wParamFlags;
1397 dump_TypeDesc(&edesc->tdesc,buf);
1398 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1399 MESSAGE("\t\tu.paramdesc.wParamFlags");
1400 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1401 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1402 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1403 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1404 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1405 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1406 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1407 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1408 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1410 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1411 int i;
1412 MESSAGE("memid is %08x\n",funcdesc->memid);
1413 for (i=0;i<funcdesc->cParams;i++) {
1414 MESSAGE("Param %d:\n",i);
1415 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1417 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1418 switch (funcdesc->funckind) {
1419 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1420 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1421 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1422 case FUNC_STATIC: MESSAGE("static");break;
1423 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1424 default: MESSAGE("unknown");break;
1426 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1427 switch (funcdesc->invkind) {
1428 case INVOKE_FUNC: MESSAGE("func");break;
1429 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1430 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1431 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1433 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1434 switch (funcdesc->callconv) {
1435 case CC_CDECL: MESSAGE("cdecl");break;
1436 case CC_PASCAL: MESSAGE("pascal");break;
1437 case CC_STDCALL: MESSAGE("stdcall");break;
1438 case CC_SYSCALL: MESSAGE("syscall");break;
1439 default:break;
1441 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1442 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1443 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1445 MESSAGE("\telemdescFunc (return value type):\n");
1446 dump_ELEMDESC(&funcdesc->elemdescFunc);
1449 static const char * const typekind_desc[] =
1451 "TKIND_ENUM",
1452 "TKIND_RECORD",
1453 "TKIND_MODULE",
1454 "TKIND_INTERFACE",
1455 "TKIND_DISPATCH",
1456 "TKIND_COCLASS",
1457 "TKIND_ALIAS",
1458 "TKIND_UNION",
1459 "TKIND_MAX"
1462 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1464 int i;
1465 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd->Name)), pfd->funcdesc.cParams);
1466 for (i=0;i<pfd->funcdesc.cParams;i++)
1467 MESSAGE("\tparm%d: %s\n",i,debugstr_w(TLB_get_bstr(pfd->pParamDesc[i].Name)));
1470 dump_FUNCDESC(&(pfd->funcdesc));
1472 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd->HelpString)));
1473 if(pfd->Entry == NULL)
1474 MESSAGE("\tentry: (null)\n");
1475 else if(pfd->Entry == (void*)-1)
1476 MESSAGE("\tentry: invalid\n");
1477 else if(IS_INTRESOURCE(pfd->Entry))
1478 MESSAGE("\tentry: %p\n", pfd->Entry);
1479 else
1480 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd->Entry)));
1482 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1484 while (n)
1486 dump_TLBFuncDescOne(pfd);
1487 ++pfd;
1488 --n;
1491 static void dump_TLBVarDesc(const TLBVarDesc * pvd, UINT n)
1493 while (n)
1495 TRACE_(typelib)("%s\n", debugstr_w(TLB_get_bstr(pvd->Name)));
1496 ++pvd;
1497 --n;
1501 static void dump_TLBImpLib(const TLBImpLib *import)
1503 TRACE_(typelib)("%s %s\n", debugstr_guid(TLB_get_guidref(import->guid)),
1504 debugstr_w(import->name));
1505 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1506 import->wVersionMinor, import->lcid, import->offset);
1509 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1511 TLBRefType *ref;
1513 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1515 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1516 if(ref->index == -1)
1517 TRACE_(typelib)("%s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
1518 else
1519 TRACE_(typelib)("type no: %d\n", ref->index);
1521 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1523 TRACE_(typelib)("in lib\n");
1524 dump_TLBImpLib(ref->pImpTLInfo);
1529 static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1531 if(!impl)
1532 return;
1533 while (n) {
1534 TRACE_(typelib)("implementing/inheriting interface hRef = %x implflags %x\n",
1535 impl->hRef, impl->implflags);
1536 ++impl;
1537 --n;
1541 static void dump_DispParms(const DISPPARAMS * pdp)
1543 unsigned int index;
1545 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1547 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1549 TRACE("named args:\n");
1550 for (index = 0; index < pdp->cNamedArgs; index++)
1551 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1554 if (pdp->cArgs && pdp->rgvarg)
1556 TRACE("args:\n");
1557 for (index = 0; index < pdp->cArgs; index++)
1558 TRACE(" [%d] %s\n", index, debugstr_variant(pdp->rgvarg+index));
1562 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1564 TRACE("%p ref=%u\n", pty, pty->ref);
1565 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty->Name)), debugstr_w(TLB_get_bstr(pty->DocString)));
1566 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty->guid)));
1567 TRACE("kind:%s\n", typekind_desc[pty->typeattr.typekind]);
1568 TRACE("fct:%u var:%u impl:%u\n", pty->typeattr.cFuncs, pty->typeattr.cVars, pty->typeattr.cImplTypes);
1569 TRACE("wTypeFlags: 0x%04x\n", pty->typeattr.wTypeFlags);
1570 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1571 if (pty->typeattr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty->DllName)));
1572 if (TRACE_ON(ole))
1573 dump_TLBFuncDesc(pty->funcdescs, pty->typeattr.cFuncs);
1574 dump_TLBVarDesc(pty->vardescs, pty->typeattr.cVars);
1575 dump_TLBImplType(pty->impltypes, pty->typeattr.cImplTypes);
1578 static void dump_VARDESC(const VARDESC *v)
1580 MESSAGE("memid %d\n",v->memid);
1581 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1582 MESSAGE("oInst %d\n",v->u.oInst);
1583 dump_ELEMDESC(&(v->elemdescVar));
1584 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1585 MESSAGE("varkind %d\n",v->varkind);
1588 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1590 /* VT_LPWSTR is largest type that, may appear in type description */
1591 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1592 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1593 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1594 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1595 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1596 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1597 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1598 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1601 static void TLB_abort(void)
1603 DebugBreak();
1606 /* returns the size required for a deep copy of a typedesc into a
1607 * flat buffer */
1608 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1610 SIZE_T size = 0;
1612 if (alloc_initial_space)
1613 size += sizeof(TYPEDESC);
1615 switch (tdesc->vt)
1617 case VT_PTR:
1618 case VT_SAFEARRAY:
1619 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1620 break;
1621 case VT_CARRAY:
1622 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1623 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1624 break;
1626 return size;
1629 /* deep copy a typedesc into a flat buffer */
1630 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1632 if (!dest)
1634 dest = buffer;
1635 buffer = (char *)buffer + sizeof(TYPEDESC);
1638 *dest = *src;
1640 switch (src->vt)
1642 case VT_PTR:
1643 case VT_SAFEARRAY:
1644 dest->u.lptdesc = buffer;
1645 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1646 break;
1647 case VT_CARRAY:
1648 dest->u.lpadesc = buffer;
1649 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1650 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1651 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1652 break;
1654 return buffer;
1657 /* free custom data allocated by MSFT_CustData */
1658 static inline void TLB_FreeCustData(struct list *custdata_list)
1660 TLBCustData *cd, *cdn;
1661 LIST_FOR_EACH_ENTRY_SAFE(cd, cdn, custdata_list, TLBCustData, entry)
1663 list_remove(&cd->entry);
1664 VariantClear(&cd->data);
1665 heap_free(cd);
1669 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1671 DWORD len;
1672 BSTR ret;
1674 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1675 ret = SysAllocStringLen(NULL, len - 1);
1676 if (!ret) return ret;
1677 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1678 return ret;
1681 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(TLBFuncDesc *funcdescs,
1682 UINT n, MEMBERID memid)
1684 while(n){
1685 if(funcdescs->funcdesc.memid == memid)
1686 return funcdescs;
1687 ++funcdescs;
1688 --n;
1690 return NULL;
1693 static inline TLBVarDesc *TLB_get_vardesc_by_memberid(TLBVarDesc *vardescs,
1694 UINT n, MEMBERID memid)
1696 while(n){
1697 if(vardescs->vardesc.memid == memid)
1698 return vardescs;
1699 ++vardescs;
1700 --n;
1702 return NULL;
1705 static inline TLBVarDesc *TLB_get_vardesc_by_name(TLBVarDesc *vardescs,
1706 UINT n, const OLECHAR *name)
1708 while(n){
1709 if(!lstrcmpiW(TLB_get_bstr(vardescs->Name), name))
1710 return vardescs;
1711 ++vardescs;
1712 --n;
1714 return NULL;
1717 static inline TLBCustData *TLB_get_custdata_by_guid(struct list *custdata_list, REFGUID guid)
1719 TLBCustData *cust_data;
1720 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1721 if(IsEqualIID(TLB_get_guid_null(cust_data->guid), guid))
1722 return cust_data;
1723 return NULL;
1726 static inline ITypeInfoImpl *TLB_get_typeinfo_by_name(ITypeInfoImpl **typeinfos,
1727 UINT n, const OLECHAR *name)
1729 while(n){
1730 if(!lstrcmpiW(TLB_get_bstr((*typeinfos)->Name), name))
1731 return *typeinfos;
1732 ++typeinfos;
1733 --n;
1735 return NULL;
1738 static void TLBVarDesc_Constructor(TLBVarDesc *var_desc)
1740 list_init(&var_desc->custdata_list);
1743 static TLBVarDesc *TLBVarDesc_Alloc(UINT n)
1745 TLBVarDesc *ret;
1747 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1748 if(!ret)
1749 return NULL;
1751 while(n){
1752 TLBVarDesc_Constructor(&ret[n-1]);
1753 --n;
1756 return ret;
1759 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1761 TLBParDesc *ret;
1763 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1764 if(!ret)
1765 return NULL;
1767 while(n){
1768 list_init(&ret[n-1].custdata_list);
1769 --n;
1772 return ret;
1775 static void TLBFuncDesc_Constructor(TLBFuncDesc *func_desc)
1777 list_init(&func_desc->custdata_list);
1780 static TLBFuncDesc *TLBFuncDesc_Alloc(UINT n)
1782 TLBFuncDesc *ret;
1784 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1785 if(!ret)
1786 return NULL;
1788 while(n){
1789 TLBFuncDesc_Constructor(&ret[n-1]);
1790 --n;
1793 return ret;
1796 static void TLBImplType_Constructor(TLBImplType *impl)
1798 list_init(&impl->custdata_list);
1801 static TLBImplType *TLBImplType_Alloc(UINT n)
1803 TLBImplType *ret;
1805 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1806 if(!ret)
1807 return NULL;
1809 while(n){
1810 TLBImplType_Constructor(&ret[n-1]);
1811 --n;
1814 return ret;
1817 static TLBGuid *TLB_append_guid(struct list *guid_list,
1818 const GUID *new_guid, HREFTYPE hreftype)
1820 TLBGuid *guid;
1822 LIST_FOR_EACH_ENTRY(guid, guid_list, TLBGuid, entry) {
1823 if (IsEqualGUID(&guid->guid, new_guid))
1824 return guid;
1827 guid = heap_alloc(sizeof(TLBGuid));
1828 if (!guid)
1829 return NULL;
1831 memcpy(&guid->guid, new_guid, sizeof(GUID));
1832 guid->hreftype = hreftype;
1834 list_add_tail(guid_list, &guid->entry);
1836 return guid;
1839 static HRESULT TLB_set_custdata(struct list *custdata_list, TLBGuid *tlbguid, VARIANT *var)
1841 TLBCustData *cust_data;
1843 switch(V_VT(var)){
1844 case VT_I4:
1845 case VT_R4:
1846 case VT_UI4:
1847 case VT_INT:
1848 case VT_UINT:
1849 case VT_HRESULT:
1850 case VT_BSTR:
1851 break;
1852 default:
1853 return DISP_E_BADVARTYPE;
1856 cust_data = TLB_get_custdata_by_guid(custdata_list, TLB_get_guid_null(tlbguid));
1858 if (!cust_data) {
1859 cust_data = heap_alloc(sizeof(TLBCustData));
1860 if (!cust_data)
1861 return E_OUTOFMEMORY;
1863 cust_data->guid = tlbguid;
1864 VariantInit(&cust_data->data);
1866 list_add_tail(custdata_list, &cust_data->entry);
1867 }else
1868 VariantClear(&cust_data->data);
1870 return VariantCopy(&cust_data->data, var);
1873 static TLBString *TLB_append_str(struct list *string_list, BSTR new_str)
1875 TLBString *str;
1877 if(!new_str)
1878 return NULL;
1880 LIST_FOR_EACH_ENTRY(str, string_list, TLBString, entry) {
1881 if (strcmpW(str->str, new_str) == 0)
1882 return str;
1885 str = heap_alloc(sizeof(TLBString));
1886 if (!str)
1887 return NULL;
1889 str->str = SysAllocString(new_str);
1890 if (!str->str) {
1891 heap_free(str);
1892 return NULL;
1895 list_add_tail(string_list, &str->entry);
1897 return str;
1900 static HRESULT TLB_get_size_from_hreftype(ITypeInfoImpl *info, HREFTYPE href,
1901 ULONG *size, WORD *align)
1903 ITypeInfo *other;
1904 TYPEATTR *attr;
1905 HRESULT hr;
1907 hr = ITypeInfo2_GetRefTypeInfo(&info->ITypeInfo2_iface, href, &other);
1908 if(FAILED(hr))
1909 return hr;
1911 hr = ITypeInfo_GetTypeAttr(other, &attr);
1912 if(FAILED(hr)){
1913 ITypeInfo_Release(other);
1914 return hr;
1917 if(size)
1918 *size = attr->cbSizeInstance;
1919 if(align)
1920 *align = attr->cbAlignment;
1922 ITypeInfo_ReleaseTypeAttr(other, attr);
1923 ITypeInfo_Release(other);
1925 return S_OK;
1928 static HRESULT TLB_size_instance(ITypeInfoImpl *info, SYSKIND sys,
1929 TYPEDESC *tdesc, ULONG *size, WORD *align)
1931 ULONG i, sub, ptr_size;
1932 HRESULT hr;
1934 ptr_size = get_ptr_size(sys);
1936 switch(tdesc->vt){
1937 case VT_VOID:
1938 *size = 0;
1939 break;
1940 case VT_I1:
1941 case VT_UI1:
1942 *size = 1;
1943 break;
1944 case VT_I2:
1945 case VT_BOOL:
1946 case VT_UI2:
1947 *size = 2;
1948 break;
1949 case VT_I4:
1950 case VT_R4:
1951 case VT_ERROR:
1952 case VT_UI4:
1953 case VT_INT:
1954 case VT_UINT:
1955 case VT_HRESULT:
1956 *size = 4;
1957 break;
1958 case VT_R8:
1959 case VT_I8:
1960 case VT_UI8:
1961 *size = 8;
1962 break;
1963 case VT_BSTR:
1964 case VT_DISPATCH:
1965 case VT_UNKNOWN:
1966 case VT_PTR:
1967 case VT_SAFEARRAY:
1968 case VT_LPSTR:
1969 case VT_LPWSTR:
1970 *size = ptr_size;
1971 break;
1972 case VT_DATE:
1973 *size = sizeof(DATE);
1974 break;
1975 case VT_VARIANT:
1976 *size = sizeof(VARIANT);
1977 #ifdef _WIN64
1978 if(sys == SYS_WIN32)
1979 *size -= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
1980 #endif
1981 break;
1982 case VT_DECIMAL:
1983 *size = sizeof(DECIMAL);
1984 break;
1985 case VT_CY:
1986 *size = sizeof(CY);
1987 break;
1988 case VT_CARRAY:
1989 *size = 0;
1990 for(i = 0; i < tdesc->u.lpadesc->cDims; ++i)
1991 *size += tdesc->u.lpadesc->rgbounds[i].cElements;
1992 hr = TLB_size_instance(info, sys, &tdesc->u.lpadesc->tdescElem, &sub, align);
1993 if(FAILED(hr))
1994 return hr;
1995 *size *= sub;
1996 return S_OK;
1997 case VT_USERDEFINED:
1998 return TLB_get_size_from_hreftype(info, tdesc->u.hreftype, size, align);
1999 default:
2000 FIXME("Unsized VT: 0x%x\n", tdesc->vt);
2001 return E_FAIL;
2004 if(align){
2005 if(*size < 4)
2006 *align = *size;
2007 else
2008 *align = 4;
2011 return S_OK;
2014 /**********************************************************************
2016 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2019 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
2021 if (where != DO_NOT_SEEK)
2023 where += pcx->oStart;
2024 if (where > pcx->length)
2026 /* FIXME */
2027 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
2028 TLB_abort();
2030 pcx->pos = where;
2034 /* read function */
2035 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
2037 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2038 pcx->pos, count, pcx->oStart, pcx->length, where);
2040 MSFT_Seek(pcx, where);
2041 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
2042 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
2043 pcx->pos += count;
2044 return count;
2047 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
2048 LONG where )
2050 DWORD ret;
2052 ret = MSFT_Read(buffer, count, pcx, where);
2053 FromLEDWords(buffer, ret);
2055 return ret;
2058 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
2059 LONG where )
2061 DWORD ret;
2063 ret = MSFT_Read(buffer, count, pcx, where);
2064 FromLEWords(buffer, ret);
2066 return ret;
2069 static HRESULT MSFT_ReadAllGuids(TLBContext *pcx)
2071 TLBGuid *guid;
2072 MSFT_GuidEntry entry;
2073 int offs = 0;
2075 MSFT_Seek(pcx, pcx->pTblDir->pGuidTab.offset);
2076 while (1) {
2077 if (offs >= pcx->pTblDir->pGuidTab.length)
2078 return S_OK;
2080 MSFT_ReadLEWords(&entry, sizeof(MSFT_GuidEntry), pcx, DO_NOT_SEEK);
2082 guid = heap_alloc(sizeof(TLBGuid));
2084 guid->offset = offs;
2085 guid->guid = entry.guid;
2086 guid->hreftype = entry.hreftype;
2088 list_add_tail(&pcx->pLibInfo->guid_list, &guid->entry);
2090 offs += sizeof(MSFT_GuidEntry);
2094 static TLBGuid *MSFT_ReadGuid( int offset, TLBContext *pcx)
2096 TLBGuid *ret;
2098 LIST_FOR_EACH_ENTRY(ret, &pcx->pLibInfo->guid_list, TLBGuid, entry){
2099 if(ret->offset == offset){
2100 TRACE_(typelib)("%s\n", debugstr_guid(&ret->guid));
2101 return ret;
2105 return NULL;
2108 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
2110 MSFT_NameIntro niName;
2112 if (offset < 0)
2114 ERR_(typelib)("bad offset %d\n", offset);
2115 return -1;
2118 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
2119 pcx->pTblDir->pNametab.offset+offset);
2121 return niName.hreftype;
2124 static HRESULT MSFT_ReadAllNames(TLBContext *pcx)
2126 char *string;
2127 MSFT_NameIntro intro;
2128 INT16 len_piece;
2129 int offs = 0, lengthInChars;
2131 MSFT_Seek(pcx, pcx->pTblDir->pNametab.offset);
2132 while (1) {
2133 TLBString *tlbstr;
2135 if (offs >= pcx->pTblDir->pNametab.length)
2136 return S_OK;
2138 MSFT_ReadLEWords(&intro, sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2139 intro.namelen &= 0xFF;
2140 len_piece = intro.namelen + sizeof(MSFT_NameIntro);
2141 if(len_piece % 4)
2142 len_piece = (len_piece + 4) & ~0x3;
2143 if(len_piece < 8)
2144 len_piece = 8;
2146 string = heap_alloc(len_piece + 1);
2147 MSFT_Read(string, len_piece - sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2148 string[intro.namelen] = '\0';
2150 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2151 string, -1, NULL, 0);
2152 if (!lengthInChars) {
2153 heap_free(string);
2154 return E_UNEXPECTED;
2157 tlbstr = heap_alloc(sizeof(TLBString));
2159 tlbstr->offset = offs;
2160 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2161 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2163 heap_free(string);
2165 list_add_tail(&pcx->pLibInfo->name_list, &tlbstr->entry);
2167 offs += len_piece;
2171 static TLBString *MSFT_ReadName( TLBContext *pcx, int offset)
2173 TLBString *tlbstr;
2175 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->name_list, TLBString, entry) {
2176 if (tlbstr->offset == offset) {
2177 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2178 return tlbstr;
2182 return NULL;
2185 static TLBString *MSFT_ReadString( TLBContext *pcx, int offset)
2187 TLBString *tlbstr;
2189 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->string_list, TLBString, entry) {
2190 if (tlbstr->offset == offset) {
2191 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2192 return tlbstr;
2196 return NULL;
2200 * read a value and fill a VARIANT structure
2202 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
2204 int size;
2206 TRACE_(typelib)("\n");
2208 if(offset <0) { /* data are packed in here */
2209 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
2210 V_I4(pVar) = offset & 0x3ffffff;
2211 return;
2213 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
2214 pcx->pTblDir->pCustData.offset + offset );
2215 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
2216 switch (V_VT(pVar)){
2217 case VT_EMPTY: /* FIXME: is this right? */
2218 case VT_NULL: /* FIXME: is this right? */
2219 case VT_I2 : /* this should not happen */
2220 case VT_I4 :
2221 case VT_R4 :
2222 case VT_ERROR :
2223 case VT_BOOL :
2224 case VT_I1 :
2225 case VT_UI1 :
2226 case VT_UI2 :
2227 case VT_UI4 :
2228 case VT_INT :
2229 case VT_UINT :
2230 case VT_VOID : /* FIXME: is this right? */
2231 case VT_HRESULT :
2232 size=4; break;
2233 case VT_R8 :
2234 case VT_CY :
2235 case VT_DATE :
2236 case VT_I8 :
2237 case VT_UI8 :
2238 case VT_DECIMAL : /* FIXME: is this right? */
2239 case VT_FILETIME :
2240 size=8;break;
2241 /* pointer types with known behaviour */
2242 case VT_BSTR :{
2243 char * ptr;
2244 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
2245 if(size == -1){
2246 V_BSTR(pVar) = NULL;
2247 }else{
2248 ptr = heap_alloc_zero(size);
2249 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);
2250 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
2251 /* FIXME: do we need a AtoW conversion here? */
2252 V_UNION(pVar, bstrVal[size])='\0';
2253 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
2254 heap_free(ptr);
2257 size=-4; break;
2258 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2259 case VT_DISPATCH :
2260 case VT_VARIANT :
2261 case VT_UNKNOWN :
2262 case VT_PTR :
2263 case VT_SAFEARRAY :
2264 case VT_CARRAY :
2265 case VT_USERDEFINED :
2266 case VT_LPSTR :
2267 case VT_LPWSTR :
2268 case VT_BLOB :
2269 case VT_STREAM :
2270 case VT_STORAGE :
2271 case VT_STREAMED_OBJECT :
2272 case VT_STORED_OBJECT :
2273 case VT_BLOB_OBJECT :
2274 case VT_CF :
2275 case VT_CLSID :
2276 default:
2277 size=0;
2278 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2279 V_VT(pVar));
2282 if(size>0) /* (big|small) endian correct? */
2283 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
2284 return;
2287 * create a linked list with custom data
2289 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
2291 MSFT_CDGuid entry;
2292 TLBCustData* pNew;
2293 int count=0;
2295 TRACE_(typelib)("\n");
2297 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
2299 while(offset >=0){
2300 count++;
2301 pNew=heap_alloc_zero(sizeof(TLBCustData));
2302 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
2303 pNew->guid = MSFT_ReadGuid(entry.GuidOffset, pcx);
2304 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
2305 list_add_head(custdata_list, &pNew->entry);
2306 offset = entry.next;
2308 return count;
2311 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd)
2313 if(type <0)
2314 pTd->vt=type & VT_TYPEMASK;
2315 else
2316 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
2318 TRACE_(typelib)("vt type = %X\n", pTd->vt);
2321 static BOOL TLB_is_propgetput(INVOKEKIND invkind)
2323 return (invkind == INVOKE_PROPERTYGET ||
2324 invkind == INVOKE_PROPERTYPUT ||
2325 invkind == INVOKE_PROPERTYPUTREF);
2328 static void
2329 MSFT_DoFuncs(TLBContext* pcx,
2330 ITypeInfoImpl* pTI,
2331 int cFuncs,
2332 int cVars,
2333 int offset,
2334 TLBFuncDesc** pptfd)
2337 * member information is stored in a data structure at offset
2338 * indicated by the memoffset field of the typeinfo structure
2339 * There are several distinctive parts.
2340 * The first part starts with a field that holds the total length
2341 * of this (first) part excluding this field. Then follow the records,
2342 * for each member there is one record.
2344 * The first entry is always the length of the record (including this
2345 * length word).
2346 * The rest of the record depends on the type of the member. If there is
2347 * a field indicating the member type (function, variable, interface, etc)
2348 * I have not found it yet. At this time we depend on the information
2349 * in the type info and the usual order how things are stored.
2351 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2352 * for each member;
2354 * Third is an equal sized array with file offsets to the name entry
2355 * of each member.
2357 * The fourth and last (?) part is an array with offsets to the records
2358 * in the first part of this file segment.
2361 int infolen, nameoffset, reclength, i;
2362 int recoffset = offset + sizeof(INT);
2364 char *recbuf = heap_alloc(0xffff);
2365 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2366 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2368 TRACE_(typelib)("\n");
2370 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2372 *pptfd = TLBFuncDesc_Alloc(cFuncs);
2373 ptfd = *pptfd;
2374 for ( i = 0; i < cFuncs ; i++ )
2376 int optional;
2378 /* name, eventually add to a hash table */
2379 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2380 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2382 /* read the function information record */
2383 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2385 reclength &= 0xffff;
2387 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2389 /* size without argument data */
2390 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2391 if (pFuncRec->FKCCIC & 0x1000)
2392 optional -= pFuncRec->nrargs * sizeof(INT);
2394 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2395 ptfd->helpcontext = pFuncRec->HelpContext;
2397 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2398 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2400 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2402 if (pFuncRec->FKCCIC & 0x2000 )
2404 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2405 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2406 ptfd->Entry = (TLBString*)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2408 else
2409 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2411 else
2412 ptfd->Entry = (TLBString*)-1;
2414 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2415 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2417 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2418 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2420 /* fill the FuncDesc Structure */
2421 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2422 offset + infolen + ( i + 1) * sizeof(INT));
2424 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2425 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2426 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2427 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2428 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2429 ptfd->funcdesc.oVft = pFuncRec->VtableOffset & ~1;
2430 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2432 /* nameoffset is sometimes -1 on the second half of a propget/propput
2433 * pair of functions */
2434 if ((nameoffset == -1) && (i > 0) &&
2435 TLB_is_propgetput(ptfd_prev->funcdesc.invkind) &&
2436 TLB_is_propgetput(ptfd->funcdesc.invkind))
2437 ptfd->Name = ptfd_prev->Name;
2438 else
2439 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2441 MSFT_GetTdesc(pcx,
2442 pFuncRec->DataType,
2443 &ptfd->funcdesc.elemdescFunc.tdesc);
2445 /* do the parameters/arguments */
2446 if(pFuncRec->nrargs)
2448 int j = 0;
2449 MSFT_ParameterInfo paraminfo;
2451 ptfd->funcdesc.lprgelemdescParam =
2452 heap_alloc_zero(pFuncRec->nrargs * (sizeof(ELEMDESC) + sizeof(PARAMDESCEX)));
2454 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2456 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2457 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2459 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2461 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2463 MSFT_GetTdesc(pcx,
2464 paraminfo.DataType,
2465 &elemdesc->tdesc);
2467 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2469 /* name */
2470 if (paraminfo.oName != -1)
2471 ptfd->pParamDesc[j].Name =
2472 MSFT_ReadName( pcx, paraminfo.oName );
2473 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(TLB_get_bstr(ptfd->pParamDesc[j].Name)));
2475 /* default value */
2476 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2477 (pFuncRec->FKCCIC & 0x1000) )
2479 INT* pInt = (INT *)((char *)pFuncRec +
2480 reclength -
2481 (pFuncRec->nrargs * 4) * sizeof(INT) );
2483 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2485 pParamDesc->pparamdescex = (PARAMDESCEX*)(ptfd->funcdesc.lprgelemdescParam+pFuncRec->nrargs)+j;
2486 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2488 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2489 pInt[j], pcx);
2491 else
2492 elemdesc->u.paramdesc.pparamdescex = NULL;
2494 /* custom info */
2495 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2496 j*sizeof(pFuncRec->oArgCustData[0])) &&
2497 pFuncRec->FKCCIC & 0x80 )
2499 MSFT_CustData(pcx,
2500 pFuncRec->oArgCustData[j],
2501 &ptfd->pParamDesc[j].custdata_list);
2504 /* SEEK value = jump to offset,
2505 * from there jump to the end of record,
2506 * go back by (j-1) arguments
2508 MSFT_ReadLEDWords( &paraminfo ,
2509 sizeof(MSFT_ParameterInfo), pcx,
2510 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2511 * sizeof(MSFT_ParameterInfo)));
2515 /* scode is not used: archaic win16 stuff FIXME: right? */
2516 ptfd->funcdesc.cScodes = 0 ;
2517 ptfd->funcdesc.lprgscode = NULL ;
2519 ptfd_prev = ptfd;
2520 ++ptfd;
2521 recoffset += reclength;
2523 heap_free(recbuf);
2526 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2527 int cVars, int offset, TLBVarDesc ** pptvd)
2529 int infolen, nameoffset, reclength;
2530 char recbuf[256];
2531 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2532 TLBVarDesc *ptvd;
2533 int i;
2534 int recoffset;
2536 TRACE_(typelib)("\n");
2538 ptvd = *pptvd = TLBVarDesc_Alloc(cVars);
2539 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2540 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2541 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2542 recoffset += offset+sizeof(INT);
2543 for(i=0;i<cVars;i++, ++ptvd){
2544 /* name, eventually add to a hash table */
2545 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2546 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2547 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2548 /* read the variable information record */
2549 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2550 reclength &= 0xff;
2551 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2553 /* optional data */
2554 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2555 ptvd->HelpContext = pVarRec->HelpContext;
2557 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2558 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2560 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2561 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2563 /* fill the VarDesc Structure */
2564 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2565 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2566 ptvd->vardesc.varkind = pVarRec->VarKind;
2567 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2568 MSFT_GetTdesc(pcx, pVarRec->DataType,
2569 &ptvd->vardesc.elemdescVar.tdesc);
2570 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2571 if(pVarRec->VarKind == VAR_CONST ){
2572 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2573 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2574 pVarRec->OffsValue, pcx);
2575 } else
2576 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2577 recoffset += reclength;
2581 /* process Implemented Interfaces of a com class */
2582 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2583 int offset)
2585 int i;
2586 MSFT_RefRecord refrec;
2587 TLBImplType *pImpl;
2589 TRACE_(typelib)("\n");
2591 pTI->impltypes = TLBImplType_Alloc(count);
2592 pImpl = pTI->impltypes;
2593 for(i=0;i<count;i++){
2594 if(offset<0) break; /* paranoia */
2595 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2596 pImpl->hRef = refrec.reftype;
2597 pImpl->implflags=refrec.flags;
2598 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2599 offset=refrec.onext;
2600 ++pImpl;
2604 #ifdef _WIN64
2605 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2606 * and some structures, and fix the alignment */
2607 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl *info)
2609 if(info->typeattr.typekind == TKIND_ALIAS){
2610 switch(info->tdescAlias->vt){
2611 case VT_BSTR:
2612 case VT_DISPATCH:
2613 case VT_UNKNOWN:
2614 case VT_PTR:
2615 case VT_SAFEARRAY:
2616 case VT_LPSTR:
2617 case VT_LPWSTR:
2618 info->typeattr.cbSizeInstance = sizeof(void*);
2619 info->typeattr.cbAlignment = sizeof(void*);
2620 break;
2621 case VT_CARRAY:
2622 case VT_USERDEFINED:
2623 TLB_size_instance(info, SYS_WIN64, info->tdescAlias, &info->typeattr.cbSizeInstance, &info->typeattr.cbAlignment);
2624 break;
2625 case VT_VARIANT:
2626 info->typeattr.cbSizeInstance = sizeof(VARIANT);
2627 info->typeattr.cbAlignment = 8;
2628 default:
2629 if(info->typeattr.cbSizeInstance < sizeof(void*))
2630 info->typeattr.cbAlignment = info->typeattr.cbSizeInstance;
2631 else
2632 info->typeattr.cbAlignment = sizeof(void*);
2633 break;
2635 }else if(info->typeattr.typekind == TKIND_INTERFACE ||
2636 info->typeattr.typekind == TKIND_DISPATCH ||
2637 info->typeattr.typekind == TKIND_COCLASS){
2638 info->typeattr.cbSizeInstance = sizeof(void*);
2639 info->typeattr.cbAlignment = sizeof(void*);
2642 #endif
2645 * process a typeinfo record
2647 static ITypeInfoImpl * MSFT_DoTypeInfo(
2648 TLBContext *pcx,
2649 int count,
2650 ITypeLibImpl * pLibInfo)
2652 MSFT_TypeInfoBase tiBase;
2653 ITypeInfoImpl *ptiRet;
2655 TRACE_(typelib)("count=%u\n", count);
2657 ptiRet = ITypeInfoImpl_Constructor();
2658 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2659 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2661 /* this is where we are coming from */
2662 ptiRet->pTypeLib = pLibInfo;
2663 ptiRet->index=count;
2665 ptiRet->guid = MSFT_ReadGuid(tiBase.posguid, pcx);
2666 ptiRet->typeattr.lcid = pLibInfo->set_lcid; /* FIXME: correct? */
2667 ptiRet->typeattr.lpstrSchema = NULL; /* reserved */
2668 ptiRet->typeattr.cbSizeInstance = tiBase.size;
2669 ptiRet->typeattr.typekind = tiBase.typekind & 0xF;
2670 ptiRet->typeattr.cFuncs = LOWORD(tiBase.cElement);
2671 ptiRet->typeattr.cVars = HIWORD(tiBase.cElement);
2672 ptiRet->typeattr.cbAlignment = (tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2673 ptiRet->typeattr.wTypeFlags = tiBase.flags;
2674 ptiRet->typeattr.wMajorVerNum = LOWORD(tiBase.version);
2675 ptiRet->typeattr.wMinorVerNum = HIWORD(tiBase.version);
2676 ptiRet->typeattr.cImplTypes = tiBase.cImplTypes;
2677 ptiRet->typeattr.cbSizeVft = tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2678 if (ptiRet->typeattr.typekind == TKIND_ALIAS) {
2679 TYPEDESC tmp;
2680 MSFT_GetTdesc(pcx, tiBase.datatype1, &tmp);
2681 ptiRet->tdescAlias = heap_alloc(TLB_SizeTypeDesc(&tmp, TRUE));
2682 TLB_CopyTypeDesc(NULL, &tmp, ptiRet->tdescAlias);
2685 /* FIXME: */
2686 /* IDLDESC idldescType; *//* never saw this one != zero */
2688 /* name, eventually add to a hash table */
2689 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2690 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2691 TRACE_(typelib)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet->Name)));
2692 /* help info */
2693 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2694 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2695 ptiRet->dwHelpContext=tiBase.helpcontext;
2697 if (ptiRet->typeattr.typekind == TKIND_MODULE)
2698 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2700 /* note: InfoType's Help file and HelpStringDll come from the containing
2701 * library. Further HelpString and Docstring appear to be the same thing :(
2703 /* functions */
2704 if(ptiRet->typeattr.cFuncs >0 )
2705 MSFT_DoFuncs(pcx, ptiRet, ptiRet->typeattr.cFuncs,
2706 ptiRet->typeattr.cVars,
2707 tiBase.memoffset, &ptiRet->funcdescs);
2708 /* variables */
2709 if(ptiRet->typeattr.cVars >0 )
2710 MSFT_DoVars(pcx, ptiRet, ptiRet->typeattr.cFuncs,
2711 ptiRet->typeattr.cVars,
2712 tiBase.memoffset, &ptiRet->vardescs);
2713 if(ptiRet->typeattr.cImplTypes >0 ) {
2714 switch(ptiRet->typeattr.typekind)
2716 case TKIND_COCLASS:
2717 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->typeattr.cImplTypes,
2718 tiBase.datatype1);
2719 break;
2720 case TKIND_DISPATCH:
2721 /* This is not -1 when the interface is a non-base dual interface or
2722 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2723 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2724 not this interface.
2727 if (tiBase.datatype1 != -1)
2729 ptiRet->impltypes = TLBImplType_Alloc(1);
2730 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2732 break;
2733 default:
2734 ptiRet->impltypes = TLBImplType_Alloc(1);
2735 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2736 break;
2739 MSFT_CustData(pcx, tiBase.oCustData, ptiRet->pcustdata_list);
2741 TRACE_(typelib)("%s guid: %s kind:%s\n",
2742 debugstr_w(TLB_get_bstr(ptiRet->Name)),
2743 debugstr_guid(TLB_get_guidref(ptiRet->guid)),
2744 typekind_desc[ptiRet->typeattr.typekind]);
2745 if (TRACE_ON(typelib))
2746 dump_TypeInfo(ptiRet);
2748 return ptiRet;
2751 static HRESULT MSFT_ReadAllStrings(TLBContext *pcx)
2753 char *string;
2754 INT16 len_str, len_piece;
2755 int offs = 0, lengthInChars;
2757 MSFT_Seek(pcx, pcx->pTblDir->pStringtab.offset);
2758 while (1) {
2759 TLBString *tlbstr;
2761 if (offs >= pcx->pTblDir->pStringtab.length)
2762 return S_OK;
2764 MSFT_ReadLEWords(&len_str, sizeof(INT16), pcx, DO_NOT_SEEK);
2765 len_piece = len_str + sizeof(INT16);
2766 if(len_piece % 4)
2767 len_piece = (len_piece + 4) & ~0x3;
2768 if(len_piece < 8)
2769 len_piece = 8;
2771 string = heap_alloc(len_piece + 1);
2772 MSFT_Read(string, len_piece - sizeof(INT16), pcx, DO_NOT_SEEK);
2773 string[len_str] = '\0';
2775 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2776 string, -1, NULL, 0);
2777 if (!lengthInChars) {
2778 heap_free(string);
2779 return E_UNEXPECTED;
2782 tlbstr = heap_alloc(sizeof(TLBString));
2784 tlbstr->offset = offs;
2785 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2786 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2788 heap_free(string);
2790 list_add_tail(&pcx->pLibInfo->string_list, &tlbstr->entry);
2792 offs += len_piece;
2796 static HRESULT MSFT_ReadAllRefs(TLBContext *pcx)
2798 TLBRefType *ref;
2799 int offs = 0;
2801 MSFT_Seek(pcx, pcx->pTblDir->pImpInfo.offset);
2802 while (offs < pcx->pTblDir->pImpInfo.length) {
2803 MSFT_ImpInfo impinfo;
2804 TLBImpLib *pImpLib;
2806 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx, DO_NOT_SEEK);
2808 ref = heap_alloc_zero(sizeof(TLBRefType));
2809 list_add_tail(&pcx->pLibInfo->ref_list, &ref->entry);
2811 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2812 if(pImpLib->offset==impinfo.oImpFile)
2813 break;
2815 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2816 ref->reference = offs;
2817 ref->pImpTLInfo = pImpLib;
2818 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2819 ref->guid = MSFT_ReadGuid(impinfo.oGuid, pcx);
2820 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
2821 ref->index = TLB_REF_USE_GUID;
2822 } else
2823 ref->index = impinfo.oGuid;
2824 }else{
2825 ERR("Cannot find a reference\n");
2826 ref->reference = -1;
2827 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2830 offs += sizeof(impinfo);
2833 return S_OK;
2836 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2837 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2838 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2839 * tradeoff here.
2841 static struct list tlb_cache = LIST_INIT(tlb_cache);
2842 static CRITICAL_SECTION cache_section;
2843 static CRITICAL_SECTION_DEBUG cache_section_debug =
2845 0, 0, &cache_section,
2846 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2847 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2849 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2852 typedef struct TLB_PEFile
2854 IUnknown IUnknown_iface;
2855 LONG refs;
2856 HMODULE dll;
2857 HRSRC typelib_resource;
2858 HGLOBAL typelib_global;
2859 LPVOID typelib_base;
2860 } TLB_PEFile;
2862 static inline TLB_PEFile *pefile_impl_from_IUnknown(IUnknown *iface)
2864 return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2867 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2869 if (IsEqualIID(riid, &IID_IUnknown))
2871 *ppv = iface;
2872 IUnknown_AddRef(iface);
2873 return S_OK;
2875 *ppv = NULL;
2876 return E_NOINTERFACE;
2879 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2881 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2882 return InterlockedIncrement(&This->refs);
2885 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2887 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2888 ULONG refs = InterlockedDecrement(&This->refs);
2889 if (!refs)
2891 if (This->typelib_global)
2892 FreeResource(This->typelib_global);
2893 if (This->dll)
2894 FreeLibrary(This->dll);
2895 heap_free(This);
2897 return refs;
2900 static const IUnknownVtbl TLB_PEFile_Vtable =
2902 TLB_PEFile_QueryInterface,
2903 TLB_PEFile_AddRef,
2904 TLB_PEFile_Release
2907 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2909 TLB_PEFile *This;
2910 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2912 This = heap_alloc(sizeof(TLB_PEFile));
2913 if (!This)
2914 return E_OUTOFMEMORY;
2916 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
2917 This->refs = 1;
2918 This->dll = NULL;
2919 This->typelib_resource = NULL;
2920 This->typelib_global = NULL;
2921 This->typelib_base = NULL;
2923 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2924 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2926 if (This->dll)
2928 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2929 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2930 if (This->typelib_resource)
2932 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2933 if (This->typelib_global)
2935 This->typelib_base = LockResource(This->typelib_global);
2937 if (This->typelib_base)
2939 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2940 *ppBase = This->typelib_base;
2941 *ppFile = &This->IUnknown_iface;
2942 return S_OK;
2947 TRACE("No TYPELIB resource found\n");
2948 hr = E_FAIL;
2951 TLB_PEFile_Release(&This->IUnknown_iface);
2952 return hr;
2955 typedef struct TLB_NEFile
2957 IUnknown IUnknown_iface;
2958 LONG refs;
2959 LPVOID typelib_base;
2960 } TLB_NEFile;
2962 static inline TLB_NEFile *nefile_impl_from_IUnknown(IUnknown *iface)
2964 return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
2967 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2969 if (IsEqualIID(riid, &IID_IUnknown))
2971 *ppv = iface;
2972 IUnknown_AddRef(iface);
2973 return S_OK;
2975 *ppv = NULL;
2976 return E_NOINTERFACE;
2979 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2981 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2982 return InterlockedIncrement(&This->refs);
2985 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2987 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2988 ULONG refs = InterlockedDecrement(&This->refs);
2989 if (!refs)
2991 heap_free(This->typelib_base);
2992 heap_free(This);
2994 return refs;
2997 static const IUnknownVtbl TLB_NEFile_Vtable =
2999 TLB_NEFile_QueryInterface,
3000 TLB_NEFile_AddRef,
3001 TLB_NEFile_Release
3004 /***********************************************************************
3005 * read_xx_header [internal]
3007 static int read_xx_header( HFILE lzfd )
3009 IMAGE_DOS_HEADER mzh;
3010 char magic[3];
3012 LZSeek( lzfd, 0, SEEK_SET );
3013 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
3014 return 0;
3015 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
3016 return 0;
3018 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3019 if ( 2 != LZRead( lzfd, magic, 2 ) )
3020 return 0;
3022 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3024 if ( magic[0] == 'N' && magic[1] == 'E' )
3025 return IMAGE_OS2_SIGNATURE;
3026 if ( magic[0] == 'P' && magic[1] == 'E' )
3027 return IMAGE_NT_SIGNATURE;
3029 magic[2] = '\0';
3030 WARN("Can't handle %s files.\n", magic );
3031 return 0;
3035 /***********************************************************************
3036 * find_ne_resource [internal]
3038 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
3039 DWORD *resLen, DWORD *resOff )
3041 IMAGE_OS2_HEADER nehd;
3042 NE_TYPEINFO *typeInfo;
3043 NE_NAMEINFO *nameInfo;
3044 DWORD nehdoffset;
3045 LPBYTE resTab;
3046 DWORD resTabSize;
3047 int count;
3049 /* Read in NE header */
3050 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
3051 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return FALSE;
3053 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
3054 if ( !resTabSize )
3056 TRACE("No resources in NE dll\n" );
3057 return FALSE;
3060 /* Read in resource table */
3061 resTab = heap_alloc( resTabSize );
3062 if ( !resTab ) return FALSE;
3064 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
3065 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
3067 heap_free( resTab );
3068 return FALSE;
3071 /* Find resource */
3072 typeInfo = (NE_TYPEINFO *)(resTab + 2);
3074 if (!IS_INTRESOURCE(typeid)) /* named type */
3076 BYTE len = strlen( typeid );
3077 while (typeInfo->type_id)
3079 if (!(typeInfo->type_id & 0x8000))
3081 BYTE *p = resTab + typeInfo->type_id;
3082 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
3084 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3085 typeInfo->count * sizeof(NE_NAMEINFO));
3088 else /* numeric type id */
3090 WORD id = LOWORD(typeid) | 0x8000;
3091 while (typeInfo->type_id)
3093 if (typeInfo->type_id == id) goto found_type;
3094 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3095 typeInfo->count * sizeof(NE_NAMEINFO));
3098 TRACE("No typeid entry found for %p\n", typeid );
3099 heap_free( resTab );
3100 return FALSE;
3102 found_type:
3103 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
3105 if (!IS_INTRESOURCE(resid)) /* named resource */
3107 BYTE len = strlen( resid );
3108 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3110 BYTE *p = resTab + nameInfo->id;
3111 if (nameInfo->id & 0x8000) continue;
3112 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
3115 else /* numeric resource id */
3117 WORD id = LOWORD(resid) | 0x8000;
3118 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3119 if (nameInfo->id == id) goto found_name;
3121 TRACE("No resid entry found for %p\n", typeid );
3122 heap_free( resTab );
3123 return FALSE;
3125 found_name:
3126 /* Return resource data */
3127 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
3128 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
3130 heap_free( resTab );
3131 return TRUE;
3134 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
3136 HFILE lzfd = -1;
3137 OFSTRUCT ofs;
3138 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
3139 TLB_NEFile *This;
3141 This = heap_alloc(sizeof(TLB_NEFile));
3142 if (!This) return E_OUTOFMEMORY;
3144 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
3145 This->refs = 1;
3146 This->typelib_base = NULL;
3148 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
3149 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
3151 DWORD reslen, offset;
3152 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
3154 This->typelib_base = heap_alloc(reslen);
3155 if( !This->typelib_base )
3156 hr = E_OUTOFMEMORY;
3157 else
3159 LZSeek( lzfd, offset, SEEK_SET );
3160 reslen = LZRead( lzfd, This->typelib_base, reslen );
3161 LZClose( lzfd );
3162 *ppBase = This->typelib_base;
3163 *pdwTLBLength = reslen;
3164 *ppFile = &This->IUnknown_iface;
3165 return S_OK;
3170 if( lzfd >= 0) LZClose( lzfd );
3171 TLB_NEFile_Release(&This->IUnknown_iface);
3172 return hr;
3175 typedef struct TLB_Mapping
3177 IUnknown IUnknown_iface;
3178 LONG refs;
3179 HANDLE file;
3180 HANDLE mapping;
3181 LPVOID typelib_base;
3182 } TLB_Mapping;
3184 static inline TLB_Mapping *mapping_impl_from_IUnknown(IUnknown *iface)
3186 return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
3189 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3191 if (IsEqualIID(riid, &IID_IUnknown))
3193 *ppv = iface;
3194 IUnknown_AddRef(iface);
3195 return S_OK;
3197 *ppv = NULL;
3198 return E_NOINTERFACE;
3201 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
3203 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3204 return InterlockedIncrement(&This->refs);
3207 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
3209 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3210 ULONG refs = InterlockedDecrement(&This->refs);
3211 if (!refs)
3213 if (This->typelib_base)
3214 UnmapViewOfFile(This->typelib_base);
3215 if (This->mapping)
3216 CloseHandle(This->mapping);
3217 if (This->file != INVALID_HANDLE_VALUE)
3218 CloseHandle(This->file);
3219 heap_free(This);
3221 return refs;
3224 static const IUnknownVtbl TLB_Mapping_Vtable =
3226 TLB_Mapping_QueryInterface,
3227 TLB_Mapping_AddRef,
3228 TLB_Mapping_Release
3231 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
3233 TLB_Mapping *This;
3235 This = heap_alloc(sizeof(TLB_Mapping));
3236 if (!This)
3237 return E_OUTOFMEMORY;
3239 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
3240 This->refs = 1;
3241 This->file = INVALID_HANDLE_VALUE;
3242 This->mapping = NULL;
3243 This->typelib_base = NULL;
3245 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3246 if (INVALID_HANDLE_VALUE != This->file)
3248 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
3249 if (This->mapping)
3251 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
3252 if(This->typelib_base)
3254 /* retrieve file size */
3255 *pdwTLBLength = GetFileSize(This->file, NULL);
3256 *ppBase = This->typelib_base;
3257 *ppFile = &This->IUnknown_iface;
3258 return S_OK;
3263 IUnknown_Release(&This->IUnknown_iface);
3264 return TYPE_E_CANTLOADLIBRARY;
3267 /****************************************************************************
3268 * TLB_ReadTypeLib
3270 * find the type of the typelib file and map the typelib resource into
3271 * the memory
3274 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3275 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
3277 ITypeLibImpl *entry;
3278 HRESULT ret;
3279 INT index = 1;
3280 LPWSTR index_str, file = (LPWSTR)pszFileName;
3281 LPVOID pBase = NULL;
3282 DWORD dwTLBLength = 0;
3283 IUnknown *pFile = NULL;
3284 HANDLE h;
3286 *ppTypeLib = NULL;
3288 index_str = strrchrW(pszFileName, '\\');
3289 if(index_str && *++index_str != '\0')
3291 LPWSTR end_ptr;
3292 LONG idx = strtolW(index_str, &end_ptr, 10);
3293 if(*end_ptr == '\0')
3295 int str_len = index_str - pszFileName - 1;
3296 index = idx;
3297 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
3298 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
3299 file[str_len] = 0;
3303 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
3305 if(strchrW(file, '\\'))
3307 lstrcpyW(pszPath, file);
3309 else
3311 int len = GetSystemDirectoryW(pszPath, cchPath);
3312 pszPath[len] = '\\';
3313 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
3317 if(file != pszFileName) heap_free(file);
3319 h = CreateFileW(pszPath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
3320 if(h != INVALID_HANDLE_VALUE){
3321 FILE_NAME_INFORMATION size_info;
3322 BOOL br;
3324 /* GetFileInformationByHandleEx returns the path of the file without
3325 * WOW64 redirection */
3326 br = GetFileInformationByHandleEx(h, FileNameInfo, &size_info, sizeof(size_info));
3327 if(br || GetLastError() == ERROR_MORE_DATA){
3328 FILE_NAME_INFORMATION *info;
3329 DWORD size = sizeof(*info) + size_info.FileNameLength + sizeof(WCHAR);
3331 info = HeapAlloc(GetProcessHeap(), 0, size);
3333 br = GetFileInformationByHandleEx(h, FileNameInfo, info, size);
3334 if(br){
3335 info->FileName[info->FileNameLength / sizeof(WCHAR)] = 0;
3336 lstrcpynW(pszPath + 2, info->FileName, cchPath - 2);
3339 HeapFree(GetProcessHeap(), 0, info);
3342 CloseHandle(h);
3345 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
3347 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3348 EnterCriticalSection(&cache_section);
3349 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
3351 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
3353 TRACE("cache hit\n");
3354 *ppTypeLib = &entry->ITypeLib2_iface;
3355 ITypeLib2_AddRef(*ppTypeLib);
3356 LeaveCriticalSection(&cache_section);
3357 return S_OK;
3360 LeaveCriticalSection(&cache_section);
3362 /* now actually load and parse the typelib */
3364 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3365 if (ret == TYPE_E_CANTLOADLIBRARY)
3366 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3367 if (ret == TYPE_E_CANTLOADLIBRARY)
3368 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
3369 if (SUCCEEDED(ret))
3371 if (dwTLBLength >= 4)
3373 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
3374 if (dwSignature == MSFT_SIGNATURE)
3375 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
3376 else if (dwSignature == SLTG_SIGNATURE)
3377 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
3378 else
3380 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
3381 ret = TYPE_E_CANTLOADLIBRARY;
3384 else
3385 ret = TYPE_E_CANTLOADLIBRARY;
3386 IUnknown_Release(pFile);
3389 if(*ppTypeLib) {
3390 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
3392 TRACE("adding to cache\n");
3393 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
3394 lstrcpyW(impl->path, pszPath);
3395 /* We should really canonicalise the path here. */
3396 impl->index = index;
3398 /* FIXME: check if it has added already in the meantime */
3399 EnterCriticalSection(&cache_section);
3400 list_add_head(&tlb_cache, &impl->entry);
3401 LeaveCriticalSection(&cache_section);
3402 ret = S_OK;
3404 else
3406 if(ret != E_FAIL)
3407 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
3409 ret = TYPE_E_CANTLOADLIBRARY;
3413 return ret;
3416 /*================== ITypeLib(2) Methods ===================================*/
3418 static ITypeLibImpl* TypeLibImpl_Constructor(void)
3420 ITypeLibImpl* pTypeLibImpl;
3422 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
3423 if (!pTypeLibImpl) return NULL;
3425 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3426 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3427 pTypeLibImpl->ICreateTypeLib2_iface.lpVtbl = &CreateTypeLib2Vtbl;
3428 pTypeLibImpl->ref = 1;
3430 list_init(&pTypeLibImpl->implib_list);
3431 list_init(&pTypeLibImpl->custdata_list);
3432 list_init(&pTypeLibImpl->name_list);
3433 list_init(&pTypeLibImpl->string_list);
3434 list_init(&pTypeLibImpl->guid_list);
3435 list_init(&pTypeLibImpl->ref_list);
3436 pTypeLibImpl->dispatch_href = -1;
3438 return pTypeLibImpl;
3441 /****************************************************************************
3442 * ITypeLib2_Constructor_MSFT
3444 * loading an MSFT typelib from an in-memory image
3446 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3448 TLBContext cx;
3449 LONG lPSegDir;
3450 MSFT_Header tlbHeader;
3451 MSFT_SegDir tlbSegDir;
3452 ITypeLibImpl * pTypeLibImpl;
3453 int i;
3455 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3457 pTypeLibImpl = TypeLibImpl_Constructor();
3458 if (!pTypeLibImpl) return NULL;
3460 /* get pointer to beginning of typelib data */
3461 cx.pos = 0;
3462 cx.oStart=0;
3463 cx.mapping = pLib;
3464 cx.pLibInfo = pTypeLibImpl;
3465 cx.length = dwTLBLength;
3467 /* read header */
3468 MSFT_ReadLEDWords(&tlbHeader, sizeof(tlbHeader), &cx, 0);
3469 TRACE_(typelib)("header:\n");
3470 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3471 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3472 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3473 return NULL;
3475 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3477 /* there is a small amount of information here until the next important
3478 * part:
3479 * the segment directory . Try to calculate the amount of data */
3480 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3482 /* now read the segment directory */
3483 TRACE("read segment directory (at %d)\n",lPSegDir);
3484 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3485 cx.pTblDir = &tlbSegDir;
3487 /* just check two entries */
3488 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3490 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3491 heap_free(pTypeLibImpl);
3492 return NULL;
3495 MSFT_ReadAllNames(&cx);
3496 MSFT_ReadAllStrings(&cx);
3497 MSFT_ReadAllGuids(&cx);
3499 /* now fill our internal data */
3500 /* TLIBATTR fields */
3501 pTypeLibImpl->guid = MSFT_ReadGuid(tlbHeader.posguid, &cx);
3503 pTypeLibImpl->syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3504 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3505 pTypeLibImpl->ver_major = LOWORD(tlbHeader.version);
3506 pTypeLibImpl->ver_minor = HIWORD(tlbHeader.version);
3507 pTypeLibImpl->libflags = ((WORD) tlbHeader.flags & 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE;
3509 pTypeLibImpl->set_lcid = tlbHeader.lcid2;
3510 pTypeLibImpl->lcid = tlbHeader.lcid;
3512 /* name, eventually add to a hash table */
3513 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3515 /* help info */
3516 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3517 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3519 if( tlbHeader.varflags & HELPDLLFLAG)
3521 int offset;
3522 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3523 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3526 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3528 /* custom data */
3529 if(tlbHeader.CustomDataOffset >= 0)
3531 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3534 /* fill in type descriptions */
3535 if(tlbSegDir.pTypdescTab.length > 0)
3537 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3538 INT16 td[4];
3539 pTypeLibImpl->ctTypeDesc = cTD;
3540 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3541 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3542 for(i=0; i<cTD; )
3544 /* FIXME: add several sanity checks here */
3545 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3546 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3548 /* FIXME: check safearray */
3549 if(td[3] < 0)
3550 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3551 else
3552 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3554 else if(td[0] == VT_CARRAY)
3556 /* array descr table here */
3557 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3559 else if(td[0] == VT_USERDEFINED)
3561 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3563 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3566 /* second time around to fill the array subscript info */
3567 for(i=0;i<cTD;i++)
3569 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3570 if(tlbSegDir.pArrayDescriptions.offset>0)
3572 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3573 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3575 if(td[1]<0)
3576 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3577 else
3578 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3580 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3582 for(j = 0; j<td[2]; j++)
3584 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3585 sizeof(INT), &cx, DO_NOT_SEEK);
3586 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3587 sizeof(INT), &cx, DO_NOT_SEEK);
3590 else
3592 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3593 ERR("didn't find array description data\n");
3598 /* imported type libs */
3599 if(tlbSegDir.pImpFiles.offset>0)
3601 TLBImpLib *pImpLib;
3602 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3603 UINT16 size;
3605 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3607 char *name;
3609 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3610 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3611 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3613 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3614 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3615 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3616 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3618 size >>= 2;
3619 name = heap_alloc_zero(size+1);
3620 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3621 pImpLib->name = TLB_MultiByteToBSTR(name);
3622 heap_free(name);
3624 pImpLib->guid = MSFT_ReadGuid(oGuid, &cx);
3625 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3627 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3631 MSFT_ReadAllRefs(&cx);
3633 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3635 /* type infos */
3636 if(tlbHeader.nrtypeinfos >= 0 )
3638 ITypeInfoImpl **ppTI;
3640 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3642 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3644 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3646 ++ppTI;
3647 (pTypeLibImpl->TypeInfoCount)++;
3651 #ifdef _WIN64
3652 if(pTypeLibImpl->syskind == SYS_WIN32){
3653 for(i = 0; i < pTypeLibImpl->TypeInfoCount; ++i)
3654 TLB_fix_32on64_typeinfo(pTypeLibImpl->typeinfos[i]);
3656 #endif
3658 TRACE("(%p)\n", pTypeLibImpl);
3659 return &pTypeLibImpl->ITypeLib2_iface;
3663 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3665 char b[3];
3666 int i;
3667 short s;
3669 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3670 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3671 return FALSE;
3674 guid->Data4[0] = s >> 8;
3675 guid->Data4[1] = s & 0xff;
3677 b[2] = '\0';
3678 for(i = 0; i < 6; i++) {
3679 memcpy(b, str + 24 + 2 * i, 2);
3680 guid->Data4[i + 2] = strtol(b, NULL, 16);
3682 return TRUE;
3685 static WORD SLTG_ReadString(const char *ptr, const TLBString **pStr, ITypeLibImpl *lib)
3687 WORD bytelen;
3688 DWORD len;
3689 BSTR tmp_str;
3691 *pStr = NULL;
3692 bytelen = *(const WORD*)ptr;
3693 if(bytelen == 0xffff) return 2;
3695 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3696 tmp_str = SysAllocStringLen(NULL, len);
3697 if (tmp_str) {
3698 MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, tmp_str, len);
3699 *pStr = TLB_append_str(&lib->string_list, tmp_str);
3700 SysFreeString(tmp_str);
3702 return bytelen + 2;
3705 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3707 WORD bytelen;
3709 *str = NULL;
3710 bytelen = *(const WORD*)ptr;
3711 if(bytelen == 0xffff) return 2;
3712 *str = heap_alloc(bytelen + 1);
3713 memcpy(*str, ptr + 2, bytelen);
3714 (*str)[bytelen] = '\0';
3715 return bytelen + 2;
3718 static TLBString *SLTG_ReadName(const char *pNameTable, int offset, ITypeLibImpl *lib)
3720 BSTR tmp_str;
3721 TLBString *tlbstr;
3723 LIST_FOR_EACH_ENTRY(tlbstr, &lib->name_list, TLBString, entry) {
3724 if (tlbstr->offset == offset)
3725 return tlbstr;
3728 tmp_str = TLB_MultiByteToBSTR(pNameTable + offset);
3729 tlbstr = TLB_append_str(&lib->name_list, tmp_str);
3730 SysFreeString(tmp_str);
3732 return tlbstr;
3735 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3737 char *ptr = pLibBlk;
3738 WORD w;
3740 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3741 FIXME("libblk magic = %04x\n", w);
3742 return 0;
3745 ptr += 6;
3746 if((w = *(WORD*)ptr) != 0xffff) {
3747 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3748 ptr += w;
3750 ptr += 2;
3752 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString, pTypeLibImpl);
3754 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile, pTypeLibImpl);
3756 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3757 ptr += 4;
3759 pTypeLibImpl->syskind = *(WORD*)ptr;
3760 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3761 ptr += 2;
3763 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3764 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3765 else
3766 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = 0;
3767 ptr += 2;
3769 ptr += 4; /* skip res12 */
3771 pTypeLibImpl->libflags = *(WORD*)ptr;
3772 ptr += 2;
3774 pTypeLibImpl->ver_major = *(WORD*)ptr;
3775 ptr += 2;
3777 pTypeLibImpl->ver_minor = *(WORD*)ptr;
3778 ptr += 2;
3780 pTypeLibImpl->guid = TLB_append_guid(&pTypeLibImpl->guid_list, (GUID*)ptr, -2);
3781 ptr += sizeof(GUID);
3783 return ptr - (char*)pLibBlk;
3786 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3787 typedef struct
3789 unsigned int num;
3790 HREFTYPE refs[1];
3791 } sltg_ref_lookup_t;
3793 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3794 HREFTYPE *typelib_ref)
3796 if(table && typeinfo_ref < table->num)
3798 *typelib_ref = table->refs[typeinfo_ref];
3799 return S_OK;
3802 ERR_(typelib)("Unable to find reference\n");
3803 *typelib_ref = -1;
3804 return E_FAIL;
3807 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3809 BOOL done = FALSE;
3811 while(!done) {
3812 if((*pType & 0xe00) == 0xe00) {
3813 pTD->vt = VT_PTR;
3814 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3815 pTD = pTD->u.lptdesc;
3817 switch(*pType & 0x3f) {
3818 case VT_PTR:
3819 pTD->vt = VT_PTR;
3820 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3821 pTD = pTD->u.lptdesc;
3822 break;
3824 case VT_USERDEFINED:
3825 pTD->vt = VT_USERDEFINED;
3826 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3827 done = TRUE;
3828 break;
3830 case VT_CARRAY:
3832 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3833 array */
3835 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3837 pTD->vt = VT_CARRAY;
3838 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3839 pTD->u.lpadesc->cDims = pSA->cDims;
3840 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3841 pSA->cDims * sizeof(SAFEARRAYBOUND));
3843 pTD = &pTD->u.lpadesc->tdescElem;
3844 break;
3847 case VT_SAFEARRAY:
3849 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3850 useful? */
3852 pType++;
3853 pTD->vt = VT_SAFEARRAY;
3854 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3855 pTD = pTD->u.lptdesc;
3856 break;
3858 default:
3859 pTD->vt = *pType & 0x3f;
3860 done = TRUE;
3861 break;
3863 pType++;
3865 return pType;
3868 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3869 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3871 /* Handle [in/out] first */
3872 if((*pType & 0xc000) == 0xc000)
3873 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3874 else if(*pType & 0x8000)
3875 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3876 else if(*pType & 0x4000)
3877 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3878 else
3879 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3881 if(*pType & 0x2000)
3882 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3884 if(*pType & 0x80)
3885 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3887 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3891 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3892 char *pNameTable)
3894 unsigned int ref;
3895 char *name;
3896 TLBRefType *ref_type;
3897 sltg_ref_lookup_t *table;
3898 HREFTYPE typelib_ref;
3900 if(pRef->magic != SLTG_REF_MAGIC) {
3901 FIXME("Ref magic = %x\n", pRef->magic);
3902 return NULL;
3904 name = ( (char*)pRef->names + pRef->number);
3906 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3907 table->num = pRef->number >> 3;
3909 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3911 /* We don't want the first href to be 0 */
3912 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3914 for(ref = 0; ref < pRef->number >> 3; ref++) {
3915 char *refname;
3916 unsigned int lib_offs, type_num;
3918 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3920 name += SLTG_ReadStringA(name, &refname);
3921 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3922 FIXME_(typelib)("Can't sscanf ref\n");
3923 if(lib_offs != 0xffff) {
3924 TLBImpLib *import;
3926 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
3927 if(import->offset == lib_offs)
3928 break;
3930 if(&import->entry == &pTL->implib_list) {
3931 char fname[MAX_PATH+1];
3932 int len;
3933 GUID tmpguid;
3935 import = heap_alloc_zero(sizeof(*import));
3936 import->offset = lib_offs;
3937 TLB_GUIDFromString( pNameTable + lib_offs + 4, &tmpguid);
3938 import->guid = TLB_append_guid(&pTL->guid_list, &tmpguid, 2);
3939 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3940 &import->wVersionMajor,
3941 &import->wVersionMinor,
3942 &import->lcid, fname) != 4) {
3943 FIXME_(typelib)("can't sscanf ref %s\n",
3944 pNameTable + lib_offs + 40);
3946 len = strlen(fname);
3947 if(fname[len-1] != '#')
3948 FIXME("fname = %s\n", fname);
3949 fname[len-1] = '\0';
3950 import->name = TLB_MultiByteToBSTR(fname);
3951 list_add_tail(&pTL->implib_list, &import->entry);
3953 ref_type->pImpTLInfo = import;
3955 /* Store a reference to IDispatch */
3956 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid->guid, &IID_StdOle) && type_num == 4)
3957 pTL->dispatch_href = typelib_ref;
3959 } else { /* internal ref */
3960 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3962 ref_type->reference = typelib_ref;
3963 ref_type->index = type_num;
3965 heap_free(refname);
3966 list_add_tail(&pTL->ref_list, &ref_type->entry);
3968 table->refs[ref] = typelib_ref;
3969 typelib_ref += 4;
3971 if((BYTE)*name != SLTG_REF_MAGIC)
3972 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3973 dump_TLBRefType(pTL);
3974 return table;
3977 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3978 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3980 SLTG_ImplInfo *info;
3981 TLBImplType *pImplType;
3982 /* I don't really get this structure, usually it's 0x16 bytes
3983 long, but iuser.tlb contains some that are 0x18 bytes long.
3984 That's ok because we can use the next ptr to jump to the next
3985 one. But how do we know the length of the last one? The WORD
3986 at offs 0x8 might be the clue. For now I'm just assuming that
3987 the last one is the regular 0x16 bytes. */
3989 info = (SLTG_ImplInfo*)pBlk;
3990 while(1){
3991 pTI->typeattr.cImplTypes++;
3992 if(info->next == 0xffff)
3993 break;
3994 info = (SLTG_ImplInfo*)(pBlk + info->next);
3997 info = (SLTG_ImplInfo*)pBlk;
3998 pTI->impltypes = TLBImplType_Alloc(pTI->typeattr.cImplTypes);
3999 pImplType = pTI->impltypes;
4000 while(1) {
4001 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
4002 pImplType->implflags = info->impltypeflags;
4003 ++pImplType;
4005 if(info->next == 0xffff)
4006 break;
4007 if(OneOnly)
4008 FIXME_(typelib)("Interface inheriting more than one interface\n");
4009 info = (SLTG_ImplInfo*)(pBlk + info->next);
4011 info++; /* see comment at top of function */
4012 return (char*)info;
4015 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
4016 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4018 TLBVarDesc *pVarDesc;
4019 const TLBString *prevName = NULL;
4020 SLTG_Variable *pItem;
4021 unsigned short i;
4022 WORD *pType;
4024 pVarDesc = pTI->vardescs = TLBVarDesc_Alloc(cVars);
4026 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
4027 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
4029 pVarDesc->vardesc.memid = pItem->memid;
4031 if (pItem->magic != SLTG_VAR_MAGIC &&
4032 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
4033 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
4034 return;
4037 if (pItem->name == 0xfffe)
4038 pVarDesc->Name = prevName;
4039 else
4040 pVarDesc->Name = SLTG_ReadName(pNameTable, pItem->name, pTI->pTypeLib);
4042 TRACE_(typelib)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc->Name)));
4043 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
4044 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
4046 if(pItem->flags & 0x02)
4047 pType = &pItem->type;
4048 else
4049 pType = (WORD*)(pBlk + pItem->type);
4051 if (pItem->flags & ~0xda)
4052 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
4054 SLTG_DoElem(pType, pBlk,
4055 &pVarDesc->vardesc.elemdescVar, ref_lookup);
4057 if (TRACE_ON(typelib)) {
4058 char buf[300];
4059 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
4060 TRACE_(typelib)("elemdescVar: %s\n", buf);
4063 if (pItem->flags & 0x40) {
4064 TRACE_(typelib)("VAR_DISPATCH\n");
4065 pVarDesc->vardesc.varkind = VAR_DISPATCH;
4067 else if (pItem->flags & 0x10) {
4068 TRACE_(typelib)("VAR_CONST\n");
4069 pVarDesc->vardesc.varkind = VAR_CONST;
4070 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
4071 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
4072 if (pItem->flags & 0x08)
4073 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
4074 else {
4075 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
4077 case VT_LPSTR:
4078 case VT_LPWSTR:
4079 case VT_BSTR:
4081 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
4082 BSTR str;
4083 TRACE_(typelib)("len = %u\n", len);
4084 if (len == 0xffff) {
4085 str = NULL;
4086 } else {
4087 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
4088 str = SysAllocStringLen(NULL, alloc_len);
4089 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
4091 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
4092 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
4093 break;
4095 case VT_I2:
4096 case VT_UI2:
4097 case VT_I4:
4098 case VT_UI4:
4099 case VT_INT:
4100 case VT_UINT:
4101 V_INT(pVarDesc->vardesc.u.lpvarValue) =
4102 *(INT*)(pBlk + pItem->byte_offs);
4103 break;
4104 default:
4105 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
4109 else {
4110 TRACE_(typelib)("VAR_PERINSTANCE\n");
4111 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
4112 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
4115 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
4116 pVarDesc->vardesc.wVarFlags = pItem->varflags;
4118 if (pItem->flags & 0x80)
4119 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
4121 prevName = pVarDesc->Name;
4123 pTI->typeattr.cVars = cVars;
4126 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
4127 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4129 SLTG_Function *pFunc;
4130 unsigned short i;
4131 TLBFuncDesc *pFuncDesc;
4133 pTI->funcdescs = TLBFuncDesc_Alloc(cFuncs);
4135 pFuncDesc = pTI->funcdescs;
4136 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
4137 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
4139 int param;
4140 WORD *pType, *pArg;
4142 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
4143 case SLTG_FUNCTION_MAGIC:
4144 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
4145 break;
4146 case SLTG_DISPATCH_FUNCTION_MAGIC:
4147 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
4148 break;
4149 case SLTG_STATIC_FUNCTION_MAGIC:
4150 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
4151 break;
4152 default:
4153 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
4154 continue;
4156 pFuncDesc->Name = SLTG_ReadName(pNameTable, pFunc->name, pTI->pTypeLib);
4158 pFuncDesc->funcdesc.memid = pFunc->dispid;
4159 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
4160 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
4161 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
4162 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
4163 pFuncDesc->funcdesc.oVft = pFunc->vtblpos & ~1;
4165 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
4166 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
4168 if(pFunc->retnextopt & 0x80)
4169 pType = &pFunc->rettype;
4170 else
4171 pType = (WORD*)(pBlk + pFunc->rettype);
4173 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
4175 pFuncDesc->funcdesc.lprgelemdescParam =
4176 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
4177 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
4179 pArg = (WORD*)(pBlk + pFunc->arg_off);
4181 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
4182 char *paramName = pNameTable + *pArg;
4183 BOOL HaveOffs;
4184 /* If arg type follows then paramName points to the 2nd
4185 letter of the name, else the next WORD is an offset to
4186 the arg type and paramName points to the first letter.
4187 So let's take one char off paramName and see if we're
4188 pointing at an alpha-numeric char. However if *pArg is
4189 0xffff or 0xfffe then the param has no name, the former
4190 meaning that the next WORD is the type, the latter
4191 meaning that the next WORD is an offset to the type. */
4193 HaveOffs = FALSE;
4194 if(*pArg == 0xffff)
4195 paramName = NULL;
4196 else if(*pArg == 0xfffe) {
4197 paramName = NULL;
4198 HaveOffs = TRUE;
4200 else if(paramName[-1] && !isalnum(paramName[-1]))
4201 HaveOffs = TRUE;
4203 pArg++;
4205 if(HaveOffs) { /* the next word is an offset to type */
4206 pType = (WORD*)(pBlk + *pArg);
4207 SLTG_DoElem(pType, pBlk,
4208 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4209 pArg++;
4210 } else {
4211 if(paramName)
4212 paramName--;
4213 pArg = SLTG_DoElem(pArg, pBlk,
4214 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4217 /* Are we an optional param ? */
4218 if(pFuncDesc->funcdesc.cParams - param <=
4219 pFuncDesc->funcdesc.cParamsOpt)
4220 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
4222 if(paramName) {
4223 pFuncDesc->pParamDesc[param].Name = SLTG_ReadName(pNameTable,
4224 paramName - pNameTable, pTI->pTypeLib);
4225 } else {
4226 pFuncDesc->pParamDesc[param].Name = pFuncDesc->Name;
4230 pTI->typeattr.cFuncs = cFuncs;
4233 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
4234 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4235 SLTG_TypeInfoTail *pTITail)
4237 char *pFirstItem;
4238 sltg_ref_lookup_t *ref_lookup = NULL;
4240 if(pTIHeader->href_table != 0xffffffff) {
4241 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4242 pNameTable);
4245 pFirstItem = pBlk;
4247 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4248 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
4250 heap_free(ref_lookup);
4254 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
4255 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4256 const SLTG_TypeInfoTail *pTITail)
4258 char *pFirstItem;
4259 sltg_ref_lookup_t *ref_lookup = NULL;
4261 if(pTIHeader->href_table != 0xffffffff) {
4262 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4263 pNameTable);
4266 pFirstItem = pBlk;
4268 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4269 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
4272 if (pTITail->funcs_off != 0xffff)
4273 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4275 heap_free(ref_lookup);
4277 if (TRACE_ON(typelib))
4278 dump_TLBFuncDesc(pTI->funcdescs, pTI->typeattr.cFuncs);
4281 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
4282 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4283 const SLTG_TypeInfoTail *pTITail)
4285 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4288 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
4289 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4290 const SLTG_TypeInfoTail *pTITail)
4292 WORD *pType;
4293 sltg_ref_lookup_t *ref_lookup = NULL;
4295 if (pTITail->simple_alias) {
4296 /* if simple alias, no more processing required */
4297 pTI->tdescAlias = heap_alloc_zero(sizeof(TYPEDESC));
4298 pTI->tdescAlias->vt = pTITail->tdescalias_vt;
4299 return;
4302 if(pTIHeader->href_table != 0xffffffff) {
4303 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4304 pNameTable);
4307 /* otherwise it is an offset to a type */
4308 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
4310 pTI->tdescAlias = heap_alloc(sizeof(TYPEDESC));
4311 SLTG_DoType(pType, pBlk, pTI->tdescAlias, ref_lookup);
4313 heap_free(ref_lookup);
4316 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
4317 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4318 const SLTG_TypeInfoTail *pTITail)
4320 sltg_ref_lookup_t *ref_lookup = NULL;
4321 if (pTIHeader->href_table != 0xffffffff)
4322 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4323 pNameTable);
4325 if (pTITail->vars_off != 0xffff)
4326 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4328 if (pTITail->funcs_off != 0xffff)
4329 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4331 if (pTITail->impls_off != 0xffff)
4332 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
4334 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4335 * of dispinterface functions including the IDispatch ones, so
4336 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4337 pTI->typeattr.cbSizeVft = pTI->typeattr.cFuncs * pTI->pTypeLib->ptr_size;
4339 heap_free(ref_lookup);
4340 if (TRACE_ON(typelib))
4341 dump_TLBFuncDesc(pTI->funcdescs, pTI->typeattr.cFuncs);
4344 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
4345 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4346 const SLTG_TypeInfoTail *pTITail)
4348 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4351 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
4352 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4353 const SLTG_TypeInfoTail *pTITail)
4355 sltg_ref_lookup_t *ref_lookup = NULL;
4356 if (pTIHeader->href_table != 0xffffffff)
4357 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4358 pNameTable);
4360 if (pTITail->vars_off != 0xffff)
4361 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4363 if (pTITail->funcs_off != 0xffff)
4364 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4365 heap_free(ref_lookup);
4366 if (TRACE_ON(typelib))
4367 dump_TypeInfo(pTI);
4370 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4371 manageable copy of it into this */
4372 typedef struct {
4373 WORD small_no;
4374 char *index_name;
4375 char *other_name;
4376 WORD res1a;
4377 WORD name_offs;
4378 WORD more_bytes;
4379 char *extra;
4380 WORD res20;
4381 DWORD helpcontext;
4382 WORD res26;
4383 GUID uuid;
4384 } SLTG_InternalOtherTypeInfo;
4386 /****************************************************************************
4387 * ITypeLib2_Constructor_SLTG
4389 * loading a SLTG typelib from an in-memory image
4391 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
4393 ITypeLibImpl *pTypeLibImpl;
4394 SLTG_Header *pHeader;
4395 SLTG_BlkEntry *pBlkEntry;
4396 SLTG_Magic *pMagic;
4397 SLTG_Index *pIndex;
4398 SLTG_Pad9 *pPad9;
4399 LPVOID pBlk, pFirstBlk;
4400 SLTG_LibBlk *pLibBlk;
4401 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
4402 char *pAfterOTIBlks = NULL;
4403 char *pNameTable, *ptr;
4404 int i;
4405 DWORD len, order;
4406 ITypeInfoImpl **ppTypeInfoImpl;
4408 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
4411 pTypeLibImpl = TypeLibImpl_Constructor();
4412 if (!pTypeLibImpl) return NULL;
4414 pHeader = pLib;
4416 TRACE_(typelib)("header:\n");
4417 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
4418 pHeader->nrOfFileBlks );
4419 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
4420 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
4421 pHeader->SLTG_magic);
4422 return NULL;
4425 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4426 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
4428 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4429 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
4431 /* Next we have a magic block */
4432 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
4434 /* Let's see if we're still in sync */
4435 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
4436 sizeof(SLTG_COMPOBJ_MAGIC))) {
4437 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
4438 return NULL;
4440 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
4441 sizeof(SLTG_DIR_MAGIC))) {
4442 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
4443 return NULL;
4446 pIndex = (SLTG_Index*)(pMagic+1);
4448 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
4450 pFirstBlk = pPad9 + 1;
4452 /* We'll set up a ptr to the main library block, which is the last one. */
4454 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1;
4455 pBlkEntry[order].next != 0;
4456 order = pBlkEntry[order].next - 1) {
4457 pBlk = (char*)pBlk + pBlkEntry[order].len;
4459 pLibBlk = pBlk;
4461 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
4463 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4464 interspersed */
4466 len += 0x40;
4468 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4470 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
4473 ptr = (char*)pLibBlk + len;
4475 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4476 WORD w, extra;
4477 len = 0;
4479 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
4481 w = *(WORD*)(ptr + 2);
4482 if(w != 0xffff) {
4483 len += w;
4484 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
4485 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4486 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4488 w = *(WORD*)(ptr + 4 + len);
4489 if(w != 0xffff) {
4490 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4491 len += w;
4492 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4493 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4494 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4496 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4497 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4498 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4499 if(extra) {
4500 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4501 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4502 len += extra;
4504 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4505 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4506 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4507 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4508 len += sizeof(SLTG_OtherTypeInfo);
4509 ptr += len;
4512 pAfterOTIBlks = ptr;
4514 /* Skip this WORD and get the next DWORD */
4515 len = *(DWORD*)(pAfterOTIBlks + 2);
4517 /* Now add this to pLibBLk look at what we're pointing at and
4518 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4519 dust and we should be pointing at the beginning of the name
4520 table */
4522 pNameTable = (char*)pLibBlk + len;
4524 switch(*(WORD*)pNameTable) {
4525 case 0xffff:
4526 break;
4527 case 0x0200:
4528 pNameTable += 0x20;
4529 break;
4530 default:
4531 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4532 break;
4535 pNameTable += 0x216;
4537 pNameTable += 2;
4539 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4541 pTypeLibImpl->Name = SLTG_ReadName(pNameTable, pLibBlk->name, pTypeLibImpl);
4544 /* Hopefully we now have enough ptrs set up to actually read in
4545 some TypeInfos. It's not clear which order to do them in, so
4546 I'll just follow the links along the BlkEntry chain and read
4547 them in the order in which they are in the file */
4549 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4550 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4552 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4553 pBlkEntry[order].next != 0;
4554 order = pBlkEntry[order].next - 1, i++) {
4556 SLTG_TypeInfoHeader *pTIHeader;
4557 SLTG_TypeInfoTail *pTITail;
4558 SLTG_MemberHeader *pMemHeader;
4560 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4561 FIXME_(typelib)("Index strings don't match\n");
4562 heap_free(pOtherTypeInfoBlks);
4563 return NULL;
4566 pTIHeader = pBlk;
4567 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4568 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4569 heap_free(pOtherTypeInfoBlks);
4570 return NULL;
4572 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4573 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4574 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4576 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4577 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4578 (*ppTypeInfoImpl)->index = i;
4579 (*ppTypeInfoImpl)->Name = SLTG_ReadName(pNameTable, pOtherTypeInfoBlks[i].name_offs, pTypeLibImpl);
4580 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4581 (*ppTypeInfoImpl)->guid = TLB_append_guid(&pTypeLibImpl->guid_list, &pOtherTypeInfoBlks[i].uuid, 2);
4582 (*ppTypeInfoImpl)->typeattr.typekind = pTIHeader->typekind;
4583 (*ppTypeInfoImpl)->typeattr.wMajorVerNum = pTIHeader->major_version;
4584 (*ppTypeInfoImpl)->typeattr.wMinorVerNum = pTIHeader->minor_version;
4585 (*ppTypeInfoImpl)->typeattr.wTypeFlags =
4586 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4588 if((*ppTypeInfoImpl)->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
4589 (*ppTypeInfoImpl)->typeattr.typekind = TKIND_DISPATCH;
4591 if((pTIHeader->typeflags1 & 7) != 2)
4592 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4593 if(pTIHeader->typeflags3 != 2)
4594 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4596 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4597 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl)->Name)),
4598 typekind_desc[pTIHeader->typekind],
4599 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl)->guid)),
4600 (*ppTypeInfoImpl)->typeattr.wTypeFlags);
4602 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4604 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4606 (*ppTypeInfoImpl)->typeattr.cbAlignment = pTITail->cbAlignment;
4607 (*ppTypeInfoImpl)->typeattr.cbSizeInstance = pTITail->cbSizeInstance;
4608 (*ppTypeInfoImpl)->typeattr.cbSizeVft = pTITail->cbSizeVft;
4610 switch(pTIHeader->typekind) {
4611 case TKIND_ENUM:
4612 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4613 pTIHeader, pTITail);
4614 break;
4616 case TKIND_RECORD:
4617 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4618 pTIHeader, pTITail);
4619 break;
4621 case TKIND_INTERFACE:
4622 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4623 pTIHeader, pTITail);
4624 break;
4626 case TKIND_COCLASS:
4627 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4628 pTIHeader, pTITail);
4629 break;
4631 case TKIND_ALIAS:
4632 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4633 pTIHeader, pTITail);
4634 break;
4636 case TKIND_DISPATCH:
4637 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4638 pTIHeader, pTITail);
4639 break;
4641 case TKIND_MODULE:
4642 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4643 pTIHeader, pTITail);
4644 break;
4646 default:
4647 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4648 break;
4652 /* could get cFuncs, cVars and cImplTypes from here
4653 but we've already set those */
4654 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4655 X(06);
4656 X(16);
4657 X(18);
4658 X(1a);
4659 X(1e);
4660 X(24);
4661 X(26);
4662 X(2a);
4663 X(2c);
4664 X(2e);
4665 X(30);
4666 X(32);
4667 X(34);
4668 #undef X
4669 ++ppTypeInfoImpl;
4670 pBlk = (char*)pBlk + pBlkEntry[order].len;
4673 if(i != pTypeLibImpl->TypeInfoCount) {
4674 FIXME("Somehow processed %d TypeInfos\n", i);
4675 heap_free(pOtherTypeInfoBlks);
4676 return NULL;
4679 heap_free(pOtherTypeInfoBlks);
4680 return &pTypeLibImpl->ITypeLib2_iface;
4683 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4685 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4687 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4689 if(IsEqualIID(riid, &IID_IUnknown) ||
4690 IsEqualIID(riid,&IID_ITypeLib)||
4691 IsEqualIID(riid,&IID_ITypeLib2))
4693 *ppv = &This->ITypeLib2_iface;
4695 else if(IsEqualIID(riid, &IID_ICreateTypeLib) ||
4696 IsEqualIID(riid, &IID_ICreateTypeLib2))
4698 *ppv = &This->ICreateTypeLib2_iface;
4700 else
4702 *ppv = NULL;
4703 TRACE("-- Interface: E_NOINTERFACE\n");
4704 return E_NOINTERFACE;
4707 IUnknown_AddRef((IUnknown*)*ppv);
4708 return S_OK;
4711 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4713 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4714 ULONG ref = InterlockedIncrement(&This->ref);
4716 TRACE("(%p) ref=%u\n", This, ref);
4718 return ref;
4721 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4723 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4724 ULONG ref = InterlockedDecrement(&This->ref);
4726 TRACE("(%p) ref=%u\n",This, ref);
4728 if (!ref)
4730 TLBImpLib *pImpLib, *pImpLibNext;
4731 TLBRefType *ref_type, *ref_type_next;
4732 TLBString *tlbstr, *tlbstr_next;
4733 TLBGuid *tlbguid, *tlbguid_next;
4734 int i;
4736 /* remove cache entry */
4737 if(This->path)
4739 TRACE("removing from cache list\n");
4740 EnterCriticalSection(&cache_section);
4741 if(This->entry.next)
4742 list_remove(&This->entry);
4743 LeaveCriticalSection(&cache_section);
4744 heap_free(This->path);
4746 TRACE(" destroying ITypeLib(%p)\n",This);
4748 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->string_list, TLBString, entry) {
4749 list_remove(&tlbstr->entry);
4750 SysFreeString(tlbstr->str);
4751 heap_free(tlbstr);
4754 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->name_list, TLBString, entry) {
4755 list_remove(&tlbstr->entry);
4756 SysFreeString(tlbstr->str);
4757 heap_free(tlbstr);
4760 LIST_FOR_EACH_ENTRY_SAFE(tlbguid, tlbguid_next, &This->guid_list, TLBGuid, entry) {
4761 list_remove(&tlbguid->entry);
4762 heap_free(tlbguid);
4765 TLB_FreeCustData(&This->custdata_list);
4767 for (i = 0; i < This->ctTypeDesc; i++)
4768 if (This->pTypeDesc[i].vt == VT_CARRAY)
4769 heap_free(This->pTypeDesc[i].u.lpadesc);
4771 heap_free(This->pTypeDesc);
4773 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4775 if (pImpLib->pImpTypeLib)
4776 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4777 SysFreeString(pImpLib->name);
4779 list_remove(&pImpLib->entry);
4780 heap_free(pImpLib);
4783 LIST_FOR_EACH_ENTRY_SAFE(ref_type, ref_type_next, &This->ref_list, TLBRefType, entry)
4785 list_remove(&ref_type->entry);
4786 heap_free(ref_type);
4789 for (i = 0; i < This->TypeInfoCount; ++i){
4790 heap_free(This->typeinfos[i]->tdescAlias);
4791 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4793 heap_free(This->typeinfos);
4794 heap_free(This);
4795 return 0;
4798 return ref;
4801 /* ITypeLib::GetTypeInfoCount
4803 * Returns the number of type descriptions in the type library
4805 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4807 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4808 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4809 return This->TypeInfoCount;
4812 /* ITypeLib::GetTypeInfo
4814 * retrieves the specified type description in the library.
4816 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4817 ITypeLib2 *iface,
4818 UINT index,
4819 ITypeInfo **ppTInfo)
4821 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4823 TRACE("%p %u %p\n", This, index, ppTInfo);
4825 if(!ppTInfo)
4826 return E_INVALIDARG;
4828 if(index >= This->TypeInfoCount)
4829 return TYPE_E_ELEMENTNOTFOUND;
4831 *ppTInfo = (ITypeInfo *)&This->typeinfos[index]->ITypeInfo2_iface;
4832 ITypeInfo_AddRef(*ppTInfo);
4834 return S_OK;
4838 /* ITypeLibs::GetTypeInfoType
4840 * Retrieves the type of a type description.
4842 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4843 ITypeLib2 *iface,
4844 UINT index,
4845 TYPEKIND *pTKind)
4847 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4849 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4851 if(!pTKind)
4852 return E_INVALIDARG;
4854 if(index >= This->TypeInfoCount)
4855 return TYPE_E_ELEMENTNOTFOUND;
4857 *pTKind = This->typeinfos[index]->typeattr.typekind;
4859 return S_OK;
4862 /* ITypeLib::GetTypeInfoOfGuid
4864 * Retrieves the type description that corresponds to the specified GUID.
4867 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4868 ITypeLib2 *iface,
4869 REFGUID guid,
4870 ITypeInfo **ppTInfo)
4872 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4873 int i;
4875 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4877 for(i = 0; i < This->TypeInfoCount; ++i){
4878 if(IsEqualIID(TLB_get_guid_null(This->typeinfos[i]->guid), guid)){
4879 *ppTInfo = (ITypeInfo *)&This->typeinfos[i]->ITypeInfo2_iface;
4880 ITypeInfo_AddRef(*ppTInfo);
4881 return S_OK;
4885 return TYPE_E_ELEMENTNOTFOUND;
4888 /* ITypeLib::GetLibAttr
4890 * Retrieves the structure that contains the library's attributes.
4893 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4894 ITypeLib2 *iface,
4895 LPTLIBATTR *attr)
4897 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4899 TRACE("(%p, %p)\n", This, attr);
4901 if (!attr) return E_INVALIDARG;
4903 *attr = heap_alloc(sizeof(**attr));
4904 if (!*attr) return E_OUTOFMEMORY;
4906 (*attr)->guid = *TLB_get_guid_null(This->guid);
4907 (*attr)->lcid = This->set_lcid;
4908 (*attr)->syskind = This->syskind;
4909 (*attr)->wMajorVerNum = This->ver_major;
4910 (*attr)->wMinorVerNum = This->ver_minor;
4911 (*attr)->wLibFlags = This->libflags;
4913 return S_OK;
4916 /* ITypeLib::GetTypeComp
4918 * Enables a client compiler to bind to a library's types, variables,
4919 * constants, and global functions.
4922 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4923 ITypeLib2 *iface,
4924 ITypeComp **ppTComp)
4926 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4928 TRACE("(%p)->(%p)\n",This,ppTComp);
4929 *ppTComp = &This->ITypeComp_iface;
4930 ITypeComp_AddRef(*ppTComp);
4932 return S_OK;
4935 /* ITypeLib::GetDocumentation
4937 * Retrieves the library's documentation string, the complete Help file name
4938 * and path, and the context identifier for the library Help topic in the Help
4939 * file.
4941 * On a successful return all non-null BSTR pointers will have been set,
4942 * possibly to NULL.
4944 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4945 ITypeLib2 *iface,
4946 INT index,
4947 BSTR *pBstrName,
4948 BSTR *pBstrDocString,
4949 DWORD *pdwHelpContext,
4950 BSTR *pBstrHelpFile)
4952 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4953 HRESULT result = E_INVALIDARG;
4954 ITypeInfo *pTInfo;
4956 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4957 This, index,
4958 pBstrName, pBstrDocString,
4959 pdwHelpContext, pBstrHelpFile);
4961 if(index<0)
4963 /* documentation for the typelib */
4964 if(pBstrName)
4966 if (This->Name)
4968 if(!(*pBstrName = SysAllocString(TLB_get_bstr(This->Name))))
4969 goto memerr1;
4971 else
4972 *pBstrName = NULL;
4974 if(pBstrDocString)
4976 if (This->DocString)
4978 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->DocString))))
4979 goto memerr2;
4981 else
4982 *pBstrDocString = NULL;
4984 if(pdwHelpContext)
4986 *pdwHelpContext = This->dwHelpContext;
4988 if(pBstrHelpFile)
4990 if (This->HelpFile)
4992 if(!(*pBstrHelpFile = SysAllocString(TLB_get_bstr(This->HelpFile))))
4993 goto memerr3;
4995 else
4996 *pBstrHelpFile = NULL;
4999 result = S_OK;
5001 else
5003 /* for a typeinfo */
5004 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
5006 if(SUCCEEDED(result))
5008 result = ITypeInfo_GetDocumentation(pTInfo,
5009 MEMBERID_NIL,
5010 pBstrName,
5011 pBstrDocString,
5012 pdwHelpContext, pBstrHelpFile);
5014 ITypeInfo_Release(pTInfo);
5017 return result;
5018 memerr3:
5019 if (pBstrDocString) SysFreeString (*pBstrDocString);
5020 memerr2:
5021 if (pBstrName) SysFreeString (*pBstrName);
5022 memerr1:
5023 return STG_E_INSUFFICIENTMEMORY;
5026 /* ITypeLib::IsName
5028 * Indicates whether a passed-in string contains the name of a type or member
5029 * described in the library.
5032 static HRESULT WINAPI ITypeLib2_fnIsName(
5033 ITypeLib2 *iface,
5034 LPOLESTR szNameBuf,
5035 ULONG lHashVal,
5036 BOOL *pfName)
5038 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5039 int tic;
5040 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
5042 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
5043 pfName);
5045 *pfName=TRUE;
5046 for(tic = 0; tic < This->TypeInfoCount; ++tic){
5047 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5048 if(!TLB_str_memcmp(szNameBuf, pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5049 for(fdc = 0; fdc < pTInfo->typeattr.cFuncs; ++fdc) {
5050 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
5051 int pc;
5052 if(!TLB_str_memcmp(szNameBuf, pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5053 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++){
5054 if(!TLB_str_memcmp(szNameBuf, pFInfo->pParamDesc[pc].Name, nNameBufLen))
5055 goto ITypeLib2_fnIsName_exit;
5058 for(vrc = 0; vrc < pTInfo->typeattr.cVars; ++vrc){
5059 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
5060 if(!TLB_str_memcmp(szNameBuf, pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5064 *pfName=FALSE;
5066 ITypeLib2_fnIsName_exit:
5067 TRACE("(%p)slow! search for %s: %sfound!\n", This,
5068 debugstr_w(szNameBuf), *pfName ? "" : "NOT ");
5070 return S_OK;
5073 /* ITypeLib::FindName
5075 * Finds occurrences of a type description in a type library. This may be used
5076 * to quickly verify that a name exists in a type library.
5079 static HRESULT WINAPI ITypeLib2_fnFindName(
5080 ITypeLib2 *iface,
5081 LPOLESTR name,
5082 ULONG hash,
5083 ITypeInfo **ppTInfo,
5084 MEMBERID *memid,
5085 UINT16 *found)
5087 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5088 int tic;
5089 UINT count = 0;
5090 UINT len;
5092 TRACE("(%p)->(%s %u %p %p %p)\n", This, debugstr_w(name), hash, ppTInfo, memid, found);
5094 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
5095 return E_INVALIDARG;
5097 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
5098 for(tic = 0; count < *found && tic < This->TypeInfoCount; ++tic) {
5099 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5100 TLBVarDesc *var;
5101 UINT fdc;
5103 if(!TLB_str_memcmp(name, pTInfo->Name, len)) {
5104 memid[count] = MEMBERID_NIL;
5105 goto ITypeLib2_fnFindName_exit;
5108 for(fdc = 0; fdc < pTInfo->typeattr.cFuncs; ++fdc) {
5109 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
5111 if(!TLB_str_memcmp(name, func->Name, len)) {
5112 memid[count] = func->funcdesc.memid;
5113 goto ITypeLib2_fnFindName_exit;
5117 var = TLB_get_vardesc_by_name(pTInfo->vardescs, pTInfo->typeattr.cVars, name);
5118 if (var) {
5119 memid[count] = var->vardesc.memid;
5120 goto ITypeLib2_fnFindName_exit;
5123 continue;
5124 ITypeLib2_fnFindName_exit:
5125 ITypeInfo2_AddRef(&pTInfo->ITypeInfo2_iface);
5126 ppTInfo[count] = (ITypeInfo *)&pTInfo->ITypeInfo2_iface;
5127 count++;
5129 TRACE("found %d typeinfos\n", count);
5131 *found = count;
5133 return S_OK;
5136 /* ITypeLib::ReleaseTLibAttr
5138 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5141 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
5142 ITypeLib2 *iface,
5143 TLIBATTR *pTLibAttr)
5145 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5146 TRACE("(%p)->(%p)\n", This, pTLibAttr);
5147 heap_free(pTLibAttr);
5150 /* ITypeLib2::GetCustData
5152 * gets the custom data
5154 static HRESULT WINAPI ITypeLib2_fnGetCustData(
5155 ITypeLib2 * iface,
5156 REFGUID guid,
5157 VARIANT *pVarVal)
5159 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5160 TLBCustData *pCData;
5162 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
5164 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
5165 if(!pCData)
5166 return TYPE_E_ELEMENTNOTFOUND;
5168 VariantInit(pVarVal);
5169 VariantCopy(pVarVal, &pCData->data);
5171 return S_OK;
5174 /* ITypeLib2::GetLibStatistics
5176 * Returns statistics about a type library that are required for efficient
5177 * sizing of hash tables.
5180 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
5181 ITypeLib2 * iface,
5182 ULONG *pcUniqueNames,
5183 ULONG *pcchUniqueNames)
5185 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5187 FIXME("(%p): stub!\n", This);
5189 if(pcUniqueNames) *pcUniqueNames=1;
5190 if(pcchUniqueNames) *pcchUniqueNames=1;
5191 return S_OK;
5194 /* ITypeLib2::GetDocumentation2
5196 * Retrieves the library's documentation string, the complete Help file name
5197 * and path, the localization context to use, and the context ID for the
5198 * library Help topic in the Help file.
5201 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
5202 ITypeLib2 * iface,
5203 INT index,
5204 LCID lcid,
5205 BSTR *pbstrHelpString,
5206 DWORD *pdwHelpStringContext,
5207 BSTR *pbstrHelpStringDll)
5209 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5210 HRESULT result;
5211 ITypeInfo *pTInfo;
5213 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
5215 /* the help string should be obtained from the helpstringdll,
5216 * using the _DLLGetDocumentation function, based on the supplied
5217 * lcid. Nice to do sometime...
5219 if(index<0)
5221 /* documentation for the typelib */
5222 if(pbstrHelpString)
5223 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->DocString));
5224 if(pdwHelpStringContext)
5225 *pdwHelpStringContext=This->dwHelpContext;
5226 if(pbstrHelpStringDll)
5227 *pbstrHelpStringDll=SysAllocString(TLB_get_bstr(This->HelpStringDll));
5229 result = S_OK;
5231 else
5233 /* for a typeinfo */
5234 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
5236 if(SUCCEEDED(result))
5238 ITypeInfo2 * pTInfo2;
5239 result = ITypeInfo_QueryInterface(pTInfo,
5240 &IID_ITypeInfo2,
5241 (LPVOID*) &pTInfo2);
5243 if(SUCCEEDED(result))
5245 result = ITypeInfo2_GetDocumentation2(pTInfo2,
5246 MEMBERID_NIL,
5247 lcid,
5248 pbstrHelpString,
5249 pdwHelpStringContext,
5250 pbstrHelpStringDll);
5252 ITypeInfo2_Release(pTInfo2);
5255 ITypeInfo_Release(pTInfo);
5258 return result;
5261 static HRESULT TLB_copy_all_custdata(struct list *custdata_list, CUSTDATA *pCustData)
5263 TLBCustData *pCData;
5264 unsigned int ct;
5265 CUSTDATAITEM *cdi;
5267 ct = list_count(custdata_list);
5269 pCustData->prgCustData = CoTaskMemAlloc(ct * sizeof(CUSTDATAITEM));
5270 if(!pCustData->prgCustData)
5271 return E_OUTOFMEMORY;
5273 pCustData->cCustData = ct;
5275 cdi = pCustData->prgCustData;
5276 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
5277 cdi->guid = *TLB_get_guid_null(pCData->guid);
5278 VariantCopy(&cdi->varValue, &pCData->data);
5279 ++cdi;
5282 return S_OK;
5286 /* ITypeLib2::GetAllCustData
5288 * Gets all custom data items for the library.
5291 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
5292 ITypeLib2 * iface,
5293 CUSTDATA *pCustData)
5295 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5296 TRACE("(%p)->(%p)\n", This, pCustData);
5297 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
5300 static const ITypeLib2Vtbl tlbvt = {
5301 ITypeLib2_fnQueryInterface,
5302 ITypeLib2_fnAddRef,
5303 ITypeLib2_fnRelease,
5304 ITypeLib2_fnGetTypeInfoCount,
5305 ITypeLib2_fnGetTypeInfo,
5306 ITypeLib2_fnGetTypeInfoType,
5307 ITypeLib2_fnGetTypeInfoOfGuid,
5308 ITypeLib2_fnGetLibAttr,
5309 ITypeLib2_fnGetTypeComp,
5310 ITypeLib2_fnGetDocumentation,
5311 ITypeLib2_fnIsName,
5312 ITypeLib2_fnFindName,
5313 ITypeLib2_fnReleaseTLibAttr,
5315 ITypeLib2_fnGetCustData,
5316 ITypeLib2_fnGetLibStatistics,
5317 ITypeLib2_fnGetDocumentation2,
5318 ITypeLib2_fnGetAllCustData
5322 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5324 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5326 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
5329 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
5331 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5333 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
5336 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
5338 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5340 return ITypeLib2_Release(&This->ITypeLib2_iface);
5343 static HRESULT WINAPI ITypeLibComp_fnBind(
5344 ITypeComp * iface,
5345 OLECHAR * szName,
5346 ULONG lHash,
5347 WORD wFlags,
5348 ITypeInfo ** ppTInfo,
5349 DESCKIND * pDescKind,
5350 BINDPTR * pBindPtr)
5352 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5353 BOOL typemismatch = FALSE;
5354 int i;
5356 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5358 *pDescKind = DESCKIND_NONE;
5359 pBindPtr->lptcomp = NULL;
5360 *ppTInfo = NULL;
5362 for(i = 0; i < This->TypeInfoCount; ++i){
5363 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5364 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo->Name)));
5366 /* FIXME: check wFlags here? */
5367 /* FIXME: we should use a hash table to look this info up using lHash
5368 * instead of an O(n) search */
5369 if ((pTypeInfo->typeattr.typekind == TKIND_ENUM) ||
5370 (pTypeInfo->typeattr.typekind == TKIND_MODULE))
5372 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name->str, szName))
5374 *pDescKind = DESCKIND_TYPECOMP;
5375 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
5376 ITypeComp_AddRef(pBindPtr->lptcomp);
5377 TRACE("module or enum: %s\n", debugstr_w(szName));
5378 return S_OK;
5382 if ((pTypeInfo->typeattr.typekind == TKIND_MODULE) ||
5383 (pTypeInfo->typeattr.typekind == TKIND_ENUM))
5385 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5386 HRESULT hr;
5388 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5389 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
5391 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
5392 return S_OK;
5394 else if (hr == TYPE_E_TYPEMISMATCH)
5395 typemismatch = TRUE;
5398 if ((pTypeInfo->typeattr.typekind == TKIND_COCLASS) &&
5399 (pTypeInfo->typeattr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
5401 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5402 HRESULT hr;
5403 ITypeInfo *subtypeinfo;
5404 BINDPTR subbindptr;
5405 DESCKIND subdesckind;
5407 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
5408 &subtypeinfo, &subdesckind, &subbindptr);
5409 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
5411 TYPEDESC tdesc_appobject;
5412 const VARDESC vardesc_appobject =
5414 -2, /* memid */
5415 NULL, /* lpstrSchema */
5417 0 /* oInst */
5420 /* ELEMDESC */
5422 /* TYPEDESC */
5424 &tdesc_appobject
5426 VT_PTR
5429 0, /* wVarFlags */
5430 VAR_STATIC /* varkind */
5433 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
5434 tdesc_appobject.vt = VT_USERDEFINED;
5436 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
5438 /* cleanup things filled in by Bind call so we can put our
5439 * application object data in there instead */
5440 switch (subdesckind)
5442 case DESCKIND_FUNCDESC:
5443 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
5444 break;
5445 case DESCKIND_VARDESC:
5446 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
5447 break;
5448 default:
5449 break;
5451 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
5453 if (pTypeInfo->hreftype == -1)
5454 FIXME("no hreftype for interface %p\n", pTypeInfo);
5456 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
5457 if (FAILED(hr))
5458 return hr;
5460 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5461 *ppTInfo = (ITypeInfo *)&pTypeInfo->ITypeInfo2_iface;
5462 ITypeInfo_AddRef(*ppTInfo);
5463 return S_OK;
5465 else if (hr == TYPE_E_TYPEMISMATCH)
5466 typemismatch = TRUE;
5470 if (typemismatch)
5472 TRACE("type mismatch %s\n", debugstr_w(szName));
5473 return TYPE_E_TYPEMISMATCH;
5475 else
5477 TRACE("name not found %s\n", debugstr_w(szName));
5478 return S_OK;
5482 static HRESULT WINAPI ITypeLibComp_fnBindType(
5483 ITypeComp * iface,
5484 OLECHAR * szName,
5485 ULONG lHash,
5486 ITypeInfo ** ppTInfo,
5487 ITypeComp ** ppTComp)
5489 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5490 ITypeInfoImpl *info;
5492 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5494 if(!szName || !ppTInfo || !ppTComp)
5495 return E_INVALIDARG;
5497 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, szName);
5498 if(!info){
5499 *ppTInfo = NULL;
5500 *ppTComp = NULL;
5501 return S_OK;
5504 *ppTInfo = (ITypeInfo *)&info->ITypeInfo2_iface;
5505 ITypeInfo_AddRef(*ppTInfo);
5506 *ppTComp = &info->ITypeComp_iface;
5507 ITypeComp_AddRef(*ppTComp);
5509 return S_OK;
5512 static const ITypeCompVtbl tlbtcvt =
5515 ITypeLibComp_fnQueryInterface,
5516 ITypeLibComp_fnAddRef,
5517 ITypeLibComp_fnRelease,
5519 ITypeLibComp_fnBind,
5520 ITypeLibComp_fnBindType
5523 /*================== ITypeInfo(2) Methods ===================================*/
5524 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5526 ITypeInfoImpl *pTypeInfoImpl;
5528 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5529 if (pTypeInfoImpl)
5531 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5532 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5533 pTypeInfoImpl->ICreateTypeInfo2_iface.lpVtbl = &CreateTypeInfo2Vtbl;
5534 pTypeInfoImpl->ref = 0;
5535 pTypeInfoImpl->hreftype = -1;
5536 pTypeInfoImpl->typeattr.memidConstructor = MEMBERID_NIL;
5537 pTypeInfoImpl->typeattr.memidDestructor = MEMBERID_NIL;
5538 pTypeInfoImpl->pcustdata_list = &pTypeInfoImpl->custdata_list;
5539 list_init(pTypeInfoImpl->pcustdata_list);
5541 TRACE("(%p)\n", pTypeInfoImpl);
5542 return pTypeInfoImpl;
5545 /* ITypeInfo::QueryInterface
5547 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5548 ITypeInfo2 *iface,
5549 REFIID riid,
5550 VOID **ppvObject)
5552 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5554 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5556 *ppvObject=NULL;
5557 if(IsEqualIID(riid, &IID_IUnknown) ||
5558 IsEqualIID(riid,&IID_ITypeInfo)||
5559 IsEqualIID(riid,&IID_ITypeInfo2))
5560 *ppvObject = &This->ITypeInfo2_iface;
5561 else if(IsEqualIID(riid, &IID_ICreateTypeInfo) ||
5562 IsEqualIID(riid, &IID_ICreateTypeInfo2))
5563 *ppvObject = &This->ICreateTypeInfo2_iface;
5564 else if(IsEqualIID(riid, &IID_ITypeComp))
5565 *ppvObject = &This->ITypeComp_iface;
5567 if(*ppvObject){
5568 IUnknown_AddRef((IUnknown*)*ppvObject);
5569 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5570 return S_OK;
5572 TRACE("-- Interface: E_NOINTERFACE\n");
5573 return E_NOINTERFACE;
5576 /* ITypeInfo::AddRef
5578 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5580 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5581 ULONG ref = InterlockedIncrement(&This->ref);
5583 TRACE("(%p)->ref is %u\n",This, ref);
5585 if (ref == 1 /* incremented from 0 */)
5586 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5588 return ref;
5591 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5593 UINT i;
5595 TRACE("destroying ITypeInfo(%p)\n",This);
5597 for (i = 0; i < This->typeattr.cFuncs; ++i)
5599 int j;
5600 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5601 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5603 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5604 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5605 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5606 TLB_FreeCustData(&pFInfo->pParamDesc[j].custdata_list);
5608 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5609 heap_free(pFInfo->pParamDesc);
5610 TLB_FreeCustData(&pFInfo->custdata_list);
5612 heap_free(This->funcdescs);
5614 for(i = 0; i < This->typeattr.cVars; ++i)
5616 TLBVarDesc *pVInfo = &This->vardescs[i];
5617 if (pVInfo->vardesc_create) {
5618 TLB_FreeVarDesc(pVInfo->vardesc_create);
5619 } else if (pVInfo->vardesc.varkind == VAR_CONST) {
5620 VariantClear(pVInfo->vardesc.u.lpvarValue);
5621 heap_free(pVInfo->vardesc.u.lpvarValue);
5623 TLB_FreeCustData(&pVInfo->custdata_list);
5625 heap_free(This->vardescs);
5627 if(This->impltypes){
5628 for (i = 0; i < This->typeattr.cImplTypes; ++i){
5629 TLBImplType *pImpl = &This->impltypes[i];
5630 TLB_FreeCustData(&pImpl->custdata_list);
5632 heap_free(This->impltypes);
5635 TLB_FreeCustData(&This->custdata_list);
5637 heap_free(This);
5640 /* ITypeInfo::Release
5642 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5644 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5645 ULONG ref = InterlockedDecrement(&This->ref);
5647 TRACE("(%p)->(%u)\n",This, ref);
5649 if (!ref)
5651 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5652 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5653 if (not_attached_to_typelib)
5654 heap_free(This);
5655 /* otherwise This will be freed when typelib is freed */
5658 return ref;
5661 /* ITypeInfo::GetTypeAttr
5663 * Retrieves a TYPEATTR structure that contains the attributes of the type
5664 * description.
5667 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5668 LPTYPEATTR *ppTypeAttr)
5670 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5671 SIZE_T size;
5673 TRACE("(%p)\n",This);
5675 size = sizeof(**ppTypeAttr);
5676 if (This->typeattr.typekind == TKIND_ALIAS && This->tdescAlias)
5677 size += TLB_SizeTypeDesc(This->tdescAlias, FALSE);
5679 *ppTypeAttr = heap_alloc(size);
5680 if (!*ppTypeAttr)
5681 return E_OUTOFMEMORY;
5683 **ppTypeAttr = This->typeattr;
5684 (*ppTypeAttr)->guid = *TLB_get_guid_null(This->guid);
5686 if (This->tdescAlias)
5687 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias, This->tdescAlias, *ppTypeAttr + 1);
5689 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5690 /* This should include all the inherited funcs */
5691 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / This->pTypeLib->ptr_size;
5692 /* This is always the size of IDispatch's vtbl */
5693 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5694 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5696 return S_OK;
5699 /* ITypeInfo::GetTypeComp
5701 * Retrieves the ITypeComp interface for the type description, which enables a
5702 * client compiler to bind to the type description's members.
5705 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5706 ITypeComp * *ppTComp)
5708 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5710 TRACE("(%p)->(%p)\n", This, ppTComp);
5712 *ppTComp = &This->ITypeComp_iface;
5713 ITypeComp_AddRef(*ppTComp);
5714 return S_OK;
5717 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5719 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5720 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5721 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5722 return size;
5725 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5727 *dest = *src;
5728 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5729 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5731 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5732 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5733 *buffer += sizeof(PARAMDESCEX);
5734 *pparamdescex_dest = *pparamdescex_src;
5735 pparamdescex_dest->cBytes = sizeof(PARAMDESCEX);
5736 VariantInit(&pparamdescex_dest->varDefaultValue);
5737 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5738 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5740 else
5741 dest->u.paramdesc.pparamdescex = NULL;
5742 return S_OK;
5745 static HRESULT TLB_SanitizeBSTR(BSTR str)
5747 UINT len = SysStringLen(str), i;
5748 for (i = 0; i < len; ++i)
5749 if (str[i] > 0x7f)
5750 str[i] = '?';
5751 return S_OK;
5754 static HRESULT TLB_SanitizeVariant(VARIANT *var)
5756 if (V_VT(var) == VT_INT)
5757 return VariantChangeType(var, var, 0, VT_I4);
5758 else if (V_VT(var) == VT_UINT)
5759 return VariantChangeType(var, var, 0, VT_UI4);
5760 else if (V_VT(var) == VT_BSTR)
5761 return TLB_SanitizeBSTR(V_BSTR(var));
5763 return S_OK;
5766 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5768 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5769 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5772 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5774 FUNCDESC *dest;
5775 char *buffer;
5776 SIZE_T size = sizeof(*src);
5777 SHORT i;
5778 HRESULT hr;
5780 size += sizeof(*src->lprgscode) * src->cScodes;
5781 size += TLB_SizeElemDesc(&src->elemdescFunc);
5782 for (i = 0; i < src->cParams; i++)
5784 size += sizeof(ELEMDESC);
5785 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5788 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5789 if (!dest) return E_OUTOFMEMORY;
5791 *dest = *src;
5792 if (dispinterface) /* overwrite funckind */
5793 dest->funckind = FUNC_DISPATCH;
5794 buffer = (char *)(dest + 1);
5796 dest->oVft = dest->oVft & 0xFFFC;
5798 if (dest->cScodes) {
5799 dest->lprgscode = (SCODE *)buffer;
5800 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5801 buffer += sizeof(*src->lprgscode) * src->cScodes;
5802 } else
5803 dest->lprgscode = NULL;
5805 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5806 if (FAILED(hr))
5808 SysFreeString((BSTR)dest);
5809 return hr;
5812 if (dest->cParams) {
5813 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5814 buffer += sizeof(ELEMDESC) * src->cParams;
5815 for (i = 0; i < src->cParams; i++)
5817 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5818 if (FAILED(hr))
5819 break;
5821 if (FAILED(hr))
5823 /* undo the above actions */
5824 for (i = i - 1; i >= 0; i--)
5825 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5826 TLB_FreeElemDesc(&dest->elemdescFunc);
5827 SysFreeString((BSTR)dest);
5828 return hr;
5830 } else
5831 dest->lprgelemdescParam = NULL;
5833 /* special treatment for dispinterfaces: this makes functions appear
5834 * to return their [retval] value when it is really returning an
5835 * HRESULT */
5836 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5838 if (dest->cParams &&
5839 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5841 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5842 if (elemdesc->tdesc.vt != VT_PTR)
5844 ERR("elemdesc should have started with VT_PTR instead of:\n");
5845 if (ERR_ON(ole))
5846 dump_ELEMDESC(elemdesc);
5847 return E_UNEXPECTED;
5850 /* copy last parameter to the return value. we are using a flat
5851 * buffer so there is no danger of leaking memory in
5852 * elemdescFunc */
5853 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5855 /* remove the last parameter */
5856 dest->cParams--;
5858 else
5859 /* otherwise this function is made to appear to have no return
5860 * value */
5861 dest->elemdescFunc.tdesc.vt = VT_VOID;
5865 *dest_ptr = dest;
5866 return S_OK;
5869 static void TLB_FreeVarDesc(VARDESC *var_desc)
5871 TLB_FreeElemDesc(&var_desc->elemdescVar);
5872 if (var_desc->varkind == VAR_CONST)
5873 VariantClear(var_desc->u.lpvarValue);
5874 SysFreeString((BSTR)var_desc);
5877 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5879 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5881 if (index >= This->typeattr.cFuncs)
5882 return TYPE_E_ELEMENTNOTFOUND;
5884 *ppFuncDesc = &This->funcdescs[index].funcdesc;
5885 return S_OK;
5888 /* internal function to make the inherited interfaces' methods appear
5889 * part of the interface */
5890 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5891 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5893 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5894 HRESULT hr;
5895 UINT implemented_funcs = 0;
5897 if (funcs)
5898 *funcs = 0;
5899 else
5900 *hrefoffset = DISPATCH_HREF_OFFSET;
5902 if(This->impltypes)
5904 ITypeInfo *pSubTypeInfo;
5905 UINT sub_funcs;
5907 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5908 if (FAILED(hr))
5909 return hr;
5911 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5912 index,
5913 ppFuncDesc,
5914 &sub_funcs, hrefoffset);
5915 implemented_funcs += sub_funcs;
5916 ITypeInfo_Release(pSubTypeInfo);
5917 if (SUCCEEDED(hr))
5918 return hr;
5919 *hrefoffset += DISPATCH_HREF_OFFSET;
5922 if (funcs)
5923 *funcs = implemented_funcs + This->typeattr.cFuncs;
5924 else
5925 *hrefoffset = 0;
5927 if (index < implemented_funcs)
5928 return E_INVALIDARG;
5929 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5930 ppFuncDesc);
5933 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5935 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5936 while (TRUE)
5938 switch (pTypeDesc->vt)
5940 case VT_USERDEFINED:
5941 pTypeDesc->u.hreftype += hrefoffset;
5942 return;
5943 case VT_PTR:
5944 case VT_SAFEARRAY:
5945 pTypeDesc = pTypeDesc->u.lptdesc;
5946 break;
5947 case VT_CARRAY:
5948 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5949 break;
5950 default:
5951 return;
5956 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5958 SHORT i;
5959 for (i = 0; i < pFuncDesc->cParams; i++)
5960 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5961 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5964 /* ITypeInfo::GetFuncDesc
5966 * Retrieves the FUNCDESC structure that contains information about a
5967 * specified function.
5970 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5971 LPFUNCDESC *ppFuncDesc)
5973 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5974 const FUNCDESC *internal_funcdesc;
5975 HRESULT hr;
5976 UINT hrefoffset = 0;
5978 TRACE("(%p) index %d\n", This, index);
5980 if (!ppFuncDesc)
5981 return E_INVALIDARG;
5983 if (This->needs_layout)
5984 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
5986 if (This->typeattr.typekind == TKIND_DISPATCH)
5987 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5988 &internal_funcdesc, NULL,
5989 &hrefoffset);
5990 else
5991 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5992 &internal_funcdesc);
5993 if (FAILED(hr))
5995 WARN("description for function %d not found\n", index);
5996 return hr;
5999 hr = TLB_AllocAndInitFuncDesc(
6000 internal_funcdesc,
6001 ppFuncDesc,
6002 This->typeattr.typekind == TKIND_DISPATCH);
6004 if ((This->typeattr.typekind == TKIND_DISPATCH) && hrefoffset)
6005 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
6007 TRACE("-- 0x%08x\n", hr);
6008 return hr;
6011 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
6013 VARDESC *dest;
6014 char *buffer;
6015 SIZE_T size = sizeof(*src);
6016 HRESULT hr;
6018 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
6019 if (src->varkind == VAR_CONST)
6020 size += sizeof(VARIANT);
6021 size += TLB_SizeElemDesc(&src->elemdescVar);
6023 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
6024 if (!dest) return E_OUTOFMEMORY;
6026 *dest = *src;
6027 buffer = (char *)(dest + 1);
6028 if (src->lpstrSchema)
6030 int len;
6031 dest->lpstrSchema = (LPOLESTR)buffer;
6032 len = strlenW(src->lpstrSchema);
6033 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
6034 buffer += (len + 1) * sizeof(WCHAR);
6037 if (src->varkind == VAR_CONST)
6039 HRESULT hr;
6041 dest->u.lpvarValue = (VARIANT *)buffer;
6042 *dest->u.lpvarValue = *src->u.lpvarValue;
6043 buffer += sizeof(VARIANT);
6044 VariantInit(dest->u.lpvarValue);
6045 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
6046 if (FAILED(hr))
6048 SysFreeString((BSTR)dest);
6049 return hr;
6052 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
6053 if (FAILED(hr))
6055 if (src->varkind == VAR_CONST)
6056 VariantClear(dest->u.lpvarValue);
6057 SysFreeString((BSTR)dest);
6058 return hr;
6060 *dest_ptr = dest;
6061 return S_OK;
6064 /* ITypeInfo::GetVarDesc
6066 * Retrieves a VARDESC structure that describes the specified variable.
6069 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
6070 LPVARDESC *ppVarDesc)
6072 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6073 const TLBVarDesc *pVDesc = &This->vardescs[index];
6075 TRACE("(%p) index %d\n", This, index);
6077 if(index >= This->typeattr.cVars)
6078 return TYPE_E_ELEMENTNOTFOUND;
6080 if (This->needs_layout)
6081 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6083 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
6086 /* ITypeInfo_GetNames
6088 * Retrieves the variable with the specified member ID (or the name of the
6089 * property or method and its parameters) that correspond to the specified
6090 * function ID.
6092 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
6093 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
6095 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6096 const TLBFuncDesc *pFDesc;
6097 const TLBVarDesc *pVDesc;
6098 int i;
6099 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
6101 if(!rgBstrNames)
6102 return E_INVALIDARG;
6104 *pcNames = 0;
6106 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->typeattr.cFuncs, memid);
6107 if(pFDesc)
6109 if(!cMaxNames || !pFDesc->Name)
6110 return S_OK;
6112 *rgBstrNames = SysAllocString(TLB_get_bstr(pFDesc->Name));
6113 ++(*pcNames);
6115 for(i = 0; i < pFDesc->funcdesc.cParams; ++i){
6116 if(*pcNames >= cMaxNames || !pFDesc->pParamDesc[i].Name)
6117 return S_OK;
6118 rgBstrNames[*pcNames] = SysAllocString(TLB_get_bstr(pFDesc->pParamDesc[i].Name));
6119 ++(*pcNames);
6121 return S_OK;
6124 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->typeattr.cVars, memid);
6125 if(pVDesc)
6127 *rgBstrNames=SysAllocString(TLB_get_bstr(pVDesc->Name));
6128 *pcNames=1;
6130 else
6132 if(This->impltypes &&
6133 (This->typeattr.typekind == TKIND_INTERFACE || This->typeattr.typekind == TKIND_DISPATCH)) {
6134 /* recursive search */
6135 ITypeInfo *pTInfo;
6136 HRESULT result;
6137 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6138 if(SUCCEEDED(result))
6140 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
6141 ITypeInfo_Release(pTInfo);
6142 return result;
6144 WARN("Could not search inherited interface!\n");
6146 else
6148 WARN("no names found\n");
6150 *pcNames=0;
6151 return TYPE_E_ELEMENTNOTFOUND;
6153 return S_OK;
6157 /* ITypeInfo::GetRefTypeOfImplType
6159 * If a type description describes a COM class, it retrieves the type
6160 * description of the implemented interface types. For an interface,
6161 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6162 * if any exist.
6165 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
6166 ITypeInfo2 *iface,
6167 UINT index,
6168 HREFTYPE *pRefType)
6170 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6171 HRESULT hr = S_OK;
6173 TRACE("(%p) index %d\n", This, index);
6174 if (TRACE_ON(ole)) dump_TypeInfo(This);
6176 if(index==(UINT)-1)
6178 /* only valid on dual interfaces;
6179 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6182 if (This->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
6184 *pRefType = -2;
6186 else
6188 hr = TYPE_E_ELEMENTNOTFOUND;
6191 else if(index == 0 && This->typeattr.typekind == TKIND_DISPATCH)
6193 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6194 *pRefType = This->pTypeLib->dispatch_href;
6196 else
6198 if(index >= This->typeattr.cImplTypes)
6199 hr = TYPE_E_ELEMENTNOTFOUND;
6200 else{
6201 *pRefType = This->impltypes[index].hRef;
6202 if (This->typeattr.typekind == TKIND_INTERFACE)
6203 *pRefType |= 0x2;
6207 if(TRACE_ON(ole))
6209 if(SUCCEEDED(hr))
6210 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
6211 else
6212 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
6215 return hr;
6218 /* ITypeInfo::GetImplTypeFlags
6220 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6221 * or base interface in a type description.
6223 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
6224 UINT index, INT *pImplTypeFlags)
6226 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6228 TRACE("(%p) index %d\n", This, index);
6230 if(!pImplTypeFlags)
6231 return E_INVALIDARG;
6233 if(This->typeattr.typekind == TKIND_DISPATCH && index == 0){
6234 *pImplTypeFlags = 0;
6235 return S_OK;
6238 if(index >= This->typeattr.cImplTypes)
6239 return TYPE_E_ELEMENTNOTFOUND;
6241 *pImplTypeFlags = This->impltypes[index].implflags;
6243 return S_OK;
6246 /* GetIDsOfNames
6247 * Maps between member names and member IDs, and parameter names and
6248 * parameter IDs.
6250 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
6251 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
6253 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6254 const TLBVarDesc *pVDesc;
6255 HRESULT ret=S_OK;
6256 UINT i, fdc;
6258 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
6259 cNames);
6261 /* init out parameters in case of failure */
6262 for (i = 0; i < cNames; i++)
6263 pMemId[i] = MEMBERID_NIL;
6265 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc) {
6266 int j;
6267 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
6268 if(!lstrcmpiW(*rgszNames, TLB_get_bstr(pFDesc->Name))) {
6269 if(cNames) *pMemId=pFDesc->funcdesc.memid;
6270 for(i=1; i < cNames; i++){
6271 for(j=0; j<pFDesc->funcdesc.cParams; j++)
6272 if(!lstrcmpiW(rgszNames[i],TLB_get_bstr(pFDesc->pParamDesc[j].Name)))
6273 break;
6274 if( j<pFDesc->funcdesc.cParams)
6275 pMemId[i]=j;
6276 else
6277 ret=DISP_E_UNKNOWNNAME;
6279 TRACE("-- 0x%08x\n", ret);
6280 return ret;
6283 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->typeattr.cVars, *rgszNames);
6284 if(pVDesc){
6285 if(cNames)
6286 *pMemId = pVDesc->vardesc.memid;
6287 return ret;
6289 /* not found, see if it can be found in an inherited interface */
6290 if(This->impltypes) {
6291 /* recursive search */
6292 ITypeInfo *pTInfo;
6293 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6294 if(SUCCEEDED(ret)){
6295 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
6296 ITypeInfo_Release(pTInfo);
6297 return ret;
6299 WARN("Could not search inherited interface!\n");
6300 } else
6301 WARN("no names found\n");
6302 return DISP_E_UNKNOWNNAME;
6306 #ifdef __i386__
6308 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6309 __ASM_GLOBAL_FUNC( call_method,
6310 "pushl %ebp\n\t"
6311 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6312 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6313 "movl %esp,%ebp\n\t"
6314 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6315 "pushl %esi\n\t"
6316 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6317 "pushl %edi\n\t"
6318 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6319 "movl 12(%ebp),%edx\n\t"
6320 "movl %esp,%edi\n\t"
6321 "shll $2,%edx\n\t"
6322 "jz 1f\n\t"
6323 "subl %edx,%edi\n\t"
6324 "andl $~15,%edi\n\t"
6325 "movl %edi,%esp\n\t"
6326 "movl 12(%ebp),%ecx\n\t"
6327 "movl 16(%ebp),%esi\n\t"
6328 "cld\n\t"
6329 "rep; movsl\n"
6330 "1:\tcall *8(%ebp)\n\t"
6331 "subl %esp,%edi\n\t"
6332 "movl 20(%ebp),%ecx\n\t"
6333 "movl %edi,(%ecx)\n\t"
6334 "leal -8(%ebp),%esp\n\t"
6335 "popl %edi\n\t"
6336 __ASM_CFI(".cfi_same_value %edi\n\t")
6337 "popl %esi\n\t"
6338 __ASM_CFI(".cfi_same_value %esi\n\t")
6339 "popl %ebp\n\t"
6340 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6341 __ASM_CFI(".cfi_same_value %ebp\n\t")
6342 "ret" )
6344 /* same function but returning floating point */
6345 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
6347 /* ITypeInfo::Invoke
6349 * Invokes a method, or accesses a property of an object, that implements the
6350 * interface described by the type description.
6352 DWORD
6353 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
6354 DWORD res;
6355 int stack_offset;
6357 if (TRACE_ON(ole)) {
6358 int i;
6359 TRACE("Calling %p(",func);
6360 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
6361 if (nrargs > 30) TRACE("...");
6362 TRACE(")\n");
6365 switch (callconv) {
6366 case CC_STDCALL:
6367 case CC_CDECL:
6368 res = call_method( func, nrargs, args, &stack_offset );
6369 break;
6370 default:
6371 FIXME("unsupported calling convention %d\n",callconv);
6372 res = -1;
6373 break;
6375 TRACE("returns %08x\n",res);
6376 return res;
6379 #elif defined(__x86_64__)
6381 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
6382 __ASM_GLOBAL_FUNC( call_method,
6383 "pushq %rbp\n\t"
6384 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6385 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6386 "movq %rsp,%rbp\n\t"
6387 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6388 "pushq %rsi\n\t"
6389 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6390 "pushq %rdi\n\t"
6391 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6392 "movq %rcx,%rax\n\t"
6393 "movq $4,%rcx\n\t"
6394 "cmp %rcx,%rdx\n\t"
6395 "cmovgq %rdx,%rcx\n\t"
6396 "leaq 0(,%rcx,8),%rdx\n\t"
6397 "subq %rdx,%rsp\n\t"
6398 "andq $~15,%rsp\n\t"
6399 "movq %rsp,%rdi\n\t"
6400 "movq %r8,%rsi\n\t"
6401 "rep; movsq\n\t"
6402 "movq 0(%rsp),%rcx\n\t"
6403 "movq 8(%rsp),%rdx\n\t"
6404 "movq 16(%rsp),%r8\n\t"
6405 "movq 24(%rsp),%r9\n\t"
6406 "movq 0(%rsp),%xmm0\n\t"
6407 "movq 8(%rsp),%xmm1\n\t"
6408 "movq 16(%rsp),%xmm2\n\t"
6409 "movq 24(%rsp),%xmm3\n\t"
6410 "callq *%rax\n\t"
6411 "leaq -16(%rbp),%rsp\n\t"
6412 "popq %rdi\n\t"
6413 __ASM_CFI(".cfi_same_value %rdi\n\t")
6414 "popq %rsi\n\t"
6415 __ASM_CFI(".cfi_same_value %rsi\n\t")
6416 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6417 "popq %rbp\n\t"
6418 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6419 __ASM_CFI(".cfi_same_value %rbp\n\t")
6420 "ret")
6422 /* same function but returning floating point */
6423 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
6425 #elif defined(__arm__)
6427 extern LONGLONG CDECL call_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6428 __ASM_GLOBAL_FUNC( call_method,
6429 /* r0 = *func
6430 * r1 = nb_stk_args
6431 * r2 = *stk_args (pointer to 'nb_stk_args' DWORD values to push on stack)
6432 * 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)
6435 "push {fp, lr}\n\t" /* Save frame pointer and return address (stack still aligned to 8 bytes) */
6436 "mov fp, sp\n\t" /* Save stack pointer as our frame for cleaning the stack on return */
6438 "lsls r1, r1, #2\n\t" /* r1 = nb_stk_args * sizeof(DWORD) */
6439 "beq 1f\n\t" /* Skip allocation if no stack args */
6440 "add r2, r2, r1\n" /* Calculate ending address of incoming stack data */
6441 "2:\tldr ip, [r2, #-4]!\n\t" /* Get next value */
6442 "str ip, [sp, #-4]!\n\t" /* Push it on the stack */
6443 "subs r1, r1, #4\n\t" /* Decrement count */
6444 "bgt 2b\n\t" /* Loop till done */
6446 "1:\tvldm r3!, {s0-s15}\n\t" /* Load the s0-s15/d0-d7 arguments */
6447 "mov ip, r0\n\t" /* Save the function call address to ip before we nuke r0 with arguments to pass */
6448 "ldm r3, {r0-r3}\n\t" /* Load the r0-r3 arguments */
6450 "blx ip\n\t" /* Call the target function */
6452 "mov sp, fp\n\t" /* Clean the stack using fp */
6453 "pop {fp, pc}\n\t" /* Restore fp and return */
6456 /* same function but returning single/double floating point */
6457 static float (CDECL * const call_float_method)(void *, int, const DWORD *, const DWORD *) = (void *)call_method;
6458 static double (CDECL * const call_double_method)(void *, int, const DWORD *, const DWORD *) = (void *)call_method;
6460 #endif /* __x86_64__ */
6462 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6464 HRESULT hr = S_OK;
6465 ITypeInfo *tinfo2 = NULL;
6466 TYPEATTR *tattr = NULL;
6468 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6469 if (hr)
6471 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6472 "hr = 0x%08x\n",
6473 tdesc->u.hreftype, hr);
6474 return hr;
6476 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6477 if (hr)
6479 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
6480 ITypeInfo_Release(tinfo2);
6481 return hr;
6484 switch (tattr->typekind)
6486 case TKIND_ENUM:
6487 *vt |= VT_I4;
6488 break;
6490 case TKIND_ALIAS:
6491 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
6492 break;
6494 case TKIND_INTERFACE:
6495 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
6496 *vt |= VT_DISPATCH;
6497 else
6498 *vt |= VT_UNKNOWN;
6499 break;
6501 case TKIND_DISPATCH:
6502 *vt |= VT_DISPATCH;
6503 break;
6505 case TKIND_COCLASS:
6506 *vt |= VT_DISPATCH;
6507 break;
6509 case TKIND_RECORD:
6510 FIXME("TKIND_RECORD unhandled.\n");
6511 hr = E_NOTIMPL;
6512 break;
6514 case TKIND_UNION:
6515 FIXME("TKIND_UNION unhandled.\n");
6516 hr = E_NOTIMPL;
6517 break;
6519 default:
6520 FIXME("TKIND %d unhandled.\n",tattr->typekind);
6521 hr = E_NOTIMPL;
6522 break;
6524 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6525 ITypeInfo_Release(tinfo2);
6526 return hr;
6529 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6531 HRESULT hr = S_OK;
6533 /* enforce only one level of pointer indirection */
6534 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
6536 tdesc = tdesc->u.lptdesc;
6538 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6539 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6540 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6541 if ((tdesc->vt == VT_USERDEFINED) ||
6542 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
6544 VARTYPE vt_userdefined = 0;
6545 const TYPEDESC *tdesc_userdefined = tdesc;
6546 if (tdesc->vt == VT_PTR)
6548 vt_userdefined = VT_BYREF;
6549 tdesc_userdefined = tdesc->u.lptdesc;
6551 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
6552 if ((hr == S_OK) &&
6553 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
6554 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
6556 *vt |= vt_userdefined;
6557 return S_OK;
6560 *vt = VT_BYREF;
6563 switch (tdesc->vt)
6565 case VT_HRESULT:
6566 *vt |= VT_ERROR;
6567 break;
6568 case VT_USERDEFINED:
6569 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
6570 break;
6571 case VT_VOID:
6572 case VT_CARRAY:
6573 case VT_PTR:
6574 case VT_LPSTR:
6575 case VT_LPWSTR:
6576 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
6577 hr = DISP_E_BADVARTYPE;
6578 break;
6579 case VT_SAFEARRAY:
6580 *vt |= VT_ARRAY;
6581 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
6582 break;
6583 case VT_INT:
6584 *vt |= VT_I4;
6585 break;
6586 case VT_UINT:
6587 *vt |= VT_UI4;
6588 break;
6589 default:
6590 *vt |= tdesc->vt;
6591 break;
6593 return hr;
6596 static HRESULT get_iface_guid(ITypeInfo *tinfo, const TYPEDESC *tdesc, GUID *guid)
6598 ITypeInfo *tinfo2;
6599 TYPEATTR *tattr;
6600 HRESULT hres;
6602 hres = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6603 if(FAILED(hres))
6604 return hres;
6606 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6607 if(FAILED(hres)) {
6608 ITypeInfo_Release(tinfo2);
6609 return hres;
6612 switch(tattr->typekind) {
6613 case TKIND_ALIAS:
6614 hres = get_iface_guid(tinfo2, &tattr->tdescAlias, guid);
6615 break;
6617 case TKIND_INTERFACE:
6618 case TKIND_DISPATCH:
6619 *guid = tattr->guid;
6620 break;
6622 default:
6623 ERR("Unexpected typekind %d\n", tattr->typekind);
6624 hres = E_UNEXPECTED;
6627 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6628 ITypeInfo_Release(tinfo2);
6629 return hres;
6632 /***********************************************************************
6633 * DispCallFunc (OLEAUT32.@)
6635 * Invokes a function of the specified calling convention, passing the
6636 * specified arguments and returns the result.
6638 * PARAMS
6639 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6640 * oVft [I] The offset in the vtable. See notes.
6641 * cc [I] Calling convention of the function to call.
6642 * vtReturn [I] The return type of the function.
6643 * cActuals [I] Number of parameters.
6644 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6645 * prgpvarg [I] The arguments to pass.
6646 * pvargResult [O] The return value of the function. Can be NULL.
6648 * RETURNS
6649 * Success: S_OK.
6650 * Failure: HRESULT code.
6652 * NOTES
6653 * The HRESULT return value of this function is not affected by the return
6654 * value of the user supplied function, which is returned in pvargResult.
6656 * If pvInstance is NULL then a non-object function is to be called and oVft
6657 * is the address of the function to call.
6659 * The cc parameter can be one of the following values:
6660 *|CC_FASTCALL
6661 *|CC_CDECL
6662 *|CC_PASCAL
6663 *|CC_STDCALL
6664 *|CC_FPFASTCALL
6665 *|CC_SYSCALL
6666 *|CC_MPWCDECL
6667 *|CC_MPWPASCAL
6670 HRESULT WINAPI
6671 DispCallFunc(
6672 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
6673 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
6675 #ifdef __i386__
6676 int argspos, stack_offset;
6677 void *func;
6678 UINT i;
6679 DWORD *args;
6681 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6682 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6683 pvargResult, V_VT(pvargResult));
6685 if (cc != CC_STDCALL && cc != CC_CDECL)
6687 FIXME("unsupported calling convention %d\n",cc);
6688 return E_INVALIDARG;
6691 /* maximum size for an argument is sizeof(VARIANT) */
6692 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6694 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6695 argspos = 1;
6696 if (pvInstance)
6698 const FARPROC *vtable = *(FARPROC **)pvInstance;
6699 func = vtable[oVft/sizeof(void *)];
6700 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6702 else func = (void *)oVft;
6704 for (i = 0; i < cActuals; i++)
6706 VARIANT *arg = prgpvarg[i];
6708 switch (prgvt[i])
6710 case VT_EMPTY:
6711 break;
6712 case VT_I8:
6713 case VT_UI8:
6714 case VT_R8:
6715 case VT_DATE:
6716 case VT_CY:
6717 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6718 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6719 break;
6720 case VT_DECIMAL:
6721 case VT_VARIANT:
6722 memcpy( &args[argspos], arg, sizeof(*arg) );
6723 argspos += sizeof(*arg) / sizeof(DWORD);
6724 break;
6725 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6726 args[argspos++] = V_BOOL(arg);
6727 break;
6728 default:
6729 args[argspos++] = V_UI4(arg);
6730 break;
6732 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6735 switch (vtReturn)
6737 case VT_EMPTY:
6738 call_method( func, argspos - 1, args + 1, &stack_offset );
6739 break;
6740 case VT_R4:
6741 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6742 break;
6743 case VT_R8:
6744 case VT_DATE:
6745 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6746 break;
6747 case VT_DECIMAL:
6748 case VT_VARIANT:
6749 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6750 call_method( func, argspos, args, &stack_offset );
6751 break;
6752 case VT_I8:
6753 case VT_UI8:
6754 case VT_CY:
6755 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6756 break;
6757 case VT_HRESULT:
6758 WARN("invalid return type %u\n", vtReturn);
6759 heap_free( args );
6760 return E_INVALIDARG;
6761 default:
6762 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6763 break;
6765 heap_free( args );
6766 if (stack_offset && cc == CC_STDCALL)
6768 WARN( "stack pointer off by %d\n", stack_offset );
6769 return DISP_E_BADCALLEE;
6771 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6772 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6773 return S_OK;
6775 #elif defined(__x86_64__)
6776 int argspos;
6777 UINT i;
6778 DWORD_PTR *args;
6779 void *func;
6781 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6782 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6783 pvargResult, V_VT(pvargResult));
6785 if (cc != CC_STDCALL && cc != CC_CDECL)
6787 FIXME("unsupported calling convention %d\n",cc);
6788 return E_INVALIDARG;
6791 /* maximum size for an argument is sizeof(DWORD_PTR) */
6792 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6794 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6795 argspos = 1;
6796 if (pvInstance)
6798 const FARPROC *vtable = *(FARPROC **)pvInstance;
6799 func = vtable[oVft/sizeof(void *)];
6800 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6802 else func = (void *)oVft;
6804 for (i = 0; i < cActuals; i++)
6806 VARIANT *arg = prgpvarg[i];
6808 switch (prgvt[i])
6810 case VT_DECIMAL:
6811 case VT_VARIANT:
6812 args[argspos++] = (ULONG_PTR)arg;
6813 break;
6814 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6815 args[argspos++] = V_BOOL(arg);
6816 break;
6817 default:
6818 args[argspos++] = V_UI8(arg);
6819 break;
6821 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6824 switch (vtReturn)
6826 case VT_R4:
6827 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6828 break;
6829 case VT_R8:
6830 case VT_DATE:
6831 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6832 break;
6833 case VT_DECIMAL:
6834 case VT_VARIANT:
6835 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6836 call_method( func, argspos, args );
6837 break;
6838 case VT_HRESULT:
6839 WARN("invalid return type %u\n", vtReturn);
6840 heap_free( args );
6841 return E_INVALIDARG;
6842 default:
6843 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6844 break;
6846 heap_free( args );
6847 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6848 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6849 return S_OK;
6851 #elif defined(__arm__)
6852 int argspos;
6853 void *func;
6854 UINT i;
6855 DWORD *args;
6856 struct {
6857 union {
6858 float s[16];
6859 double d[8];
6860 } sd;
6861 DWORD r[4];
6862 } regs;
6863 int rcount; /* 32-bit register index count */
6864 int scount; /* single-precision float register index count (will be incremented twice for doubles, plus alignment) */
6866 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6867 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6869 if (cc != CC_STDCALL && cc != CC_CDECL)
6871 FIXME("unsupported calling convention %d\n",cc);
6872 return E_INVALIDARG;
6875 argspos = 0;
6876 rcount = 0;
6877 scount = 0;
6879 /* Determine if we need to pass a pointer for the return value as arg 0. If so, do that */
6880 /* first as it will need to be in the 'r' registers: */
6881 switch (vtReturn)
6883 case VT_DECIMAL:
6884 case VT_VARIANT:
6885 regs.r[rcount++] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6886 break;
6887 case VT_HRESULT:
6888 WARN("invalid return type %u\n", vtReturn);
6889 return E_INVALIDARG;
6890 default: /* And all others are in 'r', 's', or 'd' registers or have no return value */
6891 break;
6894 if (pvInstance)
6896 const FARPROC *vtable = *(FARPROC **)pvInstance;
6897 func = vtable[oVft/sizeof(void *)];
6898 regs.r[rcount++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6900 else func = (void *)oVft;
6902 /* maximum size for an argument is sizeof(VARIANT). Also allow for return pointer and stack alignment. */
6903 args = heap_alloc( sizeof(VARIANT) * cActuals + sizeof(DWORD) * 4 );
6905 for (i = 0; i < cActuals; i++)
6907 VARIANT *arg = prgpvarg[i];
6908 DWORD *pdwarg = (DWORD *)(arg); /* a reinterpret_cast of the variant, used for copying structures when they are split between registers and stack */
6909 int ntemp; /* Used for counting words split between registers and stack */
6911 switch (prgvt[i])
6913 case VT_EMPTY:
6914 break;
6915 case VT_R4: /* these must be 4-byte aligned, and put in 's' regs or stack, as they are single-floats */
6916 if (scount < 16)
6917 regs.sd.s[scount++] = V_R4(arg);
6918 else
6919 args[argspos++] = V_UI4(arg);
6920 break;
6921 case VT_R8: /* these must be 8-byte aligned, and put in 'd' regs or stack, as they are double-floats */
6922 case VT_DATE:
6923 if (scount < 15)
6925 scount += (scount % 2); /* align scount to next whole double */
6926 regs.sd.d[scount/2] = V_R8(arg);
6927 scount += 2;
6929 else
6931 scount = 16; /* Make sure we flag that all 's' regs are full */
6932 argspos += (argspos % 2); /* align argspos to 8-bytes */
6933 memcpy( &args[argspos], &V_R8(arg), sizeof(V_R8(arg)) );
6934 argspos += sizeof(V_R8(arg)) / sizeof(DWORD);
6936 break;
6937 case VT_I8: /* these must be 8-byte aligned, and put in 'r' regs or stack, as they are long-longs */
6938 case VT_UI8:
6939 case VT_CY:
6940 if (rcount < 3)
6942 rcount += (rcount % 2); /* align rcount to 8-byte register pair */
6943 memcpy( &regs.r[rcount], &V_UI8(arg), sizeof(V_UI8(arg)) );
6944 rcount += sizeof(V_UI8(arg)) / sizeof(DWORD);
6946 else
6948 rcount = 4; /* Make sure we flag that all 'r' regs are full */
6949 argspos += (argspos % 2); /* align argspos to 8-bytes */
6950 memcpy( &args[argspos], &V_UI8(arg), sizeof(V_UI8(arg)) );
6951 argspos += sizeof(V_UI8(arg)) / sizeof(DWORD);
6953 break;
6954 case VT_DECIMAL: /* these structures are 8-byte aligned, and put in 'r' regs or stack, can be split between the two */
6955 case VT_VARIANT:
6956 /* 8-byte align 'r' and/or stack: */
6957 if (rcount < 3)
6958 rcount += (rcount % 2);
6959 else
6961 rcount = 4;
6962 argspos += (argspos % 2);
6964 ntemp = sizeof(*arg) / sizeof(DWORD);
6965 while (ntemp > 0)
6967 if (rcount < 4)
6968 regs.r[rcount++] = *pdwarg++;
6969 else
6970 args[argspos++] = *pdwarg++;
6971 --ntemp;
6973 break;
6974 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6975 if (rcount < 4)
6976 regs.r[rcount++] = V_BOOL(arg);
6977 else
6978 args[argspos++] = V_BOOL(arg);
6979 break;
6980 default:
6981 if (rcount < 4)
6982 regs.r[rcount++] = V_UI4(arg);
6983 else
6984 args[argspos++] = V_UI4(arg);
6985 break;
6987 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6990 argspos += (argspos % 2); /* Make sure stack function alignment is 8-byte */
6992 TRACE("rcount: %d, scount: %d, argspos: %d\n", rcount, scount, argspos);
6994 switch (vtReturn)
6996 case VT_EMPTY: /* EMPTY = no return value */
6997 case VT_DECIMAL: /* DECIMAL and VARIANT already have a pointer argument passed (see above) */
6998 case VT_VARIANT:
6999 call_method( func, argspos, args, (DWORD*)&regs );
7000 break;
7001 case VT_R4:
7002 V_R4(pvargResult) = call_float_method( func, argspos, args, (DWORD*)&regs );
7003 break;
7004 case VT_R8:
7005 case VT_DATE:
7006 V_R8(pvargResult) = call_double_method( func, argspos, args, (DWORD*)&regs );
7007 break;
7008 case VT_I8:
7009 case VT_UI8:
7010 case VT_CY:
7011 V_UI8(pvargResult) = call_method( func, argspos, args, (DWORD*)&regs );
7012 break;
7013 default:
7014 V_UI4(pvargResult) = call_method( func, argspos, args, (DWORD*)&regs );
7015 break;
7017 heap_free( args );
7018 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
7019 TRACE("retval: %s\n", debugstr_variant(pvargResult));
7020 return S_OK;
7022 #else
7023 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
7024 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
7025 return E_NOTIMPL;
7026 #endif
7029 static inline BOOL func_restricted( const FUNCDESC *desc )
7031 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
7034 #define INVBUF_ELEMENT_SIZE \
7035 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
7036 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
7037 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
7038 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
7039 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
7040 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
7041 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
7042 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
7044 static HRESULT WINAPI ITypeInfo_fnInvoke(
7045 ITypeInfo2 *iface,
7046 VOID *pIUnk,
7047 MEMBERID memid,
7048 UINT16 wFlags,
7049 DISPPARAMS *pDispParams,
7050 VARIANT *pVarResult,
7051 EXCEPINFO *pExcepInfo,
7052 UINT *pArgErr)
7054 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7055 int i;
7056 unsigned int var_index;
7057 TYPEKIND type_kind;
7058 HRESULT hres;
7059 const TLBFuncDesc *pFuncInfo;
7060 UINT fdc;
7062 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
7063 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
7066 if( This->typeattr.wTypeFlags & TYPEFLAG_FRESTRICTED )
7067 return DISP_E_MEMBERNOTFOUND;
7069 if (!pDispParams)
7071 ERR("NULL pDispParams not allowed\n");
7072 return E_INVALIDARG;
7075 dump_DispParms(pDispParams);
7077 if (pDispParams->cNamedArgs > pDispParams->cArgs)
7079 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
7080 pDispParams->cNamedArgs, pDispParams->cArgs);
7081 return E_INVALIDARG;
7084 /* we do this instead of using GetFuncDesc since it will return a fake
7085 * FUNCDESC for dispinterfaces and we want the real function description */
7086 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
7087 pFuncInfo = &This->funcdescs[fdc];
7088 if ((memid == pFuncInfo->funcdesc.memid) &&
7089 (wFlags & pFuncInfo->funcdesc.invkind) &&
7090 !func_restricted( &pFuncInfo->funcdesc ))
7091 break;
7094 if (fdc < This->typeattr.cFuncs) {
7095 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
7097 if (TRACE_ON(ole))
7099 TRACE("invoking:\n");
7100 dump_TLBFuncDescOne(pFuncInfo);
7103 switch (func_desc->funckind) {
7104 case FUNC_PUREVIRTUAL:
7105 case FUNC_VIRTUAL: {
7106 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
7107 VARIANT varresult;
7108 VARIANT retval; /* pointer for storing byref retvals in */
7109 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
7110 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
7111 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
7112 UINT cNamedArgs = pDispParams->cNamedArgs;
7113 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
7114 UINT vargs_converted=0;
7116 hres = S_OK;
7118 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
7120 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
7122 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
7123 hres = DISP_E_PARAMNOTFOUND;
7124 goto func_fail;
7128 if (func_desc->cParamsOpt < 0 && cNamedArgs)
7130 ERR("functions with the vararg attribute do not support named arguments\n");
7131 hres = DISP_E_NONAMEDARGS;
7132 goto func_fail;
7135 for (i = 0; i < func_desc->cParams; i++)
7137 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7138 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
7139 if (FAILED(hres))
7140 goto func_fail;
7143 TRACE("changing args\n");
7144 for (i = 0; i < func_desc->cParams; i++)
7146 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7147 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7148 VARIANTARG *src_arg;
7150 if (wParamFlags & PARAMFLAG_FLCID)
7152 VARIANTARG *arg;
7153 arg = prgpvarg[i] = &rgvarg[i];
7154 V_VT(arg) = VT_I4;
7155 V_I4(arg) = This->pTypeLib->lcid;
7156 continue;
7159 src_arg = NULL;
7161 if (cNamedArgs)
7163 USHORT j;
7164 for (j = 0; j < cNamedArgs; j++)
7165 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
7167 src_arg = &pDispParams->rgvarg[j];
7168 break;
7172 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
7174 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7175 vargs_converted++;
7178 if (wParamFlags & PARAMFLAG_FRETVAL)
7180 /* under most conditions the caller is not allowed to
7181 * pass in a dispparam arg in the index of what would be
7182 * the retval parameter. however, there is an exception
7183 * where the extra parameter is used in an extra
7184 * IDispatch::Invoke below */
7185 if ((i < pDispParams->cArgs) &&
7186 ((func_desc->cParams != 1) || !pVarResult ||
7187 !(func_desc->invkind & INVOKE_PROPERTYGET)))
7189 hres = DISP_E_BADPARAMCOUNT;
7190 break;
7193 /* note: this check is placed so that if the caller passes
7194 * in a VARIANTARG for the retval we just ignore it, like
7195 * native does */
7196 if (i == func_desc->cParams - 1)
7198 VARIANTARG *arg;
7199 arg = prgpvarg[i] = &rgvarg[i];
7200 memset(arg, 0, sizeof(*arg));
7201 V_VT(arg) = rgvt[i];
7202 memset(&retval, 0, sizeof(retval));
7203 V_BYREF(arg) = &retval;
7205 else
7207 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
7208 hres = E_UNEXPECTED;
7209 break;
7212 else if (src_arg)
7214 TRACE("%s\n", debugstr_variant(src_arg));
7216 if(rgvt[i]!=V_VT(src_arg))
7218 if (rgvt[i] == VT_VARIANT)
7219 hres = VariantCopy(&rgvarg[i], src_arg);
7220 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
7222 if (rgvt[i] == V_VT(src_arg))
7223 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
7224 else
7226 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7227 if (wParamFlags & PARAMFLAG_FIN)
7228 hres = VariantCopy(&missing_arg[i], src_arg);
7229 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
7231 V_VT(&rgvarg[i]) = rgvt[i];
7233 else if ((rgvt[i] == (VT_VARIANT | VT_ARRAY) || rgvt[i] == (VT_VARIANT | VT_ARRAY | VT_BYREF)) && func_desc->cParamsOpt < 0)
7235 SAFEARRAY *a;
7236 SAFEARRAYBOUND bound;
7237 VARIANT *v;
7238 LONG j;
7239 bound.lLbound = 0;
7240 bound.cElements = pDispParams->cArgs-i;
7241 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
7243 ERR("SafeArrayCreate failed\n");
7244 break;
7246 hres = SafeArrayAccessData(a, (LPVOID)&v);
7247 if (hres != S_OK)
7249 ERR("SafeArrayAccessData failed with %x\n", hres);
7250 SafeArrayDestroy(a);
7251 break;
7253 for (j = 0; j < bound.cElements; j++)
7254 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
7255 hres = SafeArrayUnaccessData(a);
7256 if (hres != S_OK)
7258 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7259 SafeArrayDestroy(a);
7260 break;
7262 if (rgvt[i] & VT_BYREF)
7263 V_BYREF(&rgvarg[i]) = &a;
7264 else
7265 V_ARRAY(&rgvarg[i]) = a;
7266 V_VT(&rgvarg[i]) = rgvt[i];
7268 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
7270 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7271 if (wParamFlags & PARAMFLAG_FIN)
7272 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
7273 else
7274 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
7275 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
7276 V_VT(&rgvarg[i]) = rgvt[i];
7278 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
7280 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
7281 V_VT(&rgvarg[i]) = rgvt[i];
7283 else
7285 /* FIXME: this doesn't work for VT_BYREF arguments if
7286 * they are not the same type as in the paramdesc */
7287 V_VT(&rgvarg[i]) = V_VT(src_arg);
7288 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
7289 V_VT(&rgvarg[i]) = rgvt[i];
7292 if (FAILED(hres))
7294 ERR("failed to convert param %d to %s from %s\n", i,
7295 debugstr_vt(rgvt[i]), debugstr_variant(src_arg));
7296 break;
7298 prgpvarg[i] = &rgvarg[i];
7300 else
7302 prgpvarg[i] = src_arg;
7305 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
7306 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
7307 && V_UNKNOWN(prgpvarg[i])) {
7308 IUnknown *userdefined_iface;
7309 GUID guid;
7311 hres = get_iface_guid((ITypeInfo*)iface, tdesc->vt == VT_PTR ? tdesc->u.lptdesc : tdesc, &guid);
7312 if(FAILED(hres))
7313 break;
7315 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
7316 if(FAILED(hres)) {
7317 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
7318 break;
7321 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
7322 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
7325 else if (wParamFlags & PARAMFLAG_FOPT)
7327 VARIANTARG *arg;
7328 arg = prgpvarg[i] = &rgvarg[i];
7329 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7331 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
7332 if (FAILED(hres))
7333 break;
7335 else
7337 VARIANTARG *missing_arg;
7338 /* if the function wants a pointer to a variant then
7339 * set that up, otherwise just pass the VT_ERROR in
7340 * the argument by value */
7341 if (rgvt[i] & VT_BYREF)
7343 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
7344 V_VT(arg) = VT_VARIANT | VT_BYREF;
7345 V_VARIANTREF(arg) = missing_arg;
7347 else
7348 missing_arg = arg;
7349 V_VT(missing_arg) = VT_ERROR;
7350 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
7353 else
7355 hres = DISP_E_BADPARAMCOUNT;
7356 break;
7359 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7361 /* VT_VOID is a special case for return types, so it is not
7362 * handled in the general function */
7363 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
7364 V_VT(&varresult) = VT_EMPTY;
7365 else
7367 V_VT(&varresult) = 0;
7368 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
7369 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7372 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv,
7373 V_VT(&varresult), func_desc->cParams, rgvt,
7374 prgpvarg, &varresult);
7376 vargs_converted = 0;
7378 for (i = 0; i < func_desc->cParams; i++)
7380 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7381 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7383 if (wParamFlags & PARAMFLAG_FLCID)
7384 continue;
7385 else if (wParamFlags & PARAMFLAG_FRETVAL)
7387 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg[i]));
7389 if (pVarResult)
7391 VariantInit(pVarResult);
7392 /* deref return value */
7393 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
7396 VARIANT_ClearInd(prgpvarg[i]);
7398 else if (vargs_converted < pDispParams->cArgs)
7400 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7401 if (wParamFlags & PARAMFLAG_FOUT)
7403 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
7405 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
7407 if (FAILED(hres))
7409 ERR("failed to convert param %d to vt %d\n", i,
7410 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
7411 break;
7415 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
7416 func_desc->cParamsOpt < 0 &&
7417 i == func_desc->cParams-1)
7419 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
7420 LONG j, ubound;
7421 VARIANT *v;
7422 hres = SafeArrayGetUBound(a, 1, &ubound);
7423 if (hres != S_OK)
7425 ERR("SafeArrayGetUBound failed with %x\n", hres);
7426 break;
7428 hres = SafeArrayAccessData(a, (LPVOID)&v);
7429 if (hres != S_OK)
7431 ERR("SafeArrayAccessData failed with %x\n", hres);
7432 break;
7434 for (j = 0; j <= ubound; j++)
7435 VariantClear(&v[j]);
7436 hres = SafeArrayUnaccessData(a);
7437 if (hres != S_OK)
7439 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7440 break;
7443 VariantClear(&rgvarg[i]);
7444 vargs_converted++;
7446 else if (wParamFlags & PARAMFLAG_FOPT)
7448 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7449 VariantClear(&rgvarg[i]);
7452 VariantClear(&missing_arg[i]);
7455 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
7457 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
7458 hres = DISP_E_EXCEPTION;
7459 if (pExcepInfo)
7461 IErrorInfo *pErrorInfo;
7462 pExcepInfo->scode = V_ERROR(&varresult);
7463 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
7465 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
7466 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
7467 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
7468 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
7470 IErrorInfo_Release(pErrorInfo);
7474 if (V_VT(&varresult) != VT_ERROR)
7476 TRACE("varresult value: %s\n", debugstr_variant(&varresult));
7478 if (pVarResult)
7480 VariantClear(pVarResult);
7481 *pVarResult = varresult;
7483 else
7484 VariantClear(&varresult);
7487 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
7488 (func_desc->invkind & INVOKE_PROPERTYGET) &&
7489 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
7490 (pDispParams->cArgs != 0))
7492 if (V_VT(pVarResult) == VT_DISPATCH)
7494 IDispatch *pDispatch = V_DISPATCH(pVarResult);
7495 /* Note: not VariantClear; we still need the dispatch
7496 * pointer to be valid */
7497 VariantInit(pVarResult);
7498 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
7499 GetSystemDefaultLCID(), wFlags,
7500 pDispParams, pVarResult, pExcepInfo, pArgErr);
7501 IDispatch_Release(pDispatch);
7503 else
7505 VariantClear(pVarResult);
7506 hres = DISP_E_NOTACOLLECTION;
7510 func_fail:
7511 heap_free(buffer);
7512 break;
7514 case FUNC_DISPATCH: {
7515 IDispatch *disp;
7517 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
7518 if (SUCCEEDED(hres)) {
7519 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7520 hres = IDispatch_Invoke(
7521 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
7522 pVarResult,pExcepInfo,pArgErr
7524 if (FAILED(hres))
7525 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
7526 IDispatch_Release(disp);
7527 } else
7528 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7529 break;
7531 default:
7532 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
7533 hres = E_FAIL;
7534 break;
7537 TRACE("-- 0x%08x\n", hres);
7538 return hres;
7540 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
7541 VARDESC *var_desc;
7543 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
7544 if(FAILED(hres)) return hres;
7546 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7547 dump_VARDESC(var_desc);
7548 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
7549 return E_NOTIMPL;
7552 /* not found, look for it in inherited interfaces */
7553 ITypeInfo2_GetTypeKind(iface, &type_kind);
7554 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
7555 if(This->impltypes) {
7556 /* recursive search */
7557 ITypeInfo *pTInfo;
7558 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7559 if(SUCCEEDED(hres)){
7560 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
7561 ITypeInfo_Release(pTInfo);
7562 return hres;
7564 WARN("Could not search inherited interface!\n");
7567 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
7568 return DISP_E_MEMBERNOTFOUND;
7571 /* ITypeInfo::GetDocumentation
7573 * Retrieves the documentation string, the complete Help file name and path,
7574 * and the context ID for the Help topic for a specified type description.
7576 * (Can be tested by the Visual Basic Editor in Word for instance.)
7578 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
7579 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
7580 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
7582 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7583 const TLBFuncDesc *pFDesc;
7584 const TLBVarDesc *pVDesc;
7585 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7586 " HelpContext(%p) HelpFile(%p)\n",
7587 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
7588 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7589 if(pBstrName)
7590 *pBstrName=SysAllocString(TLB_get_bstr(This->Name));
7591 if(pBstrDocString)
7592 *pBstrDocString=SysAllocString(TLB_get_bstr(This->DocString));
7593 if(pdwHelpContext)
7594 *pdwHelpContext=This->dwHelpContext;
7595 if(pBstrHelpFile)
7596 *pBstrHelpFile=SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7597 return S_OK;
7598 }else {/* for a member */
7599 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->typeattr.cFuncs, memid);
7600 if(pFDesc){
7601 if(pBstrName)
7602 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Name));
7603 if(pBstrDocString)
7604 *pBstrDocString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7605 if(pdwHelpContext)
7606 *pdwHelpContext=pFDesc->helpcontext;
7607 if(pBstrHelpFile)
7608 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7609 return S_OK;
7611 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->typeattr.cVars, memid);
7612 if(pVDesc){
7613 if(pBstrName)
7614 *pBstrName = SysAllocString(TLB_get_bstr(pVDesc->Name));
7615 if(pBstrDocString)
7616 *pBstrDocString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7617 if(pdwHelpContext)
7618 *pdwHelpContext=pVDesc->HelpContext;
7619 if(pBstrHelpFile)
7620 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7621 return S_OK;
7625 if(This->impltypes &&
7626 (This->typeattr.typekind == TKIND_INTERFACE || This->typeattr.typekind == TKIND_DISPATCH)) {
7627 /* recursive search */
7628 ITypeInfo *pTInfo;
7629 HRESULT result;
7630 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7631 if(SUCCEEDED(result)) {
7632 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
7633 pBstrDocString, pdwHelpContext, pBstrHelpFile);
7634 ITypeInfo_Release(pTInfo);
7635 return result;
7637 WARN("Could not search inherited interface!\n");
7640 WARN("member %d not found\n", memid);
7641 return TYPE_E_ELEMENTNOTFOUND;
7644 /* ITypeInfo::GetDllEntry
7646 * Retrieves a description or specification of an entry point for a function
7647 * in a DLL.
7649 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
7650 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
7651 WORD *pwOrdinal)
7653 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7654 const TLBFuncDesc *pFDesc;
7656 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
7658 if (pBstrDllName) *pBstrDllName = NULL;
7659 if (pBstrName) *pBstrName = NULL;
7660 if (pwOrdinal) *pwOrdinal = 0;
7662 if (This->typeattr.typekind != TKIND_MODULE)
7663 return TYPE_E_BADMODULEKIND;
7665 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->typeattr.cFuncs, memid);
7666 if(pFDesc){
7667 dump_TypeInfo(This);
7668 if (TRACE_ON(ole))
7669 dump_TLBFuncDescOne(pFDesc);
7671 if (pBstrDllName)
7672 *pBstrDllName = SysAllocString(TLB_get_bstr(This->DllName));
7674 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
7675 if (pBstrName)
7676 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Entry));
7677 if (pwOrdinal)
7678 *pwOrdinal = -1;
7679 return S_OK;
7681 if (pBstrName)
7682 *pBstrName = NULL;
7683 if (pwOrdinal)
7684 *pwOrdinal = LOWORD(pFDesc->Entry);
7685 return S_OK;
7687 return TYPE_E_ELEMENTNOTFOUND;
7690 /* internal function to make the inherited interfaces' methods appear
7691 * part of the interface */
7692 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7693 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7695 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7696 HRESULT hr;
7698 TRACE("%p, 0x%x\n", iface, *hRefType);
7700 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7702 ITypeInfo *pSubTypeInfo;
7704 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7705 if (FAILED(hr))
7706 return hr;
7708 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7709 hRefType, ppTInfo);
7710 ITypeInfo_Release(pSubTypeInfo);
7711 if (SUCCEEDED(hr))
7712 return hr;
7714 *hRefType -= DISPATCH_HREF_OFFSET;
7716 if (!(*hRefType & DISPATCH_HREF_MASK))
7717 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7718 else
7719 return E_FAIL;
7722 struct search_res_tlb_params
7724 const GUID *guid;
7725 ITypeLib *pTLib;
7728 static BOOL CALLBACK search_res_tlb(HMODULE hModule, LPCWSTR lpszType, LPWSTR lpszName, LONG_PTR lParam)
7730 struct search_res_tlb_params *params = (LPVOID)lParam;
7731 static const WCHAR formatW[] = {'\\','%','d',0};
7732 WCHAR szPath[MAX_PATH+1];
7733 ITypeLib *pTLib = NULL;
7734 HRESULT ret;
7735 DWORD len;
7737 if (IS_INTRESOURCE(lpszName) == FALSE)
7738 return TRUE;
7740 if (!(len = GetModuleFileNameW(hModule, szPath, MAX_PATH)))
7741 return TRUE;
7743 if (snprintfW(szPath + len, sizeof(szPath)/sizeof(WCHAR) - len, formatW, LOWORD(lpszName)) < 0)
7744 return TRUE;
7746 ret = LoadTypeLibEx(szPath, REGKIND_NONE, &pTLib);
7747 if (SUCCEEDED(ret))
7749 ITypeLibImpl *impl = impl_from_ITypeLib(pTLib);
7750 if (IsEqualGUID(params->guid, impl->guid))
7752 params->pTLib = pTLib;
7753 return FALSE; /* stop enumeration */
7755 ITypeLib_Release(pTLib);
7758 return TRUE;
7761 /* ITypeInfo::GetRefTypeInfo
7763 * If a type description references other type descriptions, it retrieves
7764 * the referenced type descriptions.
7766 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7767 ITypeInfo2 *iface,
7768 HREFTYPE hRefType,
7769 ITypeInfo **ppTInfo)
7771 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7772 HRESULT result = E_FAIL;
7774 if(!ppTInfo)
7775 return E_INVALIDARG;
7777 if ((INT)hRefType < 0) {
7778 ITypeInfoImpl *pTypeInfoImpl;
7780 if (!(This->typeattr.wTypeFlags & TYPEFLAG_FDUAL) ||
7781 !(This->typeattr.typekind == TKIND_INTERFACE ||
7782 This->typeattr.typekind == TKIND_DISPATCH))
7783 return TYPE_E_ELEMENTNOTFOUND;
7785 /* when we meet a DUAL typeinfo, we must create the alternate
7786 * version of it.
7788 pTypeInfoImpl = ITypeInfoImpl_Constructor();
7790 *pTypeInfoImpl = *This;
7791 pTypeInfoImpl->ref = 0;
7792 list_init(&pTypeInfoImpl->custdata_list);
7794 if (This->typeattr.typekind == TKIND_INTERFACE)
7795 pTypeInfoImpl->typeattr.typekind = TKIND_DISPATCH;
7796 else
7797 pTypeInfoImpl->typeattr.typekind = TKIND_INTERFACE;
7799 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface;
7800 /* the AddRef implicitly adds a reference to the parent typelib, which
7801 * stops the copied data from being destroyed until the new typeinfo's
7802 * refcount goes to zero, but we need to signal to the new instance to
7803 * not free its data structures when it is destroyed */
7804 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7806 ITypeInfo_AddRef(*ppTInfo);
7808 result = S_OK;
7809 } else if ((hRefType & DISPATCH_HREF_MASK) &&
7810 (This->typeattr.typekind == TKIND_DISPATCH))
7812 HREFTYPE href_dispatch = hRefType;
7813 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
7814 } else {
7815 TLBRefType *ref_type;
7816 ITypeLib *pTLib = NULL;
7817 UINT i;
7819 if(!(hRefType & 0x1)){
7820 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
7822 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
7824 result = S_OK;
7825 *ppTInfo = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
7826 ITypeInfo_AddRef(*ppTInfo);
7827 goto end;
7832 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7834 if(ref_type->reference == (hRefType & (~0x3)))
7835 break;
7837 if(&ref_type->entry == &This->pTypeLib->ref_list)
7839 FIXME("Can't find pRefType for ref %x\n", hRefType);
7840 goto end;
7843 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7844 UINT Index;
7845 TRACE("internal reference\n");
7846 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7847 } else {
7848 if(ref_type->pImpTLInfo->pImpTypeLib) {
7849 TRACE("typeinfo in imported typelib that is already loaded\n");
7850 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
7851 ITypeLib_AddRef(pTLib);
7852 result = S_OK;
7853 } else {
7854 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
7855 struct search_res_tlb_params params;
7856 BSTR libnam;
7858 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7860 /* Search in resource table */
7861 params.guid = TLB_get_guid_null(ref_type->pImpTLInfo->guid);
7862 params.pTLib = NULL;
7863 EnumResourceNamesW(NULL, TYPELIBW, search_res_tlb, (LONG_PTR)&params);
7864 pTLib = params.pTLib;
7865 result = S_OK;
7867 if (!pTLib)
7869 /* Search on disk */
7870 result = query_typelib_path(TLB_get_guid_null(ref_type->pImpTLInfo->guid),
7871 ref_type->pImpTLInfo->wVersionMajor,
7872 ref_type->pImpTLInfo->wVersionMinor,
7873 This->pTypeLib->syskind,
7874 ref_type->pImpTLInfo->lcid, &libnam, TRUE);
7875 if (FAILED(result))
7876 libnam = SysAllocString(ref_type->pImpTLInfo->name);
7878 result = LoadTypeLib(libnam, &pTLib);
7879 SysFreeString(libnam);
7882 if(SUCCEEDED(result)) {
7883 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
7884 ITypeLib_AddRef(pTLib);
7888 if(SUCCEEDED(result)) {
7889 if(ref_type->index == TLB_REF_USE_GUID)
7890 result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), ppTInfo);
7891 else
7892 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, ppTInfo);
7894 if (pTLib != NULL)
7895 ITypeLib_Release(pTLib);
7898 end:
7899 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
7900 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
7901 return result;
7904 /* ITypeInfo::AddressOfMember
7906 * Retrieves the addresses of static functions or variables, such as those
7907 * defined in a DLL.
7909 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
7910 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
7912 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7913 HRESULT hr;
7914 BSTR dll, entry;
7915 WORD ordinal;
7916 HMODULE module;
7918 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
7920 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
7921 if (FAILED(hr))
7922 return hr;
7924 module = LoadLibraryW(dll);
7925 if (!module)
7927 ERR("couldn't load %s\n", debugstr_w(dll));
7928 SysFreeString(dll);
7929 SysFreeString(entry);
7930 return STG_E_FILENOTFOUND;
7932 /* FIXME: store library somewhere where we can free it */
7934 if (entry)
7936 LPSTR entryA;
7937 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
7938 entryA = heap_alloc(len);
7939 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
7941 *ppv = GetProcAddress(module, entryA);
7942 if (!*ppv)
7943 ERR("function not found %s\n", debugstr_a(entryA));
7945 heap_free(entryA);
7947 else
7949 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7950 if (!*ppv)
7951 ERR("function not found %d\n", ordinal);
7954 SysFreeString(dll);
7955 SysFreeString(entry);
7957 if (!*ppv)
7958 return TYPE_E_DLLFUNCTIONNOTFOUND;
7960 return S_OK;
7963 /* ITypeInfo::CreateInstance
7965 * Creates a new instance of a type that describes a component object class
7966 * (coclass).
7968 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7969 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7971 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7972 HRESULT hr;
7973 TYPEATTR *pTA;
7975 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7977 *ppvObj = NULL;
7979 if(pOuterUnk)
7981 WARN("Not able to aggregate\n");
7982 return CLASS_E_NOAGGREGATION;
7985 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
7986 if(FAILED(hr)) return hr;
7988 if(pTA->typekind != TKIND_COCLASS)
7990 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7991 hr = E_INVALIDARG;
7992 goto end;
7995 hr = S_FALSE;
7996 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7998 IUnknown *pUnk;
7999 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
8000 TRACE("GetActiveObject rets %08x\n", hr);
8001 if(hr == S_OK)
8003 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
8004 IUnknown_Release(pUnk);
8008 if(hr != S_OK)
8009 hr = CoCreateInstance(&pTA->guid, NULL,
8010 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
8011 riid, ppvObj);
8013 end:
8014 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
8015 return hr;
8018 /* ITypeInfo::GetMops
8020 * Retrieves marshalling information.
8022 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
8023 BSTR *pBstrMops)
8025 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8026 FIXME("(%p %d) stub!\n", This, memid);
8027 *pBstrMops = NULL;
8028 return S_OK;
8031 /* ITypeInfo::GetContainingTypeLib
8033 * Retrieves the containing type library and the index of the type description
8034 * within that type library.
8036 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
8037 ITypeLib * *ppTLib, UINT *pIndex)
8039 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8041 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
8042 if (pIndex) {
8043 *pIndex=This->index;
8044 TRACE("returning pIndex=%d\n", *pIndex);
8047 if (ppTLib) {
8048 *ppTLib = (ITypeLib *)&This->pTypeLib->ITypeLib2_iface;
8049 ITypeLib_AddRef(*ppTLib);
8050 TRACE("returning ppTLib=%p\n", *ppTLib);
8053 return S_OK;
8056 /* ITypeInfo::ReleaseTypeAttr
8058 * Releases a TYPEATTR previously returned by Get
8061 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
8062 TYPEATTR* pTypeAttr)
8064 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8065 TRACE("(%p)->(%p)\n", This, pTypeAttr);
8066 heap_free(pTypeAttr);
8069 /* ITypeInfo::ReleaseFuncDesc
8071 * Releases a FUNCDESC previously returned by GetFuncDesc. *
8073 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
8074 ITypeInfo2 *iface,
8075 FUNCDESC *pFuncDesc)
8077 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8078 SHORT i;
8080 TRACE("(%p)->(%p)\n", This, pFuncDesc);
8082 for (i = 0; i < pFuncDesc->cParams; i++)
8083 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
8084 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
8086 SysFreeString((BSTR)pFuncDesc);
8089 /* ITypeInfo::ReleaseVarDesc
8091 * Releases a VARDESC previously returned by GetVarDesc.
8093 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
8094 VARDESC *pVarDesc)
8096 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8097 TRACE("(%p)->(%p)\n", This, pVarDesc);
8099 TLB_FreeVarDesc(pVarDesc);
8102 /* ITypeInfo2::GetTypeKind
8104 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
8107 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
8108 TYPEKIND *pTypeKind)
8110 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8111 *pTypeKind = This->typeattr.typekind;
8112 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
8113 return S_OK;
8116 /* ITypeInfo2::GetTypeFlags
8118 * Returns the type flags without any allocations. This returns a DWORD type
8119 * flag, which expands the type flags without growing the TYPEATTR (type
8120 * attribute).
8123 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
8125 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8126 *pTypeFlags=This->typeattr.wTypeFlags;
8127 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
8128 return S_OK;
8131 /* ITypeInfo2::GetFuncIndexOfMemId
8132 * Binds to a specific member based on a known DISPID, where the member name
8133 * is not known (for example, when binding to a default member).
8136 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
8137 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
8139 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8140 UINT fdc;
8141 HRESULT result;
8143 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
8144 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
8145 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
8146 break;
8148 if(fdc < This->typeattr.cFuncs) {
8149 *pFuncIndex = fdc;
8150 result = S_OK;
8151 } else
8152 result = TYPE_E_ELEMENTNOTFOUND;
8154 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
8155 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
8156 return result;
8159 /* TypeInfo2::GetVarIndexOfMemId
8161 * Binds to a specific member based on a known DISPID, where the member name
8162 * is not known (for example, when binding to a default member).
8165 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
8166 MEMBERID memid, UINT *pVarIndex)
8168 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8169 TLBVarDesc *pVarInfo;
8171 TRACE("%p %d %p\n", iface, memid, pVarIndex);
8173 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->typeattr.cVars, memid);
8174 if(!pVarInfo)
8175 return TYPE_E_ELEMENTNOTFOUND;
8177 *pVarIndex = (pVarInfo - This->vardescs);
8179 return S_OK;
8182 /* ITypeInfo2::GetCustData
8184 * Gets the custom data
8186 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
8187 ITypeInfo2 * iface,
8188 REFGUID guid,
8189 VARIANT *pVarVal)
8191 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8192 TLBCustData *pCData;
8194 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8196 if(!guid || !pVarVal)
8197 return E_INVALIDARG;
8199 pCData = TLB_get_custdata_by_guid(This->pcustdata_list, guid);
8201 VariantInit( pVarVal);
8202 if (pCData)
8203 VariantCopy( pVarVal, &pCData->data);
8204 else
8205 VariantClear( pVarVal );
8206 return S_OK;
8209 /* ITypeInfo2::GetFuncCustData
8211 * Gets the custom data
8213 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
8214 ITypeInfo2 * iface,
8215 UINT index,
8216 REFGUID guid,
8217 VARIANT *pVarVal)
8219 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8220 TLBCustData *pCData;
8221 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8223 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8225 if(index >= This->typeattr.cFuncs)
8226 return TYPE_E_ELEMENTNOTFOUND;
8228 pCData = TLB_get_custdata_by_guid(&pFDesc->custdata_list, guid);
8229 if(!pCData)
8230 return TYPE_E_ELEMENTNOTFOUND;
8232 VariantInit(pVarVal);
8233 VariantCopy(pVarVal, &pCData->data);
8235 return S_OK;
8238 /* ITypeInfo2::GetParamCustData
8240 * Gets the custom data
8242 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
8243 ITypeInfo2 * iface,
8244 UINT indexFunc,
8245 UINT indexParam,
8246 REFGUID guid,
8247 VARIANT *pVarVal)
8249 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8250 TLBCustData *pCData;
8251 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8253 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
8254 debugstr_guid(guid), pVarVal);
8256 if(indexFunc >= This->typeattr.cFuncs)
8257 return TYPE_E_ELEMENTNOTFOUND;
8259 if(indexParam >= pFDesc->funcdesc.cParams)
8260 return TYPE_E_ELEMENTNOTFOUND;
8262 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
8263 if(!pCData)
8264 return TYPE_E_ELEMENTNOTFOUND;
8266 VariantInit(pVarVal);
8267 VariantCopy(pVarVal, &pCData->data);
8269 return S_OK;
8272 /* ITypeInfo2::GetVarCustData
8274 * Gets the custom data
8276 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
8277 ITypeInfo2 * iface,
8278 UINT index,
8279 REFGUID guid,
8280 VARIANT *pVarVal)
8282 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8283 TLBCustData *pCData;
8284 TLBVarDesc *pVDesc = &This->vardescs[index];
8286 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8288 if(index >= This->typeattr.cVars)
8289 return TYPE_E_ELEMENTNOTFOUND;
8291 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
8292 if(!pCData)
8293 return TYPE_E_ELEMENTNOTFOUND;
8295 VariantInit(pVarVal);
8296 VariantCopy(pVarVal, &pCData->data);
8298 return S_OK;
8301 /* ITypeInfo2::GetImplCustData
8303 * Gets the custom data
8305 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
8306 ITypeInfo2 * iface,
8307 UINT index,
8308 REFGUID guid,
8309 VARIANT *pVarVal)
8311 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8312 TLBCustData *pCData;
8313 TLBImplType *pRDesc = &This->impltypes[index];
8315 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8317 if(index >= This->typeattr.cImplTypes)
8318 return TYPE_E_ELEMENTNOTFOUND;
8320 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
8321 if(!pCData)
8322 return TYPE_E_ELEMENTNOTFOUND;
8324 VariantInit(pVarVal);
8325 VariantCopy(pVarVal, &pCData->data);
8327 return S_OK;
8330 /* ITypeInfo2::GetDocumentation2
8332 * Retrieves the documentation string, the complete Help file name and path,
8333 * the localization context to use, and the context ID for the library Help
8334 * topic in the Help file.
8337 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
8338 ITypeInfo2 * iface,
8339 MEMBERID memid,
8340 LCID lcid,
8341 BSTR *pbstrHelpString,
8342 DWORD *pdwHelpStringContext,
8343 BSTR *pbstrHelpStringDll)
8345 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8346 const TLBFuncDesc *pFDesc;
8347 const TLBVarDesc *pVDesc;
8348 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8349 "HelpStringContext(%p) HelpStringDll(%p)\n",
8350 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
8351 pbstrHelpStringDll );
8352 /* the help string should be obtained from the helpstringdll,
8353 * using the _DLLGetDocumentation function, based on the supplied
8354 * lcid. Nice to do sometime...
8356 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
8357 if(pbstrHelpString)
8358 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->Name));
8359 if(pdwHelpStringContext)
8360 *pdwHelpStringContext=This->dwHelpStringContext;
8361 if(pbstrHelpStringDll)
8362 *pbstrHelpStringDll=
8363 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8364 return S_OK;
8365 }else {/* for a member */
8366 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->typeattr.cFuncs, memid);
8367 if(pFDesc){
8368 if(pbstrHelpString)
8369 *pbstrHelpString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
8370 if(pdwHelpStringContext)
8371 *pdwHelpStringContext=pFDesc->HelpStringContext;
8372 if(pbstrHelpStringDll)
8373 *pbstrHelpStringDll=
8374 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8375 return S_OK;
8377 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->typeattr.cVars, memid);
8378 if(pVDesc){
8379 if(pbstrHelpString)
8380 *pbstrHelpString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
8381 if(pdwHelpStringContext)
8382 *pdwHelpStringContext=pVDesc->HelpStringContext;
8383 if(pbstrHelpStringDll)
8384 *pbstrHelpStringDll=
8385 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8386 return S_OK;
8389 return TYPE_E_ELEMENTNOTFOUND;
8392 /* ITypeInfo2::GetAllCustData
8394 * Gets all custom data items for the Type info.
8397 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
8398 ITypeInfo2 * iface,
8399 CUSTDATA *pCustData)
8401 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8403 TRACE("%p %p\n", This, pCustData);
8405 return TLB_copy_all_custdata(This->pcustdata_list, pCustData);
8408 /* ITypeInfo2::GetAllFuncCustData
8410 * Gets all custom data items for the specified Function
8413 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
8414 ITypeInfo2 * iface,
8415 UINT index,
8416 CUSTDATA *pCustData)
8418 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8419 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8421 TRACE("%p %u %p\n", This, index, pCustData);
8423 if(index >= This->typeattr.cFuncs)
8424 return TYPE_E_ELEMENTNOTFOUND;
8426 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
8429 /* ITypeInfo2::GetAllParamCustData
8431 * Gets all custom data items for the Functions
8434 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
8435 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
8437 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8438 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8440 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
8442 if(indexFunc >= This->typeattr.cFuncs)
8443 return TYPE_E_ELEMENTNOTFOUND;
8445 if(indexParam >= pFDesc->funcdesc.cParams)
8446 return TYPE_E_ELEMENTNOTFOUND;
8448 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
8451 /* ITypeInfo2::GetAllVarCustData
8453 * Gets all custom data items for the specified Variable
8456 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
8457 UINT index, CUSTDATA *pCustData)
8459 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8460 TLBVarDesc * pVDesc = &This->vardescs[index];
8462 TRACE("%p %u %p\n", This, index, pCustData);
8464 if(index >= This->typeattr.cVars)
8465 return TYPE_E_ELEMENTNOTFOUND;
8467 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
8470 /* ITypeInfo2::GetAllImplCustData
8472 * Gets all custom data items for the specified implementation type
8475 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
8476 ITypeInfo2 * iface,
8477 UINT index,
8478 CUSTDATA *pCustData)
8480 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8481 TLBImplType *pRDesc = &This->impltypes[index];
8483 TRACE("%p %u %p\n", This, index, pCustData);
8485 if(index >= This->typeattr.cImplTypes)
8486 return TYPE_E_ELEMENTNOTFOUND;
8488 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
8491 static const ITypeInfo2Vtbl tinfvt =
8494 ITypeInfo_fnQueryInterface,
8495 ITypeInfo_fnAddRef,
8496 ITypeInfo_fnRelease,
8498 ITypeInfo_fnGetTypeAttr,
8499 ITypeInfo_fnGetTypeComp,
8500 ITypeInfo_fnGetFuncDesc,
8501 ITypeInfo_fnGetVarDesc,
8502 ITypeInfo_fnGetNames,
8503 ITypeInfo_fnGetRefTypeOfImplType,
8504 ITypeInfo_fnGetImplTypeFlags,
8505 ITypeInfo_fnGetIDsOfNames,
8506 ITypeInfo_fnInvoke,
8507 ITypeInfo_fnGetDocumentation,
8508 ITypeInfo_fnGetDllEntry,
8509 ITypeInfo_fnGetRefTypeInfo,
8510 ITypeInfo_fnAddressOfMember,
8511 ITypeInfo_fnCreateInstance,
8512 ITypeInfo_fnGetMops,
8513 ITypeInfo_fnGetContainingTypeLib,
8514 ITypeInfo_fnReleaseTypeAttr,
8515 ITypeInfo_fnReleaseFuncDesc,
8516 ITypeInfo_fnReleaseVarDesc,
8518 ITypeInfo2_fnGetTypeKind,
8519 ITypeInfo2_fnGetTypeFlags,
8520 ITypeInfo2_fnGetFuncIndexOfMemId,
8521 ITypeInfo2_fnGetVarIndexOfMemId,
8522 ITypeInfo2_fnGetCustData,
8523 ITypeInfo2_fnGetFuncCustData,
8524 ITypeInfo2_fnGetParamCustData,
8525 ITypeInfo2_fnGetVarCustData,
8526 ITypeInfo2_fnGetImplTypeCustData,
8527 ITypeInfo2_fnGetDocumentation2,
8528 ITypeInfo2_fnGetAllCustData,
8529 ITypeInfo2_fnGetAllFuncCustData,
8530 ITypeInfo2_fnGetAllParamCustData,
8531 ITypeInfo2_fnGetAllVarCustData,
8532 ITypeInfo2_fnGetAllImplTypeCustData,
8535 /******************************************************************************
8536 * CreateDispTypeInfo [OLEAUT32.31]
8538 * Build type information for an object so it can be called through an
8539 * IDispatch interface.
8541 * RETURNS
8542 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8543 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8545 * NOTES
8546 * This call allows an objects methods to be accessed through IDispatch, by
8547 * building an ITypeInfo object that IDispatch can use to call through.
8549 HRESULT WINAPI CreateDispTypeInfo(
8550 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
8551 LCID lcid, /* [I] Locale Id */
8552 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
8554 ITypeInfoImpl *pTIClass, *pTIIface;
8555 ITypeLibImpl *pTypeLibImpl;
8556 unsigned int param, func;
8557 TLBFuncDesc *pFuncDesc;
8558 TLBRefType *ref;
8560 TRACE("\n");
8561 pTypeLibImpl = TypeLibImpl_Constructor();
8562 if (!pTypeLibImpl) return E_FAIL;
8564 pTypeLibImpl->TypeInfoCount = 2;
8565 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
8567 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
8568 pTIIface->pTypeLib = pTypeLibImpl;
8569 pTIIface->index = 0;
8570 pTIIface->Name = NULL;
8571 pTIIface->dwHelpContext = -1;
8572 pTIIface->guid = NULL;
8573 pTIIface->typeattr.lcid = lcid;
8574 pTIIface->typeattr.typekind = TKIND_INTERFACE;
8575 pTIIface->typeattr.wMajorVerNum = 0;
8576 pTIIface->typeattr.wMinorVerNum = 0;
8577 pTIIface->typeattr.cbAlignment = 2;
8578 pTIIface->typeattr.cbSizeInstance = -1;
8579 pTIIface->typeattr.cbSizeVft = -1;
8580 pTIIface->typeattr.cFuncs = 0;
8581 pTIIface->typeattr.cImplTypes = 0;
8582 pTIIface->typeattr.cVars = 0;
8583 pTIIface->typeattr.wTypeFlags = 0;
8584 pTIIface->hreftype = 0;
8586 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers);
8587 pFuncDesc = pTIIface->funcdescs;
8588 for(func = 0; func < pidata->cMembers; func++) {
8589 METHODDATA *md = pidata->pmethdata + func;
8590 pFuncDesc->Name = TLB_append_str(&pTypeLibImpl->name_list, md->szName);
8591 pFuncDesc->funcdesc.memid = md->dispid;
8592 pFuncDesc->funcdesc.lprgscode = NULL;
8593 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
8594 pFuncDesc->funcdesc.invkind = md->wFlags;
8595 pFuncDesc->funcdesc.callconv = md->cc;
8596 pFuncDesc->funcdesc.cParams = md->cArgs;
8597 pFuncDesc->funcdesc.cParamsOpt = 0;
8598 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
8599 pFuncDesc->funcdesc.cScodes = 0;
8600 pFuncDesc->funcdesc.wFuncFlags = 0;
8601 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
8602 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
8603 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
8604 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8605 md->cArgs * sizeof(ELEMDESC));
8606 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
8607 for(param = 0; param < md->cArgs; param++) {
8608 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
8609 pFuncDesc->pParamDesc[param].Name = TLB_append_str(&pTypeLibImpl->name_list, md->ppdata[param].szName);
8611 pFuncDesc->helpcontext = 0;
8612 pFuncDesc->HelpStringContext = 0;
8613 pFuncDesc->HelpString = NULL;
8614 pFuncDesc->Entry = NULL;
8615 list_init(&pFuncDesc->custdata_list);
8616 pTIIface->typeattr.cFuncs++;
8617 ++pFuncDesc;
8620 dump_TypeInfo(pTIIface);
8622 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
8623 pTIClass->pTypeLib = pTypeLibImpl;
8624 pTIClass->index = 1;
8625 pTIClass->Name = NULL;
8626 pTIClass->dwHelpContext = -1;
8627 pTIClass->guid = NULL;
8628 pTIClass->typeattr.lcid = lcid;
8629 pTIClass->typeattr.typekind = TKIND_COCLASS;
8630 pTIClass->typeattr.wMajorVerNum = 0;
8631 pTIClass->typeattr.wMinorVerNum = 0;
8632 pTIClass->typeattr.cbAlignment = 2;
8633 pTIClass->typeattr.cbSizeInstance = -1;
8634 pTIClass->typeattr.cbSizeVft = -1;
8635 pTIClass->typeattr.cFuncs = 0;
8636 pTIClass->typeattr.cImplTypes = 1;
8637 pTIClass->typeattr.cVars = 0;
8638 pTIClass->typeattr.wTypeFlags = 0;
8639 pTIClass->hreftype = sizeof(MSFT_TypeInfoBase);
8641 pTIClass->impltypes = TLBImplType_Alloc(1);
8643 ref = heap_alloc_zero(sizeof(*ref));
8644 ref->pImpTLInfo = TLB_REF_INTERNAL;
8645 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
8647 dump_TypeInfo(pTIClass);
8649 *pptinfo = (ITypeInfo *)&pTIClass->ITypeInfo2_iface;
8651 ITypeInfo_AddRef(*pptinfo);
8652 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
8654 return S_OK;
8658 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
8660 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8662 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, ppv);
8665 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
8667 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8669 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
8672 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
8674 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8676 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
8679 static HRESULT WINAPI ITypeComp_fnBind(
8680 ITypeComp * iface,
8681 OLECHAR * szName,
8682 ULONG lHash,
8683 WORD wFlags,
8684 ITypeInfo ** ppTInfo,
8685 DESCKIND * pDescKind,
8686 BINDPTR * pBindPtr)
8688 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8689 const TLBFuncDesc *pFDesc;
8690 const TLBVarDesc *pVDesc;
8691 HRESULT hr = DISP_E_MEMBERNOTFOUND;
8692 UINT fdc;
8694 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8696 *pDescKind = DESCKIND_NONE;
8697 pBindPtr->lpfuncdesc = NULL;
8698 *ppTInfo = NULL;
8700 for(fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
8701 pFDesc = &This->funcdescs[fdc];
8702 if (!lstrcmpiW(TLB_get_bstr(pFDesc->Name), szName)) {
8703 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
8704 break;
8705 else
8706 /* name found, but wrong flags */
8707 hr = TYPE_E_TYPEMISMATCH;
8711 if (fdc < This->typeattr.cFuncs)
8713 HRESULT hr = TLB_AllocAndInitFuncDesc(
8714 &pFDesc->funcdesc,
8715 &pBindPtr->lpfuncdesc,
8716 This->typeattr.typekind == TKIND_DISPATCH);
8717 if (FAILED(hr))
8718 return hr;
8719 *pDescKind = DESCKIND_FUNCDESC;
8720 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8721 ITypeInfo_AddRef(*ppTInfo);
8722 return S_OK;
8723 } else {
8724 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->typeattr.cVars, szName);
8725 if(pVDesc){
8726 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
8727 if (FAILED(hr))
8728 return hr;
8729 *pDescKind = DESCKIND_VARDESC;
8730 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8731 ITypeInfo_AddRef(*ppTInfo);
8732 return S_OK;
8736 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
8737 /* recursive search */
8738 ITypeInfo *pTInfo;
8739 ITypeComp *pTComp;
8740 HRESULT hr;
8741 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
8742 if (SUCCEEDED(hr))
8744 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
8745 ITypeInfo_Release(pTInfo);
8747 if (SUCCEEDED(hr))
8749 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8750 ITypeComp_Release(pTComp);
8751 if (SUCCEEDED(hr) && *pDescKind == DESCKIND_FUNCDESC &&
8752 This->typeattr.typekind == TKIND_DISPATCH)
8754 FUNCDESC *tmp = pBindPtr->lpfuncdesc;
8755 hr = TLB_AllocAndInitFuncDesc(tmp, &pBindPtr->lpfuncdesc, TRUE);
8756 SysFreeString((BSTR)tmp);
8758 return hr;
8760 WARN("Could not search inherited interface!\n");
8762 if (hr == DISP_E_MEMBERNOTFOUND)
8763 hr = S_OK;
8764 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
8765 return hr;
8768 static HRESULT WINAPI ITypeComp_fnBindType(
8769 ITypeComp * iface,
8770 OLECHAR * szName,
8771 ULONG lHash,
8772 ITypeInfo ** ppTInfo,
8773 ITypeComp ** ppTComp)
8775 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
8777 /* strange behaviour (does nothing) but like the
8778 * original */
8780 if (!ppTInfo || !ppTComp)
8781 return E_POINTER;
8783 *ppTInfo = NULL;
8784 *ppTComp = NULL;
8786 return S_OK;
8789 static const ITypeCompVtbl tcompvt =
8792 ITypeComp_fnQueryInterface,
8793 ITypeComp_fnAddRef,
8794 ITypeComp_fnRelease,
8796 ITypeComp_fnBind,
8797 ITypeComp_fnBindType
8800 HRESULT WINAPI CreateTypeLib2(SYSKIND syskind, LPCOLESTR szFile,
8801 ICreateTypeLib2** ppctlib)
8803 ITypeLibImpl *This;
8804 HRESULT hres;
8806 TRACE("(%d,%s,%p)\n", syskind, debugstr_w(szFile), ppctlib);
8808 if (!szFile) return E_INVALIDARG;
8810 This = TypeLibImpl_Constructor();
8811 if (!This)
8812 return E_OUTOFMEMORY;
8814 This->lcid = GetSystemDefaultLCID();
8815 This->syskind = syskind;
8816 This->ptr_size = get_ptr_size(syskind);
8818 This->path = heap_alloc((lstrlenW(szFile) + 1) * sizeof(WCHAR));
8819 if (!This->path) {
8820 ITypeLib2_Release(&This->ITypeLib2_iface);
8821 return E_OUTOFMEMORY;
8823 lstrcpyW(This->path, szFile);
8825 hres = ITypeLib2_QueryInterface(&This->ITypeLib2_iface, &IID_ICreateTypeLib2, (LPVOID*)ppctlib);
8826 ITypeLib2_Release(&This->ITypeLib2_iface);
8827 return hres;
8830 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
8831 REFIID riid, void **object)
8833 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8835 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, object);
8838 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
8840 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8842 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
8845 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
8847 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8849 return ITypeLib2_Release(&This->ITypeLib2_iface);
8852 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
8853 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
8855 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8856 ITypeInfoImpl *info;
8857 HRESULT hres;
8859 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo);
8861 if (!ctinfo || !name)
8862 return E_INVALIDARG;
8864 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, name);
8865 if (info)
8866 return TYPE_E_NAMECONFLICT;
8868 if (This->typeinfos)
8869 This->typeinfos = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->typeinfos,
8870 sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1));
8871 else
8872 This->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*));
8874 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor();
8876 info->pTypeLib = This;
8877 info->Name = TLB_append_str(&This->name_list, name);
8878 info->index = This->TypeInfoCount;
8879 info->typeattr.typekind = kind;
8880 info->typeattr.cbAlignment = 4;
8882 switch (info->typeattr.typekind) {
8883 case TKIND_ENUM:
8884 case TKIND_INTERFACE:
8885 case TKIND_DISPATCH:
8886 case TKIND_COCLASS:
8887 info->typeattr.cbSizeInstance = This->ptr_size;
8888 break;
8889 case TKIND_RECORD:
8890 case TKIND_UNION:
8891 info->typeattr.cbSizeInstance = 0;
8892 break;
8893 case TKIND_MODULE:
8894 info->typeattr.cbSizeInstance = 2;
8895 break;
8896 case TKIND_ALIAS:
8897 info->typeattr.cbSizeInstance = -0x75;
8898 break;
8899 default:
8900 FIXME("unrecognized typekind %d\n", info->typeattr.typekind);
8901 info->typeattr.cbSizeInstance = 0xdeadbeef;
8902 break;
8905 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface,
8906 &IID_ICreateTypeInfo, (void **)ctinfo);
8907 if (FAILED(hres)) {
8908 ITypeInfo2_Release(&info->ITypeInfo2_iface);
8909 return hres;
8912 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase);
8914 ++This->TypeInfoCount;
8916 return S_OK;
8919 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
8920 LPOLESTR name)
8922 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8924 TRACE("%p %s\n", This, wine_dbgstr_w(name));
8926 if (!name)
8927 return E_INVALIDARG;
8929 This->Name = TLB_append_str(&This->name_list, name);
8931 return S_OK;
8934 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
8935 WORD majorVerNum, WORD minorVerNum)
8937 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8939 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
8941 This->ver_major = majorVerNum;
8942 This->ver_minor = minorVerNum;
8944 return S_OK;
8947 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
8948 REFGUID guid)
8950 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8952 TRACE("%p %s\n", This, debugstr_guid(guid));
8954 This->guid = TLB_append_guid(&This->guid_list, guid, -2);
8956 return S_OK;
8959 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
8960 LPOLESTR doc)
8962 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8964 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
8966 if (!doc)
8967 return E_INVALIDARG;
8969 This->DocString = TLB_append_str(&This->string_list, doc);
8971 return S_OK;
8974 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
8975 LPOLESTR helpFileName)
8977 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8979 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
8981 if (!helpFileName)
8982 return E_INVALIDARG;
8984 This->HelpFile = TLB_append_str(&This->string_list, helpFileName);
8986 return S_OK;
8989 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
8990 DWORD helpContext)
8992 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8994 TRACE("%p %d\n", This, helpContext);
8996 This->dwHelpContext = helpContext;
8998 return S_OK;
9001 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
9002 LCID lcid)
9004 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9006 TRACE("%p %x\n", This, lcid);
9008 This->set_lcid = lcid;
9010 return S_OK;
9013 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
9014 UINT libFlags)
9016 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9018 TRACE("%p %x\n", This, libFlags);
9020 This->libflags = libFlags;
9022 return S_OK;
9025 typedef struct tagWMSFT_SegContents {
9026 DWORD len;
9027 void *data;
9028 } WMSFT_SegContents;
9030 typedef struct tagWMSFT_TLBFile {
9031 MSFT_Header header;
9032 WMSFT_SegContents typeinfo_seg;
9033 WMSFT_SegContents impfile_seg;
9034 WMSFT_SegContents impinfo_seg;
9035 WMSFT_SegContents ref_seg;
9036 WMSFT_SegContents guidhash_seg;
9037 WMSFT_SegContents guid_seg;
9038 WMSFT_SegContents namehash_seg;
9039 WMSFT_SegContents name_seg;
9040 WMSFT_SegContents string_seg;
9041 WMSFT_SegContents typdesc_seg;
9042 WMSFT_SegContents arraydesc_seg;
9043 WMSFT_SegContents custdata_seg;
9044 WMSFT_SegContents cdguids_seg;
9045 MSFT_SegDir segdir;
9046 WMSFT_SegContents aux_seg;
9047 } WMSFT_TLBFile;
9049 static HRESULT WMSFT_compile_strings(ITypeLibImpl *This,
9050 WMSFT_TLBFile *file)
9052 TLBString *str;
9053 UINT last_offs;
9054 char *data;
9056 file->string_seg.len = 0;
9057 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
9058 int size;
9060 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str), NULL, 0, NULL, NULL);
9061 if (size == 0)
9062 return E_UNEXPECTED;
9064 size += sizeof(INT16);
9065 if (size % 4)
9066 size = (size + 4) & ~0x3;
9067 if (size < 8)
9068 size = 8;
9070 file->string_seg.len += size;
9072 /* temporarily use str->offset to store the length of the aligned,
9073 * converted string */
9074 str->offset = size;
9077 file->string_seg.data = data = heap_alloc(file->string_seg.len);
9079 last_offs = 0;
9080 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
9081 int size;
9083 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
9084 data + sizeof(INT16), file->string_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9085 if (size == 0) {
9086 heap_free(file->string_seg.data);
9087 return E_UNEXPECTED;
9090 *((INT16*)data) = size;
9092 memset(data + sizeof(INT16) + size, 0x57, str->offset - size - sizeof(INT16));
9094 size = str->offset;
9095 data += size;
9096 str->offset = last_offs;
9097 last_offs += size;
9100 return S_OK;
9103 static HRESULT WMSFT_compile_names(ITypeLibImpl *This,
9104 WMSFT_TLBFile *file)
9106 TLBString *str;
9107 UINT last_offs;
9108 char *data;
9109 MSFT_NameIntro *last_intro = NULL;
9111 file->header.nametablecount = 0;
9112 file->header.nametablechars = 0;
9114 file->name_seg.len = 0;
9115 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
9116 int size;
9118 size = strlenW(str->str);
9119 file->header.nametablechars += size;
9120 file->header.nametablecount++;
9122 size = WideCharToMultiByte(CP_ACP, 0, str->str, size, NULL, 0, NULL, NULL);
9123 if (size == 0)
9124 return E_UNEXPECTED;
9126 size += sizeof(MSFT_NameIntro);
9127 if (size % 4)
9128 size = (size + 4) & ~0x3;
9129 if (size < 8)
9130 size = 8;
9132 file->name_seg.len += size;
9134 /* temporarily use str->offset to store the length of the aligned,
9135 * converted string */
9136 str->offset = size;
9139 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
9140 file->name_seg.data = data = heap_alloc(file->name_seg.len+1);
9142 last_offs = 0;
9143 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
9144 int size, hash;
9145 MSFT_NameIntro *intro = (MSFT_NameIntro*)data;
9147 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
9148 data + sizeof(MSFT_NameIntro),
9149 file->name_seg.len - last_offs - sizeof(MSFT_NameIntro), NULL, NULL);
9150 if (size == 0) {
9151 heap_free(file->name_seg.data);
9152 return E_UNEXPECTED;
9154 data[sizeof(MSFT_NameIntro) + size] = '\0';
9156 intro->hreftype = -1; /* TODO? */
9157 intro->namelen = size & 0xFF;
9158 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9159 hash = LHashValOfNameSysA(This->syskind, This->lcid, data + sizeof(MSFT_NameIntro));
9160 intro->namelen |= hash << 16;
9161 intro->next_hash = ((DWORD*)file->namehash_seg.data)[hash & 0x7f];
9162 ((DWORD*)file->namehash_seg.data)[hash & 0x7f] = last_offs;
9164 memset(data + sizeof(MSFT_NameIntro) + size, 0x57,
9165 str->offset - size - sizeof(MSFT_NameIntro));
9167 /* update str->offset to actual value to use in other
9168 * compilation functions that require positions within
9169 * the string table */
9170 last_intro = intro;
9171 size = str->offset;
9172 data += size;
9173 str->offset = last_offs;
9174 last_offs += size;
9177 if(last_intro)
9178 last_intro->hreftype = 0; /* last one is 0? */
9180 return S_OK;
9183 static inline int hash_guid(GUID *guid)
9185 int i, hash = 0;
9187 for (i = 0; i < 8; i ++)
9188 hash ^= ((const short *)guid)[i];
9190 return hash & 0x1f;
9193 static HRESULT WMSFT_compile_guids(ITypeLibImpl *This, WMSFT_TLBFile *file)
9195 TLBGuid *guid;
9196 MSFT_GuidEntry *entry;
9197 DWORD offs;
9198 int hash_key, *guidhashtab;
9200 file->guid_seg.len = sizeof(MSFT_GuidEntry) * list_count(&This->guid_list);
9201 file->guid_seg.data = heap_alloc(file->guid_seg.len);
9203 entry = file->guid_seg.data;
9204 offs = 0;
9205 guidhashtab = file->guidhash_seg.data;
9206 LIST_FOR_EACH_ENTRY(guid, &This->guid_list, TLBGuid, entry){
9207 memcpy(&entry->guid, &guid->guid, sizeof(GUID));
9208 entry->hreftype = guid->hreftype;
9210 hash_key = hash_guid(&guid->guid);
9211 entry->next_hash = guidhashtab[hash_key];
9212 guidhashtab[hash_key] = offs;
9214 guid->offset = offs;
9215 offs += sizeof(MSFT_GuidEntry);
9216 ++entry;
9219 return S_OK;
9222 static DWORD WMSFT_encode_variant(VARIANT *value, WMSFT_TLBFile *file)
9224 VARIANT v = *value;
9225 VARTYPE arg_type = V_VT(value);
9226 int mask = 0;
9227 HRESULT hres;
9228 DWORD ret = file->custdata_seg.len;
9230 if(arg_type == VT_INT)
9231 arg_type = VT_I4;
9232 if(arg_type == VT_UINT)
9233 arg_type = VT_UI4;
9235 v = *value;
9236 if(V_VT(value) != arg_type) {
9237 hres = VariantChangeType(&v, value, 0, arg_type);
9238 if(FAILED(hres)){
9239 ERR("VariantChangeType failed: %08x\n", hres);
9240 return -1;
9244 /* Check if default value can be stored in-place */
9245 switch(arg_type){
9246 case VT_I4:
9247 case VT_UI4:
9248 mask = 0x3ffffff;
9249 if(V_UI4(&v) > 0x3ffffff)
9250 break;
9251 /* fall through */
9252 case VT_I1:
9253 case VT_UI1:
9254 case VT_BOOL:
9255 if(!mask)
9256 mask = 0xff;
9257 /* fall through */
9258 case VT_I2:
9259 case VT_UI2:
9260 if(!mask)
9261 mask = 0xffff;
9262 return ((0x80 + 0x4 * V_VT(value)) << 24) | (V_UI4(&v) & mask);
9265 /* have to allocate space in custdata_seg */
9266 switch(arg_type) {
9267 case VT_I4:
9268 case VT_R4:
9269 case VT_UI4:
9270 case VT_INT:
9271 case VT_UINT:
9272 case VT_HRESULT:
9273 case VT_PTR: {
9274 /* Construct the data to be allocated */
9275 int *data;
9277 if(file->custdata_seg.data){
9278 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + sizeof(int) * 2);
9279 data = (int *)(((char *)file->custdata_seg.data) + file->custdata_seg.len);
9280 file->custdata_seg.len += sizeof(int) * 2;
9281 }else{
9282 file->custdata_seg.len = sizeof(int) * 2;
9283 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9286 data[0] = V_VT(value) + (V_UI4(&v) << 16);
9287 data[1] = (V_UI4(&v) >> 16) + 0x57570000;
9289 /* TODO: Check if the encoded data is already present in custdata_seg */
9291 return ret;
9294 case VT_BSTR: {
9295 int i, len = (6+SysStringLen(V_BSTR(&v))+3) & ~0x3;
9296 char *data;
9298 if(file->custdata_seg.data){
9299 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + len);
9300 data = ((char *)file->custdata_seg.data) + file->custdata_seg.len;
9301 file->custdata_seg.len += len;
9302 }else{
9303 file->custdata_seg.len = len;
9304 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9307 *((unsigned short *)data) = V_VT(value);
9308 *((unsigned int *)(data+2)) = SysStringLen(V_BSTR(&v));
9309 for(i=0; i<SysStringLen(V_BSTR(&v)); i++) {
9310 if(V_BSTR(&v)[i] <= 0x7f)
9311 data[i+6] = V_BSTR(&v)[i];
9312 else
9313 data[i+6] = '?';
9315 WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], len-6, NULL, NULL);
9316 for(i=6+SysStringLen(V_BSTR(&v)); i<len; i++)
9317 data[i] = 0x57;
9319 /* TODO: Check if the encoded data is already present in custdata_seg */
9321 return ret;
9323 default:
9324 FIXME("Argument type not yet handled\n");
9325 return -1;
9329 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size);
9331 static DWORD WMSFT_append_arraydesc(ARRAYDESC *desc, WMSFT_TLBFile *file)
9333 DWORD offs = file->arraydesc_seg.len;
9334 DWORD *encoded;
9335 USHORT i;
9337 /* TODO: we should check for duplicates, but that's harder because each
9338 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9339 * at the library-level) */
9341 file->arraydesc_seg.len += (2 + desc->cDims * 2) * sizeof(DWORD);
9342 if(!file->arraydesc_seg.data)
9343 file->arraydesc_seg.data = heap_alloc(file->arraydesc_seg.len);
9344 else
9345 file->arraydesc_seg.data = heap_realloc(file->arraydesc_seg.data, file->arraydesc_seg.len);
9346 encoded = (DWORD*)((char *)file->arraydesc_seg.data + offs);
9348 encoded[0] = WMSFT_append_typedesc(&desc->tdescElem, file, NULL, NULL);
9349 encoded[1] = desc->cDims | ((desc->cDims * 2 * sizeof(DWORD)) << 16);
9350 for(i = 0; i < desc->cDims; ++i){
9351 encoded[2 + i * 2] = desc->rgbounds[i].cElements;
9352 encoded[2 + i * 2 + 1] = desc->rgbounds[i].lLbound;
9355 return offs;
9358 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size)
9360 DWORD junk;
9361 INT16 junk2;
9362 DWORD offs = 0;
9363 DWORD encoded[2];
9364 VARTYPE vt, subtype;
9365 char *data;
9367 if(!desc)
9368 return -1;
9370 if(!out_mix)
9371 out_mix = &junk;
9372 if(!out_size)
9373 out_size = &junk2;
9375 vt = desc->vt & VT_TYPEMASK;
9377 if(vt == VT_PTR || vt == VT_SAFEARRAY){
9378 DWORD mix;
9379 encoded[1] = WMSFT_append_typedesc(desc->u.lptdesc, file, &mix, out_size);
9380 encoded[0] = desc->vt | ((mix | VT_BYREF) << 16);
9381 *out_mix = 0x7FFF;
9382 *out_size += 2 * sizeof(DWORD);
9383 }else if(vt == VT_CARRAY){
9384 encoded[0] = desc->vt | (0x7FFE << 16);
9385 encoded[1] = WMSFT_append_arraydesc(desc->u.lpadesc, file);
9386 *out_mix = 0x7FFE;
9387 }else if(vt == VT_USERDEFINED){
9388 encoded[0] = desc->vt | (0x7FFF << 16);
9389 encoded[1] = desc->u.hreftype;
9390 *out_mix = 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9391 }else{
9392 TRACE("Mixing in-place, VT: 0x%x\n", desc->vt);
9394 switch(vt){
9395 case VT_INT:
9396 subtype = VT_I4;
9397 break;
9398 case VT_UINT:
9399 subtype = VT_UI4;
9400 break;
9401 case VT_VOID:
9402 subtype = VT_EMPTY;
9403 break;
9404 default:
9405 subtype = vt;
9406 break;
9409 *out_mix = subtype;
9410 return 0x80000000 | (subtype << 16) | desc->vt;
9413 data = file->typdesc_seg.data;
9414 while(offs < file->typdesc_seg.len){
9415 if(!memcmp(&data[offs], encoded, sizeof(encoded)))
9416 return offs;
9417 offs += sizeof(encoded);
9420 file->typdesc_seg.len += sizeof(encoded);
9421 if(!file->typdesc_seg.data)
9422 data = file->typdesc_seg.data = heap_alloc(file->typdesc_seg.len);
9423 else
9424 data = file->typdesc_seg.data = heap_realloc(file->typdesc_seg.data, file->typdesc_seg.len);
9426 memcpy(&data[offs], encoded, sizeof(encoded));
9428 return offs;
9431 static DWORD WMSFT_compile_custdata(struct list *custdata_list, WMSFT_TLBFile *file)
9433 WMSFT_SegContents *cdguids_seg = &file->cdguids_seg;
9434 DWORD ret = cdguids_seg->len, offs;
9435 MSFT_CDGuid *cdguid;
9436 TLBCustData *cd;
9438 if(list_empty(custdata_list))
9439 return -1;
9441 cdguids_seg->len += sizeof(MSFT_CDGuid) * list_count(custdata_list);
9442 if(!cdguids_seg->data){
9443 cdguid = cdguids_seg->data = heap_alloc(cdguids_seg->len);
9444 }else {
9445 cdguids_seg->data = heap_realloc(cdguids_seg->data, cdguids_seg->len);
9446 cdguid = (MSFT_CDGuid*)((char*)cdguids_seg->data + ret);
9449 offs = ret + sizeof(MSFT_CDGuid);
9450 LIST_FOR_EACH_ENTRY(cd, custdata_list, TLBCustData, entry){
9451 cdguid->GuidOffset = cd->guid->offset;
9452 cdguid->DataOffset = WMSFT_encode_variant(&cd->data, file);
9453 cdguid->next = offs;
9454 offs += sizeof(MSFT_CDGuid);
9455 ++cdguid;
9458 --cdguid;
9459 cdguid->next = -1;
9461 return ret;
9464 static DWORD WMSFT_compile_typeinfo_aux(ITypeInfoImpl *info,
9465 WMSFT_TLBFile *file)
9467 WMSFT_SegContents *aux_seg = &file->aux_seg;
9468 DWORD ret = aux_seg->len, i, j, recorded_size = 0, extra_size = 0;
9469 MSFT_VarRecord *varrecord;
9470 MSFT_FuncRecord *funcrecord;
9471 MEMBERID *memid;
9472 DWORD *name, *offsets, offs;
9474 for(i = 0; i < info->typeattr.cFuncs; ++i){
9475 TLBFuncDesc *desc = &info->funcdescs[i];
9477 recorded_size += 6 * sizeof(INT); /* mandatory fields */
9479 /* optional fields */
9480 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9481 if(!list_empty(&desc->custdata_list))
9482 recorded_size += 7 * sizeof(INT);
9483 else if(desc->HelpStringContext != 0)
9484 recorded_size += 6 * sizeof(INT);
9485 /* res9? resA? */
9486 else if(desc->Entry)
9487 recorded_size += 3 * sizeof(INT);
9488 else if(desc->HelpString)
9489 recorded_size += 2 * sizeof(INT);
9490 else if(desc->helpcontext)
9491 recorded_size += sizeof(INT);
9493 recorded_size += desc->funcdesc.cParams * sizeof(MSFT_ParameterInfo);
9495 for(j = 0; j < desc->funcdesc.cParams; ++j){
9496 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9497 recorded_size += desc->funcdesc.cParams * sizeof(INT);
9498 break;
9502 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9505 for(i = 0; i < info->typeattr.cVars; ++i){
9506 TLBVarDesc *desc = &info->vardescs[i];
9508 recorded_size += 5 * sizeof(INT); /* mandatory fields */
9510 /* optional fields */
9511 if(desc->HelpStringContext != 0)
9512 recorded_size += 5 * sizeof(INT);
9513 else if(!list_empty(&desc->custdata_list))
9514 recorded_size += 4 * sizeof(INT);
9515 /* res9? */
9516 else if(desc->HelpString)
9517 recorded_size += 2 * sizeof(INT);
9518 else if(desc->HelpContext != 0)
9519 recorded_size += sizeof(INT);
9521 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9524 if(!recorded_size && !extra_size)
9525 return ret;
9527 extra_size += sizeof(INT); /* total aux size for this typeinfo */
9529 aux_seg->len += recorded_size + extra_size;
9531 aux_seg->len += sizeof(INT) * (info->typeattr.cVars + info->typeattr.cFuncs); /* offsets at the end */
9533 if(aux_seg->data)
9534 aux_seg->data = heap_realloc(aux_seg->data, aux_seg->len);
9535 else
9536 aux_seg->data = heap_alloc(aux_seg->len);
9538 *((DWORD*)((char *)aux_seg->data + ret)) = recorded_size;
9540 offsets = (DWORD*)((char *)aux_seg->data + ret + recorded_size + extra_size);
9541 offs = 0;
9543 funcrecord = (MSFT_FuncRecord*)(((char *)aux_seg->data) + ret + sizeof(INT));
9544 for(i = 0; i < info->typeattr.cFuncs; ++i){
9545 TLBFuncDesc *desc = &info->funcdescs[i];
9546 DWORD size = 6 * sizeof(INT), paramdefault_size = 0, *paramdefault;
9548 funcrecord->funcdescsize = sizeof(desc->funcdesc) + desc->funcdesc.cParams * sizeof(ELEMDESC);
9549 funcrecord->DataType = WMSFT_append_typedesc(&desc->funcdesc.elemdescFunc.tdesc, file, NULL, &funcrecord->funcdescsize);
9550 funcrecord->Flags = desc->funcdesc.wFuncFlags;
9551 funcrecord->VtableOffset = desc->funcdesc.oVft;
9553 /* FKCCIC:
9554 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9555 * ^^^funckind
9556 * ^^^ ^invkind
9557 * ^has_cust_data
9558 * ^^^^callconv
9559 * ^has_param_defaults
9560 * ^oEntry_is_intresource
9562 funcrecord->FKCCIC =
9563 desc->funcdesc.funckind |
9564 (desc->funcdesc.invkind << 3) |
9565 (list_empty(&desc->custdata_list) ? 0 : 0x80) |
9566 (desc->funcdesc.callconv << 8);
9568 if(desc->Entry && desc->Entry != (TLBString*)-1 && IS_INTRESOURCE(desc->Entry))
9569 funcrecord->FKCCIC |= 0x2000;
9571 for(j = 0; j < desc->funcdesc.cParams; ++j){
9572 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9573 paramdefault_size = sizeof(INT) * desc->funcdesc.cParams;
9574 funcrecord->funcdescsize += sizeof(PARAMDESCEX);
9577 if(paramdefault_size > 0)
9578 funcrecord->FKCCIC |= 0x1000;
9580 funcrecord->nrargs = desc->funcdesc.cParams;
9581 funcrecord->nroargs = desc->funcdesc.cParamsOpt;
9583 /* optional fields */
9584 /* res9? resA? */
9585 if(!list_empty(&desc->custdata_list)){
9586 size += 7 * sizeof(INT);
9587 funcrecord->HelpContext = desc->helpcontext;
9588 if(desc->HelpString)
9589 funcrecord->oHelpString = desc->HelpString->offset;
9590 else
9591 funcrecord->oHelpString = -1;
9592 if(!desc->Entry)
9593 funcrecord->oEntry = -1;
9594 else if(IS_INTRESOURCE(desc->Entry))
9595 funcrecord->oEntry = LOWORD(desc->Entry);
9596 else
9597 funcrecord->oEntry = desc->Entry->offset;
9598 funcrecord->res9 = -1;
9599 funcrecord->resA = -1;
9600 funcrecord->HelpStringContext = desc->HelpStringContext;
9601 funcrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9602 }else if(desc->HelpStringContext != 0){
9603 size += 6 * sizeof(INT);
9604 funcrecord->HelpContext = desc->helpcontext;
9605 if(desc->HelpString)
9606 funcrecord->oHelpString = desc->HelpString->offset;
9607 else
9608 funcrecord->oHelpString = -1;
9609 if(!desc->Entry)
9610 funcrecord->oEntry = -1;
9611 else if(IS_INTRESOURCE(desc->Entry))
9612 funcrecord->oEntry = LOWORD(desc->Entry);
9613 else
9614 funcrecord->oEntry = desc->Entry->offset;
9615 funcrecord->res9 = -1;
9616 funcrecord->resA = -1;
9617 funcrecord->HelpStringContext = desc->HelpStringContext;
9618 }else if(desc->Entry){
9619 size += 3 * sizeof(INT);
9620 funcrecord->HelpContext = desc->helpcontext;
9621 if(desc->HelpString)
9622 funcrecord->oHelpString = desc->HelpString->offset;
9623 else
9624 funcrecord->oHelpString = -1;
9625 if(!desc->Entry)
9626 funcrecord->oEntry = -1;
9627 else if(IS_INTRESOURCE(desc->Entry))
9628 funcrecord->oEntry = LOWORD(desc->Entry);
9629 else
9630 funcrecord->oEntry = desc->Entry->offset;
9631 }else if(desc->HelpString){
9632 size += 2 * sizeof(INT);
9633 funcrecord->HelpContext = desc->helpcontext;
9634 funcrecord->oHelpString = desc->HelpString->offset;
9635 }else if(desc->helpcontext){
9636 size += sizeof(INT);
9637 funcrecord->HelpContext = desc->helpcontext;
9640 paramdefault = (DWORD*)((char *)funcrecord + size);
9641 size += paramdefault_size;
9643 for(j = 0; j < desc->funcdesc.cParams; ++j){
9644 MSFT_ParameterInfo *info = (MSFT_ParameterInfo*)(((char *)funcrecord) + size);
9646 info->DataType = WMSFT_append_typedesc(&desc->funcdesc.lprgelemdescParam[j].tdesc, file, NULL, &funcrecord->funcdescsize);
9647 if(desc->pParamDesc[j].Name)
9648 info->oName = desc->pParamDesc[j].Name->offset;
9649 else
9650 info->oName = -1;
9651 info->Flags = desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags;
9653 if(paramdefault_size){
9654 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
9655 *paramdefault = WMSFT_encode_variant(&desc->funcdesc.lprgelemdescParam[j].u.paramdesc.pparamdescex->varDefaultValue, file);
9656 else if(paramdefault_size)
9657 *paramdefault = -1;
9658 ++paramdefault;
9661 size += sizeof(MSFT_ParameterInfo);
9664 funcrecord->Info = size | (i << 16); /* is it just the index? */
9666 *offsets = offs;
9667 offs += size;
9668 ++offsets;
9670 funcrecord = (MSFT_FuncRecord*)(((char*)funcrecord) + size);
9673 varrecord = (MSFT_VarRecord*)funcrecord;
9674 for(i = 0; i < info->typeattr.cVars; ++i){
9675 TLBVarDesc *desc = &info->vardescs[i];
9676 DWORD size = 5 * sizeof(INT);
9678 varrecord->vardescsize = sizeof(desc->vardesc);
9679 varrecord->DataType = WMSFT_append_typedesc(&desc->vardesc.elemdescVar.tdesc, file, NULL, &varrecord->vardescsize);
9680 varrecord->Flags = desc->vardesc.wVarFlags;
9681 varrecord->VarKind = desc->vardesc.varkind;
9683 if(desc->vardesc.varkind == VAR_CONST){
9684 varrecord->vardescsize += sizeof(VARIANT);
9685 varrecord->OffsValue = WMSFT_encode_variant(desc->vardesc.u.lpvarValue, file);
9686 }else
9687 varrecord->OffsValue = desc->vardesc.u.oInst;
9689 /* res9? */
9690 if(desc->HelpStringContext != 0){
9691 size += 5 * sizeof(INT);
9692 varrecord->HelpContext = desc->HelpContext;
9693 if(desc->HelpString)
9694 varrecord->HelpString = desc->HelpString->offset;
9695 else
9696 varrecord->HelpString = -1;
9697 varrecord->res9 = -1;
9698 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9699 varrecord->HelpStringContext = desc->HelpStringContext;
9700 }else if(!list_empty(&desc->custdata_list)){
9701 size += 4 * sizeof(INT);
9702 varrecord->HelpContext = desc->HelpContext;
9703 if(desc->HelpString)
9704 varrecord->HelpString = desc->HelpString->offset;
9705 else
9706 varrecord->HelpString = -1;
9707 varrecord->res9 = -1;
9708 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9709 }else if(desc->HelpString){
9710 size += 2 * sizeof(INT);
9711 varrecord->HelpContext = desc->HelpContext;
9712 if(desc->HelpString)
9713 varrecord->HelpString = desc->HelpString->offset;
9714 else
9715 varrecord->HelpString = -1;
9716 }else if(desc->HelpContext != 0){
9717 size += sizeof(INT);
9718 varrecord->HelpContext = desc->HelpContext;
9721 varrecord->Info = size | (i << 16);
9723 *offsets = offs;
9724 offs += size;
9725 ++offsets;
9727 varrecord = (MSFT_VarRecord*)(((char*)varrecord) + size);
9730 memid = (MEMBERID*)varrecord;
9731 for(i = 0; i < info->typeattr.cFuncs; ++i){
9732 TLBFuncDesc *desc = &info->funcdescs[i];
9733 *memid = desc->funcdesc.memid;
9734 ++memid;
9736 for(i = 0; i < info->typeattr.cVars; ++i){
9737 TLBVarDesc *desc = &info->vardescs[i];
9738 *memid = desc->vardesc.memid;
9739 ++memid;
9742 name = (UINT*)memid;
9743 for(i = 0; i < info->typeattr.cFuncs; ++i){
9744 TLBFuncDesc *desc = &info->funcdescs[i];
9745 if(desc->Name)
9746 *name = desc->Name->offset;
9747 else
9748 *name = -1;
9749 ++name;
9751 for(i = 0; i < info->typeattr.cVars; ++i){
9752 TLBVarDesc *desc = &info->vardescs[i];
9753 if(desc->Name)
9754 *name = desc->Name->offset;
9755 else
9756 *name = -1;
9757 ++name;
9760 return ret;
9763 typedef struct tagWMSFT_RefChunk {
9764 DWORD href;
9765 DWORD res04;
9766 DWORD res08;
9767 DWORD next;
9768 } WMSFT_RefChunk;
9770 static DWORD WMSFT_compile_typeinfo_ref(ITypeInfoImpl *info, WMSFT_TLBFile *file)
9772 DWORD offs = file->ref_seg.len, i;
9773 WMSFT_RefChunk *chunk;
9775 file->ref_seg.len += info->typeattr.cImplTypes * sizeof(WMSFT_RefChunk);
9776 if(!file->ref_seg.data)
9777 file->ref_seg.data = heap_alloc(file->ref_seg.len);
9778 else
9779 file->ref_seg.data = heap_realloc(file->ref_seg.data, file->ref_seg.len);
9781 chunk = (WMSFT_RefChunk*)((char*)file->ref_seg.data + offs);
9783 for(i = 0; i < info->typeattr.cImplTypes; ++i){
9784 chunk->href = info->impltypes[i].hRef;
9785 chunk->res04 = info->impltypes[i].implflags;
9786 chunk->res08 = -1;
9787 if(i < info->typeattr.cImplTypes - 1)
9788 chunk->next = offs + sizeof(WMSFT_RefChunk) * (i + 1);
9789 else
9790 chunk->next = -1;
9791 ++chunk;
9794 return offs;
9797 static DWORD WMSFT_compile_typeinfo(ITypeInfoImpl *info, INT16 index, WMSFT_TLBFile *file, char *data)
9799 DWORD size;
9801 size = sizeof(MSFT_TypeInfoBase);
9803 if(data){
9804 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase*)data;
9805 if(info->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
9806 base->typekind = TKIND_DISPATCH;
9807 else
9808 base->typekind = info->typeattr.typekind;
9809 base->typekind |= index << 16; /* TODO: There are some other flags here */
9810 base->typekind |= (info->typeattr.cbAlignment << 11) | (info->typeattr.cbAlignment << 6);
9811 base->memoffset = WMSFT_compile_typeinfo_aux(info, file);
9812 base->res2 = 0;
9813 base->res3 = 0;
9814 base->res4 = 3;
9815 base->res5 = 0;
9816 base->cElement = (info->typeattr.cVars << 16) | info->typeattr.cFuncs;
9817 base->res7 = 0;
9818 base->res8 = 0;
9819 base->res9 = 0;
9820 base->resA = 0;
9821 if(info->guid)
9822 base->posguid = info->guid->offset;
9823 else
9824 base->posguid = -1;
9825 base->flags = info->typeattr.wTypeFlags;
9826 if(info->Name) {
9827 base->NameOffset = info->Name->offset;
9829 ((unsigned char*)file->name_seg.data)[info->Name->offset+9] = 0x38;
9830 *(HREFTYPE*)((unsigned char*)file->name_seg.data+info->Name->offset) = info->hreftype;
9831 }else {
9832 base->NameOffset = -1;
9834 base->version = (info->typeattr.wMinorVerNum << 16) | info->typeattr.wMajorVerNum;
9835 if(info->DocString)
9836 base->docstringoffs = info->DocString->offset;
9837 else
9838 base->docstringoffs = -1;
9839 base->helpstringcontext = info->dwHelpStringContext;
9840 base->helpcontext = info->dwHelpContext;
9841 base->oCustData = WMSFT_compile_custdata(info->pcustdata_list, file);
9842 base->cImplTypes = info->typeattr.cImplTypes;
9843 base->cbSizeVft = info->typeattr.cbSizeVft;
9844 base->size = info->typeattr.cbSizeInstance;
9845 if(info->typeattr.typekind == TKIND_COCLASS){
9846 base->datatype1 = WMSFT_compile_typeinfo_ref(info, file);
9847 }else if(info->typeattr.typekind == TKIND_ALIAS){
9848 base->datatype1 = WMSFT_append_typedesc(info->tdescAlias, file, NULL, NULL);
9849 }else if(info->typeattr.typekind == TKIND_MODULE){
9850 if(info->DllName)
9851 base->datatype1 = info->DllName->offset;
9852 else
9853 base->datatype1 = -1;
9854 }else{
9855 if(info->typeattr.cImplTypes > 0)
9856 base->datatype1 = info->impltypes[0].hRef;
9857 else
9858 base->datatype1 = -1;
9860 base->datatype2 = index; /* FIXME: i think there's more here */
9861 base->res18 = 0;
9862 base->res19 = -1;
9865 return size;
9868 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl *This, WMSFT_TLBFile *file, DWORD *junk)
9870 UINT i;
9872 file->typeinfo_seg.len = 0;
9873 for(i = 0; i < This->TypeInfoCount; ++i){
9874 ITypeInfoImpl *info = This->typeinfos[i];
9875 *junk = file->typeinfo_seg.len;
9876 ++junk;
9877 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, NULL, NULL);
9880 file->typeinfo_seg.data = heap_alloc(file->typeinfo_seg.len);
9881 memset(file->typeinfo_seg.data, 0x96, file->typeinfo_seg.len);
9883 file->aux_seg.len = 0;
9884 file->aux_seg.data = NULL;
9886 file->typeinfo_seg.len = 0;
9887 for(i = 0; i < This->TypeInfoCount; ++i){
9888 ITypeInfoImpl *info = This->typeinfos[i];
9889 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, file,
9890 ((char *)file->typeinfo_seg.data) + file->typeinfo_seg.len);
9894 typedef struct tagWMSFT_ImpFile {
9895 INT guid_offs;
9896 LCID lcid;
9897 DWORD version;
9898 } WMSFT_ImpFile;
9900 static void WMSFT_compile_impfile(ITypeLibImpl *This, WMSFT_TLBFile *file)
9902 TLBImpLib *implib;
9903 WMSFT_ImpFile *impfile;
9904 char *data;
9905 DWORD last_offs = 0;
9907 file->impfile_seg.len = 0;
9908 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9909 int size = 0;
9911 if(implib->name){
9912 WCHAR *path = strrchrW(implib->name, '\\');
9913 if(path)
9914 ++path;
9915 else
9916 path = implib->name;
9917 size = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path), NULL, 0, NULL, NULL);
9918 if (size == 0)
9919 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9922 size += sizeof(INT16);
9923 if (size % 4)
9924 size = (size + 4) & ~0x3;
9925 if (size < 8)
9926 size = 8;
9928 file->impfile_seg.len += sizeof(WMSFT_ImpFile) + size;
9931 data = file->impfile_seg.data = heap_alloc(file->impfile_seg.len);
9933 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9934 int strlen = 0, size;
9936 impfile = (WMSFT_ImpFile*)data;
9937 impfile->guid_offs = implib->guid->offset;
9938 impfile->lcid = implib->lcid;
9939 impfile->version = (implib->wVersionMinor << 16) | implib->wVersionMajor;
9941 data += sizeof(WMSFT_ImpFile);
9943 if(implib->name){
9944 WCHAR *path= strrchrW(implib->name, '\\');
9945 if(path)
9946 ++path;
9947 else
9948 path = implib->name;
9949 strlen = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path),
9950 data + sizeof(INT16), file->impfile_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9951 if (strlen == 0)
9952 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9955 *((INT16*)data) = (strlen << 2) | 1; /* FIXME: is that a flag, or what? */
9957 size = strlen + sizeof(INT16);
9958 if (size % 4)
9959 size = (size + 4) & ~0x3;
9960 if (size < 8)
9961 size = 8;
9962 memset(data + sizeof(INT16) + strlen, 0x57, size - strlen - sizeof(INT16));
9964 data += size;
9965 implib->offset = last_offs;
9966 last_offs += size + sizeof(WMSFT_ImpFile);
9970 static void WMSFT_compile_impinfo(ITypeLibImpl *This, WMSFT_TLBFile *file)
9972 MSFT_ImpInfo *info;
9973 TLBRefType *ref_type;
9974 UINT i = 0;
9976 WMSFT_compile_impfile(This, file);
9978 file->impinfo_seg.len = sizeof(MSFT_ImpInfo) * list_count(&This->ref_list);
9979 info = file->impinfo_seg.data = heap_alloc(file->impinfo_seg.len);
9981 LIST_FOR_EACH_ENTRY(ref_type, &This->ref_list, TLBRefType, entry){
9982 info->flags = i | ((ref_type->tkind & 0xFF) << 24);
9983 if(ref_type->index == TLB_REF_USE_GUID){
9984 info->flags |= MSFT_IMPINFO_OFFSET_IS_GUID;
9985 info->oGuid = ref_type->guid->offset;
9986 }else
9987 info->oGuid = ref_type->index;
9988 info->oImpFile = ref_type->pImpTLInfo->offset;
9989 ++i;
9990 ++info;
9994 static void WMSFT_compile_guidhash(ITypeLibImpl *This, WMSFT_TLBFile *file)
9996 file->guidhash_seg.len = 0x80;
9997 file->guidhash_seg.data = heap_alloc(file->guidhash_seg.len);
9998 memset(file->guidhash_seg.data, 0xFF, file->guidhash_seg.len);
10001 static void WMSFT_compile_namehash(ITypeLibImpl *This, WMSFT_TLBFile *file)
10003 file->namehash_seg.len = 0x200;
10004 file->namehash_seg.data = heap_alloc(file->namehash_seg.len);
10005 memset(file->namehash_seg.data, 0xFF, file->namehash_seg.len);
10008 static void tmp_fill_segdir_seg(MSFT_pSeg *segdir, WMSFT_SegContents *contents, DWORD *running_offset)
10010 if(contents && contents->len){
10011 segdir->offset = *running_offset;
10012 segdir->length = contents->len;
10013 *running_offset += segdir->length;
10014 }else{
10015 segdir->offset = -1;
10016 segdir->length = 0;
10019 /* TODO: do these ever change? */
10020 segdir->res08 = -1;
10021 segdir->res0c = 0xf;
10024 static void WMSFT_write_segment(HANDLE outfile, WMSFT_SegContents *segment)
10026 DWORD written;
10027 if(segment)
10028 WriteFile(outfile, segment->data, segment->len, &written, NULL);
10031 static HRESULT WMSFT_fixup_typeinfos(ITypeLibImpl *This, WMSFT_TLBFile *file,
10032 DWORD file_len)
10034 DWORD i;
10035 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase *)file->typeinfo_seg.data;
10037 for(i = 0; i < This->TypeInfoCount; ++i){
10038 base->memoffset += file_len;
10039 ++base;
10042 return S_OK;
10045 static void WMSFT_free_file(WMSFT_TLBFile *file)
10047 HeapFree(GetProcessHeap(), 0, file->typeinfo_seg.data);
10048 HeapFree(GetProcessHeap(), 0, file->guidhash_seg.data);
10049 HeapFree(GetProcessHeap(), 0, file->guid_seg.data);
10050 HeapFree(GetProcessHeap(), 0, file->ref_seg.data);
10051 HeapFree(GetProcessHeap(), 0, file->impinfo_seg.data);
10052 HeapFree(GetProcessHeap(), 0, file->impfile_seg.data);
10053 HeapFree(GetProcessHeap(), 0, file->namehash_seg.data);
10054 HeapFree(GetProcessHeap(), 0, file->name_seg.data);
10055 HeapFree(GetProcessHeap(), 0, file->string_seg.data);
10056 HeapFree(GetProcessHeap(), 0, file->typdesc_seg.data);
10057 HeapFree(GetProcessHeap(), 0, file->arraydesc_seg.data);
10058 HeapFree(GetProcessHeap(), 0, file->custdata_seg.data);
10059 HeapFree(GetProcessHeap(), 0, file->cdguids_seg.data);
10060 HeapFree(GetProcessHeap(), 0, file->aux_seg.data);
10063 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
10065 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10066 WMSFT_TLBFile file;
10067 DWORD written, junk_size, junk_offs, running_offset;
10068 BOOL br;
10069 HANDLE outfile;
10070 HRESULT hres;
10071 DWORD *junk;
10072 UINT i;
10074 TRACE("%p\n", This);
10076 for(i = 0; i < This->TypeInfoCount; ++i)
10077 if(This->typeinfos[i]->needs_layout)
10078 ICreateTypeInfo2_LayOut(&This->typeinfos[i]->ICreateTypeInfo2_iface);
10080 memset(&file, 0, sizeof(file));
10082 file.header.magic1 = 0x5446534D;
10083 file.header.magic2 = 0x00010002;
10084 file.header.lcid = This->set_lcid ? This->set_lcid : MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
10085 file.header.lcid2 = This->set_lcid;
10086 file.header.varflags = 0x40 | This->syskind;
10087 if (This->HelpFile)
10088 file.header.varflags |= 0x10;
10089 if (This->HelpStringDll)
10090 file.header.varflags |= HELPDLLFLAG;
10091 file.header.version = (This->ver_minor << 16) | This->ver_major;
10092 file.header.flags = This->libflags;
10093 file.header.helpstringcontext = 0; /* TODO - SetHelpStringContext not implemented yet */
10094 file.header.helpcontext = This->dwHelpContext;
10095 file.header.res44 = 0x20;
10096 file.header.res48 = 0x80;
10097 file.header.dispatchpos = This->dispatch_href;
10099 WMSFT_compile_namehash(This, &file);
10100 /* do name and string compilation to get offsets for other compilations */
10101 hres = WMSFT_compile_names(This, &file);
10102 if (FAILED(hres)){
10103 WMSFT_free_file(&file);
10104 return hres;
10107 hres = WMSFT_compile_strings(This, &file);
10108 if (FAILED(hres)){
10109 WMSFT_free_file(&file);
10110 return hres;
10113 WMSFT_compile_guidhash(This, &file);
10114 hres = WMSFT_compile_guids(This, &file);
10115 if (FAILED(hres)){
10116 WMSFT_free_file(&file);
10117 return hres;
10120 if(This->HelpFile)
10121 file.header.helpfile = This->HelpFile->offset;
10122 else
10123 file.header.helpfile = -1;
10125 if(This->DocString)
10126 file.header.helpstring = This->DocString->offset;
10127 else
10128 file.header.helpstring = -1;
10130 /* do some more segment compilation */
10131 file.header.nimpinfos = list_count(&This->ref_list);
10132 file.header.nrtypeinfos = This->TypeInfoCount;
10134 if(This->Name)
10135 file.header.NameOffset = This->Name->offset;
10136 else
10137 file.header.NameOffset = -1;
10139 file.header.CustomDataOffset = WMSFT_compile_custdata(&This->custdata_list, &file);
10141 if(This->guid)
10142 file.header.posguid = This->guid->offset;
10143 else
10144 file.header.posguid = -1;
10146 junk_size = file.header.nrtypeinfos * sizeof(DWORD);
10147 if(file.header.varflags & HELPDLLFLAG)
10148 junk_size += sizeof(DWORD);
10149 if(junk_size){
10150 junk = heap_alloc_zero(junk_size);
10151 if(file.header.varflags & HELPDLLFLAG){
10152 *junk = This->HelpStringDll->offset;
10153 junk_offs = 1;
10154 }else
10155 junk_offs = 0;
10156 }else{
10157 junk = NULL;
10158 junk_offs = 0;
10161 WMSFT_compile_typeinfo_seg(This, &file, junk + junk_offs);
10162 WMSFT_compile_impinfo(This, &file);
10164 running_offset = 0;
10166 TRACE("header at: 0x%x\n", running_offset);
10167 running_offset += sizeof(file.header);
10169 TRACE("junk at: 0x%x\n", running_offset);
10170 running_offset += junk_size;
10172 TRACE("segdir at: 0x%x\n", running_offset);
10173 running_offset += sizeof(file.segdir);
10175 TRACE("typeinfo at: 0x%x\n", running_offset);
10176 tmp_fill_segdir_seg(&file.segdir.pTypeInfoTab, &file.typeinfo_seg, &running_offset);
10178 TRACE("guidhashtab at: 0x%x\n", running_offset);
10179 tmp_fill_segdir_seg(&file.segdir.pGuidHashTab, &file.guidhash_seg, &running_offset);
10181 TRACE("guidtab at: 0x%x\n", running_offset);
10182 tmp_fill_segdir_seg(&file.segdir.pGuidTab, &file.guid_seg, &running_offset);
10184 TRACE("reftab at: 0x%x\n", running_offset);
10185 tmp_fill_segdir_seg(&file.segdir.pRefTab, &file.ref_seg, &running_offset);
10187 TRACE("impinfo at: 0x%x\n", running_offset);
10188 tmp_fill_segdir_seg(&file.segdir.pImpInfo, &file.impinfo_seg, &running_offset);
10190 TRACE("impfiles at: 0x%x\n", running_offset);
10191 tmp_fill_segdir_seg(&file.segdir.pImpFiles, &file.impfile_seg, &running_offset);
10193 TRACE("namehashtab at: 0x%x\n", running_offset);
10194 tmp_fill_segdir_seg(&file.segdir.pNameHashTab, &file.namehash_seg, &running_offset);
10196 TRACE("nametab at: 0x%x\n", running_offset);
10197 tmp_fill_segdir_seg(&file.segdir.pNametab, &file.name_seg, &running_offset);
10199 TRACE("stringtab at: 0x%x\n", running_offset);
10200 tmp_fill_segdir_seg(&file.segdir.pStringtab, &file.string_seg, &running_offset);
10202 TRACE("typdesc at: 0x%x\n", running_offset);
10203 tmp_fill_segdir_seg(&file.segdir.pTypdescTab, &file.typdesc_seg, &running_offset);
10205 TRACE("arraydescriptions at: 0x%x\n", running_offset);
10206 tmp_fill_segdir_seg(&file.segdir.pArrayDescriptions, &file.arraydesc_seg, &running_offset);
10208 TRACE("custdata at: 0x%x\n", running_offset);
10209 tmp_fill_segdir_seg(&file.segdir.pCustData, &file.custdata_seg, &running_offset);
10211 TRACE("cdguids at: 0x%x\n", running_offset);
10212 tmp_fill_segdir_seg(&file.segdir.pCDGuids, &file.cdguids_seg, &running_offset);
10214 TRACE("res0e at: 0x%x\n", running_offset);
10215 tmp_fill_segdir_seg(&file.segdir.res0e, NULL, &running_offset);
10217 TRACE("res0f at: 0x%x\n", running_offset);
10218 tmp_fill_segdir_seg(&file.segdir.res0f, NULL, &running_offset);
10220 TRACE("aux_seg at: 0x%x\n", running_offset);
10222 WMSFT_fixup_typeinfos(This, &file, running_offset);
10224 outfile = CreateFileW(This->path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
10225 FILE_ATTRIBUTE_NORMAL, 0);
10226 if (outfile == INVALID_HANDLE_VALUE){
10227 WMSFT_free_file(&file);
10228 heap_free(junk);
10229 return TYPE_E_IOERROR;
10232 br = WriteFile(outfile, &file.header, sizeof(file.header), &written, NULL);
10233 if (!br) {
10234 WMSFT_free_file(&file);
10235 CloseHandle(outfile);
10236 heap_free(junk);
10237 return TYPE_E_IOERROR;
10240 br = WriteFile(outfile, junk, junk_size, &written, NULL);
10241 heap_free(junk);
10242 if (!br) {
10243 WMSFT_free_file(&file);
10244 CloseHandle(outfile);
10245 return TYPE_E_IOERROR;
10248 br = WriteFile(outfile, &file.segdir, sizeof(file.segdir), &written, NULL);
10249 if (!br) {
10250 WMSFT_free_file(&file);
10251 CloseHandle(outfile);
10252 return TYPE_E_IOERROR;
10255 WMSFT_write_segment(outfile, &file.typeinfo_seg);
10256 WMSFT_write_segment(outfile, &file.guidhash_seg);
10257 WMSFT_write_segment(outfile, &file.guid_seg);
10258 WMSFT_write_segment(outfile, &file.ref_seg);
10259 WMSFT_write_segment(outfile, &file.impinfo_seg);
10260 WMSFT_write_segment(outfile, &file.impfile_seg);
10261 WMSFT_write_segment(outfile, &file.namehash_seg);
10262 WMSFT_write_segment(outfile, &file.name_seg);
10263 WMSFT_write_segment(outfile, &file.string_seg);
10264 WMSFT_write_segment(outfile, &file.typdesc_seg);
10265 WMSFT_write_segment(outfile, &file.arraydesc_seg);
10266 WMSFT_write_segment(outfile, &file.custdata_seg);
10267 WMSFT_write_segment(outfile, &file.cdguids_seg);
10268 WMSFT_write_segment(outfile, &file.aux_seg);
10270 WMSFT_free_file(&file);
10272 CloseHandle(outfile);
10274 return S_OK;
10277 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
10278 LPOLESTR name)
10280 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10281 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
10282 return E_NOTIMPL;
10285 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
10286 REFGUID guid, VARIANT *varVal)
10288 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10289 TLBGuid *tlbguid;
10291 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
10293 if (!guid || !varVal)
10294 return E_INVALIDARG;
10296 tlbguid = TLB_append_guid(&This->guid_list, guid, -1);
10298 return TLB_set_custdata(&This->custdata_list, tlbguid, varVal);
10301 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
10302 ULONG helpStringContext)
10304 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10305 FIXME("%p %u - stub\n", This, helpStringContext);
10306 return E_NOTIMPL;
10309 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
10310 LPOLESTR filename)
10312 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10313 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
10315 if (!filename)
10316 return E_INVALIDARG;
10318 This->HelpStringDll = TLB_append_str(&This->string_list, filename);
10320 return S_OK;
10323 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
10324 ICreateTypeLib2_fnQueryInterface,
10325 ICreateTypeLib2_fnAddRef,
10326 ICreateTypeLib2_fnRelease,
10327 ICreateTypeLib2_fnCreateTypeInfo,
10328 ICreateTypeLib2_fnSetName,
10329 ICreateTypeLib2_fnSetVersion,
10330 ICreateTypeLib2_fnSetGuid,
10331 ICreateTypeLib2_fnSetDocString,
10332 ICreateTypeLib2_fnSetHelpFileName,
10333 ICreateTypeLib2_fnSetHelpContext,
10334 ICreateTypeLib2_fnSetLcid,
10335 ICreateTypeLib2_fnSetLibFlags,
10336 ICreateTypeLib2_fnSaveAllChanges,
10337 ICreateTypeLib2_fnDeleteTypeInfo,
10338 ICreateTypeLib2_fnSetCustData,
10339 ICreateTypeLib2_fnSetHelpStringContext,
10340 ICreateTypeLib2_fnSetHelpStringDll
10343 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
10344 REFIID riid, void **object)
10346 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10348 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, object);
10351 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
10353 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10355 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
10358 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
10360 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10362 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
10365 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
10366 REFGUID guid)
10368 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10370 TRACE("%p %s\n", This, debugstr_guid(guid));
10372 This->guid = TLB_append_guid(&This->pTypeLib->guid_list, guid, This->hreftype);
10374 return S_OK;
10377 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
10378 UINT typeFlags)
10380 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10381 WORD old_flags;
10382 HRESULT hres;
10384 TRACE("%p %x\n", This, typeFlags);
10386 if (typeFlags & TYPEFLAG_FDUAL) {
10387 static const WCHAR stdole2tlb[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10388 ITypeLib *stdole;
10389 ITypeInfo *dispatch;
10390 HREFTYPE hreftype;
10391 HRESULT hres;
10393 hres = LoadTypeLib(stdole2tlb, &stdole);
10394 if(FAILED(hres))
10395 return hres;
10397 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
10398 ITypeLib_Release(stdole);
10399 if(FAILED(hres))
10400 return hres;
10402 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
10403 ITypeInfo_Release(dispatch);
10404 if(FAILED(hres))
10405 return hres;
10408 old_flags = This->typeattr.wTypeFlags;
10409 This->typeattr.wTypeFlags = typeFlags;
10411 hres = ICreateTypeInfo2_LayOut(iface);
10412 if (FAILED(hres)) {
10413 This->typeattr.wTypeFlags = old_flags;
10414 return hres;
10417 return S_OK;
10420 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
10421 LPOLESTR doc)
10423 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10425 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
10427 if (!doc)
10428 return E_INVALIDARG;
10430 This->DocString = TLB_append_str(&This->pTypeLib->string_list, doc);
10432 return S_OK;
10435 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
10436 DWORD helpContext)
10438 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10440 TRACE("%p %d\n", This, helpContext);
10442 This->dwHelpContext = helpContext;
10444 return S_OK;
10447 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
10448 WORD majorVerNum, WORD minorVerNum)
10450 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10452 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
10454 This->typeattr.wMajorVerNum = majorVerNum;
10455 This->typeattr.wMinorVerNum = minorVerNum;
10457 return S_OK;
10460 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
10461 ITypeInfo *typeInfo, HREFTYPE *refType)
10463 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10464 UINT index;
10465 ITypeLib *container;
10466 TLBRefType *ref_type;
10467 TLBImpLib *implib;
10468 TYPEATTR *typeattr;
10469 TLIBATTR *libattr;
10470 HRESULT hres;
10472 TRACE("%p %p %p\n", This, typeInfo, refType);
10474 if (!typeInfo || !refType)
10475 return E_INVALIDARG;
10477 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
10478 if (FAILED(hres))
10479 return hres;
10481 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
10482 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
10484 ITypeLib_Release(container);
10486 *refType = target->hreftype;
10488 return S_OK;
10491 hres = ITypeLib_GetLibAttr(container, &libattr);
10492 if (FAILED(hres)) {
10493 ITypeLib_Release(container);
10494 return hres;
10497 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
10498 if(IsEqualGUID(&implib->guid->guid, &libattr->guid) &&
10499 implib->lcid == libattr->lcid &&
10500 implib->wVersionMajor == libattr->wMajorVerNum &&
10501 implib->wVersionMinor == libattr->wMinorVerNum)
10502 break;
10505 if(&implib->entry == &This->pTypeLib->implib_list){
10506 implib = heap_alloc_zero(sizeof(TLBImpLib));
10508 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
10509 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
10510 implib->name = SysAllocString(our_container->path);
10511 }else{
10512 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
10513 libattr->wMinorVerNum, libattr->lcid, &implib->name);
10514 if(FAILED(hres)){
10515 implib->name = NULL;
10516 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres);
10520 implib->guid = TLB_append_guid(&This->pTypeLib->guid_list, &libattr->guid, 2);
10521 implib->lcid = libattr->lcid;
10522 implib->wVersionMajor = libattr->wMajorVerNum;
10523 implib->wVersionMinor = libattr->wMinorVerNum;
10525 list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
10528 ITypeLib_ReleaseTLibAttr(container, libattr);
10529 ITypeLib_Release(container);
10531 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
10532 if (FAILED(hres))
10533 return hres;
10535 index = 0;
10536 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
10537 if(ref_type->index == TLB_REF_USE_GUID &&
10538 IsEqualGUID(&ref_type->guid->guid, &typeattr->guid) &&
10539 ref_type->tkind == typeattr->typekind)
10540 break;
10541 ++index;
10544 if(&ref_type->entry == &This->pTypeLib->ref_list){
10545 ref_type = heap_alloc_zero(sizeof(TLBRefType));
10547 ref_type->tkind = typeattr->typekind;
10548 ref_type->pImpTLInfo = implib;
10549 ref_type->reference = index * sizeof(MSFT_ImpInfo);
10551 ref_type->index = TLB_REF_USE_GUID;
10553 ref_type->guid = TLB_append_guid(&This->pTypeLib->guid_list, &typeattr->guid, ref_type->reference+1);
10555 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
10558 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
10560 *refType = ref_type->reference | 0x1;
10562 if(IsEqualGUID(&ref_type->guid->guid, &IID_IDispatch))
10563 This->pTypeLib->dispatch_href = *refType;
10565 return S_OK;
10568 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
10569 UINT index, FUNCDESC *funcDesc)
10571 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10572 TLBFuncDesc tmp_func_desc, *func_desc;
10573 int buf_size, i;
10574 char *buffer;
10575 HRESULT hres;
10577 TRACE("%p %u %p\n", This, index, funcDesc);
10579 if (!funcDesc || funcDesc->oVft & 3)
10580 return E_INVALIDARG;
10582 switch (This->typeattr.typekind) {
10583 case TKIND_MODULE:
10584 if (funcDesc->funckind != FUNC_STATIC)
10585 return TYPE_E_BADMODULEKIND;
10586 break;
10587 case TKIND_DISPATCH:
10588 if (funcDesc->funckind != FUNC_DISPATCH)
10589 return TYPE_E_BADMODULEKIND;
10590 break;
10591 default:
10592 if (funcDesc->funckind != FUNC_PUREVIRTUAL)
10593 return TYPE_E_BADMODULEKIND;
10596 if (index > This->typeattr.cFuncs)
10597 return TYPE_E_ELEMENTNOTFOUND;
10599 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) &&
10600 !funcDesc->cParams)
10601 return TYPE_E_INCONSISTENTPROPFUNCS;
10603 #ifdef _WIN64
10604 if(This->pTypeLib->syskind == SYS_WIN64 &&
10605 funcDesc->oVft % 8 != 0)
10606 return E_INVALIDARG;
10607 #endif
10609 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc));
10610 TLBFuncDesc_Constructor(&tmp_func_desc);
10612 tmp_func_desc.funcdesc = *funcDesc;
10614 if (tmp_func_desc.funcdesc.oVft != 0)
10615 tmp_func_desc.funcdesc.oVft |= 1;
10617 if (funcDesc->cScodes && funcDesc->lprgscode) {
10618 tmp_func_desc.funcdesc.lprgscode = heap_alloc(sizeof(SCODE) * funcDesc->cScodes);
10619 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes);
10620 } else {
10621 tmp_func_desc.funcdesc.lprgscode = NULL;
10622 tmp_func_desc.funcdesc.cScodes = 0;
10625 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc);
10626 for (i = 0; i < funcDesc->cParams; ++i) {
10627 buf_size += sizeof(ELEMDESC);
10628 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i);
10630 tmp_func_desc.funcdesc.lprgelemdescParam = heap_alloc(buf_size);
10631 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams);
10633 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer);
10634 if (FAILED(hres)) {
10635 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10636 heap_free(tmp_func_desc.funcdesc.lprgscode);
10637 return hres;
10640 for (i = 0; i < funcDesc->cParams; ++i) {
10641 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i,
10642 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer);
10643 if (FAILED(hres)) {
10644 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10645 heap_free(tmp_func_desc.funcdesc.lprgscode);
10646 return hres;
10648 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT &&
10649 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT &&
10650 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){
10651 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
10652 if (FAILED(hres)) {
10653 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10654 heap_free(tmp_func_desc.funcdesc.lprgscode);
10655 return hres;
10660 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams);
10662 if (This->funcdescs) {
10663 This->funcdescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->funcdescs,
10664 sizeof(TLBFuncDesc) * (This->typeattr.cFuncs + 1));
10666 if (index < This->typeattr.cFuncs) {
10667 memmove(This->funcdescs + index + 1, This->funcdescs + index,
10668 (This->typeattr.cFuncs - index) * sizeof(TLBFuncDesc));
10669 func_desc = This->funcdescs + index;
10670 } else
10671 func_desc = This->funcdescs + This->typeattr.cFuncs;
10673 /* move custdata lists to the new memory location */
10674 for(i = 0; i < This->typeattr.cFuncs + 1; ++i){
10675 if(index != i){
10676 TLBFuncDesc *fd = &This->funcdescs[i];
10677 if(fd->custdata_list.prev == fd->custdata_list.next)
10678 list_init(&fd->custdata_list);
10679 else{
10680 fd->custdata_list.prev->next = &fd->custdata_list;
10681 fd->custdata_list.next->prev = &fd->custdata_list;
10685 } else
10686 func_desc = This->funcdescs = heap_alloc(sizeof(TLBFuncDesc));
10688 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc));
10689 list_init(&func_desc->custdata_list);
10691 ++This->typeattr.cFuncs;
10693 This->needs_layout = TRUE;
10695 return S_OK;
10698 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
10699 UINT index, HREFTYPE refType)
10701 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10702 TLBImplType *impl_type;
10703 HRESULT hres;
10705 TRACE("%p %u %d\n", This, index, refType);
10707 switch(This->typeattr.typekind){
10708 case TKIND_COCLASS: {
10709 if (index == -1) {
10710 FIXME("Unhandled index: -1\n");
10711 return E_NOTIMPL;
10714 if(index != This->typeattr.cImplTypes)
10715 return TYPE_E_ELEMENTNOTFOUND;
10717 break;
10719 case TKIND_INTERFACE:
10720 case TKIND_DISPATCH:
10721 if (index != 0 || This->typeattr.cImplTypes)
10722 return TYPE_E_ELEMENTNOTFOUND;
10723 break;
10724 default:
10725 FIXME("Unimplemented typekind: %d\n", This->typeattr.typekind);
10726 return E_NOTIMPL;
10729 if (This->impltypes){
10730 UINT i;
10732 This->impltypes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->impltypes,
10733 sizeof(TLBImplType) * (This->typeattr.cImplTypes + 1));
10735 if (index < This->typeattr.cImplTypes) {
10736 memmove(This->impltypes + index + 1, This->impltypes + index,
10737 (This->typeattr.cImplTypes - index) * sizeof(TLBImplType));
10738 impl_type = This->impltypes + index;
10739 } else
10740 impl_type = This->impltypes + This->typeattr.cImplTypes;
10742 /* move custdata lists to the new memory location */
10743 for(i = 0; i < This->typeattr.cImplTypes + 1; ++i){
10744 if(index != i){
10745 TLBImplType *it = &This->impltypes[i];
10746 if(it->custdata_list.prev == it->custdata_list.next)
10747 list_init(&it->custdata_list);
10748 else{
10749 it->custdata_list.prev->next = &it->custdata_list;
10750 it->custdata_list.next->prev = &it->custdata_list;
10754 } else
10755 impl_type = This->impltypes = heap_alloc(sizeof(TLBImplType));
10757 memset(impl_type, 0, sizeof(TLBImplType));
10758 TLBImplType_Constructor(impl_type);
10759 impl_type->hRef = refType;
10761 ++This->typeattr.cImplTypes;
10763 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
10764 This->typeattr.wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
10766 hres = ICreateTypeInfo2_LayOut(iface);
10767 if (FAILED(hres))
10768 return hres;
10770 return S_OK;
10773 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
10774 UINT index, INT implTypeFlags)
10776 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10777 TLBImplType *impl_type = &This->impltypes[index];
10779 TRACE("%p %u %x\n", This, index, implTypeFlags);
10781 if (This->typeattr.typekind != TKIND_COCLASS)
10782 return TYPE_E_BADMODULEKIND;
10784 if (index >= This->typeattr.cImplTypes)
10785 return TYPE_E_ELEMENTNOTFOUND;
10787 impl_type->implflags = implTypeFlags;
10789 return S_OK;
10792 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
10793 WORD alignment)
10795 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10797 TRACE("%p %d\n", This, alignment);
10799 This->typeattr.cbAlignment = alignment;
10801 return S_OK;
10804 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
10805 LPOLESTR schema)
10807 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10809 TRACE("%p %s\n", This, wine_dbgstr_w(schema));
10811 if (!schema)
10812 return E_INVALIDARG;
10814 This->Schema = TLB_append_str(&This->pTypeLib->string_list, schema);
10816 This->typeattr.lpstrSchema = This->Schema->str;
10818 return S_OK;
10821 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
10822 UINT index, VARDESC *varDesc)
10824 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10825 TLBVarDesc *var_desc;
10827 TRACE("%p %u %p\n", This, index, varDesc);
10829 if (This->vardescs){
10830 UINT i;
10832 This->vardescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->vardescs,
10833 sizeof(TLBVarDesc) * (This->typeattr.cVars + 1));
10835 if (index < This->typeattr.cVars) {
10836 memmove(This->vardescs + index + 1, This->vardescs + index,
10837 (This->typeattr.cVars - index) * sizeof(TLBVarDesc));
10838 var_desc = This->vardescs + index;
10839 } else
10840 var_desc = This->vardescs + This->typeattr.cVars;
10842 /* move custdata lists to the new memory location */
10843 for(i = 0; i < This->typeattr.cVars + 1; ++i){
10844 if(index != i){
10845 TLBVarDesc *var = &This->vardescs[i];
10846 if(var->custdata_list.prev == var->custdata_list.next)
10847 list_init(&var->custdata_list);
10848 else{
10849 var->custdata_list.prev->next = &var->custdata_list;
10850 var->custdata_list.next->prev = &var->custdata_list;
10854 } else
10855 var_desc = This->vardescs = heap_alloc_zero(sizeof(TLBVarDesc));
10857 TLBVarDesc_Constructor(var_desc);
10858 TLB_AllocAndInitVarDesc(varDesc, &var_desc->vardesc_create);
10859 var_desc->vardesc = *var_desc->vardesc_create;
10861 ++This->typeattr.cVars;
10863 This->needs_layout = TRUE;
10865 return S_OK;
10868 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
10869 UINT index, LPOLESTR *names, UINT numNames)
10871 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10872 TLBFuncDesc *func_desc = &This->funcdescs[index];
10873 int i;
10875 TRACE("%p %u %p %u\n", This, index, names, numNames);
10877 if (!names)
10878 return E_INVALIDARG;
10880 if (index >= This->typeattr.cFuncs || numNames == 0)
10881 return TYPE_E_ELEMENTNOTFOUND;
10883 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){
10884 if(numNames > func_desc->funcdesc.cParams)
10885 return TYPE_E_ELEMENTNOTFOUND;
10886 } else
10887 if(numNames > func_desc->funcdesc.cParams + 1)
10888 return TYPE_E_ELEMENTNOTFOUND;
10890 for(i = 0; i < This->typeattr.cFuncs; ++i) {
10891 TLBFuncDesc *iter = &This->funcdescs[i];
10892 if (iter->Name && !strcmpW(TLB_get_bstr(iter->Name), *names)) {
10893 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10894 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10895 func_desc->funcdesc.invkind != iter->funcdesc.invkind)
10896 continue;
10897 return TYPE_E_AMBIGUOUSNAME;
10901 func_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *names);
10903 for (i = 1; i < numNames; ++i) {
10904 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1;
10905 par_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *(names + i));
10908 return S_OK;
10911 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
10912 UINT index, LPOLESTR name)
10914 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10916 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(name));
10918 if(!name)
10919 return E_INVALIDARG;
10921 if(index >= This->typeattr.cVars)
10922 return TYPE_E_ELEMENTNOTFOUND;
10924 This->vardescs[index].Name = TLB_append_str(&This->pTypeLib->name_list, name);
10925 return S_OK;
10928 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
10929 TYPEDESC *tdescAlias)
10931 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10932 HRESULT hr;
10934 TRACE("%p %p\n", This, tdescAlias);
10936 if(!tdescAlias)
10937 return E_INVALIDARG;
10939 if(This->typeattr.typekind != TKIND_ALIAS)
10940 return TYPE_E_BADMODULEKIND;
10942 hr = TLB_size_instance(This, This->pTypeLib->syskind, tdescAlias, &This->typeattr.cbSizeInstance, &This->typeattr.cbAlignment);
10943 if(FAILED(hr))
10944 return hr;
10946 heap_free(This->tdescAlias);
10947 This->tdescAlias = heap_alloc(TLB_SizeTypeDesc(tdescAlias, TRUE));
10948 TLB_CopyTypeDesc(NULL, tdescAlias, This->tdescAlias);
10950 return S_OK;
10953 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
10954 UINT index, LPOLESTR dllName, LPOLESTR procName)
10956 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10957 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
10958 return E_NOTIMPL;
10961 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
10962 UINT index, LPOLESTR docString)
10964 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10965 TLBFuncDesc *func_desc = &This->funcdescs[index];
10967 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10969 if(!docString)
10970 return E_INVALIDARG;
10972 if(index >= This->typeattr.cFuncs)
10973 return TYPE_E_ELEMENTNOTFOUND;
10975 func_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10977 return S_OK;
10980 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
10981 UINT index, LPOLESTR docString)
10983 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10984 TLBVarDesc *var_desc = &This->vardescs[index];
10986 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10988 if(!docString)
10989 return E_INVALIDARG;
10991 if(index >= This->typeattr.cVars)
10992 return TYPE_E_ELEMENTNOTFOUND;
10994 var_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10996 return S_OK;
10999 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
11000 UINT index, DWORD helpContext)
11002 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11003 TLBFuncDesc *func_desc = &This->funcdescs[index];
11005 TRACE("%p %u %d\n", This, index, helpContext);
11007 if(index >= This->typeattr.cFuncs)
11008 return TYPE_E_ELEMENTNOTFOUND;
11010 func_desc->helpcontext = helpContext;
11012 return S_OK;
11015 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
11016 UINT index, DWORD helpContext)
11018 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11019 TLBVarDesc *var_desc = &This->vardescs[index];
11021 TRACE("%p %u %d\n", This, index, helpContext);
11023 if(index >= This->typeattr.cVars)
11024 return TYPE_E_ELEMENTNOTFOUND;
11026 var_desc->HelpContext = helpContext;
11028 return S_OK;
11031 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
11032 UINT index, BSTR bstrMops)
11034 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11035 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
11036 return E_NOTIMPL;
11039 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
11040 IDLDESC *idlDesc)
11042 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11044 TRACE("%p %p\n", This, idlDesc);
11046 if (!idlDesc)
11047 return E_INVALIDARG;
11049 This->typeattr.idldescType.dwReserved = idlDesc->dwReserved;
11050 This->typeattr.idldescType.wIDLFlags = idlDesc->wIDLFlags;
11052 return S_OK;
11055 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
11057 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11058 ITypeInfo *tinfo;
11059 TLBFuncDesc *func_desc;
11060 UINT user_vft = 0, i, depth = 0;
11061 HRESULT hres = S_OK;
11063 TRACE("%p\n", This);
11065 This->needs_layout = FALSE;
11067 hres = ICreateTypeInfo2_QueryInterface(iface, &IID_ITypeInfo, (LPVOID*)&tinfo);
11068 if (FAILED(hres))
11069 return hres;
11071 if (This->typeattr.typekind == TKIND_INTERFACE) {
11072 ITypeInfo *inh;
11073 TYPEATTR *attr;
11074 HREFTYPE inh_href;
11076 hres = ITypeInfo_GetRefTypeOfImplType(tinfo, 0, &inh_href);
11078 if (SUCCEEDED(hres)) {
11079 hres = ITypeInfo_GetRefTypeInfo(tinfo, inh_href, &inh);
11081 if (SUCCEEDED(hres)) {
11082 hres = ITypeInfo_GetTypeAttr(inh, &attr);
11083 if (FAILED(hres)) {
11084 ITypeInfo_Release(inh);
11085 ITypeInfo_Release(tinfo);
11086 return hres;
11088 This->typeattr.cbSizeVft = attr->cbSizeVft;
11089 ITypeInfo_ReleaseTypeAttr(inh, attr);
11092 ++depth;
11093 hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href);
11094 if(SUCCEEDED(hres)){
11095 ITypeInfo *next;
11096 hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next);
11097 if(SUCCEEDED(hres)){
11098 ITypeInfo_Release(inh);
11099 inh = next;
11102 }while(SUCCEEDED(hres));
11103 hres = S_OK;
11105 ITypeInfo_Release(inh);
11106 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
11107 This->typeattr.cbSizeVft = 0;
11108 hres = S_OK;
11109 } else {
11110 ITypeInfo_Release(tinfo);
11111 return hres;
11113 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
11114 This->typeattr.cbSizeVft = 0;
11115 hres = S_OK;
11116 } else {
11117 ITypeInfo_Release(tinfo);
11118 return hres;
11120 } else if (This->typeattr.typekind == TKIND_DISPATCH)
11121 This->typeattr.cbSizeVft = 7 * This->pTypeLib->ptr_size;
11122 else
11123 This->typeattr.cbSizeVft = 0;
11125 func_desc = This->funcdescs;
11126 i = 0;
11127 while (i < This->typeattr.cFuncs) {
11128 if (!(func_desc->funcdesc.oVft & 0x1))
11129 func_desc->funcdesc.oVft = This->typeattr.cbSizeVft;
11131 if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft)
11132 user_vft = func_desc->funcdesc.oVft & 0xFFFC;
11134 This->typeattr.cbSizeVft += This->pTypeLib->ptr_size;
11136 if (func_desc->funcdesc.memid == MEMBERID_NIL) {
11137 TLBFuncDesc *iter;
11138 UINT j = 0;
11139 BOOL reset = FALSE;
11141 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i;
11143 iter = This->funcdescs;
11144 while (j < This->typeattr.cFuncs) {
11145 if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) {
11146 if (!reset) {
11147 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->typeattr.cFuncs;
11148 reset = TRUE;
11149 } else
11150 ++func_desc->funcdesc.memid;
11151 iter = This->funcdescs;
11152 j = 0;
11153 } else {
11154 ++iter;
11155 ++j;
11160 ++func_desc;
11161 ++i;
11164 if (user_vft > This->typeattr.cbSizeVft)
11165 This->typeattr.cbSizeVft = user_vft + This->pTypeLib->ptr_size;
11167 for(i = 0; i < This->typeattr.cVars; ++i){
11168 TLBVarDesc *var_desc = &This->vardescs[i];
11169 if(var_desc->vardesc.memid == MEMBERID_NIL){
11170 UINT j = 0;
11171 BOOL reset = FALSE;
11172 TLBVarDesc *iter;
11174 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + i;
11176 iter = This->vardescs;
11177 while (j < This->typeattr.cVars) {
11178 if (iter != var_desc && iter->vardesc.memid == var_desc->vardesc.memid) {
11179 if (!reset) {
11180 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + This->typeattr.cVars;
11181 reset = TRUE;
11182 } else
11183 ++var_desc->vardesc.memid;
11184 iter = This->vardescs;
11185 j = 0;
11186 } else {
11187 ++iter;
11188 ++j;
11194 ITypeInfo_Release(tinfo);
11195 return hres;
11198 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
11199 UINT index)
11201 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11202 FIXME("%p %u - stub\n", This, index);
11203 return E_NOTIMPL;
11206 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
11207 MEMBERID memid, INVOKEKIND invKind)
11209 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11210 FIXME("%p %x %d - stub\n", This, memid, invKind);
11211 return E_NOTIMPL;
11214 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
11215 UINT index)
11217 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11218 FIXME("%p %u - stub\n", This, index);
11219 return E_NOTIMPL;
11222 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
11223 MEMBERID memid)
11225 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11226 FIXME("%p %x - stub\n", This, memid);
11227 return E_NOTIMPL;
11230 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
11231 UINT index)
11233 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11234 FIXME("%p %u - stub\n", This, index);
11235 return E_NOTIMPL;
11238 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
11239 REFGUID guid, VARIANT *varVal)
11241 TLBGuid *tlbguid;
11243 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11245 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
11247 if (!guid || !varVal)
11248 return E_INVALIDARG;
11250 tlbguid = TLB_append_guid(&This->pTypeLib->guid_list, guid, -1);
11252 return TLB_set_custdata(This->pcustdata_list, tlbguid, varVal);
11255 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
11256 UINT index, REFGUID guid, VARIANT *varVal)
11258 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11259 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11260 return E_NOTIMPL;
11263 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
11264 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
11266 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11267 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
11268 return E_NOTIMPL;
11271 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
11272 UINT index, REFGUID guid, VARIANT *varVal)
11274 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11275 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11276 return E_NOTIMPL;
11279 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
11280 UINT index, REFGUID guid, VARIANT *varVal)
11282 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11283 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11284 return E_NOTIMPL;
11287 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
11288 ULONG helpStringContext)
11290 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11292 TRACE("%p %u\n", This, helpStringContext);
11294 This->dwHelpStringContext = helpStringContext;
11296 return S_OK;
11299 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
11300 UINT index, ULONG helpStringContext)
11302 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11303 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11304 return E_NOTIMPL;
11307 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
11308 UINT index, ULONG helpStringContext)
11310 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11311 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11312 return E_NOTIMPL;
11315 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
11317 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11318 FIXME("%p - stub\n", This);
11319 return E_NOTIMPL;
11322 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
11323 LPOLESTR name)
11325 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11327 TRACE("%p %s\n", This, wine_dbgstr_w(name));
11329 if (!name)
11330 return E_INVALIDARG;
11332 This->Name = TLB_append_str(&This->pTypeLib->name_list, name);
11334 return S_OK;
11337 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
11338 ICreateTypeInfo2_fnQueryInterface,
11339 ICreateTypeInfo2_fnAddRef,
11340 ICreateTypeInfo2_fnRelease,
11341 ICreateTypeInfo2_fnSetGuid,
11342 ICreateTypeInfo2_fnSetTypeFlags,
11343 ICreateTypeInfo2_fnSetDocString,
11344 ICreateTypeInfo2_fnSetHelpContext,
11345 ICreateTypeInfo2_fnSetVersion,
11346 ICreateTypeInfo2_fnAddRefTypeInfo,
11347 ICreateTypeInfo2_fnAddFuncDesc,
11348 ICreateTypeInfo2_fnAddImplType,
11349 ICreateTypeInfo2_fnSetImplTypeFlags,
11350 ICreateTypeInfo2_fnSetAlignment,
11351 ICreateTypeInfo2_fnSetSchema,
11352 ICreateTypeInfo2_fnAddVarDesc,
11353 ICreateTypeInfo2_fnSetFuncAndParamNames,
11354 ICreateTypeInfo2_fnSetVarName,
11355 ICreateTypeInfo2_fnSetTypeDescAlias,
11356 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
11357 ICreateTypeInfo2_fnSetFuncDocString,
11358 ICreateTypeInfo2_fnSetVarDocString,
11359 ICreateTypeInfo2_fnSetFuncHelpContext,
11360 ICreateTypeInfo2_fnSetVarHelpContext,
11361 ICreateTypeInfo2_fnSetMops,
11362 ICreateTypeInfo2_fnSetTypeIdldesc,
11363 ICreateTypeInfo2_fnLayOut,
11364 ICreateTypeInfo2_fnDeleteFuncDesc,
11365 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
11366 ICreateTypeInfo2_fnDeleteVarDesc,
11367 ICreateTypeInfo2_fnDeleteVarDescByMemId,
11368 ICreateTypeInfo2_fnDeleteImplType,
11369 ICreateTypeInfo2_fnSetCustData,
11370 ICreateTypeInfo2_fnSetFuncCustData,
11371 ICreateTypeInfo2_fnSetParamCustData,
11372 ICreateTypeInfo2_fnSetVarCustData,
11373 ICreateTypeInfo2_fnSetImplTypeCustData,
11374 ICreateTypeInfo2_fnSetHelpStringContext,
11375 ICreateTypeInfo2_fnSetFuncHelpStringContext,
11376 ICreateTypeInfo2_fnSetVarHelpStringContext,
11377 ICreateTypeInfo2_fnInvalidate,
11378 ICreateTypeInfo2_fnSetName
11381 /******************************************************************************
11382 * ClearCustData (OLEAUT32.171)
11384 * Clear a custom data type's data.
11386 * PARAMS
11387 * lpCust [I] The custom data type instance
11389 * RETURNS
11390 * Nothing.
11392 void WINAPI ClearCustData(CUSTDATA *lpCust)
11394 if (lpCust && lpCust->cCustData)
11396 if (lpCust->prgCustData)
11398 DWORD i;
11400 for (i = 0; i < lpCust->cCustData; i++)
11401 VariantClear(&lpCust->prgCustData[i].varValue);
11403 CoTaskMemFree(lpCust->prgCustData);
11404 lpCust->prgCustData = NULL;
11406 lpCust->cCustData = 0;