reg/tests: Test case sensitivity when creating and deleting registry keys.
[wine.git] / dlls / oleaut32 / typelib.c
blobb88e6639c8e7b8fdfa570e8d1fa7ffc9f3bed9a3
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;
4732 TLBString *tlbstr, *tlbstr_next;
4733 TLBGuid *tlbguid, *tlbguid_next;
4734 void *cursor2;
4735 int i;
4737 /* remove cache entry */
4738 if(This->path)
4740 TRACE("removing from cache list\n");
4741 EnterCriticalSection(&cache_section);
4742 if(This->entry.next)
4743 list_remove(&This->entry);
4744 LeaveCriticalSection(&cache_section);
4745 heap_free(This->path);
4747 TRACE(" destroying ITypeLib(%p)\n",This);
4749 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->string_list, TLBString, entry) {
4750 list_remove(&tlbstr->entry);
4751 SysFreeString(tlbstr->str);
4752 heap_free(tlbstr);
4755 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->name_list, TLBString, entry) {
4756 list_remove(&tlbstr->entry);
4757 SysFreeString(tlbstr->str);
4758 heap_free(tlbstr);
4761 LIST_FOR_EACH_ENTRY_SAFE(tlbguid, tlbguid_next, &This->guid_list, TLBGuid, entry) {
4762 list_remove(&tlbguid->entry);
4763 heap_free(tlbguid);
4766 TLB_FreeCustData(&This->custdata_list);
4768 for (i = 0; i < This->ctTypeDesc; i++)
4769 if (This->pTypeDesc[i].vt == VT_CARRAY)
4770 heap_free(This->pTypeDesc[i].u.lpadesc);
4772 heap_free(This->pTypeDesc);
4774 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4776 if (pImpLib->pImpTypeLib)
4777 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4778 SysFreeString(pImpLib->name);
4780 list_remove(&pImpLib->entry);
4781 heap_free(pImpLib);
4784 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4786 list_remove(&ref_type->entry);
4787 heap_free(ref_type);
4790 for (i = 0; i < This->TypeInfoCount; ++i){
4791 heap_free(This->typeinfos[i]->tdescAlias);
4792 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4794 heap_free(This->typeinfos);
4795 heap_free(This);
4796 return 0;
4799 return ref;
4802 /* ITypeLib::GetTypeInfoCount
4804 * Returns the number of type descriptions in the type library
4806 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4808 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4809 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4810 return This->TypeInfoCount;
4813 /* ITypeLib::GetTypeInfo
4815 * retrieves the specified type description in the library.
4817 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4818 ITypeLib2 *iface,
4819 UINT index,
4820 ITypeInfo **ppTInfo)
4822 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4824 TRACE("%p %u %p\n", This, index, ppTInfo);
4826 if(!ppTInfo)
4827 return E_INVALIDARG;
4829 if(index >= This->TypeInfoCount)
4830 return TYPE_E_ELEMENTNOTFOUND;
4832 *ppTInfo = (ITypeInfo *)&This->typeinfos[index]->ITypeInfo2_iface;
4833 ITypeInfo_AddRef(*ppTInfo);
4835 return S_OK;
4839 /* ITypeLibs::GetTypeInfoType
4841 * Retrieves the type of a type description.
4843 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4844 ITypeLib2 *iface,
4845 UINT index,
4846 TYPEKIND *pTKind)
4848 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4850 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4852 if(!pTKind)
4853 return E_INVALIDARG;
4855 if(index >= This->TypeInfoCount)
4856 return TYPE_E_ELEMENTNOTFOUND;
4858 *pTKind = This->typeinfos[index]->typeattr.typekind;
4860 return S_OK;
4863 /* ITypeLib::GetTypeInfoOfGuid
4865 * Retrieves the type description that corresponds to the specified GUID.
4868 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4869 ITypeLib2 *iface,
4870 REFGUID guid,
4871 ITypeInfo **ppTInfo)
4873 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4874 int i;
4876 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4878 for(i = 0; i < This->TypeInfoCount; ++i){
4879 if(IsEqualIID(TLB_get_guid_null(This->typeinfos[i]->guid), guid)){
4880 *ppTInfo = (ITypeInfo *)&This->typeinfos[i]->ITypeInfo2_iface;
4881 ITypeInfo_AddRef(*ppTInfo);
4882 return S_OK;
4886 return TYPE_E_ELEMENTNOTFOUND;
4889 /* ITypeLib::GetLibAttr
4891 * Retrieves the structure that contains the library's attributes.
4894 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4895 ITypeLib2 *iface,
4896 LPTLIBATTR *attr)
4898 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4900 TRACE("(%p, %p)\n", This, attr);
4902 if (!attr) return E_INVALIDARG;
4904 *attr = heap_alloc(sizeof(**attr));
4905 if (!*attr) return E_OUTOFMEMORY;
4907 (*attr)->guid = *TLB_get_guid_null(This->guid);
4908 (*attr)->lcid = This->set_lcid;
4909 (*attr)->syskind = This->syskind;
4910 (*attr)->wMajorVerNum = This->ver_major;
4911 (*attr)->wMinorVerNum = This->ver_minor;
4912 (*attr)->wLibFlags = This->libflags;
4914 return S_OK;
4917 /* ITypeLib::GetTypeComp
4919 * Enables a client compiler to bind to a library's types, variables,
4920 * constants, and global functions.
4923 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4924 ITypeLib2 *iface,
4925 ITypeComp **ppTComp)
4927 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4929 TRACE("(%p)->(%p)\n",This,ppTComp);
4930 *ppTComp = &This->ITypeComp_iface;
4931 ITypeComp_AddRef(*ppTComp);
4933 return S_OK;
4936 /* ITypeLib::GetDocumentation
4938 * Retrieves the library's documentation string, the complete Help file name
4939 * and path, and the context identifier for the library Help topic in the Help
4940 * file.
4942 * On a successful return all non-null BSTR pointers will have been set,
4943 * possibly to NULL.
4945 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4946 ITypeLib2 *iface,
4947 INT index,
4948 BSTR *pBstrName,
4949 BSTR *pBstrDocString,
4950 DWORD *pdwHelpContext,
4951 BSTR *pBstrHelpFile)
4953 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4954 HRESULT result = E_INVALIDARG;
4955 ITypeInfo *pTInfo;
4957 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4958 This, index,
4959 pBstrName, pBstrDocString,
4960 pdwHelpContext, pBstrHelpFile);
4962 if(index<0)
4964 /* documentation for the typelib */
4965 if(pBstrName)
4967 if (This->Name)
4969 if(!(*pBstrName = SysAllocString(TLB_get_bstr(This->Name))))
4970 goto memerr1;
4972 else
4973 *pBstrName = NULL;
4975 if(pBstrDocString)
4977 if (This->DocString)
4979 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->DocString))))
4980 goto memerr2;
4982 else
4983 *pBstrDocString = NULL;
4985 if(pdwHelpContext)
4987 *pdwHelpContext = This->dwHelpContext;
4989 if(pBstrHelpFile)
4991 if (This->HelpFile)
4993 if(!(*pBstrHelpFile = SysAllocString(TLB_get_bstr(This->HelpFile))))
4994 goto memerr3;
4996 else
4997 *pBstrHelpFile = NULL;
5000 result = S_OK;
5002 else
5004 /* for a typeinfo */
5005 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
5007 if(SUCCEEDED(result))
5009 result = ITypeInfo_GetDocumentation(pTInfo,
5010 MEMBERID_NIL,
5011 pBstrName,
5012 pBstrDocString,
5013 pdwHelpContext, pBstrHelpFile);
5015 ITypeInfo_Release(pTInfo);
5018 return result;
5019 memerr3:
5020 if (pBstrDocString) SysFreeString (*pBstrDocString);
5021 memerr2:
5022 if (pBstrName) SysFreeString (*pBstrName);
5023 memerr1:
5024 return STG_E_INSUFFICIENTMEMORY;
5027 /* ITypeLib::IsName
5029 * Indicates whether a passed-in string contains the name of a type or member
5030 * described in the library.
5033 static HRESULT WINAPI ITypeLib2_fnIsName(
5034 ITypeLib2 *iface,
5035 LPOLESTR szNameBuf,
5036 ULONG lHashVal,
5037 BOOL *pfName)
5039 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5040 int tic;
5041 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
5043 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
5044 pfName);
5046 *pfName=TRUE;
5047 for(tic = 0; tic < This->TypeInfoCount; ++tic){
5048 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5049 if(!TLB_str_memcmp(szNameBuf, pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5050 for(fdc = 0; fdc < pTInfo->typeattr.cFuncs; ++fdc) {
5051 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
5052 int pc;
5053 if(!TLB_str_memcmp(szNameBuf, pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5054 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++){
5055 if(!TLB_str_memcmp(szNameBuf, pFInfo->pParamDesc[pc].Name, nNameBufLen))
5056 goto ITypeLib2_fnIsName_exit;
5059 for(vrc = 0; vrc < pTInfo->typeattr.cVars; ++vrc){
5060 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
5061 if(!TLB_str_memcmp(szNameBuf, pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5065 *pfName=FALSE;
5067 ITypeLib2_fnIsName_exit:
5068 TRACE("(%p)slow! search for %s: %sfound!\n", This,
5069 debugstr_w(szNameBuf), *pfName ? "" : "NOT ");
5071 return S_OK;
5074 /* ITypeLib::FindName
5076 * Finds occurrences of a type description in a type library. This may be used
5077 * to quickly verify that a name exists in a type library.
5080 static HRESULT WINAPI ITypeLib2_fnFindName(
5081 ITypeLib2 *iface,
5082 LPOLESTR name,
5083 ULONG hash,
5084 ITypeInfo **ppTInfo,
5085 MEMBERID *memid,
5086 UINT16 *found)
5088 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5089 int tic;
5090 UINT count = 0;
5091 UINT len;
5093 TRACE("(%p)->(%s %u %p %p %p)\n", This, debugstr_w(name), hash, ppTInfo, memid, found);
5095 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
5096 return E_INVALIDARG;
5098 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
5099 for(tic = 0; count < *found && tic < This->TypeInfoCount; ++tic) {
5100 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5101 TLBVarDesc *var;
5102 UINT fdc;
5104 if(!TLB_str_memcmp(name, pTInfo->Name, len)) {
5105 memid[count] = MEMBERID_NIL;
5106 goto ITypeLib2_fnFindName_exit;
5109 for(fdc = 0; fdc < pTInfo->typeattr.cFuncs; ++fdc) {
5110 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
5112 if(!TLB_str_memcmp(name, func->Name, len)) {
5113 memid[count] = func->funcdesc.memid;
5114 goto ITypeLib2_fnFindName_exit;
5118 var = TLB_get_vardesc_by_name(pTInfo->vardescs, pTInfo->typeattr.cVars, name);
5119 if (var) {
5120 memid[count] = var->vardesc.memid;
5121 goto ITypeLib2_fnFindName_exit;
5124 continue;
5125 ITypeLib2_fnFindName_exit:
5126 ITypeInfo2_AddRef(&pTInfo->ITypeInfo2_iface);
5127 ppTInfo[count] = (ITypeInfo *)&pTInfo->ITypeInfo2_iface;
5128 count++;
5130 TRACE("found %d typeinfos\n", count);
5132 *found = count;
5134 return S_OK;
5137 /* ITypeLib::ReleaseTLibAttr
5139 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5142 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
5143 ITypeLib2 *iface,
5144 TLIBATTR *pTLibAttr)
5146 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5147 TRACE("(%p)->(%p)\n", This, pTLibAttr);
5148 heap_free(pTLibAttr);
5151 /* ITypeLib2::GetCustData
5153 * gets the custom data
5155 static HRESULT WINAPI ITypeLib2_fnGetCustData(
5156 ITypeLib2 * iface,
5157 REFGUID guid,
5158 VARIANT *pVarVal)
5160 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5161 TLBCustData *pCData;
5163 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
5165 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
5166 if(!pCData)
5167 return TYPE_E_ELEMENTNOTFOUND;
5169 VariantInit(pVarVal);
5170 VariantCopy(pVarVal, &pCData->data);
5172 return S_OK;
5175 /* ITypeLib2::GetLibStatistics
5177 * Returns statistics about a type library that are required for efficient
5178 * sizing of hash tables.
5181 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
5182 ITypeLib2 * iface,
5183 ULONG *pcUniqueNames,
5184 ULONG *pcchUniqueNames)
5186 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5188 FIXME("(%p): stub!\n", This);
5190 if(pcUniqueNames) *pcUniqueNames=1;
5191 if(pcchUniqueNames) *pcchUniqueNames=1;
5192 return S_OK;
5195 /* ITypeLib2::GetDocumentation2
5197 * Retrieves the library's documentation string, the complete Help file name
5198 * and path, the localization context to use, and the context ID for the
5199 * library Help topic in the Help file.
5202 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
5203 ITypeLib2 * iface,
5204 INT index,
5205 LCID lcid,
5206 BSTR *pbstrHelpString,
5207 DWORD *pdwHelpStringContext,
5208 BSTR *pbstrHelpStringDll)
5210 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5211 HRESULT result;
5212 ITypeInfo *pTInfo;
5214 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
5216 /* the help string should be obtained from the helpstringdll,
5217 * using the _DLLGetDocumentation function, based on the supplied
5218 * lcid. Nice to do sometime...
5220 if(index<0)
5222 /* documentation for the typelib */
5223 if(pbstrHelpString)
5224 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->DocString));
5225 if(pdwHelpStringContext)
5226 *pdwHelpStringContext=This->dwHelpContext;
5227 if(pbstrHelpStringDll)
5228 *pbstrHelpStringDll=SysAllocString(TLB_get_bstr(This->HelpStringDll));
5230 result = S_OK;
5232 else
5234 /* for a typeinfo */
5235 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
5237 if(SUCCEEDED(result))
5239 ITypeInfo2 * pTInfo2;
5240 result = ITypeInfo_QueryInterface(pTInfo,
5241 &IID_ITypeInfo2,
5242 (LPVOID*) &pTInfo2);
5244 if(SUCCEEDED(result))
5246 result = ITypeInfo2_GetDocumentation2(pTInfo2,
5247 MEMBERID_NIL,
5248 lcid,
5249 pbstrHelpString,
5250 pdwHelpStringContext,
5251 pbstrHelpStringDll);
5253 ITypeInfo2_Release(pTInfo2);
5256 ITypeInfo_Release(pTInfo);
5259 return result;
5262 static HRESULT TLB_copy_all_custdata(struct list *custdata_list, CUSTDATA *pCustData)
5264 TLBCustData *pCData;
5265 unsigned int ct;
5266 CUSTDATAITEM *cdi;
5268 ct = list_count(custdata_list);
5270 pCustData->prgCustData = CoTaskMemAlloc(ct * sizeof(CUSTDATAITEM));
5271 if(!pCustData->prgCustData)
5272 return E_OUTOFMEMORY;
5274 pCustData->cCustData = ct;
5276 cdi = pCustData->prgCustData;
5277 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
5278 cdi->guid = *TLB_get_guid_null(pCData->guid);
5279 VariantCopy(&cdi->varValue, &pCData->data);
5280 ++cdi;
5283 return S_OK;
5287 /* ITypeLib2::GetAllCustData
5289 * Gets all custom data items for the library.
5292 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
5293 ITypeLib2 * iface,
5294 CUSTDATA *pCustData)
5296 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5297 TRACE("(%p)->(%p)\n", This, pCustData);
5298 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
5301 static const ITypeLib2Vtbl tlbvt = {
5302 ITypeLib2_fnQueryInterface,
5303 ITypeLib2_fnAddRef,
5304 ITypeLib2_fnRelease,
5305 ITypeLib2_fnGetTypeInfoCount,
5306 ITypeLib2_fnGetTypeInfo,
5307 ITypeLib2_fnGetTypeInfoType,
5308 ITypeLib2_fnGetTypeInfoOfGuid,
5309 ITypeLib2_fnGetLibAttr,
5310 ITypeLib2_fnGetTypeComp,
5311 ITypeLib2_fnGetDocumentation,
5312 ITypeLib2_fnIsName,
5313 ITypeLib2_fnFindName,
5314 ITypeLib2_fnReleaseTLibAttr,
5316 ITypeLib2_fnGetCustData,
5317 ITypeLib2_fnGetLibStatistics,
5318 ITypeLib2_fnGetDocumentation2,
5319 ITypeLib2_fnGetAllCustData
5323 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5325 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5327 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
5330 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
5332 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5334 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
5337 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
5339 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5341 return ITypeLib2_Release(&This->ITypeLib2_iface);
5344 static HRESULT WINAPI ITypeLibComp_fnBind(
5345 ITypeComp * iface,
5346 OLECHAR * szName,
5347 ULONG lHash,
5348 WORD wFlags,
5349 ITypeInfo ** ppTInfo,
5350 DESCKIND * pDescKind,
5351 BINDPTR * pBindPtr)
5353 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5354 BOOL typemismatch = FALSE;
5355 int i;
5357 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5359 *pDescKind = DESCKIND_NONE;
5360 pBindPtr->lptcomp = NULL;
5361 *ppTInfo = NULL;
5363 for(i = 0; i < This->TypeInfoCount; ++i){
5364 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5365 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo->Name)));
5367 /* FIXME: check wFlags here? */
5368 /* FIXME: we should use a hash table to look this info up using lHash
5369 * instead of an O(n) search */
5370 if ((pTypeInfo->typeattr.typekind == TKIND_ENUM) ||
5371 (pTypeInfo->typeattr.typekind == TKIND_MODULE))
5373 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name->str, szName))
5375 *pDescKind = DESCKIND_TYPECOMP;
5376 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
5377 ITypeComp_AddRef(pBindPtr->lptcomp);
5378 TRACE("module or enum: %s\n", debugstr_w(szName));
5379 return S_OK;
5383 if ((pTypeInfo->typeattr.typekind == TKIND_MODULE) ||
5384 (pTypeInfo->typeattr.typekind == TKIND_ENUM))
5386 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5387 HRESULT hr;
5389 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5390 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
5392 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
5393 return S_OK;
5395 else if (hr == TYPE_E_TYPEMISMATCH)
5396 typemismatch = TRUE;
5399 if ((pTypeInfo->typeattr.typekind == TKIND_COCLASS) &&
5400 (pTypeInfo->typeattr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
5402 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5403 HRESULT hr;
5404 ITypeInfo *subtypeinfo;
5405 BINDPTR subbindptr;
5406 DESCKIND subdesckind;
5408 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
5409 &subtypeinfo, &subdesckind, &subbindptr);
5410 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
5412 TYPEDESC tdesc_appobject;
5413 const VARDESC vardesc_appobject =
5415 -2, /* memid */
5416 NULL, /* lpstrSchema */
5418 0 /* oInst */
5421 /* ELEMDESC */
5423 /* TYPEDESC */
5425 &tdesc_appobject
5427 VT_PTR
5430 0, /* wVarFlags */
5431 VAR_STATIC /* varkind */
5434 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
5435 tdesc_appobject.vt = VT_USERDEFINED;
5437 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
5439 /* cleanup things filled in by Bind call so we can put our
5440 * application object data in there instead */
5441 switch (subdesckind)
5443 case DESCKIND_FUNCDESC:
5444 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
5445 break;
5446 case DESCKIND_VARDESC:
5447 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
5448 break;
5449 default:
5450 break;
5452 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
5454 if (pTypeInfo->hreftype == -1)
5455 FIXME("no hreftype for interface %p\n", pTypeInfo);
5457 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
5458 if (FAILED(hr))
5459 return hr;
5461 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5462 *ppTInfo = (ITypeInfo *)&pTypeInfo->ITypeInfo2_iface;
5463 ITypeInfo_AddRef(*ppTInfo);
5464 return S_OK;
5466 else if (hr == TYPE_E_TYPEMISMATCH)
5467 typemismatch = TRUE;
5471 if (typemismatch)
5473 TRACE("type mismatch %s\n", debugstr_w(szName));
5474 return TYPE_E_TYPEMISMATCH;
5476 else
5478 TRACE("name not found %s\n", debugstr_w(szName));
5479 return S_OK;
5483 static HRESULT WINAPI ITypeLibComp_fnBindType(
5484 ITypeComp * iface,
5485 OLECHAR * szName,
5486 ULONG lHash,
5487 ITypeInfo ** ppTInfo,
5488 ITypeComp ** ppTComp)
5490 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5491 ITypeInfoImpl *info;
5493 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5495 if(!szName || !ppTInfo || !ppTComp)
5496 return E_INVALIDARG;
5498 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, szName);
5499 if(!info){
5500 *ppTInfo = NULL;
5501 *ppTComp = NULL;
5502 return S_OK;
5505 *ppTInfo = (ITypeInfo *)&info->ITypeInfo2_iface;
5506 ITypeInfo_AddRef(*ppTInfo);
5507 *ppTComp = &info->ITypeComp_iface;
5508 ITypeComp_AddRef(*ppTComp);
5510 return S_OK;
5513 static const ITypeCompVtbl tlbtcvt =
5516 ITypeLibComp_fnQueryInterface,
5517 ITypeLibComp_fnAddRef,
5518 ITypeLibComp_fnRelease,
5520 ITypeLibComp_fnBind,
5521 ITypeLibComp_fnBindType
5524 /*================== ITypeInfo(2) Methods ===================================*/
5525 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5527 ITypeInfoImpl *pTypeInfoImpl;
5529 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5530 if (pTypeInfoImpl)
5532 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5533 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5534 pTypeInfoImpl->ICreateTypeInfo2_iface.lpVtbl = &CreateTypeInfo2Vtbl;
5535 pTypeInfoImpl->ref = 0;
5536 pTypeInfoImpl->hreftype = -1;
5537 pTypeInfoImpl->typeattr.memidConstructor = MEMBERID_NIL;
5538 pTypeInfoImpl->typeattr.memidDestructor = MEMBERID_NIL;
5539 pTypeInfoImpl->pcustdata_list = &pTypeInfoImpl->custdata_list;
5540 list_init(pTypeInfoImpl->pcustdata_list);
5542 TRACE("(%p)\n", pTypeInfoImpl);
5543 return pTypeInfoImpl;
5546 /* ITypeInfo::QueryInterface
5548 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5549 ITypeInfo2 *iface,
5550 REFIID riid,
5551 VOID **ppvObject)
5553 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5555 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5557 *ppvObject=NULL;
5558 if(IsEqualIID(riid, &IID_IUnknown) ||
5559 IsEqualIID(riid,&IID_ITypeInfo)||
5560 IsEqualIID(riid,&IID_ITypeInfo2))
5561 *ppvObject = &This->ITypeInfo2_iface;
5562 else if(IsEqualIID(riid, &IID_ICreateTypeInfo) ||
5563 IsEqualIID(riid, &IID_ICreateTypeInfo2))
5564 *ppvObject = &This->ICreateTypeInfo2_iface;
5565 else if(IsEqualIID(riid, &IID_ITypeComp))
5566 *ppvObject = &This->ITypeComp_iface;
5568 if(*ppvObject){
5569 IUnknown_AddRef((IUnknown*)*ppvObject);
5570 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5571 return S_OK;
5573 TRACE("-- Interface: E_NOINTERFACE\n");
5574 return E_NOINTERFACE;
5577 /* ITypeInfo::AddRef
5579 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5581 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5582 ULONG ref = InterlockedIncrement(&This->ref);
5584 TRACE("(%p)->ref is %u\n",This, ref);
5586 if (ref == 1 /* incremented from 0 */)
5587 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5589 return ref;
5592 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5594 UINT i;
5596 TRACE("destroying ITypeInfo(%p)\n",This);
5598 for (i = 0; i < This->typeattr.cFuncs; ++i)
5600 int j;
5601 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5602 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5604 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5605 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5606 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5607 TLB_FreeCustData(&pFInfo->pParamDesc[j].custdata_list);
5609 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5610 heap_free(pFInfo->pParamDesc);
5611 TLB_FreeCustData(&pFInfo->custdata_list);
5613 heap_free(This->funcdescs);
5615 for(i = 0; i < This->typeattr.cVars; ++i)
5617 TLBVarDesc *pVInfo = &This->vardescs[i];
5618 if (pVInfo->vardesc_create) {
5619 TLB_FreeVarDesc(pVInfo->vardesc_create);
5620 } else if (pVInfo->vardesc.varkind == VAR_CONST) {
5621 VariantClear(pVInfo->vardesc.u.lpvarValue);
5622 heap_free(pVInfo->vardesc.u.lpvarValue);
5624 TLB_FreeCustData(&pVInfo->custdata_list);
5626 heap_free(This->vardescs);
5628 if(This->impltypes){
5629 for (i = 0; i < This->typeattr.cImplTypes; ++i){
5630 TLBImplType *pImpl = &This->impltypes[i];
5631 TLB_FreeCustData(&pImpl->custdata_list);
5633 heap_free(This->impltypes);
5636 TLB_FreeCustData(&This->custdata_list);
5638 heap_free(This);
5641 /* ITypeInfo::Release
5643 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5645 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5646 ULONG ref = InterlockedDecrement(&This->ref);
5648 TRACE("(%p)->(%u)\n",This, ref);
5650 if (!ref)
5652 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5653 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5654 if (not_attached_to_typelib)
5655 heap_free(This);
5656 /* otherwise This will be freed when typelib is freed */
5659 return ref;
5662 /* ITypeInfo::GetTypeAttr
5664 * Retrieves a TYPEATTR structure that contains the attributes of the type
5665 * description.
5668 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5669 LPTYPEATTR *ppTypeAttr)
5671 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5672 SIZE_T size;
5674 TRACE("(%p)\n",This);
5676 size = sizeof(**ppTypeAttr);
5677 if (This->typeattr.typekind == TKIND_ALIAS && This->tdescAlias)
5678 size += TLB_SizeTypeDesc(This->tdescAlias, FALSE);
5680 *ppTypeAttr = heap_alloc(size);
5681 if (!*ppTypeAttr)
5682 return E_OUTOFMEMORY;
5684 **ppTypeAttr = This->typeattr;
5685 (*ppTypeAttr)->guid = *TLB_get_guid_null(This->guid);
5687 if (This->tdescAlias)
5688 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias, This->tdescAlias, *ppTypeAttr + 1);
5690 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5691 /* This should include all the inherited funcs */
5692 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / This->pTypeLib->ptr_size;
5693 /* This is always the size of IDispatch's vtbl */
5694 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5695 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5697 return S_OK;
5700 /* ITypeInfo::GetTypeComp
5702 * Retrieves the ITypeComp interface for the type description, which enables a
5703 * client compiler to bind to the type description's members.
5706 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5707 ITypeComp * *ppTComp)
5709 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5711 TRACE("(%p)->(%p)\n", This, ppTComp);
5713 *ppTComp = &This->ITypeComp_iface;
5714 ITypeComp_AddRef(*ppTComp);
5715 return S_OK;
5718 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5720 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5721 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5722 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5723 return size;
5726 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5728 *dest = *src;
5729 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5730 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5732 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5733 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5734 *buffer += sizeof(PARAMDESCEX);
5735 *pparamdescex_dest = *pparamdescex_src;
5736 pparamdescex_dest->cBytes = sizeof(PARAMDESCEX);
5737 VariantInit(&pparamdescex_dest->varDefaultValue);
5738 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5739 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5741 else
5742 dest->u.paramdesc.pparamdescex = NULL;
5743 return S_OK;
5746 static HRESULT TLB_SanitizeBSTR(BSTR str)
5748 UINT len = SysStringLen(str), i;
5749 for (i = 0; i < len; ++i)
5750 if (str[i] > 0x7f)
5751 str[i] = '?';
5752 return S_OK;
5755 static HRESULT TLB_SanitizeVariant(VARIANT *var)
5757 if (V_VT(var) == VT_INT)
5758 return VariantChangeType(var, var, 0, VT_I4);
5759 else if (V_VT(var) == VT_UINT)
5760 return VariantChangeType(var, var, 0, VT_UI4);
5761 else if (V_VT(var) == VT_BSTR)
5762 return TLB_SanitizeBSTR(V_BSTR(var));
5764 return S_OK;
5767 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5769 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5770 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5773 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5775 FUNCDESC *dest;
5776 char *buffer;
5777 SIZE_T size = sizeof(*src);
5778 SHORT i;
5779 HRESULT hr;
5781 size += sizeof(*src->lprgscode) * src->cScodes;
5782 size += TLB_SizeElemDesc(&src->elemdescFunc);
5783 for (i = 0; i < src->cParams; i++)
5785 size += sizeof(ELEMDESC);
5786 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5789 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5790 if (!dest) return E_OUTOFMEMORY;
5792 *dest = *src;
5793 if (dispinterface) /* overwrite funckind */
5794 dest->funckind = FUNC_DISPATCH;
5795 buffer = (char *)(dest + 1);
5797 dest->oVft = dest->oVft & 0xFFFC;
5799 if (dest->cScodes) {
5800 dest->lprgscode = (SCODE *)buffer;
5801 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5802 buffer += sizeof(*src->lprgscode) * src->cScodes;
5803 } else
5804 dest->lprgscode = NULL;
5806 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5807 if (FAILED(hr))
5809 SysFreeString((BSTR)dest);
5810 return hr;
5813 if (dest->cParams) {
5814 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5815 buffer += sizeof(ELEMDESC) * src->cParams;
5816 for (i = 0; i < src->cParams; i++)
5818 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5819 if (FAILED(hr))
5820 break;
5822 if (FAILED(hr))
5824 /* undo the above actions */
5825 for (i = i - 1; i >= 0; i--)
5826 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5827 TLB_FreeElemDesc(&dest->elemdescFunc);
5828 SysFreeString((BSTR)dest);
5829 return hr;
5831 } else
5832 dest->lprgelemdescParam = NULL;
5834 /* special treatment for dispinterfaces: this makes functions appear
5835 * to return their [retval] value when it is really returning an
5836 * HRESULT */
5837 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5839 if (dest->cParams &&
5840 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5842 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5843 if (elemdesc->tdesc.vt != VT_PTR)
5845 ERR("elemdesc should have started with VT_PTR instead of:\n");
5846 if (ERR_ON(ole))
5847 dump_ELEMDESC(elemdesc);
5848 return E_UNEXPECTED;
5851 /* copy last parameter to the return value. we are using a flat
5852 * buffer so there is no danger of leaking memory in
5853 * elemdescFunc */
5854 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5856 /* remove the last parameter */
5857 dest->cParams--;
5859 else
5860 /* otherwise this function is made to appear to have no return
5861 * value */
5862 dest->elemdescFunc.tdesc.vt = VT_VOID;
5866 *dest_ptr = dest;
5867 return S_OK;
5870 static void TLB_FreeVarDesc(VARDESC *var_desc)
5872 TLB_FreeElemDesc(&var_desc->elemdescVar);
5873 if (var_desc->varkind == VAR_CONST)
5874 VariantClear(var_desc->u.lpvarValue);
5875 SysFreeString((BSTR)var_desc);
5878 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5880 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5882 if (index >= This->typeattr.cFuncs)
5883 return TYPE_E_ELEMENTNOTFOUND;
5885 *ppFuncDesc = &This->funcdescs[index].funcdesc;
5886 return S_OK;
5889 /* internal function to make the inherited interfaces' methods appear
5890 * part of the interface */
5891 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5892 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5894 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5895 HRESULT hr;
5896 UINT implemented_funcs = 0;
5898 if (funcs)
5899 *funcs = 0;
5900 else
5901 *hrefoffset = DISPATCH_HREF_OFFSET;
5903 if(This->impltypes)
5905 ITypeInfo *pSubTypeInfo;
5906 UINT sub_funcs;
5908 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5909 if (FAILED(hr))
5910 return hr;
5912 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5913 index,
5914 ppFuncDesc,
5915 &sub_funcs, hrefoffset);
5916 implemented_funcs += sub_funcs;
5917 ITypeInfo_Release(pSubTypeInfo);
5918 if (SUCCEEDED(hr))
5919 return hr;
5920 *hrefoffset += DISPATCH_HREF_OFFSET;
5923 if (funcs)
5924 *funcs = implemented_funcs + This->typeattr.cFuncs;
5925 else
5926 *hrefoffset = 0;
5928 if (index < implemented_funcs)
5929 return E_INVALIDARG;
5930 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5931 ppFuncDesc);
5934 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5936 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5937 while (TRUE)
5939 switch (pTypeDesc->vt)
5941 case VT_USERDEFINED:
5942 pTypeDesc->u.hreftype += hrefoffset;
5943 return;
5944 case VT_PTR:
5945 case VT_SAFEARRAY:
5946 pTypeDesc = pTypeDesc->u.lptdesc;
5947 break;
5948 case VT_CARRAY:
5949 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5950 break;
5951 default:
5952 return;
5957 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5959 SHORT i;
5960 for (i = 0; i < pFuncDesc->cParams; i++)
5961 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5962 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5965 /* ITypeInfo::GetFuncDesc
5967 * Retrieves the FUNCDESC structure that contains information about a
5968 * specified function.
5971 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5972 LPFUNCDESC *ppFuncDesc)
5974 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5975 const FUNCDESC *internal_funcdesc;
5976 HRESULT hr;
5977 UINT hrefoffset = 0;
5979 TRACE("(%p) index %d\n", This, index);
5981 if (!ppFuncDesc)
5982 return E_INVALIDARG;
5984 if (This->needs_layout)
5985 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
5987 if (This->typeattr.typekind == TKIND_DISPATCH)
5988 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5989 &internal_funcdesc, NULL,
5990 &hrefoffset);
5991 else
5992 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5993 &internal_funcdesc);
5994 if (FAILED(hr))
5996 WARN("description for function %d not found\n", index);
5997 return hr;
6000 hr = TLB_AllocAndInitFuncDesc(
6001 internal_funcdesc,
6002 ppFuncDesc,
6003 This->typeattr.typekind == TKIND_DISPATCH);
6005 if ((This->typeattr.typekind == TKIND_DISPATCH) && hrefoffset)
6006 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
6008 TRACE("-- 0x%08x\n", hr);
6009 return hr;
6012 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
6014 VARDESC *dest;
6015 char *buffer;
6016 SIZE_T size = sizeof(*src);
6017 HRESULT hr;
6019 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
6020 if (src->varkind == VAR_CONST)
6021 size += sizeof(VARIANT);
6022 size += TLB_SizeElemDesc(&src->elemdescVar);
6024 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
6025 if (!dest) return E_OUTOFMEMORY;
6027 *dest = *src;
6028 buffer = (char *)(dest + 1);
6029 if (src->lpstrSchema)
6031 int len;
6032 dest->lpstrSchema = (LPOLESTR)buffer;
6033 len = strlenW(src->lpstrSchema);
6034 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
6035 buffer += (len + 1) * sizeof(WCHAR);
6038 if (src->varkind == VAR_CONST)
6040 HRESULT hr;
6042 dest->u.lpvarValue = (VARIANT *)buffer;
6043 *dest->u.lpvarValue = *src->u.lpvarValue;
6044 buffer += sizeof(VARIANT);
6045 VariantInit(dest->u.lpvarValue);
6046 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
6047 if (FAILED(hr))
6049 SysFreeString((BSTR)dest);
6050 return hr;
6053 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
6054 if (FAILED(hr))
6056 if (src->varkind == VAR_CONST)
6057 VariantClear(dest->u.lpvarValue);
6058 SysFreeString((BSTR)dest);
6059 return hr;
6061 *dest_ptr = dest;
6062 return S_OK;
6065 /* ITypeInfo::GetVarDesc
6067 * Retrieves a VARDESC structure that describes the specified variable.
6070 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
6071 LPVARDESC *ppVarDesc)
6073 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6074 const TLBVarDesc *pVDesc = &This->vardescs[index];
6076 TRACE("(%p) index %d\n", This, index);
6078 if(index >= This->typeattr.cVars)
6079 return TYPE_E_ELEMENTNOTFOUND;
6081 if (This->needs_layout)
6082 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6084 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
6087 /* ITypeInfo_GetNames
6089 * Retrieves the variable with the specified member ID (or the name of the
6090 * property or method and its parameters) that correspond to the specified
6091 * function ID.
6093 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
6094 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
6096 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6097 const TLBFuncDesc *pFDesc;
6098 const TLBVarDesc *pVDesc;
6099 int i;
6100 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
6102 if(!rgBstrNames)
6103 return E_INVALIDARG;
6105 *pcNames = 0;
6107 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->typeattr.cFuncs, memid);
6108 if(pFDesc)
6110 if(!cMaxNames || !pFDesc->Name)
6111 return S_OK;
6113 *rgBstrNames = SysAllocString(TLB_get_bstr(pFDesc->Name));
6114 ++(*pcNames);
6116 for(i = 0; i < pFDesc->funcdesc.cParams; ++i){
6117 if(*pcNames >= cMaxNames || !pFDesc->pParamDesc[i].Name)
6118 return S_OK;
6119 rgBstrNames[*pcNames] = SysAllocString(TLB_get_bstr(pFDesc->pParamDesc[i].Name));
6120 ++(*pcNames);
6122 return S_OK;
6125 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->typeattr.cVars, memid);
6126 if(pVDesc)
6128 *rgBstrNames=SysAllocString(TLB_get_bstr(pVDesc->Name));
6129 *pcNames=1;
6131 else
6133 if(This->impltypes &&
6134 (This->typeattr.typekind == TKIND_INTERFACE || This->typeattr.typekind == TKIND_DISPATCH)) {
6135 /* recursive search */
6136 ITypeInfo *pTInfo;
6137 HRESULT result;
6138 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6139 if(SUCCEEDED(result))
6141 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
6142 ITypeInfo_Release(pTInfo);
6143 return result;
6145 WARN("Could not search inherited interface!\n");
6147 else
6149 WARN("no names found\n");
6151 *pcNames=0;
6152 return TYPE_E_ELEMENTNOTFOUND;
6154 return S_OK;
6158 /* ITypeInfo::GetRefTypeOfImplType
6160 * If a type description describes a COM class, it retrieves the type
6161 * description of the implemented interface types. For an interface,
6162 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6163 * if any exist.
6166 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
6167 ITypeInfo2 *iface,
6168 UINT index,
6169 HREFTYPE *pRefType)
6171 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6172 HRESULT hr = S_OK;
6174 TRACE("(%p) index %d\n", This, index);
6175 if (TRACE_ON(ole)) dump_TypeInfo(This);
6177 if(index==(UINT)-1)
6179 /* only valid on dual interfaces;
6180 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6183 if (This->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
6185 *pRefType = -2;
6187 else
6189 hr = TYPE_E_ELEMENTNOTFOUND;
6192 else if(index == 0 && This->typeattr.typekind == TKIND_DISPATCH)
6194 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6195 *pRefType = This->pTypeLib->dispatch_href;
6197 else
6199 if(index >= This->typeattr.cImplTypes)
6200 hr = TYPE_E_ELEMENTNOTFOUND;
6201 else{
6202 *pRefType = This->impltypes[index].hRef;
6203 if (This->typeattr.typekind == TKIND_INTERFACE)
6204 *pRefType |= 0x2;
6208 if(TRACE_ON(ole))
6210 if(SUCCEEDED(hr))
6211 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
6212 else
6213 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
6216 return hr;
6219 /* ITypeInfo::GetImplTypeFlags
6221 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6222 * or base interface in a type description.
6224 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
6225 UINT index, INT *pImplTypeFlags)
6227 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6229 TRACE("(%p) index %d\n", This, index);
6231 if(!pImplTypeFlags)
6232 return E_INVALIDARG;
6234 if(This->typeattr.typekind == TKIND_DISPATCH && index == 0){
6235 *pImplTypeFlags = 0;
6236 return S_OK;
6239 if(index >= This->typeattr.cImplTypes)
6240 return TYPE_E_ELEMENTNOTFOUND;
6242 *pImplTypeFlags = This->impltypes[index].implflags;
6244 return S_OK;
6247 /* GetIDsOfNames
6248 * Maps between member names and member IDs, and parameter names and
6249 * parameter IDs.
6251 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
6252 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
6254 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6255 const TLBVarDesc *pVDesc;
6256 HRESULT ret=S_OK;
6257 UINT i, fdc;
6259 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
6260 cNames);
6262 /* init out parameters in case of failure */
6263 for (i = 0; i < cNames; i++)
6264 pMemId[i] = MEMBERID_NIL;
6266 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc) {
6267 int j;
6268 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
6269 if(!lstrcmpiW(*rgszNames, TLB_get_bstr(pFDesc->Name))) {
6270 if(cNames) *pMemId=pFDesc->funcdesc.memid;
6271 for(i=1; i < cNames; i++){
6272 for(j=0; j<pFDesc->funcdesc.cParams; j++)
6273 if(!lstrcmpiW(rgszNames[i],TLB_get_bstr(pFDesc->pParamDesc[j].Name)))
6274 break;
6275 if( j<pFDesc->funcdesc.cParams)
6276 pMemId[i]=j;
6277 else
6278 ret=DISP_E_UNKNOWNNAME;
6280 TRACE("-- 0x%08x\n", ret);
6281 return ret;
6284 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->typeattr.cVars, *rgszNames);
6285 if(pVDesc){
6286 if(cNames)
6287 *pMemId = pVDesc->vardesc.memid;
6288 return ret;
6290 /* not found, see if it can be found in an inherited interface */
6291 if(This->impltypes) {
6292 /* recursive search */
6293 ITypeInfo *pTInfo;
6294 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6295 if(SUCCEEDED(ret)){
6296 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
6297 ITypeInfo_Release(pTInfo);
6298 return ret;
6300 WARN("Could not search inherited interface!\n");
6301 } else
6302 WARN("no names found\n");
6303 return DISP_E_UNKNOWNNAME;
6307 #ifdef __i386__
6309 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6310 __ASM_GLOBAL_FUNC( call_method,
6311 "pushl %ebp\n\t"
6312 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6313 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6314 "movl %esp,%ebp\n\t"
6315 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6316 "pushl %esi\n\t"
6317 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6318 "pushl %edi\n\t"
6319 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6320 "movl 12(%ebp),%edx\n\t"
6321 "movl %esp,%edi\n\t"
6322 "shll $2,%edx\n\t"
6323 "jz 1f\n\t"
6324 "subl %edx,%edi\n\t"
6325 "andl $~15,%edi\n\t"
6326 "movl %edi,%esp\n\t"
6327 "movl 12(%ebp),%ecx\n\t"
6328 "movl 16(%ebp),%esi\n\t"
6329 "cld\n\t"
6330 "rep; movsl\n"
6331 "1:\tcall *8(%ebp)\n\t"
6332 "subl %esp,%edi\n\t"
6333 "movl 20(%ebp),%ecx\n\t"
6334 "movl %edi,(%ecx)\n\t"
6335 "leal -8(%ebp),%esp\n\t"
6336 "popl %edi\n\t"
6337 __ASM_CFI(".cfi_same_value %edi\n\t")
6338 "popl %esi\n\t"
6339 __ASM_CFI(".cfi_same_value %esi\n\t")
6340 "popl %ebp\n\t"
6341 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6342 __ASM_CFI(".cfi_same_value %ebp\n\t")
6343 "ret" )
6345 /* same function but returning floating point */
6346 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
6348 /* ITypeInfo::Invoke
6350 * Invokes a method, or accesses a property of an object, that implements the
6351 * interface described by the type description.
6353 DWORD
6354 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
6355 DWORD res;
6356 int stack_offset;
6358 if (TRACE_ON(ole)) {
6359 int i;
6360 TRACE("Calling %p(",func);
6361 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
6362 if (nrargs > 30) TRACE("...");
6363 TRACE(")\n");
6366 switch (callconv) {
6367 case CC_STDCALL:
6368 case CC_CDECL:
6369 res = call_method( func, nrargs, args, &stack_offset );
6370 break;
6371 default:
6372 FIXME("unsupported calling convention %d\n",callconv);
6373 res = -1;
6374 break;
6376 TRACE("returns %08x\n",res);
6377 return res;
6380 #elif defined(__x86_64__)
6382 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
6383 __ASM_GLOBAL_FUNC( call_method,
6384 "pushq %rbp\n\t"
6385 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6386 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6387 "movq %rsp,%rbp\n\t"
6388 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6389 "pushq %rsi\n\t"
6390 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6391 "pushq %rdi\n\t"
6392 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6393 "movq %rcx,%rax\n\t"
6394 "movq $4,%rcx\n\t"
6395 "cmp %rcx,%rdx\n\t"
6396 "cmovgq %rdx,%rcx\n\t"
6397 "leaq 0(,%rcx,8),%rdx\n\t"
6398 "subq %rdx,%rsp\n\t"
6399 "andq $~15,%rsp\n\t"
6400 "movq %rsp,%rdi\n\t"
6401 "movq %r8,%rsi\n\t"
6402 "rep; movsq\n\t"
6403 "movq 0(%rsp),%rcx\n\t"
6404 "movq 8(%rsp),%rdx\n\t"
6405 "movq 16(%rsp),%r8\n\t"
6406 "movq 24(%rsp),%r9\n\t"
6407 "movq 0(%rsp),%xmm0\n\t"
6408 "movq 8(%rsp),%xmm1\n\t"
6409 "movq 16(%rsp),%xmm2\n\t"
6410 "movq 24(%rsp),%xmm3\n\t"
6411 "callq *%rax\n\t"
6412 "leaq -16(%rbp),%rsp\n\t"
6413 "popq %rdi\n\t"
6414 __ASM_CFI(".cfi_same_value %rdi\n\t")
6415 "popq %rsi\n\t"
6416 __ASM_CFI(".cfi_same_value %rsi\n\t")
6417 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6418 "popq %rbp\n\t"
6419 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6420 __ASM_CFI(".cfi_same_value %rbp\n\t")
6421 "ret")
6423 /* same function but returning floating point */
6424 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
6426 #endif /* __x86_64__ */
6428 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6430 HRESULT hr = S_OK;
6431 ITypeInfo *tinfo2 = NULL;
6432 TYPEATTR *tattr = NULL;
6434 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6435 if (hr)
6437 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6438 "hr = 0x%08x\n",
6439 tdesc->u.hreftype, hr);
6440 return hr;
6442 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6443 if (hr)
6445 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
6446 ITypeInfo_Release(tinfo2);
6447 return hr;
6450 switch (tattr->typekind)
6452 case TKIND_ENUM:
6453 *vt |= VT_I4;
6454 break;
6456 case TKIND_ALIAS:
6457 tdesc = &tattr->tdescAlias;
6458 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
6459 break;
6461 case TKIND_INTERFACE:
6462 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
6463 *vt |= VT_DISPATCH;
6464 else
6465 *vt |= VT_UNKNOWN;
6466 break;
6468 case TKIND_DISPATCH:
6469 *vt |= VT_DISPATCH;
6470 break;
6472 case TKIND_COCLASS:
6473 *vt |= VT_DISPATCH;
6474 break;
6476 case TKIND_RECORD:
6477 FIXME("TKIND_RECORD unhandled.\n");
6478 hr = E_NOTIMPL;
6479 break;
6481 case TKIND_UNION:
6482 FIXME("TKIND_UNION unhandled.\n");
6483 hr = E_NOTIMPL;
6484 break;
6486 default:
6487 FIXME("TKIND %d unhandled.\n",tattr->typekind);
6488 hr = E_NOTIMPL;
6489 break;
6491 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6492 ITypeInfo_Release(tinfo2);
6493 return hr;
6496 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6498 HRESULT hr = S_OK;
6500 /* enforce only one level of pointer indirection */
6501 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
6503 tdesc = tdesc->u.lptdesc;
6505 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6506 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6507 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6508 if ((tdesc->vt == VT_USERDEFINED) ||
6509 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
6511 VARTYPE vt_userdefined = 0;
6512 const TYPEDESC *tdesc_userdefined = tdesc;
6513 if (tdesc->vt == VT_PTR)
6515 vt_userdefined = VT_BYREF;
6516 tdesc_userdefined = tdesc->u.lptdesc;
6518 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
6519 if ((hr == S_OK) &&
6520 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
6521 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
6523 *vt |= vt_userdefined;
6524 return S_OK;
6527 *vt = VT_BYREF;
6530 switch (tdesc->vt)
6532 case VT_HRESULT:
6533 *vt |= VT_ERROR;
6534 break;
6535 case VT_USERDEFINED:
6536 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
6537 break;
6538 case VT_VOID:
6539 case VT_CARRAY:
6540 case VT_PTR:
6541 case VT_LPSTR:
6542 case VT_LPWSTR:
6543 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
6544 hr = DISP_E_BADVARTYPE;
6545 break;
6546 case VT_SAFEARRAY:
6547 *vt |= VT_ARRAY;
6548 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
6549 break;
6550 case VT_INT:
6551 *vt |= VT_I4;
6552 break;
6553 case VT_UINT:
6554 *vt |= VT_UI4;
6555 break;
6556 default:
6557 *vt |= tdesc->vt;
6558 break;
6560 return hr;
6563 static HRESULT get_iface_guid(ITypeInfo *tinfo, const TYPEDESC *tdesc, GUID *guid)
6565 ITypeInfo *tinfo2;
6566 TYPEATTR *tattr;
6567 HRESULT hres;
6569 hres = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6570 if(FAILED(hres))
6571 return hres;
6573 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6574 if(FAILED(hres)) {
6575 ITypeInfo_Release(tinfo2);
6576 return hres;
6579 switch(tattr->typekind) {
6580 case TKIND_ALIAS:
6581 hres = get_iface_guid(tinfo2, &tattr->tdescAlias, guid);
6582 break;
6584 case TKIND_INTERFACE:
6585 case TKIND_DISPATCH:
6586 *guid = tattr->guid;
6587 break;
6589 default:
6590 ERR("Unexpected typekind %d\n", tattr->typekind);
6591 hres = E_UNEXPECTED;
6594 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6595 ITypeInfo_Release(tinfo2);
6596 return hres;
6599 /***********************************************************************
6600 * DispCallFunc (OLEAUT32.@)
6602 * Invokes a function of the specified calling convention, passing the
6603 * specified arguments and returns the result.
6605 * PARAMS
6606 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6607 * oVft [I] The offset in the vtable. See notes.
6608 * cc [I] Calling convention of the function to call.
6609 * vtReturn [I] The return type of the function.
6610 * cActuals [I] Number of parameters.
6611 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6612 * prgpvarg [I] The arguments to pass.
6613 * pvargResult [O] The return value of the function. Can be NULL.
6615 * RETURNS
6616 * Success: S_OK.
6617 * Failure: HRESULT code.
6619 * NOTES
6620 * The HRESULT return value of this function is not affected by the return
6621 * value of the user supplied function, which is returned in pvargResult.
6623 * If pvInstance is NULL then a non-object function is to be called and oVft
6624 * is the address of the function to call.
6626 * The cc parameter can be one of the following values:
6627 *|CC_FASTCALL
6628 *|CC_CDECL
6629 *|CC_PASCAL
6630 *|CC_STDCALL
6631 *|CC_FPFASTCALL
6632 *|CC_SYSCALL
6633 *|CC_MPWCDECL
6634 *|CC_MPWPASCAL
6637 HRESULT WINAPI
6638 DispCallFunc(
6639 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
6640 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
6642 #ifdef __i386__
6643 int argspos, stack_offset;
6644 void *func;
6645 UINT i;
6646 DWORD *args;
6648 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6649 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6650 pvargResult, V_VT(pvargResult));
6652 if (cc != CC_STDCALL && cc != CC_CDECL)
6654 FIXME("unsupported calling convention %d\n",cc);
6655 return E_INVALIDARG;
6658 /* maximum size for an argument is sizeof(VARIANT) */
6659 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6661 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6662 argspos = 1;
6663 if (pvInstance)
6665 const FARPROC *vtable = *(FARPROC **)pvInstance;
6666 func = vtable[oVft/sizeof(void *)];
6667 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6669 else func = (void *)oVft;
6671 for (i = 0; i < cActuals; i++)
6673 VARIANT *arg = prgpvarg[i];
6675 switch (prgvt[i])
6677 case VT_EMPTY:
6678 break;
6679 case VT_I8:
6680 case VT_UI8:
6681 case VT_R8:
6682 case VT_DATE:
6683 case VT_CY:
6684 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6685 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6686 break;
6687 case VT_DECIMAL:
6688 case VT_VARIANT:
6689 memcpy( &args[argspos], arg, sizeof(*arg) );
6690 argspos += sizeof(*arg) / sizeof(DWORD);
6691 break;
6692 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6693 args[argspos++] = V_BOOL(arg);
6694 break;
6695 default:
6696 args[argspos++] = V_UI4(arg);
6697 break;
6699 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6702 switch (vtReturn)
6704 case VT_EMPTY:
6705 call_method( func, argspos - 1, args + 1, &stack_offset );
6706 break;
6707 case VT_R4:
6708 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6709 break;
6710 case VT_R8:
6711 case VT_DATE:
6712 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6713 break;
6714 case VT_DECIMAL:
6715 case VT_VARIANT:
6716 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6717 call_method( func, argspos, args, &stack_offset );
6718 break;
6719 case VT_I8:
6720 case VT_UI8:
6721 case VT_CY:
6722 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6723 break;
6724 case VT_HRESULT:
6725 WARN("invalid return type %u\n", vtReturn);
6726 heap_free( args );
6727 return E_INVALIDARG;
6728 default:
6729 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6730 break;
6732 heap_free( args );
6733 if (stack_offset && cc == CC_STDCALL)
6735 WARN( "stack pointer off by %d\n", stack_offset );
6736 return DISP_E_BADCALLEE;
6738 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6739 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6740 return S_OK;
6742 #elif defined(__x86_64__)
6743 int argspos;
6744 UINT i;
6745 DWORD_PTR *args;
6746 void *func;
6748 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6749 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6750 pvargResult, V_VT(pvargResult));
6752 if (cc != CC_STDCALL && cc != CC_CDECL)
6754 FIXME("unsupported calling convention %d\n",cc);
6755 return E_INVALIDARG;
6758 /* maximum size for an argument is sizeof(DWORD_PTR) */
6759 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6761 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6762 argspos = 1;
6763 if (pvInstance)
6765 const FARPROC *vtable = *(FARPROC **)pvInstance;
6766 func = vtable[oVft/sizeof(void *)];
6767 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6769 else func = (void *)oVft;
6771 for (i = 0; i < cActuals; i++)
6773 VARIANT *arg = prgpvarg[i];
6775 switch (prgvt[i])
6777 case VT_DECIMAL:
6778 case VT_VARIANT:
6779 args[argspos++] = (ULONG_PTR)arg;
6780 break;
6781 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6782 args[argspos++] = V_BOOL(arg);
6783 break;
6784 default:
6785 args[argspos++] = V_UI8(arg);
6786 break;
6788 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6791 switch (vtReturn)
6793 case VT_R4:
6794 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6795 break;
6796 case VT_R8:
6797 case VT_DATE:
6798 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6799 break;
6800 case VT_DECIMAL:
6801 case VT_VARIANT:
6802 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6803 call_method( func, argspos, args );
6804 break;
6805 case VT_HRESULT:
6806 WARN("invalid return type %u\n", vtReturn);
6807 heap_free( args );
6808 return E_INVALIDARG;
6809 default:
6810 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6811 break;
6813 heap_free( args );
6814 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6815 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6816 return S_OK;
6818 #else
6819 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6820 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6821 return E_NOTIMPL;
6822 #endif
6825 static inline BOOL func_restricted( const FUNCDESC *desc )
6827 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
6830 #define INVBUF_ELEMENT_SIZE \
6831 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6832 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6833 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6834 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6835 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6836 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6837 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6838 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6840 static HRESULT WINAPI ITypeInfo_fnInvoke(
6841 ITypeInfo2 *iface,
6842 VOID *pIUnk,
6843 MEMBERID memid,
6844 UINT16 wFlags,
6845 DISPPARAMS *pDispParams,
6846 VARIANT *pVarResult,
6847 EXCEPINFO *pExcepInfo,
6848 UINT *pArgErr)
6850 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6851 int i;
6852 unsigned int var_index;
6853 TYPEKIND type_kind;
6854 HRESULT hres;
6855 const TLBFuncDesc *pFuncInfo;
6856 UINT fdc;
6858 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6859 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6862 if( This->typeattr.wTypeFlags & TYPEFLAG_FRESTRICTED )
6863 return DISP_E_MEMBERNOTFOUND;
6865 if (!pDispParams)
6867 ERR("NULL pDispParams not allowed\n");
6868 return E_INVALIDARG;
6871 dump_DispParms(pDispParams);
6873 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6875 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6876 pDispParams->cNamedArgs, pDispParams->cArgs);
6877 return E_INVALIDARG;
6880 /* we do this instead of using GetFuncDesc since it will return a fake
6881 * FUNCDESC for dispinterfaces and we want the real function description */
6882 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
6883 pFuncInfo = &This->funcdescs[fdc];
6884 if ((memid == pFuncInfo->funcdesc.memid) &&
6885 (wFlags & pFuncInfo->funcdesc.invkind) &&
6886 !func_restricted( &pFuncInfo->funcdesc ))
6887 break;
6890 if (fdc < This->typeattr.cFuncs) {
6891 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6893 if (TRACE_ON(ole))
6895 TRACE("invoking:\n");
6896 dump_TLBFuncDescOne(pFuncInfo);
6899 switch (func_desc->funckind) {
6900 case FUNC_PUREVIRTUAL:
6901 case FUNC_VIRTUAL: {
6902 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
6903 VARIANT varresult;
6904 VARIANT retval; /* pointer for storing byref retvals in */
6905 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6906 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6907 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6908 UINT cNamedArgs = pDispParams->cNamedArgs;
6909 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6910 UINT vargs_converted=0;
6912 hres = S_OK;
6914 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6916 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6918 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6919 hres = DISP_E_PARAMNOTFOUND;
6920 goto func_fail;
6924 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6926 ERR("functions with the vararg attribute do not support named arguments\n");
6927 hres = DISP_E_NONAMEDARGS;
6928 goto func_fail;
6931 for (i = 0; i < func_desc->cParams; i++)
6933 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6934 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6935 if (FAILED(hres))
6936 goto func_fail;
6939 TRACE("changing args\n");
6940 for (i = 0; i < func_desc->cParams; i++)
6942 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6943 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6944 VARIANTARG *src_arg;
6946 if (wParamFlags & PARAMFLAG_FLCID)
6948 VARIANTARG *arg;
6949 arg = prgpvarg[i] = &rgvarg[i];
6950 V_VT(arg) = VT_I4;
6951 V_I4(arg) = This->pTypeLib->lcid;
6952 continue;
6955 src_arg = NULL;
6957 if (cNamedArgs)
6959 USHORT j;
6960 for (j = 0; j < cNamedArgs; j++)
6961 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
6963 src_arg = &pDispParams->rgvarg[j];
6964 break;
6968 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
6970 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6971 vargs_converted++;
6974 if (wParamFlags & PARAMFLAG_FRETVAL)
6976 /* under most conditions the caller is not allowed to
6977 * pass in a dispparam arg in the index of what would be
6978 * the retval parameter. however, there is an exception
6979 * where the extra parameter is used in an extra
6980 * IDispatch::Invoke below */
6981 if ((i < pDispParams->cArgs) &&
6982 ((func_desc->cParams != 1) || !pVarResult ||
6983 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6985 hres = DISP_E_BADPARAMCOUNT;
6986 break;
6989 /* note: this check is placed so that if the caller passes
6990 * in a VARIANTARG for the retval we just ignore it, like
6991 * native does */
6992 if (i == func_desc->cParams - 1)
6994 VARIANTARG *arg;
6995 arg = prgpvarg[i] = &rgvarg[i];
6996 memset(arg, 0, sizeof(*arg));
6997 V_VT(arg) = rgvt[i];
6998 memset(&retval, 0, sizeof(retval));
6999 V_BYREF(arg) = &retval;
7001 else
7003 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
7004 hres = E_UNEXPECTED;
7005 break;
7008 else if (src_arg)
7010 TRACE("%s\n", debugstr_variant(src_arg));
7012 if(rgvt[i]!=V_VT(src_arg))
7014 if (rgvt[i] == VT_VARIANT)
7015 hres = VariantCopy(&rgvarg[i], src_arg);
7016 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
7018 if (rgvt[i] == V_VT(src_arg))
7019 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
7020 else
7022 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7023 if (wParamFlags & PARAMFLAG_FIN)
7024 hres = VariantCopy(&missing_arg[i], src_arg);
7025 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
7027 V_VT(&rgvarg[i]) = rgvt[i];
7029 else if ((rgvt[i] == (VT_VARIANT | VT_ARRAY) || rgvt[i] == (VT_VARIANT | VT_ARRAY | VT_BYREF)) && func_desc->cParamsOpt < 0)
7031 SAFEARRAY *a;
7032 SAFEARRAYBOUND bound;
7033 VARIANT *v;
7034 LONG j;
7035 bound.lLbound = 0;
7036 bound.cElements = pDispParams->cArgs-i;
7037 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
7039 ERR("SafeArrayCreate failed\n");
7040 break;
7042 hres = SafeArrayAccessData(a, (LPVOID)&v);
7043 if (hres != S_OK)
7045 ERR("SafeArrayAccessData failed with %x\n", hres);
7046 SafeArrayDestroy(a);
7047 break;
7049 for (j = 0; j < bound.cElements; j++)
7050 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
7051 hres = SafeArrayUnaccessData(a);
7052 if (hres != S_OK)
7054 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7055 SafeArrayDestroy(a);
7056 break;
7058 if (rgvt[i] & VT_BYREF)
7059 V_BYREF(&rgvarg[i]) = &a;
7060 else
7061 V_ARRAY(&rgvarg[i]) = a;
7062 V_VT(&rgvarg[i]) = rgvt[i];
7064 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
7066 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7067 if (wParamFlags & PARAMFLAG_FIN)
7068 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
7069 else
7070 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
7071 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
7072 V_VT(&rgvarg[i]) = rgvt[i];
7074 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
7076 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
7077 V_VT(&rgvarg[i]) = rgvt[i];
7079 else
7081 /* FIXME: this doesn't work for VT_BYREF arguments if
7082 * they are not the same type as in the paramdesc */
7083 V_VT(&rgvarg[i]) = V_VT(src_arg);
7084 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
7085 V_VT(&rgvarg[i]) = rgvt[i];
7088 if (FAILED(hres))
7090 ERR("failed to convert param %d to %s from %s\n", i,
7091 debugstr_vt(rgvt[i]), debugstr_variant(src_arg));
7092 break;
7094 prgpvarg[i] = &rgvarg[i];
7096 else
7098 prgpvarg[i] = src_arg;
7101 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
7102 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
7103 && V_UNKNOWN(prgpvarg[i])) {
7104 IUnknown *userdefined_iface;
7105 GUID guid;
7107 hres = get_iface_guid((ITypeInfo*)iface, tdesc->vt == VT_PTR ? tdesc->u.lptdesc : tdesc, &guid);
7108 if(FAILED(hres))
7109 break;
7111 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
7112 if(FAILED(hres)) {
7113 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
7114 break;
7117 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
7118 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
7121 else if (wParamFlags & PARAMFLAG_FOPT)
7123 VARIANTARG *arg;
7124 arg = prgpvarg[i] = &rgvarg[i];
7125 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7127 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
7128 if (FAILED(hres))
7129 break;
7131 else
7133 VARIANTARG *missing_arg;
7134 /* if the function wants a pointer to a variant then
7135 * set that up, otherwise just pass the VT_ERROR in
7136 * the argument by value */
7137 if (rgvt[i] & VT_BYREF)
7139 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
7140 V_VT(arg) = VT_VARIANT | VT_BYREF;
7141 V_VARIANTREF(arg) = missing_arg;
7143 else
7144 missing_arg = arg;
7145 V_VT(missing_arg) = VT_ERROR;
7146 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
7149 else
7151 hres = DISP_E_BADPARAMCOUNT;
7152 break;
7155 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7157 /* VT_VOID is a special case for return types, so it is not
7158 * handled in the general function */
7159 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
7160 V_VT(&varresult) = VT_EMPTY;
7161 else
7163 V_VT(&varresult) = 0;
7164 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
7165 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7168 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv,
7169 V_VT(&varresult), func_desc->cParams, rgvt,
7170 prgpvarg, &varresult);
7172 vargs_converted = 0;
7174 for (i = 0; i < func_desc->cParams; i++)
7176 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7177 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7179 if (wParamFlags & PARAMFLAG_FLCID)
7180 continue;
7181 else if (wParamFlags & PARAMFLAG_FRETVAL)
7183 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg[i]));
7185 if (pVarResult)
7187 VariantInit(pVarResult);
7188 /* deref return value */
7189 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
7192 VARIANT_ClearInd(prgpvarg[i]);
7194 else if (vargs_converted < pDispParams->cArgs)
7196 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7197 if (wParamFlags & PARAMFLAG_FOUT)
7199 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
7201 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
7203 if (FAILED(hres))
7205 ERR("failed to convert param %d to vt %d\n", i,
7206 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
7207 break;
7211 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
7212 func_desc->cParamsOpt < 0 &&
7213 i == func_desc->cParams-1)
7215 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
7216 LONG j, ubound;
7217 VARIANT *v;
7218 hres = SafeArrayGetUBound(a, 1, &ubound);
7219 if (hres != S_OK)
7221 ERR("SafeArrayGetUBound failed with %x\n", hres);
7222 break;
7224 hres = SafeArrayAccessData(a, (LPVOID)&v);
7225 if (hres != S_OK)
7227 ERR("SafeArrayAccessData failed with %x\n", hres);
7228 break;
7230 for (j = 0; j <= ubound; j++)
7231 VariantClear(&v[j]);
7232 hres = SafeArrayUnaccessData(a);
7233 if (hres != S_OK)
7235 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7236 break;
7239 VariantClear(&rgvarg[i]);
7240 vargs_converted++;
7242 else if (wParamFlags & PARAMFLAG_FOPT)
7244 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7245 VariantClear(&rgvarg[i]);
7248 VariantClear(&missing_arg[i]);
7251 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
7253 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
7254 hres = DISP_E_EXCEPTION;
7255 if (pExcepInfo)
7257 IErrorInfo *pErrorInfo;
7258 pExcepInfo->scode = V_ERROR(&varresult);
7259 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
7261 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
7262 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
7263 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
7264 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
7266 IErrorInfo_Release(pErrorInfo);
7270 if (V_VT(&varresult) != VT_ERROR)
7272 TRACE("varresult value: %s\n", debugstr_variant(&varresult));
7274 if (pVarResult)
7276 VariantClear(pVarResult);
7277 *pVarResult = varresult;
7279 else
7280 VariantClear(&varresult);
7283 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
7284 (func_desc->invkind & INVOKE_PROPERTYGET) &&
7285 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
7286 (pDispParams->cArgs != 0))
7288 if (V_VT(pVarResult) == VT_DISPATCH)
7290 IDispatch *pDispatch = V_DISPATCH(pVarResult);
7291 /* Note: not VariantClear; we still need the dispatch
7292 * pointer to be valid */
7293 VariantInit(pVarResult);
7294 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
7295 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
7296 pDispParams, pVarResult, pExcepInfo, pArgErr);
7297 IDispatch_Release(pDispatch);
7299 else
7301 VariantClear(pVarResult);
7302 hres = DISP_E_NOTACOLLECTION;
7306 func_fail:
7307 heap_free(buffer);
7308 break;
7310 case FUNC_DISPATCH: {
7311 IDispatch *disp;
7313 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
7314 if (SUCCEEDED(hres)) {
7315 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7316 hres = IDispatch_Invoke(
7317 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
7318 pVarResult,pExcepInfo,pArgErr
7320 if (FAILED(hres))
7321 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
7322 IDispatch_Release(disp);
7323 } else
7324 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7325 break;
7327 default:
7328 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
7329 hres = E_FAIL;
7330 break;
7333 TRACE("-- 0x%08x\n", hres);
7334 return hres;
7336 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
7337 VARDESC *var_desc;
7339 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
7340 if(FAILED(hres)) return hres;
7342 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7343 dump_VARDESC(var_desc);
7344 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
7345 return E_NOTIMPL;
7348 /* not found, look for it in inherited interfaces */
7349 ITypeInfo2_GetTypeKind(iface, &type_kind);
7350 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
7351 if(This->impltypes) {
7352 /* recursive search */
7353 ITypeInfo *pTInfo;
7354 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7355 if(SUCCEEDED(hres)){
7356 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
7357 ITypeInfo_Release(pTInfo);
7358 return hres;
7360 WARN("Could not search inherited interface!\n");
7363 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
7364 return DISP_E_MEMBERNOTFOUND;
7367 /* ITypeInfo::GetDocumentation
7369 * Retrieves the documentation string, the complete Help file name and path,
7370 * and the context ID for the Help topic for a specified type description.
7372 * (Can be tested by the Visual Basic Editor in Word for instance.)
7374 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
7375 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
7376 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
7378 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7379 const TLBFuncDesc *pFDesc;
7380 const TLBVarDesc *pVDesc;
7381 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7382 " HelpContext(%p) HelpFile(%p)\n",
7383 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
7384 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7385 if(pBstrName)
7386 *pBstrName=SysAllocString(TLB_get_bstr(This->Name));
7387 if(pBstrDocString)
7388 *pBstrDocString=SysAllocString(TLB_get_bstr(This->DocString));
7389 if(pdwHelpContext)
7390 *pdwHelpContext=This->dwHelpContext;
7391 if(pBstrHelpFile)
7392 *pBstrHelpFile=SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7393 return S_OK;
7394 }else {/* for a member */
7395 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->typeattr.cFuncs, memid);
7396 if(pFDesc){
7397 if(pBstrName)
7398 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Name));
7399 if(pBstrDocString)
7400 *pBstrDocString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7401 if(pdwHelpContext)
7402 *pdwHelpContext=pFDesc->helpcontext;
7403 if(pBstrHelpFile)
7404 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7405 return S_OK;
7407 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->typeattr.cVars, memid);
7408 if(pVDesc){
7409 if(pBstrName)
7410 *pBstrName = SysAllocString(TLB_get_bstr(pVDesc->Name));
7411 if(pBstrDocString)
7412 *pBstrDocString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7413 if(pdwHelpContext)
7414 *pdwHelpContext=pVDesc->HelpContext;
7415 if(pBstrHelpFile)
7416 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7417 return S_OK;
7421 if(This->impltypes &&
7422 (This->typeattr.typekind == TKIND_INTERFACE || This->typeattr.typekind == TKIND_DISPATCH)) {
7423 /* recursive search */
7424 ITypeInfo *pTInfo;
7425 HRESULT result;
7426 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7427 if(SUCCEEDED(result)) {
7428 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
7429 pBstrDocString, pdwHelpContext, pBstrHelpFile);
7430 ITypeInfo_Release(pTInfo);
7431 return result;
7433 WARN("Could not search inherited interface!\n");
7436 WARN("member %d not found\n", memid);
7437 return TYPE_E_ELEMENTNOTFOUND;
7440 /* ITypeInfo::GetDllEntry
7442 * Retrieves a description or specification of an entry point for a function
7443 * in a DLL.
7445 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
7446 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
7447 WORD *pwOrdinal)
7449 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7450 const TLBFuncDesc *pFDesc;
7452 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
7454 if (pBstrDllName) *pBstrDllName = NULL;
7455 if (pBstrName) *pBstrName = NULL;
7456 if (pwOrdinal) *pwOrdinal = 0;
7458 if (This->typeattr.typekind != TKIND_MODULE)
7459 return TYPE_E_BADMODULEKIND;
7461 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->typeattr.cFuncs, memid);
7462 if(pFDesc){
7463 dump_TypeInfo(This);
7464 if (TRACE_ON(ole))
7465 dump_TLBFuncDescOne(pFDesc);
7467 if (pBstrDllName)
7468 *pBstrDllName = SysAllocString(TLB_get_bstr(This->DllName));
7470 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
7471 if (pBstrName)
7472 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Entry));
7473 if (pwOrdinal)
7474 *pwOrdinal = -1;
7475 return S_OK;
7477 if (pBstrName)
7478 *pBstrName = NULL;
7479 if (pwOrdinal)
7480 *pwOrdinal = LOWORD(pFDesc->Entry);
7481 return S_OK;
7483 return TYPE_E_ELEMENTNOTFOUND;
7486 /* internal function to make the inherited interfaces' methods appear
7487 * part of the interface */
7488 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7489 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7491 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7492 HRESULT hr;
7494 TRACE("%p, 0x%x\n", iface, *hRefType);
7496 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7498 ITypeInfo *pSubTypeInfo;
7500 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7501 if (FAILED(hr))
7502 return hr;
7504 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7505 hRefType, ppTInfo);
7506 ITypeInfo_Release(pSubTypeInfo);
7507 if (SUCCEEDED(hr))
7508 return hr;
7510 *hRefType -= DISPATCH_HREF_OFFSET;
7512 if (!(*hRefType & DISPATCH_HREF_MASK))
7513 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7514 else
7515 return E_FAIL;
7518 struct search_res_tlb_params
7520 const GUID *guid;
7521 ITypeLib *pTLib;
7524 static BOOL CALLBACK search_res_tlb(HMODULE hModule, LPCWSTR lpszType, LPWSTR lpszName, LONG_PTR lParam)
7526 struct search_res_tlb_params *params = (LPVOID)lParam;
7527 static const WCHAR formatW[] = {'\\','%','d',0};
7528 WCHAR szPath[MAX_PATH+1];
7529 ITypeLib *pTLib = NULL;
7530 HRESULT ret;
7531 DWORD len;
7533 if (IS_INTRESOURCE(lpszName) == FALSE)
7534 return TRUE;
7536 if (!(len = GetModuleFileNameW(hModule, szPath, MAX_PATH)))
7537 return TRUE;
7539 if (snprintfW(szPath + len, sizeof(szPath)/sizeof(WCHAR) - len, formatW, LOWORD(lpszName)) < 0)
7540 return TRUE;
7542 ret = LoadTypeLibEx(szPath, REGKIND_NONE, &pTLib);
7543 if (SUCCEEDED(ret))
7545 ITypeLibImpl *impl = impl_from_ITypeLib(pTLib);
7546 if (IsEqualGUID(params->guid, impl->guid))
7548 params->pTLib = pTLib;
7549 return FALSE; /* stop enumeration */
7551 ITypeLib_Release(pTLib);
7554 return TRUE;
7557 /* ITypeInfo::GetRefTypeInfo
7559 * If a type description references other type descriptions, it retrieves
7560 * the referenced type descriptions.
7562 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7563 ITypeInfo2 *iface,
7564 HREFTYPE hRefType,
7565 ITypeInfo **ppTInfo)
7567 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7568 HRESULT result = E_FAIL;
7570 if(!ppTInfo)
7571 return E_INVALIDARG;
7573 if ((INT)hRefType < 0) {
7574 ITypeInfoImpl *pTypeInfoImpl;
7576 if (!(This->typeattr.wTypeFlags & TYPEFLAG_FDUAL) ||
7577 !(This->typeattr.typekind == TKIND_INTERFACE ||
7578 This->typeattr.typekind == TKIND_DISPATCH))
7579 return TYPE_E_ELEMENTNOTFOUND;
7581 /* when we meet a DUAL typeinfo, we must create the alternate
7582 * version of it.
7584 pTypeInfoImpl = ITypeInfoImpl_Constructor();
7586 *pTypeInfoImpl = *This;
7587 pTypeInfoImpl->ref = 0;
7588 list_init(&pTypeInfoImpl->custdata_list);
7590 if (This->typeattr.typekind == TKIND_INTERFACE)
7591 pTypeInfoImpl->typeattr.typekind = TKIND_DISPATCH;
7592 else
7593 pTypeInfoImpl->typeattr.typekind = TKIND_INTERFACE;
7595 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface;
7596 /* the AddRef implicitly adds a reference to the parent typelib, which
7597 * stops the copied data from being destroyed until the new typeinfo's
7598 * refcount goes to zero, but we need to signal to the new instance to
7599 * not free its data structures when it is destroyed */
7600 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7602 ITypeInfo_AddRef(*ppTInfo);
7604 result = S_OK;
7605 } else if ((hRefType & DISPATCH_HREF_MASK) &&
7606 (This->typeattr.typekind == TKIND_DISPATCH))
7608 HREFTYPE href_dispatch = hRefType;
7609 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
7610 } else {
7611 TLBRefType *ref_type;
7612 ITypeLib *pTLib = NULL;
7613 UINT i;
7615 if(!(hRefType & 0x1)){
7616 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
7618 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
7620 result = S_OK;
7621 *ppTInfo = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
7622 ITypeInfo_AddRef(*ppTInfo);
7623 goto end;
7628 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7630 if(ref_type->reference == (hRefType & (~0x3)))
7631 break;
7633 if(&ref_type->entry == &This->pTypeLib->ref_list)
7635 FIXME("Can't find pRefType for ref %x\n", hRefType);
7636 goto end;
7639 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7640 UINT Index;
7641 TRACE("internal reference\n");
7642 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7643 } else {
7644 if(ref_type->pImpTLInfo->pImpTypeLib) {
7645 TRACE("typeinfo in imported typelib that is already loaded\n");
7646 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
7647 ITypeLib_AddRef(pTLib);
7648 result = S_OK;
7649 } else {
7650 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
7651 struct search_res_tlb_params params;
7652 BSTR libnam;
7654 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7656 /* Search in resource table */
7657 params.guid = TLB_get_guid_null(ref_type->pImpTLInfo->guid);
7658 params.pTLib = NULL;
7659 EnumResourceNamesW(NULL, TYPELIBW, search_res_tlb, (LONG_PTR)&params);
7660 pTLib = params.pTLib;
7661 result = S_OK;
7663 if (!pTLib)
7665 /* Search on disk */
7666 result = query_typelib_path(TLB_get_guid_null(ref_type->pImpTLInfo->guid),
7667 ref_type->pImpTLInfo->wVersionMajor,
7668 ref_type->pImpTLInfo->wVersionMinor,
7669 This->pTypeLib->syskind,
7670 ref_type->pImpTLInfo->lcid, &libnam, TRUE);
7671 if (FAILED(result))
7672 libnam = SysAllocString(ref_type->pImpTLInfo->name);
7674 result = LoadTypeLib(libnam, &pTLib);
7675 SysFreeString(libnam);
7678 if(SUCCEEDED(result)) {
7679 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
7680 ITypeLib_AddRef(pTLib);
7684 if(SUCCEEDED(result)) {
7685 if(ref_type->index == TLB_REF_USE_GUID)
7686 result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), ppTInfo);
7687 else
7688 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, ppTInfo);
7690 if (pTLib != NULL)
7691 ITypeLib_Release(pTLib);
7694 end:
7695 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
7696 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
7697 return result;
7700 /* ITypeInfo::AddressOfMember
7702 * Retrieves the addresses of static functions or variables, such as those
7703 * defined in a DLL.
7705 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
7706 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
7708 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7709 HRESULT hr;
7710 BSTR dll, entry;
7711 WORD ordinal;
7712 HMODULE module;
7714 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
7716 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
7717 if (FAILED(hr))
7718 return hr;
7720 module = LoadLibraryW(dll);
7721 if (!module)
7723 ERR("couldn't load %s\n", debugstr_w(dll));
7724 SysFreeString(dll);
7725 SysFreeString(entry);
7726 return STG_E_FILENOTFOUND;
7728 /* FIXME: store library somewhere where we can free it */
7730 if (entry)
7732 LPSTR entryA;
7733 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
7734 entryA = heap_alloc(len);
7735 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
7737 *ppv = GetProcAddress(module, entryA);
7738 if (!*ppv)
7739 ERR("function not found %s\n", debugstr_a(entryA));
7741 heap_free(entryA);
7743 else
7745 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7746 if (!*ppv)
7747 ERR("function not found %d\n", ordinal);
7750 SysFreeString(dll);
7751 SysFreeString(entry);
7753 if (!*ppv)
7754 return TYPE_E_DLLFUNCTIONNOTFOUND;
7756 return S_OK;
7759 /* ITypeInfo::CreateInstance
7761 * Creates a new instance of a type that describes a component object class
7762 * (coclass).
7764 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7765 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7767 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7768 HRESULT hr;
7769 TYPEATTR *pTA;
7771 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7773 *ppvObj = NULL;
7775 if(pOuterUnk)
7777 WARN("Not able to aggregate\n");
7778 return CLASS_E_NOAGGREGATION;
7781 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
7782 if(FAILED(hr)) return hr;
7784 if(pTA->typekind != TKIND_COCLASS)
7786 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7787 hr = E_INVALIDARG;
7788 goto end;
7791 hr = S_FALSE;
7792 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7794 IUnknown *pUnk;
7795 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7796 TRACE("GetActiveObject rets %08x\n", hr);
7797 if(hr == S_OK)
7799 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7800 IUnknown_Release(pUnk);
7804 if(hr != S_OK)
7805 hr = CoCreateInstance(&pTA->guid, NULL,
7806 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7807 riid, ppvObj);
7809 end:
7810 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
7811 return hr;
7814 /* ITypeInfo::GetMops
7816 * Retrieves marshalling information.
7818 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7819 BSTR *pBstrMops)
7821 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7822 FIXME("(%p %d) stub!\n", This, memid);
7823 *pBstrMops = NULL;
7824 return S_OK;
7827 /* ITypeInfo::GetContainingTypeLib
7829 * Retrieves the containing type library and the index of the type description
7830 * within that type library.
7832 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7833 ITypeLib * *ppTLib, UINT *pIndex)
7835 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7837 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7838 if (pIndex) {
7839 *pIndex=This->index;
7840 TRACE("returning pIndex=%d\n", *pIndex);
7843 if (ppTLib) {
7844 *ppTLib = (ITypeLib *)&This->pTypeLib->ITypeLib2_iface;
7845 ITypeLib_AddRef(*ppTLib);
7846 TRACE("returning ppTLib=%p\n", *ppTLib);
7849 return S_OK;
7852 /* ITypeInfo::ReleaseTypeAttr
7854 * Releases a TYPEATTR previously returned by Get
7857 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7858 TYPEATTR* pTypeAttr)
7860 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7861 TRACE("(%p)->(%p)\n", This, pTypeAttr);
7862 heap_free(pTypeAttr);
7865 /* ITypeInfo::ReleaseFuncDesc
7867 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7869 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7870 ITypeInfo2 *iface,
7871 FUNCDESC *pFuncDesc)
7873 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7874 SHORT i;
7876 TRACE("(%p)->(%p)\n", This, pFuncDesc);
7878 for (i = 0; i < pFuncDesc->cParams; i++)
7879 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7880 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7882 SysFreeString((BSTR)pFuncDesc);
7885 /* ITypeInfo::ReleaseVarDesc
7887 * Releases a VARDESC previously returned by GetVarDesc.
7889 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7890 VARDESC *pVarDesc)
7892 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7893 TRACE("(%p)->(%p)\n", This, pVarDesc);
7895 TLB_FreeVarDesc(pVarDesc);
7898 /* ITypeInfo2::GetTypeKind
7900 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7903 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7904 TYPEKIND *pTypeKind)
7906 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7907 *pTypeKind = This->typeattr.typekind;
7908 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7909 return S_OK;
7912 /* ITypeInfo2::GetTypeFlags
7914 * Returns the type flags without any allocations. This returns a DWORD type
7915 * flag, which expands the type flags without growing the TYPEATTR (type
7916 * attribute).
7919 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7921 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7922 *pTypeFlags=This->typeattr.wTypeFlags;
7923 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7924 return S_OK;
7927 /* ITypeInfo2::GetFuncIndexOfMemId
7928 * Binds to a specific member based on a known DISPID, where the member name
7929 * is not known (for example, when binding to a default member).
7932 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7933 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7935 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7936 UINT fdc;
7937 HRESULT result;
7939 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
7940 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
7941 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7942 break;
7944 if(fdc < This->typeattr.cFuncs) {
7945 *pFuncIndex = fdc;
7946 result = S_OK;
7947 } else
7948 result = TYPE_E_ELEMENTNOTFOUND;
7950 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7951 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7952 return result;
7955 /* TypeInfo2::GetVarIndexOfMemId
7957 * Binds to a specific member based on a known DISPID, where the member name
7958 * is not known (for example, when binding to a default member).
7961 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7962 MEMBERID memid, UINT *pVarIndex)
7964 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7965 TLBVarDesc *pVarInfo;
7967 TRACE("%p %d %p\n", iface, memid, pVarIndex);
7969 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->typeattr.cVars, memid);
7970 if(!pVarInfo)
7971 return TYPE_E_ELEMENTNOTFOUND;
7973 *pVarIndex = (pVarInfo - This->vardescs);
7975 return S_OK;
7978 /* ITypeInfo2::GetCustData
7980 * Gets the custom data
7982 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7983 ITypeInfo2 * iface,
7984 REFGUID guid,
7985 VARIANT *pVarVal)
7987 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7988 TLBCustData *pCData;
7990 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7992 if(!guid || !pVarVal)
7993 return E_INVALIDARG;
7995 pCData = TLB_get_custdata_by_guid(This->pcustdata_list, guid);
7997 VariantInit( pVarVal);
7998 if (pCData)
7999 VariantCopy( pVarVal, &pCData->data);
8000 else
8001 VariantClear( pVarVal );
8002 return S_OK;
8005 /* ITypeInfo2::GetFuncCustData
8007 * Gets the custom data
8009 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
8010 ITypeInfo2 * iface,
8011 UINT index,
8012 REFGUID guid,
8013 VARIANT *pVarVal)
8015 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8016 TLBCustData *pCData;
8017 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8019 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8021 if(index >= This->typeattr.cFuncs)
8022 return TYPE_E_ELEMENTNOTFOUND;
8024 pCData = TLB_get_custdata_by_guid(&pFDesc->custdata_list, guid);
8025 if(!pCData)
8026 return TYPE_E_ELEMENTNOTFOUND;
8028 VariantInit(pVarVal);
8029 VariantCopy(pVarVal, &pCData->data);
8031 return S_OK;
8034 /* ITypeInfo2::GetParamCustData
8036 * Gets the custom data
8038 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
8039 ITypeInfo2 * iface,
8040 UINT indexFunc,
8041 UINT indexParam,
8042 REFGUID guid,
8043 VARIANT *pVarVal)
8045 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8046 TLBCustData *pCData;
8047 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8049 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
8050 debugstr_guid(guid), pVarVal);
8052 if(indexFunc >= This->typeattr.cFuncs)
8053 return TYPE_E_ELEMENTNOTFOUND;
8055 if(indexParam >= pFDesc->funcdesc.cParams)
8056 return TYPE_E_ELEMENTNOTFOUND;
8058 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
8059 if(!pCData)
8060 return TYPE_E_ELEMENTNOTFOUND;
8062 VariantInit(pVarVal);
8063 VariantCopy(pVarVal, &pCData->data);
8065 return S_OK;
8068 /* ITypeInfo2::GetVarCustData
8070 * Gets the custom data
8072 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
8073 ITypeInfo2 * iface,
8074 UINT index,
8075 REFGUID guid,
8076 VARIANT *pVarVal)
8078 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8079 TLBCustData *pCData;
8080 TLBVarDesc *pVDesc = &This->vardescs[index];
8082 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8084 if(index >= This->typeattr.cVars)
8085 return TYPE_E_ELEMENTNOTFOUND;
8087 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
8088 if(!pCData)
8089 return TYPE_E_ELEMENTNOTFOUND;
8091 VariantInit(pVarVal);
8092 VariantCopy(pVarVal, &pCData->data);
8094 return S_OK;
8097 /* ITypeInfo2::GetImplCustData
8099 * Gets the custom data
8101 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
8102 ITypeInfo2 * iface,
8103 UINT index,
8104 REFGUID guid,
8105 VARIANT *pVarVal)
8107 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8108 TLBCustData *pCData;
8109 TLBImplType *pRDesc = &This->impltypes[index];
8111 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8113 if(index >= This->typeattr.cImplTypes)
8114 return TYPE_E_ELEMENTNOTFOUND;
8116 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
8117 if(!pCData)
8118 return TYPE_E_ELEMENTNOTFOUND;
8120 VariantInit(pVarVal);
8121 VariantCopy(pVarVal, &pCData->data);
8123 return S_OK;
8126 /* ITypeInfo2::GetDocumentation2
8128 * Retrieves the documentation string, the complete Help file name and path,
8129 * the localization context to use, and the context ID for the library Help
8130 * topic in the Help file.
8133 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
8134 ITypeInfo2 * iface,
8135 MEMBERID memid,
8136 LCID lcid,
8137 BSTR *pbstrHelpString,
8138 DWORD *pdwHelpStringContext,
8139 BSTR *pbstrHelpStringDll)
8141 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8142 const TLBFuncDesc *pFDesc;
8143 const TLBVarDesc *pVDesc;
8144 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8145 "HelpStringContext(%p) HelpStringDll(%p)\n",
8146 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
8147 pbstrHelpStringDll );
8148 /* the help string should be obtained from the helpstringdll,
8149 * using the _DLLGetDocumentation function, based on the supplied
8150 * lcid. Nice to do sometime...
8152 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
8153 if(pbstrHelpString)
8154 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->Name));
8155 if(pdwHelpStringContext)
8156 *pdwHelpStringContext=This->dwHelpStringContext;
8157 if(pbstrHelpStringDll)
8158 *pbstrHelpStringDll=
8159 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8160 return S_OK;
8161 }else {/* for a member */
8162 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->typeattr.cFuncs, memid);
8163 if(pFDesc){
8164 if(pbstrHelpString)
8165 *pbstrHelpString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
8166 if(pdwHelpStringContext)
8167 *pdwHelpStringContext=pFDesc->HelpStringContext;
8168 if(pbstrHelpStringDll)
8169 *pbstrHelpStringDll=
8170 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8171 return S_OK;
8173 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->typeattr.cVars, memid);
8174 if(pVDesc){
8175 if(pbstrHelpString)
8176 *pbstrHelpString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
8177 if(pdwHelpStringContext)
8178 *pdwHelpStringContext=pVDesc->HelpStringContext;
8179 if(pbstrHelpStringDll)
8180 *pbstrHelpStringDll=
8181 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8182 return S_OK;
8185 return TYPE_E_ELEMENTNOTFOUND;
8188 /* ITypeInfo2::GetAllCustData
8190 * Gets all custom data items for the Type info.
8193 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
8194 ITypeInfo2 * iface,
8195 CUSTDATA *pCustData)
8197 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8199 TRACE("%p %p\n", This, pCustData);
8201 return TLB_copy_all_custdata(This->pcustdata_list, pCustData);
8204 /* ITypeInfo2::GetAllFuncCustData
8206 * Gets all custom data items for the specified Function
8209 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
8210 ITypeInfo2 * iface,
8211 UINT index,
8212 CUSTDATA *pCustData)
8214 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8215 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8217 TRACE("%p %u %p\n", This, index, pCustData);
8219 if(index >= This->typeattr.cFuncs)
8220 return TYPE_E_ELEMENTNOTFOUND;
8222 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
8225 /* ITypeInfo2::GetAllParamCustData
8227 * Gets all custom data items for the Functions
8230 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
8231 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
8233 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8234 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8236 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
8238 if(indexFunc >= This->typeattr.cFuncs)
8239 return TYPE_E_ELEMENTNOTFOUND;
8241 if(indexParam >= pFDesc->funcdesc.cParams)
8242 return TYPE_E_ELEMENTNOTFOUND;
8244 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
8247 /* ITypeInfo2::GetAllVarCustData
8249 * Gets all custom data items for the specified Variable
8252 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
8253 UINT index, CUSTDATA *pCustData)
8255 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8256 TLBVarDesc * pVDesc = &This->vardescs[index];
8258 TRACE("%p %u %p\n", This, index, pCustData);
8260 if(index >= This->typeattr.cVars)
8261 return TYPE_E_ELEMENTNOTFOUND;
8263 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
8266 /* ITypeInfo2::GetAllImplCustData
8268 * Gets all custom data items for the specified implementation type
8271 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
8272 ITypeInfo2 * iface,
8273 UINT index,
8274 CUSTDATA *pCustData)
8276 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8277 TLBImplType *pRDesc = &This->impltypes[index];
8279 TRACE("%p %u %p\n", This, index, pCustData);
8281 if(index >= This->typeattr.cImplTypes)
8282 return TYPE_E_ELEMENTNOTFOUND;
8284 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
8287 static const ITypeInfo2Vtbl tinfvt =
8290 ITypeInfo_fnQueryInterface,
8291 ITypeInfo_fnAddRef,
8292 ITypeInfo_fnRelease,
8294 ITypeInfo_fnGetTypeAttr,
8295 ITypeInfo_fnGetTypeComp,
8296 ITypeInfo_fnGetFuncDesc,
8297 ITypeInfo_fnGetVarDesc,
8298 ITypeInfo_fnGetNames,
8299 ITypeInfo_fnGetRefTypeOfImplType,
8300 ITypeInfo_fnGetImplTypeFlags,
8301 ITypeInfo_fnGetIDsOfNames,
8302 ITypeInfo_fnInvoke,
8303 ITypeInfo_fnGetDocumentation,
8304 ITypeInfo_fnGetDllEntry,
8305 ITypeInfo_fnGetRefTypeInfo,
8306 ITypeInfo_fnAddressOfMember,
8307 ITypeInfo_fnCreateInstance,
8308 ITypeInfo_fnGetMops,
8309 ITypeInfo_fnGetContainingTypeLib,
8310 ITypeInfo_fnReleaseTypeAttr,
8311 ITypeInfo_fnReleaseFuncDesc,
8312 ITypeInfo_fnReleaseVarDesc,
8314 ITypeInfo2_fnGetTypeKind,
8315 ITypeInfo2_fnGetTypeFlags,
8316 ITypeInfo2_fnGetFuncIndexOfMemId,
8317 ITypeInfo2_fnGetVarIndexOfMemId,
8318 ITypeInfo2_fnGetCustData,
8319 ITypeInfo2_fnGetFuncCustData,
8320 ITypeInfo2_fnGetParamCustData,
8321 ITypeInfo2_fnGetVarCustData,
8322 ITypeInfo2_fnGetImplTypeCustData,
8323 ITypeInfo2_fnGetDocumentation2,
8324 ITypeInfo2_fnGetAllCustData,
8325 ITypeInfo2_fnGetAllFuncCustData,
8326 ITypeInfo2_fnGetAllParamCustData,
8327 ITypeInfo2_fnGetAllVarCustData,
8328 ITypeInfo2_fnGetAllImplTypeCustData,
8331 /******************************************************************************
8332 * CreateDispTypeInfo [OLEAUT32.31]
8334 * Build type information for an object so it can be called through an
8335 * IDispatch interface.
8337 * RETURNS
8338 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8339 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8341 * NOTES
8342 * This call allows an objects methods to be accessed through IDispatch, by
8343 * building an ITypeInfo object that IDispatch can use to call through.
8345 HRESULT WINAPI CreateDispTypeInfo(
8346 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
8347 LCID lcid, /* [I] Locale Id */
8348 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
8350 ITypeInfoImpl *pTIClass, *pTIIface;
8351 ITypeLibImpl *pTypeLibImpl;
8352 unsigned int param, func;
8353 TLBFuncDesc *pFuncDesc;
8354 TLBRefType *ref;
8356 TRACE("\n");
8357 pTypeLibImpl = TypeLibImpl_Constructor();
8358 if (!pTypeLibImpl) return E_FAIL;
8360 pTypeLibImpl->TypeInfoCount = 2;
8361 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
8363 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
8364 pTIIface->pTypeLib = pTypeLibImpl;
8365 pTIIface->index = 0;
8366 pTIIface->Name = NULL;
8367 pTIIface->dwHelpContext = -1;
8368 pTIIface->guid = NULL;
8369 pTIIface->typeattr.lcid = lcid;
8370 pTIIface->typeattr.typekind = TKIND_INTERFACE;
8371 pTIIface->typeattr.wMajorVerNum = 0;
8372 pTIIface->typeattr.wMinorVerNum = 0;
8373 pTIIface->typeattr.cbAlignment = 2;
8374 pTIIface->typeattr.cbSizeInstance = -1;
8375 pTIIface->typeattr.cbSizeVft = -1;
8376 pTIIface->typeattr.cFuncs = 0;
8377 pTIIface->typeattr.cImplTypes = 0;
8378 pTIIface->typeattr.cVars = 0;
8379 pTIIface->typeattr.wTypeFlags = 0;
8380 pTIIface->hreftype = 0;
8382 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers);
8383 pFuncDesc = pTIIface->funcdescs;
8384 for(func = 0; func < pidata->cMembers; func++) {
8385 METHODDATA *md = pidata->pmethdata + func;
8386 pFuncDesc->Name = TLB_append_str(&pTypeLibImpl->name_list, md->szName);
8387 pFuncDesc->funcdesc.memid = md->dispid;
8388 pFuncDesc->funcdesc.lprgscode = NULL;
8389 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
8390 pFuncDesc->funcdesc.invkind = md->wFlags;
8391 pFuncDesc->funcdesc.callconv = md->cc;
8392 pFuncDesc->funcdesc.cParams = md->cArgs;
8393 pFuncDesc->funcdesc.cParamsOpt = 0;
8394 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
8395 pFuncDesc->funcdesc.cScodes = 0;
8396 pFuncDesc->funcdesc.wFuncFlags = 0;
8397 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
8398 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
8399 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
8400 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8401 md->cArgs * sizeof(ELEMDESC));
8402 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
8403 for(param = 0; param < md->cArgs; param++) {
8404 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
8405 pFuncDesc->pParamDesc[param].Name = TLB_append_str(&pTypeLibImpl->name_list, md->ppdata[param].szName);
8407 pFuncDesc->helpcontext = 0;
8408 pFuncDesc->HelpStringContext = 0;
8409 pFuncDesc->HelpString = NULL;
8410 pFuncDesc->Entry = NULL;
8411 list_init(&pFuncDesc->custdata_list);
8412 pTIIface->typeattr.cFuncs++;
8413 ++pFuncDesc;
8416 dump_TypeInfo(pTIIface);
8418 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
8419 pTIClass->pTypeLib = pTypeLibImpl;
8420 pTIClass->index = 1;
8421 pTIClass->Name = NULL;
8422 pTIClass->dwHelpContext = -1;
8423 pTIClass->guid = NULL;
8424 pTIClass->typeattr.lcid = lcid;
8425 pTIClass->typeattr.typekind = TKIND_COCLASS;
8426 pTIClass->typeattr.wMajorVerNum = 0;
8427 pTIClass->typeattr.wMinorVerNum = 0;
8428 pTIClass->typeattr.cbAlignment = 2;
8429 pTIClass->typeattr.cbSizeInstance = -1;
8430 pTIClass->typeattr.cbSizeVft = -1;
8431 pTIClass->typeattr.cFuncs = 0;
8432 pTIClass->typeattr.cImplTypes = 1;
8433 pTIClass->typeattr.cVars = 0;
8434 pTIClass->typeattr.wTypeFlags = 0;
8435 pTIClass->hreftype = sizeof(MSFT_TypeInfoBase);
8437 pTIClass->impltypes = TLBImplType_Alloc(1);
8439 ref = heap_alloc_zero(sizeof(*ref));
8440 ref->pImpTLInfo = TLB_REF_INTERNAL;
8441 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
8443 dump_TypeInfo(pTIClass);
8445 *pptinfo = (ITypeInfo *)&pTIClass->ITypeInfo2_iface;
8447 ITypeInfo_AddRef(*pptinfo);
8448 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
8450 return S_OK;
8454 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
8456 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8458 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, ppv);
8461 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
8463 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8465 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
8468 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
8470 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8472 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
8475 static HRESULT WINAPI ITypeComp_fnBind(
8476 ITypeComp * iface,
8477 OLECHAR * szName,
8478 ULONG lHash,
8479 WORD wFlags,
8480 ITypeInfo ** ppTInfo,
8481 DESCKIND * pDescKind,
8482 BINDPTR * pBindPtr)
8484 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8485 const TLBFuncDesc *pFDesc;
8486 const TLBVarDesc *pVDesc;
8487 HRESULT hr = DISP_E_MEMBERNOTFOUND;
8488 UINT fdc;
8490 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8492 *pDescKind = DESCKIND_NONE;
8493 pBindPtr->lpfuncdesc = NULL;
8494 *ppTInfo = NULL;
8496 for(fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
8497 pFDesc = &This->funcdescs[fdc];
8498 if (!lstrcmpiW(TLB_get_bstr(pFDesc->Name), szName)) {
8499 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
8500 break;
8501 else
8502 /* name found, but wrong flags */
8503 hr = TYPE_E_TYPEMISMATCH;
8507 if (fdc < This->typeattr.cFuncs)
8509 HRESULT hr = TLB_AllocAndInitFuncDesc(
8510 &pFDesc->funcdesc,
8511 &pBindPtr->lpfuncdesc,
8512 This->typeattr.typekind == TKIND_DISPATCH);
8513 if (FAILED(hr))
8514 return hr;
8515 *pDescKind = DESCKIND_FUNCDESC;
8516 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8517 ITypeInfo_AddRef(*ppTInfo);
8518 return S_OK;
8519 } else {
8520 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->typeattr.cVars, szName);
8521 if(pVDesc){
8522 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
8523 if (FAILED(hr))
8524 return hr;
8525 *pDescKind = DESCKIND_VARDESC;
8526 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8527 ITypeInfo_AddRef(*ppTInfo);
8528 return S_OK;
8532 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
8533 /* recursive search */
8534 ITypeInfo *pTInfo;
8535 ITypeComp *pTComp;
8536 HRESULT hr;
8537 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
8538 if (SUCCEEDED(hr))
8540 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
8541 ITypeInfo_Release(pTInfo);
8543 if (SUCCEEDED(hr))
8545 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8546 ITypeComp_Release(pTComp);
8547 if (SUCCEEDED(hr) && *pDescKind == DESCKIND_FUNCDESC &&
8548 This->typeattr.typekind == TKIND_DISPATCH)
8550 FUNCDESC *tmp = pBindPtr->lpfuncdesc;
8551 hr = TLB_AllocAndInitFuncDesc(tmp, &pBindPtr->lpfuncdesc, TRUE);
8552 SysFreeString((BSTR)tmp);
8554 return hr;
8556 WARN("Could not search inherited interface!\n");
8558 if (hr == DISP_E_MEMBERNOTFOUND)
8559 hr = S_OK;
8560 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
8561 return hr;
8564 static HRESULT WINAPI ITypeComp_fnBindType(
8565 ITypeComp * iface,
8566 OLECHAR * szName,
8567 ULONG lHash,
8568 ITypeInfo ** ppTInfo,
8569 ITypeComp ** ppTComp)
8571 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
8573 /* strange behaviour (does nothing) but like the
8574 * original */
8576 if (!ppTInfo || !ppTComp)
8577 return E_POINTER;
8579 *ppTInfo = NULL;
8580 *ppTComp = NULL;
8582 return S_OK;
8585 static const ITypeCompVtbl tcompvt =
8588 ITypeComp_fnQueryInterface,
8589 ITypeComp_fnAddRef,
8590 ITypeComp_fnRelease,
8592 ITypeComp_fnBind,
8593 ITypeComp_fnBindType
8596 HRESULT WINAPI CreateTypeLib2(SYSKIND syskind, LPCOLESTR szFile,
8597 ICreateTypeLib2** ppctlib)
8599 ITypeLibImpl *This;
8600 HRESULT hres;
8602 TRACE("(%d,%s,%p)\n", syskind, debugstr_w(szFile), ppctlib);
8604 if (!szFile) return E_INVALIDARG;
8606 This = TypeLibImpl_Constructor();
8607 if (!This)
8608 return E_OUTOFMEMORY;
8610 This->lcid = GetSystemDefaultLCID();
8611 This->syskind = syskind;
8612 This->ptr_size = get_ptr_size(syskind);
8614 This->path = heap_alloc((lstrlenW(szFile) + 1) * sizeof(WCHAR));
8615 if (!This->path) {
8616 ITypeLib2_Release(&This->ITypeLib2_iface);
8617 return E_OUTOFMEMORY;
8619 lstrcpyW(This->path, szFile);
8621 hres = ITypeLib2_QueryInterface(&This->ITypeLib2_iface, &IID_ICreateTypeLib2, (LPVOID*)ppctlib);
8622 ITypeLib2_Release(&This->ITypeLib2_iface);
8623 return hres;
8626 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
8627 REFIID riid, void **object)
8629 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8631 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, object);
8634 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
8636 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8638 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
8641 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
8643 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8645 return ITypeLib2_Release(&This->ITypeLib2_iface);
8648 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
8649 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
8651 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8652 ITypeInfoImpl *info;
8653 HRESULT hres;
8655 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo);
8657 if (!ctinfo || !name)
8658 return E_INVALIDARG;
8660 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, name);
8661 if (info)
8662 return TYPE_E_NAMECONFLICT;
8664 if (This->typeinfos)
8665 This->typeinfos = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->typeinfos,
8666 sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1));
8667 else
8668 This->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*));
8670 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor();
8672 info->pTypeLib = This;
8673 info->Name = TLB_append_str(&This->name_list, name);
8674 info->index = This->TypeInfoCount;
8675 info->typeattr.typekind = kind;
8676 info->typeattr.cbAlignment = 4;
8678 switch (info->typeattr.typekind) {
8679 case TKIND_ENUM:
8680 case TKIND_INTERFACE:
8681 case TKIND_DISPATCH:
8682 case TKIND_COCLASS:
8683 info->typeattr.cbSizeInstance = This->ptr_size;
8684 break;
8685 case TKIND_RECORD:
8686 case TKIND_UNION:
8687 info->typeattr.cbSizeInstance = 0;
8688 break;
8689 case TKIND_MODULE:
8690 info->typeattr.cbSizeInstance = 2;
8691 break;
8692 case TKIND_ALIAS:
8693 info->typeattr.cbSizeInstance = -0x75;
8694 break;
8695 default:
8696 FIXME("unrecognized typekind %d\n", info->typeattr.typekind);
8697 info->typeattr.cbSizeInstance = 0xdeadbeef;
8698 break;
8701 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface,
8702 &IID_ICreateTypeInfo, (void **)ctinfo);
8703 if (FAILED(hres)) {
8704 ITypeInfo2_Release(&info->ITypeInfo2_iface);
8705 return hres;
8708 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase);
8710 ++This->TypeInfoCount;
8712 return S_OK;
8715 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
8716 LPOLESTR name)
8718 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8720 TRACE("%p %s\n", This, wine_dbgstr_w(name));
8722 if (!name)
8723 return E_INVALIDARG;
8725 This->Name = TLB_append_str(&This->name_list, name);
8727 return S_OK;
8730 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
8731 WORD majorVerNum, WORD minorVerNum)
8733 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8735 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
8737 This->ver_major = majorVerNum;
8738 This->ver_minor = minorVerNum;
8740 return S_OK;
8743 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
8744 REFGUID guid)
8746 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8748 TRACE("%p %s\n", This, debugstr_guid(guid));
8750 This->guid = TLB_append_guid(&This->guid_list, guid, -2);
8752 return S_OK;
8755 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
8756 LPOLESTR doc)
8758 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8760 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
8762 if (!doc)
8763 return E_INVALIDARG;
8765 This->DocString = TLB_append_str(&This->string_list, doc);
8767 return S_OK;
8770 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
8771 LPOLESTR helpFileName)
8773 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8775 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
8777 if (!helpFileName)
8778 return E_INVALIDARG;
8780 This->HelpFile = TLB_append_str(&This->string_list, helpFileName);
8782 return S_OK;
8785 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
8786 DWORD helpContext)
8788 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8790 TRACE("%p %d\n", This, helpContext);
8792 This->dwHelpContext = helpContext;
8794 return S_OK;
8797 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
8798 LCID lcid)
8800 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8802 TRACE("%p %x\n", This, lcid);
8804 This->set_lcid = lcid;
8806 return S_OK;
8809 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
8810 UINT libFlags)
8812 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8814 TRACE("%p %x\n", This, libFlags);
8816 This->libflags = libFlags;
8818 return S_OK;
8821 typedef struct tagWMSFT_SegContents {
8822 DWORD len;
8823 void *data;
8824 } WMSFT_SegContents;
8826 typedef struct tagWMSFT_TLBFile {
8827 MSFT_Header header;
8828 WMSFT_SegContents typeinfo_seg;
8829 WMSFT_SegContents impfile_seg;
8830 WMSFT_SegContents impinfo_seg;
8831 WMSFT_SegContents ref_seg;
8832 WMSFT_SegContents guidhash_seg;
8833 WMSFT_SegContents guid_seg;
8834 WMSFT_SegContents namehash_seg;
8835 WMSFT_SegContents name_seg;
8836 WMSFT_SegContents string_seg;
8837 WMSFT_SegContents typdesc_seg;
8838 WMSFT_SegContents arraydesc_seg;
8839 WMSFT_SegContents custdata_seg;
8840 WMSFT_SegContents cdguids_seg;
8841 MSFT_SegDir segdir;
8842 WMSFT_SegContents aux_seg;
8843 } WMSFT_TLBFile;
8845 static HRESULT WMSFT_compile_strings(ITypeLibImpl *This,
8846 WMSFT_TLBFile *file)
8848 TLBString *str;
8849 UINT last_offs;
8850 char *data;
8852 file->string_seg.len = 0;
8853 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8854 int size;
8856 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str), NULL, 0, NULL, NULL);
8857 if (size == 0)
8858 return E_UNEXPECTED;
8860 size += sizeof(INT16);
8861 if (size % 4)
8862 size = (size + 4) & ~0x3;
8863 if (size < 8)
8864 size = 8;
8866 file->string_seg.len += size;
8868 /* temporarily use str->offset to store the length of the aligned,
8869 * converted string */
8870 str->offset = size;
8873 file->string_seg.data = data = heap_alloc(file->string_seg.len);
8875 last_offs = 0;
8876 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8877 int size;
8879 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8880 data + sizeof(INT16), file->string_seg.len - last_offs - sizeof(INT16), NULL, NULL);
8881 if (size == 0) {
8882 heap_free(file->string_seg.data);
8883 return E_UNEXPECTED;
8886 *((INT16*)data) = size;
8888 memset(data + sizeof(INT16) + size, 0x57, str->offset - size - sizeof(INT16));
8890 size = str->offset;
8891 data += size;
8892 str->offset = last_offs;
8893 last_offs += size;
8896 return S_OK;
8899 static HRESULT WMSFT_compile_names(ITypeLibImpl *This,
8900 WMSFT_TLBFile *file)
8902 TLBString *str;
8903 UINT last_offs;
8904 char *data;
8905 MSFT_NameIntro *last_intro = NULL;
8907 file->header.nametablecount = 0;
8908 file->header.nametablechars = 0;
8910 file->name_seg.len = 0;
8911 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8912 int size;
8914 size = strlenW(str->str);
8915 file->header.nametablechars += size;
8916 file->header.nametablecount++;
8918 size = WideCharToMultiByte(CP_ACP, 0, str->str, size, NULL, 0, NULL, NULL);
8919 if (size == 0)
8920 return E_UNEXPECTED;
8922 size += sizeof(MSFT_NameIntro);
8923 if (size % 4)
8924 size = (size + 4) & ~0x3;
8925 if (size < 8)
8926 size = 8;
8928 file->name_seg.len += size;
8930 /* temporarily use str->offset to store the length of the aligned,
8931 * converted string */
8932 str->offset = size;
8935 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
8936 file->name_seg.data = data = heap_alloc(file->name_seg.len+1);
8938 last_offs = 0;
8939 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8940 int size, hash;
8941 MSFT_NameIntro *intro = (MSFT_NameIntro*)data;
8943 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8944 data + sizeof(MSFT_NameIntro),
8945 file->name_seg.len - last_offs - sizeof(MSFT_NameIntro), NULL, NULL);
8946 if (size == 0) {
8947 heap_free(file->name_seg.data);
8948 return E_UNEXPECTED;
8950 data[sizeof(MSFT_NameIntro) + size] = '\0';
8952 intro->hreftype = -1; /* TODO? */
8953 intro->namelen = size & 0xFF;
8954 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
8955 hash = LHashValOfNameSysA(This->syskind, This->lcid, data + sizeof(MSFT_NameIntro));
8956 intro->namelen |= hash << 16;
8957 intro->next_hash = ((DWORD*)file->namehash_seg.data)[hash & 0x7f];
8958 ((DWORD*)file->namehash_seg.data)[hash & 0x7f] = last_offs;
8960 memset(data + sizeof(MSFT_NameIntro) + size, 0x57,
8961 str->offset - size - sizeof(MSFT_NameIntro));
8963 /* update str->offset to actual value to use in other
8964 * compilation functions that require positions within
8965 * the string table */
8966 last_intro = intro;
8967 size = str->offset;
8968 data += size;
8969 str->offset = last_offs;
8970 last_offs += size;
8973 if(last_intro)
8974 last_intro->hreftype = 0; /* last one is 0? */
8976 return S_OK;
8979 static inline int hash_guid(GUID *guid)
8981 int i, hash = 0;
8983 for (i = 0; i < 8; i ++)
8984 hash ^= ((const short *)guid)[i];
8986 return hash & 0x1f;
8989 static HRESULT WMSFT_compile_guids(ITypeLibImpl *This, WMSFT_TLBFile *file)
8991 TLBGuid *guid;
8992 MSFT_GuidEntry *entry;
8993 DWORD offs;
8994 int hash_key, *guidhashtab;
8996 file->guid_seg.len = sizeof(MSFT_GuidEntry) * list_count(&This->guid_list);
8997 file->guid_seg.data = heap_alloc(file->guid_seg.len);
8999 entry = file->guid_seg.data;
9000 offs = 0;
9001 guidhashtab = file->guidhash_seg.data;
9002 LIST_FOR_EACH_ENTRY(guid, &This->guid_list, TLBGuid, entry){
9003 memcpy(&entry->guid, &guid->guid, sizeof(GUID));
9004 entry->hreftype = guid->hreftype;
9006 hash_key = hash_guid(&guid->guid);
9007 entry->next_hash = guidhashtab[hash_key];
9008 guidhashtab[hash_key] = offs;
9010 guid->offset = offs;
9011 offs += sizeof(MSFT_GuidEntry);
9012 ++entry;
9015 return S_OK;
9018 static DWORD WMSFT_encode_variant(VARIANT *value, WMSFT_TLBFile *file)
9020 VARIANT v = *value;
9021 VARTYPE arg_type = V_VT(value);
9022 int mask = 0;
9023 HRESULT hres;
9024 DWORD ret = file->custdata_seg.len;
9026 if(arg_type == VT_INT)
9027 arg_type = VT_I4;
9028 if(arg_type == VT_UINT)
9029 arg_type = VT_UI4;
9031 v = *value;
9032 if(V_VT(value) != arg_type) {
9033 hres = VariantChangeType(&v, value, 0, arg_type);
9034 if(FAILED(hres)){
9035 ERR("VariantChangeType failed: %08x\n", hres);
9036 return -1;
9040 /* Check if default value can be stored in-place */
9041 switch(arg_type){
9042 case VT_I4:
9043 case VT_UI4:
9044 mask = 0x3ffffff;
9045 if(V_UI4(&v) > 0x3ffffff)
9046 break;
9047 /* fall through */
9048 case VT_I1:
9049 case VT_UI1:
9050 case VT_BOOL:
9051 if(!mask)
9052 mask = 0xff;
9053 /* fall through */
9054 case VT_I2:
9055 case VT_UI2:
9056 if(!mask)
9057 mask = 0xffff;
9058 return ((0x80 + 0x4 * V_VT(value)) << 24) | (V_UI4(&v) & mask);
9061 /* have to allocate space in custdata_seg */
9062 switch(arg_type) {
9063 case VT_I4:
9064 case VT_R4:
9065 case VT_UI4:
9066 case VT_INT:
9067 case VT_UINT:
9068 case VT_HRESULT:
9069 case VT_PTR: {
9070 /* Construct the data to be allocated */
9071 int *data;
9073 if(file->custdata_seg.data){
9074 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + sizeof(int) * 2);
9075 data = (int *)(((char *)file->custdata_seg.data) + file->custdata_seg.len);
9076 file->custdata_seg.len += sizeof(int) * 2;
9077 }else{
9078 file->custdata_seg.len = sizeof(int) * 2;
9079 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9082 data[0] = V_VT(value) + (V_UI4(&v) << 16);
9083 data[1] = (V_UI4(&v) >> 16) + 0x57570000;
9085 /* TODO: Check if the encoded data is already present in custdata_seg */
9087 return ret;
9090 case VT_BSTR: {
9091 int i, len = (6+SysStringLen(V_BSTR(&v))+3) & ~0x3;
9092 char *data;
9094 if(file->custdata_seg.data){
9095 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + len);
9096 data = ((char *)file->custdata_seg.data) + file->custdata_seg.len;
9097 file->custdata_seg.len += len;
9098 }else{
9099 file->custdata_seg.len = len;
9100 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9103 *((unsigned short *)data) = V_VT(value);
9104 *((unsigned int *)(data+2)) = SysStringLen(V_BSTR(&v));
9105 for(i=0; i<SysStringLen(V_BSTR(&v)); i++) {
9106 if(V_BSTR(&v)[i] <= 0x7f)
9107 data[i+6] = V_BSTR(&v)[i];
9108 else
9109 data[i+6] = '?';
9111 WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], len-6, NULL, NULL);
9112 for(i=6+SysStringLen(V_BSTR(&v)); i<len; i++)
9113 data[i] = 0x57;
9115 /* TODO: Check if the encoded data is already present in custdata_seg */
9117 return ret;
9119 default:
9120 FIXME("Argument type not yet handled\n");
9121 return -1;
9125 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size);
9127 static DWORD WMSFT_append_arraydesc(ARRAYDESC *desc, WMSFT_TLBFile *file)
9129 DWORD offs = file->arraydesc_seg.len;
9130 DWORD *encoded;
9131 USHORT i;
9133 /* TODO: we should check for duplicates, but that's harder because each
9134 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9135 * at the library-level) */
9137 file->arraydesc_seg.len += (2 + desc->cDims * 2) * sizeof(DWORD);
9138 if(!file->arraydesc_seg.data)
9139 file->arraydesc_seg.data = heap_alloc(file->arraydesc_seg.len);
9140 else
9141 file->arraydesc_seg.data = heap_realloc(file->arraydesc_seg.data, file->arraydesc_seg.len);
9142 encoded = (DWORD*)((char *)file->arraydesc_seg.data + offs);
9144 encoded[0] = WMSFT_append_typedesc(&desc->tdescElem, file, NULL, NULL);
9145 encoded[1] = desc->cDims | ((desc->cDims * 2 * sizeof(DWORD)) << 16);
9146 for(i = 0; i < desc->cDims; ++i){
9147 encoded[2 + i * 2] = desc->rgbounds[i].cElements;
9148 encoded[2 + i * 2 + 1] = desc->rgbounds[i].lLbound;
9151 return offs;
9154 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size)
9156 DWORD junk;
9157 INT16 junk2;
9158 DWORD offs = 0;
9159 DWORD encoded[2];
9160 VARTYPE vt, subtype;
9161 char *data;
9163 if(!desc)
9164 return -1;
9166 if(!out_mix)
9167 out_mix = &junk;
9168 if(!out_size)
9169 out_size = &junk2;
9171 vt = desc->vt & VT_TYPEMASK;
9173 if(vt == VT_PTR || vt == VT_SAFEARRAY){
9174 DWORD mix;
9175 encoded[1] = WMSFT_append_typedesc(desc->u.lptdesc, file, &mix, out_size);
9176 encoded[0] = desc->vt | ((mix | VT_BYREF) << 16);
9177 *out_mix = 0x7FFF;
9178 *out_size += 2 * sizeof(DWORD);
9179 }else if(vt == VT_CARRAY){
9180 encoded[0] = desc->vt | (0x7FFE << 16);
9181 encoded[1] = WMSFT_append_arraydesc(desc->u.lpadesc, file);
9182 *out_mix = 0x7FFE;
9183 }else if(vt == VT_USERDEFINED){
9184 encoded[0] = desc->vt | (0x7FFF << 16);
9185 encoded[1] = desc->u.hreftype;
9186 *out_mix = 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9187 }else{
9188 TRACE("Mixing in-place, VT: 0x%x\n", desc->vt);
9190 switch(vt){
9191 case VT_INT:
9192 subtype = VT_I4;
9193 break;
9194 case VT_UINT:
9195 subtype = VT_UI4;
9196 break;
9197 case VT_VOID:
9198 subtype = VT_EMPTY;
9199 break;
9200 default:
9201 subtype = vt;
9202 break;
9205 *out_mix = subtype;
9206 return 0x80000000 | (subtype << 16) | desc->vt;
9209 data = file->typdesc_seg.data;
9210 while(offs < file->typdesc_seg.len){
9211 if(!memcmp(&data[offs], encoded, sizeof(encoded)))
9212 return offs;
9213 offs += sizeof(encoded);
9216 file->typdesc_seg.len += sizeof(encoded);
9217 if(!file->typdesc_seg.data)
9218 data = file->typdesc_seg.data = heap_alloc(file->typdesc_seg.len);
9219 else
9220 data = file->typdesc_seg.data = heap_realloc(file->typdesc_seg.data, file->typdesc_seg.len);
9222 memcpy(&data[offs], encoded, sizeof(encoded));
9224 return offs;
9227 static DWORD WMSFT_compile_custdata(struct list *custdata_list, WMSFT_TLBFile *file)
9229 WMSFT_SegContents *cdguids_seg = &file->cdguids_seg;
9230 DWORD ret = cdguids_seg->len, offs;
9231 MSFT_CDGuid *cdguid;
9232 TLBCustData *cd;
9234 if(list_empty(custdata_list))
9235 return -1;
9237 cdguids_seg->len += sizeof(MSFT_CDGuid) * list_count(custdata_list);
9238 if(!cdguids_seg->data){
9239 cdguid = cdguids_seg->data = heap_alloc(cdguids_seg->len);
9240 }else {
9241 cdguids_seg->data = heap_realloc(cdguids_seg->data, cdguids_seg->len);
9242 cdguid = (MSFT_CDGuid*)((char*)cdguids_seg->data + ret);
9245 offs = ret + sizeof(MSFT_CDGuid);
9246 LIST_FOR_EACH_ENTRY(cd, custdata_list, TLBCustData, entry){
9247 cdguid->GuidOffset = cd->guid->offset;
9248 cdguid->DataOffset = WMSFT_encode_variant(&cd->data, file);
9249 cdguid->next = offs;
9250 offs += sizeof(MSFT_CDGuid);
9251 ++cdguid;
9254 --cdguid;
9255 cdguid->next = -1;
9257 return ret;
9260 static DWORD WMSFT_compile_typeinfo_aux(ITypeInfoImpl *info,
9261 WMSFT_TLBFile *file)
9263 WMSFT_SegContents *aux_seg = &file->aux_seg;
9264 DWORD ret = aux_seg->len, i, j, recorded_size = 0, extra_size = 0;
9265 MSFT_VarRecord *varrecord;
9266 MSFT_FuncRecord *funcrecord;
9267 MEMBERID *memid;
9268 DWORD *name, *offsets, offs;
9270 for(i = 0; i < info->typeattr.cFuncs; ++i){
9271 TLBFuncDesc *desc = &info->funcdescs[i];
9273 recorded_size += 6 * sizeof(INT); /* mandatory fields */
9275 /* optional fields */
9276 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9277 if(!list_empty(&desc->custdata_list))
9278 recorded_size += 7 * sizeof(INT);
9279 else if(desc->HelpStringContext != 0)
9280 recorded_size += 6 * sizeof(INT);
9281 /* res9? resA? */
9282 else if(desc->Entry)
9283 recorded_size += 3 * sizeof(INT);
9284 else if(desc->HelpString)
9285 recorded_size += 2 * sizeof(INT);
9286 else if(desc->helpcontext)
9287 recorded_size += sizeof(INT);
9289 recorded_size += desc->funcdesc.cParams * sizeof(MSFT_ParameterInfo);
9291 for(j = 0; j < desc->funcdesc.cParams; ++j){
9292 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9293 recorded_size += desc->funcdesc.cParams * sizeof(INT);
9294 break;
9298 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9301 for(i = 0; i < info->typeattr.cVars; ++i){
9302 TLBVarDesc *desc = &info->vardescs[i];
9304 recorded_size += 5 * sizeof(INT); /* mandatory fields */
9306 /* optional fields */
9307 if(desc->HelpStringContext != 0)
9308 recorded_size += 5 * sizeof(INT);
9309 else if(!list_empty(&desc->custdata_list))
9310 recorded_size += 4 * sizeof(INT);
9311 /* res9? */
9312 else if(desc->HelpString)
9313 recorded_size += 2 * sizeof(INT);
9314 else if(desc->HelpContext != 0)
9315 recorded_size += sizeof(INT);
9317 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9320 if(!recorded_size && !extra_size)
9321 return ret;
9323 extra_size += sizeof(INT); /* total aux size for this typeinfo */
9325 aux_seg->len += recorded_size + extra_size;
9327 aux_seg->len += sizeof(INT) * (info->typeattr.cVars + info->typeattr.cFuncs); /* offsets at the end */
9329 if(aux_seg->data)
9330 aux_seg->data = heap_realloc(aux_seg->data, aux_seg->len);
9331 else
9332 aux_seg->data = heap_alloc(aux_seg->len);
9334 *((DWORD*)((char *)aux_seg->data + ret)) = recorded_size;
9336 offsets = (DWORD*)((char *)aux_seg->data + ret + recorded_size + extra_size);
9337 offs = 0;
9339 funcrecord = (MSFT_FuncRecord*)(((char *)aux_seg->data) + ret + sizeof(INT));
9340 for(i = 0; i < info->typeattr.cFuncs; ++i){
9341 TLBFuncDesc *desc = &info->funcdescs[i];
9342 DWORD size = 6 * sizeof(INT), paramdefault_size = 0, *paramdefault;
9344 funcrecord->funcdescsize = sizeof(desc->funcdesc) + desc->funcdesc.cParams * sizeof(ELEMDESC);
9345 funcrecord->DataType = WMSFT_append_typedesc(&desc->funcdesc.elemdescFunc.tdesc, file, NULL, &funcrecord->funcdescsize);
9346 funcrecord->Flags = desc->funcdesc.wFuncFlags;
9347 funcrecord->VtableOffset = desc->funcdesc.oVft;
9349 /* FKCCIC:
9350 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9351 * ^^^funckind
9352 * ^^^ ^invkind
9353 * ^has_cust_data
9354 * ^^^^callconv
9355 * ^has_param_defaults
9356 * ^oEntry_is_intresource
9358 funcrecord->FKCCIC =
9359 desc->funcdesc.funckind |
9360 (desc->funcdesc.invkind << 3) |
9361 (list_empty(&desc->custdata_list) ? 0 : 0x80) |
9362 (desc->funcdesc.callconv << 8);
9364 if(desc->Entry && desc->Entry != (TLBString*)-1 && IS_INTRESOURCE(desc->Entry))
9365 funcrecord->FKCCIC |= 0x2000;
9367 for(j = 0; j < desc->funcdesc.cParams; ++j){
9368 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9369 paramdefault_size = sizeof(INT) * desc->funcdesc.cParams;
9370 funcrecord->funcdescsize += sizeof(PARAMDESCEX);
9373 if(paramdefault_size > 0)
9374 funcrecord->FKCCIC |= 0x1000;
9376 funcrecord->nrargs = desc->funcdesc.cParams;
9377 funcrecord->nroargs = desc->funcdesc.cParamsOpt;
9379 /* optional fields */
9380 /* res9? resA? */
9381 if(!list_empty(&desc->custdata_list)){
9382 size += 7 * sizeof(INT);
9383 funcrecord->HelpContext = desc->helpcontext;
9384 if(desc->HelpString)
9385 funcrecord->oHelpString = desc->HelpString->offset;
9386 else
9387 funcrecord->oHelpString = -1;
9388 if(!desc->Entry)
9389 funcrecord->oEntry = -1;
9390 else if(IS_INTRESOURCE(desc->Entry))
9391 funcrecord->oEntry = LOWORD(desc->Entry);
9392 else
9393 funcrecord->oEntry = desc->Entry->offset;
9394 funcrecord->res9 = -1;
9395 funcrecord->resA = -1;
9396 funcrecord->HelpStringContext = desc->HelpStringContext;
9397 funcrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9398 }else if(desc->HelpStringContext != 0){
9399 size += 6 * sizeof(INT);
9400 funcrecord->HelpContext = desc->helpcontext;
9401 if(desc->HelpString)
9402 funcrecord->oHelpString = desc->HelpString->offset;
9403 else
9404 funcrecord->oHelpString = -1;
9405 if(!desc->Entry)
9406 funcrecord->oEntry = -1;
9407 else if(IS_INTRESOURCE(desc->Entry))
9408 funcrecord->oEntry = LOWORD(desc->Entry);
9409 else
9410 funcrecord->oEntry = desc->Entry->offset;
9411 funcrecord->res9 = -1;
9412 funcrecord->resA = -1;
9413 funcrecord->HelpStringContext = desc->HelpStringContext;
9414 }else if(desc->Entry){
9415 size += 3 * sizeof(INT);
9416 funcrecord->HelpContext = desc->helpcontext;
9417 if(desc->HelpString)
9418 funcrecord->oHelpString = desc->HelpString->offset;
9419 else
9420 funcrecord->oHelpString = -1;
9421 if(!desc->Entry)
9422 funcrecord->oEntry = -1;
9423 else if(IS_INTRESOURCE(desc->Entry))
9424 funcrecord->oEntry = LOWORD(desc->Entry);
9425 else
9426 funcrecord->oEntry = desc->Entry->offset;
9427 }else if(desc->HelpString){
9428 size += 2 * sizeof(INT);
9429 funcrecord->HelpContext = desc->helpcontext;
9430 funcrecord->oHelpString = desc->HelpString->offset;
9431 }else if(desc->helpcontext){
9432 size += sizeof(INT);
9433 funcrecord->HelpContext = desc->helpcontext;
9436 paramdefault = (DWORD*)((char *)funcrecord + size);
9437 size += paramdefault_size;
9439 for(j = 0; j < desc->funcdesc.cParams; ++j){
9440 MSFT_ParameterInfo *info = (MSFT_ParameterInfo*)(((char *)funcrecord) + size);
9442 info->DataType = WMSFT_append_typedesc(&desc->funcdesc.lprgelemdescParam[j].tdesc, file, NULL, &funcrecord->funcdescsize);
9443 if(desc->pParamDesc[j].Name)
9444 info->oName = desc->pParamDesc[j].Name->offset;
9445 else
9446 info->oName = -1;
9447 info->Flags = desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags;
9449 if(paramdefault_size){
9450 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
9451 *paramdefault = WMSFT_encode_variant(&desc->funcdesc.lprgelemdescParam[j].u.paramdesc.pparamdescex->varDefaultValue, file);
9452 else if(paramdefault_size)
9453 *paramdefault = -1;
9454 ++paramdefault;
9457 size += sizeof(MSFT_ParameterInfo);
9460 funcrecord->Info = size | (i << 16); /* is it just the index? */
9462 *offsets = offs;
9463 offs += size;
9464 ++offsets;
9466 funcrecord = (MSFT_FuncRecord*)(((char*)funcrecord) + size);
9469 varrecord = (MSFT_VarRecord*)funcrecord;
9470 for(i = 0; i < info->typeattr.cVars; ++i){
9471 TLBVarDesc *desc = &info->vardescs[i];
9472 DWORD size = 5 * sizeof(INT);
9474 varrecord->vardescsize = sizeof(desc->vardesc);
9475 varrecord->DataType = WMSFT_append_typedesc(&desc->vardesc.elemdescVar.tdesc, file, NULL, &varrecord->vardescsize);
9476 varrecord->Flags = desc->vardesc.wVarFlags;
9477 varrecord->VarKind = desc->vardesc.varkind;
9479 if(desc->vardesc.varkind == VAR_CONST){
9480 varrecord->vardescsize += sizeof(VARIANT);
9481 varrecord->OffsValue = WMSFT_encode_variant(desc->vardesc.u.lpvarValue, file);
9482 }else
9483 varrecord->OffsValue = desc->vardesc.u.oInst;
9485 /* res9? */
9486 if(desc->HelpStringContext != 0){
9487 size += 5 * sizeof(INT);
9488 varrecord->HelpContext = desc->HelpContext;
9489 if(desc->HelpString)
9490 varrecord->HelpString = desc->HelpString->offset;
9491 else
9492 varrecord->HelpString = -1;
9493 varrecord->res9 = -1;
9494 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9495 varrecord->HelpStringContext = desc->HelpStringContext;
9496 }else if(!list_empty(&desc->custdata_list)){
9497 size += 4 * sizeof(INT);
9498 varrecord->HelpContext = desc->HelpContext;
9499 if(desc->HelpString)
9500 varrecord->HelpString = desc->HelpString->offset;
9501 else
9502 varrecord->HelpString = -1;
9503 varrecord->res9 = -1;
9504 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9505 }else if(desc->HelpString){
9506 size += 2 * sizeof(INT);
9507 varrecord->HelpContext = desc->HelpContext;
9508 if(desc->HelpString)
9509 varrecord->HelpString = desc->HelpString->offset;
9510 else
9511 varrecord->HelpString = -1;
9512 }else if(desc->HelpContext != 0){
9513 size += sizeof(INT);
9514 varrecord->HelpContext = desc->HelpContext;
9517 varrecord->Info = size | (i << 16);
9519 *offsets = offs;
9520 offs += size;
9521 ++offsets;
9523 varrecord = (MSFT_VarRecord*)(((char*)varrecord) + size);
9526 memid = (MEMBERID*)varrecord;
9527 for(i = 0; i < info->typeattr.cFuncs; ++i){
9528 TLBFuncDesc *desc = &info->funcdescs[i];
9529 *memid = desc->funcdesc.memid;
9530 ++memid;
9532 for(i = 0; i < info->typeattr.cVars; ++i){
9533 TLBVarDesc *desc = &info->vardescs[i];
9534 *memid = desc->vardesc.memid;
9535 ++memid;
9538 name = (UINT*)memid;
9539 for(i = 0; i < info->typeattr.cFuncs; ++i){
9540 TLBFuncDesc *desc = &info->funcdescs[i];
9541 if(desc->Name)
9542 *name = desc->Name->offset;
9543 else
9544 *name = -1;
9545 ++name;
9547 for(i = 0; i < info->typeattr.cVars; ++i){
9548 TLBVarDesc *desc = &info->vardescs[i];
9549 if(desc->Name)
9550 *name = desc->Name->offset;
9551 else
9552 *name = -1;
9553 ++name;
9556 return ret;
9559 typedef struct tagWMSFT_RefChunk {
9560 DWORD href;
9561 DWORD res04;
9562 DWORD res08;
9563 DWORD next;
9564 } WMSFT_RefChunk;
9566 static DWORD WMSFT_compile_typeinfo_ref(ITypeInfoImpl *info, WMSFT_TLBFile *file)
9568 DWORD offs = file->ref_seg.len, i;
9569 WMSFT_RefChunk *chunk;
9571 file->ref_seg.len += info->typeattr.cImplTypes * sizeof(WMSFT_RefChunk);
9572 if(!file->ref_seg.data)
9573 file->ref_seg.data = heap_alloc(file->ref_seg.len);
9574 else
9575 file->ref_seg.data = heap_realloc(file->ref_seg.data, file->ref_seg.len);
9577 chunk = (WMSFT_RefChunk*)((char*)file->ref_seg.data + offs);
9579 for(i = 0; i < info->typeattr.cImplTypes; ++i){
9580 chunk->href = info->impltypes[i].hRef;
9581 chunk->res04 = info->impltypes[i].implflags;
9582 chunk->res08 = -1;
9583 if(i < info->typeattr.cImplTypes - 1)
9584 chunk->next = offs + sizeof(WMSFT_RefChunk) * (i + 1);
9585 else
9586 chunk->next = -1;
9587 ++chunk;
9590 return offs;
9593 static DWORD WMSFT_compile_typeinfo(ITypeInfoImpl *info, INT16 index, WMSFT_TLBFile *file, char *data)
9595 DWORD size;
9597 size = sizeof(MSFT_TypeInfoBase);
9599 if(data){
9600 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase*)data;
9601 if(info->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
9602 base->typekind = TKIND_DISPATCH;
9603 else
9604 base->typekind = info->typeattr.typekind;
9605 base->typekind |= index << 16; /* TODO: There are some other flags here */
9606 base->typekind |= (info->typeattr.cbAlignment << 11) | (info->typeattr.cbAlignment << 6);
9607 base->memoffset = WMSFT_compile_typeinfo_aux(info, file);
9608 base->res2 = 0;
9609 base->res3 = 0;
9610 base->res4 = 3;
9611 base->res5 = 0;
9612 base->cElement = (info->typeattr.cVars << 16) | info->typeattr.cFuncs;
9613 base->res7 = 0;
9614 base->res8 = 0;
9615 base->res9 = 0;
9616 base->resA = 0;
9617 if(info->guid)
9618 base->posguid = info->guid->offset;
9619 else
9620 base->posguid = -1;
9621 base->flags = info->typeattr.wTypeFlags;
9622 if(info->Name) {
9623 base->NameOffset = info->Name->offset;
9625 ((unsigned char*)file->name_seg.data)[info->Name->offset+9] = 0x38;
9626 *(HREFTYPE*)((unsigned char*)file->name_seg.data+info->Name->offset) = info->hreftype;
9627 }else {
9628 base->NameOffset = -1;
9630 base->version = (info->typeattr.wMinorVerNum << 16) | info->typeattr.wMajorVerNum;
9631 if(info->DocString)
9632 base->docstringoffs = info->DocString->offset;
9633 else
9634 base->docstringoffs = -1;
9635 base->helpstringcontext = info->dwHelpStringContext;
9636 base->helpcontext = info->dwHelpContext;
9637 base->oCustData = WMSFT_compile_custdata(info->pcustdata_list, file);
9638 base->cImplTypes = info->typeattr.cImplTypes;
9639 base->cbSizeVft = info->typeattr.cbSizeVft;
9640 base->size = info->typeattr.cbSizeInstance;
9641 if(info->typeattr.typekind == TKIND_COCLASS){
9642 base->datatype1 = WMSFT_compile_typeinfo_ref(info, file);
9643 }else if(info->typeattr.typekind == TKIND_ALIAS){
9644 base->datatype1 = WMSFT_append_typedesc(info->tdescAlias, file, NULL, NULL);
9645 }else if(info->typeattr.typekind == TKIND_MODULE){
9646 if(info->DllName)
9647 base->datatype1 = info->DllName->offset;
9648 else
9649 base->datatype1 = -1;
9650 }else{
9651 if(info->typeattr.cImplTypes > 0)
9652 base->datatype1 = info->impltypes[0].hRef;
9653 else
9654 base->datatype1 = -1;
9656 base->datatype2 = index; /* FIXME: i think there's more here */
9657 base->res18 = 0;
9658 base->res19 = -1;
9661 return size;
9664 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl *This, WMSFT_TLBFile *file, DWORD *junk)
9666 UINT i;
9668 file->typeinfo_seg.len = 0;
9669 for(i = 0; i < This->TypeInfoCount; ++i){
9670 ITypeInfoImpl *info = This->typeinfos[i];
9671 *junk = file->typeinfo_seg.len;
9672 ++junk;
9673 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, NULL, NULL);
9676 file->typeinfo_seg.data = heap_alloc(file->typeinfo_seg.len);
9677 memset(file->typeinfo_seg.data, 0x96, file->typeinfo_seg.len);
9679 file->aux_seg.len = 0;
9680 file->aux_seg.data = NULL;
9682 file->typeinfo_seg.len = 0;
9683 for(i = 0; i < This->TypeInfoCount; ++i){
9684 ITypeInfoImpl *info = This->typeinfos[i];
9685 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, file,
9686 ((char *)file->typeinfo_seg.data) + file->typeinfo_seg.len);
9690 typedef struct tagWMSFT_ImpFile {
9691 INT guid_offs;
9692 LCID lcid;
9693 DWORD version;
9694 } WMSFT_ImpFile;
9696 static void WMSFT_compile_impfile(ITypeLibImpl *This, WMSFT_TLBFile *file)
9698 TLBImpLib *implib;
9699 WMSFT_ImpFile *impfile;
9700 char *data;
9701 DWORD last_offs = 0;
9703 file->impfile_seg.len = 0;
9704 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9705 int size = 0;
9707 if(implib->name){
9708 WCHAR *path = strrchrW(implib->name, '\\');
9709 if(path)
9710 ++path;
9711 else
9712 path = implib->name;
9713 size = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path), NULL, 0, NULL, NULL);
9714 if (size == 0)
9715 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9718 size += sizeof(INT16);
9719 if (size % 4)
9720 size = (size + 4) & ~0x3;
9721 if (size < 8)
9722 size = 8;
9724 file->impfile_seg.len += sizeof(WMSFT_ImpFile) + size;
9727 data = file->impfile_seg.data = heap_alloc(file->impfile_seg.len);
9729 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9730 int strlen = 0, size;
9732 impfile = (WMSFT_ImpFile*)data;
9733 impfile->guid_offs = implib->guid->offset;
9734 impfile->lcid = implib->lcid;
9735 impfile->version = (implib->wVersionMinor << 16) | implib->wVersionMajor;
9737 data += sizeof(WMSFT_ImpFile);
9739 if(implib->name){
9740 WCHAR *path= strrchrW(implib->name, '\\');
9741 if(path)
9742 ++path;
9743 else
9744 path = implib->name;
9745 strlen = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path),
9746 data + sizeof(INT16), file->impfile_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9747 if (strlen == 0)
9748 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9751 *((INT16*)data) = (strlen << 2) | 1; /* FIXME: is that a flag, or what? */
9753 size = strlen + sizeof(INT16);
9754 if (size % 4)
9755 size = (size + 4) & ~0x3;
9756 if (size < 8)
9757 size = 8;
9758 memset(data + sizeof(INT16) + strlen, 0x57, size - strlen - sizeof(INT16));
9760 data += size;
9761 implib->offset = last_offs;
9762 last_offs += size + sizeof(WMSFT_ImpFile);
9766 static void WMSFT_compile_impinfo(ITypeLibImpl *This, WMSFT_TLBFile *file)
9768 MSFT_ImpInfo *info;
9769 TLBRefType *ref_type;
9770 UINT i = 0;
9772 WMSFT_compile_impfile(This, file);
9774 file->impinfo_seg.len = sizeof(MSFT_ImpInfo) * list_count(&This->ref_list);
9775 info = file->impinfo_seg.data = heap_alloc(file->impinfo_seg.len);
9777 LIST_FOR_EACH_ENTRY(ref_type, &This->ref_list, TLBRefType, entry){
9778 info->flags = i | ((ref_type->tkind & 0xFF) << 24);
9779 if(ref_type->index == TLB_REF_USE_GUID){
9780 info->flags |= MSFT_IMPINFO_OFFSET_IS_GUID;
9781 info->oGuid = ref_type->guid->offset;
9782 }else
9783 info->oGuid = ref_type->index;
9784 info->oImpFile = ref_type->pImpTLInfo->offset;
9785 ++i;
9786 ++info;
9790 static void WMSFT_compile_guidhash(ITypeLibImpl *This, WMSFT_TLBFile *file)
9792 file->guidhash_seg.len = 0x80;
9793 file->guidhash_seg.data = heap_alloc(file->guidhash_seg.len);
9794 memset(file->guidhash_seg.data, 0xFF, file->guidhash_seg.len);
9797 static void WMSFT_compile_namehash(ITypeLibImpl *This, WMSFT_TLBFile *file)
9799 file->namehash_seg.len = 0x200;
9800 file->namehash_seg.data = heap_alloc(file->namehash_seg.len);
9801 memset(file->namehash_seg.data, 0xFF, file->namehash_seg.len);
9804 static void tmp_fill_segdir_seg(MSFT_pSeg *segdir, WMSFT_SegContents *contents, DWORD *running_offset)
9806 if(contents && contents->len){
9807 segdir->offset = *running_offset;
9808 segdir->length = contents->len;
9809 *running_offset += segdir->length;
9810 }else{
9811 segdir->offset = -1;
9812 segdir->length = 0;
9815 /* TODO: do these ever change? */
9816 segdir->res08 = -1;
9817 segdir->res0c = 0xf;
9820 static void WMSFT_write_segment(HANDLE outfile, WMSFT_SegContents *segment)
9822 DWORD written;
9823 if(segment)
9824 WriteFile(outfile, segment->data, segment->len, &written, NULL);
9827 static HRESULT WMSFT_fixup_typeinfos(ITypeLibImpl *This, WMSFT_TLBFile *file,
9828 DWORD file_len)
9830 DWORD i;
9831 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase *)file->typeinfo_seg.data;
9833 for(i = 0; i < This->TypeInfoCount; ++i){
9834 base->memoffset += file_len;
9835 ++base;
9838 return S_OK;
9841 static void WMSFT_free_file(WMSFT_TLBFile *file)
9843 HeapFree(GetProcessHeap(), 0, file->typeinfo_seg.data);
9844 HeapFree(GetProcessHeap(), 0, file->guidhash_seg.data);
9845 HeapFree(GetProcessHeap(), 0, file->guid_seg.data);
9846 HeapFree(GetProcessHeap(), 0, file->ref_seg.data);
9847 HeapFree(GetProcessHeap(), 0, file->impinfo_seg.data);
9848 HeapFree(GetProcessHeap(), 0, file->impfile_seg.data);
9849 HeapFree(GetProcessHeap(), 0, file->namehash_seg.data);
9850 HeapFree(GetProcessHeap(), 0, file->name_seg.data);
9851 HeapFree(GetProcessHeap(), 0, file->string_seg.data);
9852 HeapFree(GetProcessHeap(), 0, file->typdesc_seg.data);
9853 HeapFree(GetProcessHeap(), 0, file->arraydesc_seg.data);
9854 HeapFree(GetProcessHeap(), 0, file->custdata_seg.data);
9855 HeapFree(GetProcessHeap(), 0, file->cdguids_seg.data);
9856 HeapFree(GetProcessHeap(), 0, file->aux_seg.data);
9859 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
9861 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9862 WMSFT_TLBFile file;
9863 DWORD written, junk_size, junk_offs, running_offset;
9864 BOOL br;
9865 HANDLE outfile;
9866 HRESULT hres;
9867 DWORD *junk;
9868 UINT i;
9870 TRACE("%p\n", This);
9872 for(i = 0; i < This->TypeInfoCount; ++i)
9873 if(This->typeinfos[i]->needs_layout)
9874 ICreateTypeInfo2_LayOut(&This->typeinfos[i]->ICreateTypeInfo2_iface);
9876 memset(&file, 0, sizeof(file));
9878 file.header.magic1 = 0x5446534D;
9879 file.header.magic2 = 0x00010002;
9880 file.header.lcid = This->set_lcid ? This->set_lcid : MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
9881 file.header.lcid2 = This->set_lcid;
9882 file.header.varflags = 0x40 | This->syskind;
9883 if (This->HelpFile)
9884 file.header.varflags |= 0x10;
9885 if (This->HelpStringDll)
9886 file.header.varflags |= HELPDLLFLAG;
9887 file.header.version = (This->ver_minor << 16) | This->ver_major;
9888 file.header.flags = This->libflags;
9889 file.header.helpstringcontext = 0; /* TODO - SetHelpStringContext not implemented yet */
9890 file.header.helpcontext = This->dwHelpContext;
9891 file.header.res44 = 0x20;
9892 file.header.res48 = 0x80;
9893 file.header.dispatchpos = This->dispatch_href;
9895 WMSFT_compile_namehash(This, &file);
9896 /* do name and string compilation to get offsets for other compilations */
9897 hres = WMSFT_compile_names(This, &file);
9898 if (FAILED(hres)){
9899 WMSFT_free_file(&file);
9900 return hres;
9903 hres = WMSFT_compile_strings(This, &file);
9904 if (FAILED(hres)){
9905 WMSFT_free_file(&file);
9906 return hres;
9909 WMSFT_compile_guidhash(This, &file);
9910 hres = WMSFT_compile_guids(This, &file);
9911 if (FAILED(hres)){
9912 WMSFT_free_file(&file);
9913 return hres;
9916 if(This->HelpFile)
9917 file.header.helpfile = This->HelpFile->offset;
9918 else
9919 file.header.helpfile = -1;
9921 if(This->DocString)
9922 file.header.helpstring = This->DocString->offset;
9923 else
9924 file.header.helpstring = -1;
9926 /* do some more segment compilation */
9927 file.header.nimpinfos = list_count(&This->ref_list);
9928 file.header.nrtypeinfos = This->TypeInfoCount;
9930 if(This->Name)
9931 file.header.NameOffset = This->Name->offset;
9932 else
9933 file.header.NameOffset = -1;
9935 file.header.CustomDataOffset = WMSFT_compile_custdata(&This->custdata_list, &file);
9937 if(This->guid)
9938 file.header.posguid = This->guid->offset;
9939 else
9940 file.header.posguid = -1;
9942 junk_size = file.header.nrtypeinfos * sizeof(DWORD);
9943 if(file.header.varflags & HELPDLLFLAG)
9944 junk_size += sizeof(DWORD);
9945 if(junk_size){
9946 junk = heap_alloc_zero(junk_size);
9947 if(file.header.varflags & HELPDLLFLAG){
9948 *junk = This->HelpStringDll->offset;
9949 junk_offs = 1;
9950 }else
9951 junk_offs = 0;
9952 }else{
9953 junk = NULL;
9954 junk_offs = 0;
9957 WMSFT_compile_typeinfo_seg(This, &file, junk + junk_offs);
9958 WMSFT_compile_impinfo(This, &file);
9960 running_offset = 0;
9962 TRACE("header at: 0x%x\n", running_offset);
9963 running_offset += sizeof(file.header);
9965 TRACE("junk at: 0x%x\n", running_offset);
9966 running_offset += junk_size;
9968 TRACE("segdir at: 0x%x\n", running_offset);
9969 running_offset += sizeof(file.segdir);
9971 TRACE("typeinfo at: 0x%x\n", running_offset);
9972 tmp_fill_segdir_seg(&file.segdir.pTypeInfoTab, &file.typeinfo_seg, &running_offset);
9974 TRACE("guidhashtab at: 0x%x\n", running_offset);
9975 tmp_fill_segdir_seg(&file.segdir.pGuidHashTab, &file.guidhash_seg, &running_offset);
9977 TRACE("guidtab at: 0x%x\n", running_offset);
9978 tmp_fill_segdir_seg(&file.segdir.pGuidTab, &file.guid_seg, &running_offset);
9980 TRACE("reftab at: 0x%x\n", running_offset);
9981 tmp_fill_segdir_seg(&file.segdir.pRefTab, &file.ref_seg, &running_offset);
9983 TRACE("impinfo at: 0x%x\n", running_offset);
9984 tmp_fill_segdir_seg(&file.segdir.pImpInfo, &file.impinfo_seg, &running_offset);
9986 TRACE("impfiles at: 0x%x\n", running_offset);
9987 tmp_fill_segdir_seg(&file.segdir.pImpFiles, &file.impfile_seg, &running_offset);
9989 TRACE("namehashtab at: 0x%x\n", running_offset);
9990 tmp_fill_segdir_seg(&file.segdir.pNameHashTab, &file.namehash_seg, &running_offset);
9992 TRACE("nametab at: 0x%x\n", running_offset);
9993 tmp_fill_segdir_seg(&file.segdir.pNametab, &file.name_seg, &running_offset);
9995 TRACE("stringtab at: 0x%x\n", running_offset);
9996 tmp_fill_segdir_seg(&file.segdir.pStringtab, &file.string_seg, &running_offset);
9998 TRACE("typdesc at: 0x%x\n", running_offset);
9999 tmp_fill_segdir_seg(&file.segdir.pTypdescTab, &file.typdesc_seg, &running_offset);
10001 TRACE("arraydescriptions at: 0x%x\n", running_offset);
10002 tmp_fill_segdir_seg(&file.segdir.pArrayDescriptions, &file.arraydesc_seg, &running_offset);
10004 TRACE("custdata at: 0x%x\n", running_offset);
10005 tmp_fill_segdir_seg(&file.segdir.pCustData, &file.custdata_seg, &running_offset);
10007 TRACE("cdguids at: 0x%x\n", running_offset);
10008 tmp_fill_segdir_seg(&file.segdir.pCDGuids, &file.cdguids_seg, &running_offset);
10010 TRACE("res0e at: 0x%x\n", running_offset);
10011 tmp_fill_segdir_seg(&file.segdir.res0e, NULL, &running_offset);
10013 TRACE("res0f at: 0x%x\n", running_offset);
10014 tmp_fill_segdir_seg(&file.segdir.res0f, NULL, &running_offset);
10016 TRACE("aux_seg at: 0x%x\n", running_offset);
10018 WMSFT_fixup_typeinfos(This, &file, running_offset);
10020 outfile = CreateFileW(This->path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
10021 FILE_ATTRIBUTE_NORMAL, 0);
10022 if (outfile == INVALID_HANDLE_VALUE){
10023 WMSFT_free_file(&file);
10024 heap_free(junk);
10025 return TYPE_E_IOERROR;
10028 br = WriteFile(outfile, &file.header, sizeof(file.header), &written, NULL);
10029 if (!br) {
10030 WMSFT_free_file(&file);
10031 CloseHandle(outfile);
10032 heap_free(junk);
10033 return TYPE_E_IOERROR;
10036 br = WriteFile(outfile, junk, junk_size, &written, NULL);
10037 heap_free(junk);
10038 if (!br) {
10039 WMSFT_free_file(&file);
10040 CloseHandle(outfile);
10041 return TYPE_E_IOERROR;
10044 br = WriteFile(outfile, &file.segdir, sizeof(file.segdir), &written, NULL);
10045 if (!br) {
10046 WMSFT_free_file(&file);
10047 CloseHandle(outfile);
10048 return TYPE_E_IOERROR;
10051 WMSFT_write_segment(outfile, &file.typeinfo_seg);
10052 WMSFT_write_segment(outfile, &file.guidhash_seg);
10053 WMSFT_write_segment(outfile, &file.guid_seg);
10054 WMSFT_write_segment(outfile, &file.ref_seg);
10055 WMSFT_write_segment(outfile, &file.impinfo_seg);
10056 WMSFT_write_segment(outfile, &file.impfile_seg);
10057 WMSFT_write_segment(outfile, &file.namehash_seg);
10058 WMSFT_write_segment(outfile, &file.name_seg);
10059 WMSFT_write_segment(outfile, &file.string_seg);
10060 WMSFT_write_segment(outfile, &file.typdesc_seg);
10061 WMSFT_write_segment(outfile, &file.arraydesc_seg);
10062 WMSFT_write_segment(outfile, &file.custdata_seg);
10063 WMSFT_write_segment(outfile, &file.cdguids_seg);
10064 WMSFT_write_segment(outfile, &file.aux_seg);
10066 WMSFT_free_file(&file);
10068 CloseHandle(outfile);
10070 return S_OK;
10073 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
10074 LPOLESTR name)
10076 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10077 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
10078 return E_NOTIMPL;
10081 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
10082 REFGUID guid, VARIANT *varVal)
10084 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10085 TLBGuid *tlbguid;
10087 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
10089 if (!guid || !varVal)
10090 return E_INVALIDARG;
10092 tlbguid = TLB_append_guid(&This->guid_list, guid, -1);
10094 return TLB_set_custdata(&This->custdata_list, tlbguid, varVal);
10097 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
10098 ULONG helpStringContext)
10100 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10101 FIXME("%p %u - stub\n", This, helpStringContext);
10102 return E_NOTIMPL;
10105 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
10106 LPOLESTR filename)
10108 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10109 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
10111 if (!filename)
10112 return E_INVALIDARG;
10114 This->HelpStringDll = TLB_append_str(&This->string_list, filename);
10116 return S_OK;
10119 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
10120 ICreateTypeLib2_fnQueryInterface,
10121 ICreateTypeLib2_fnAddRef,
10122 ICreateTypeLib2_fnRelease,
10123 ICreateTypeLib2_fnCreateTypeInfo,
10124 ICreateTypeLib2_fnSetName,
10125 ICreateTypeLib2_fnSetVersion,
10126 ICreateTypeLib2_fnSetGuid,
10127 ICreateTypeLib2_fnSetDocString,
10128 ICreateTypeLib2_fnSetHelpFileName,
10129 ICreateTypeLib2_fnSetHelpContext,
10130 ICreateTypeLib2_fnSetLcid,
10131 ICreateTypeLib2_fnSetLibFlags,
10132 ICreateTypeLib2_fnSaveAllChanges,
10133 ICreateTypeLib2_fnDeleteTypeInfo,
10134 ICreateTypeLib2_fnSetCustData,
10135 ICreateTypeLib2_fnSetHelpStringContext,
10136 ICreateTypeLib2_fnSetHelpStringDll
10139 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
10140 REFIID riid, void **object)
10142 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10144 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, object);
10147 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
10149 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10151 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
10154 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
10156 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10158 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
10161 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
10162 REFGUID guid)
10164 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10166 TRACE("%p %s\n", This, debugstr_guid(guid));
10168 This->guid = TLB_append_guid(&This->pTypeLib->guid_list, guid, This->hreftype);
10170 return S_OK;
10173 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
10174 UINT typeFlags)
10176 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10177 WORD old_flags;
10178 HRESULT hres;
10180 TRACE("%p %x\n", This, typeFlags);
10182 if (typeFlags & TYPEFLAG_FDUAL) {
10183 static const WCHAR stdole2tlb[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10184 ITypeLib *stdole;
10185 ITypeInfo *dispatch;
10186 HREFTYPE hreftype;
10187 HRESULT hres;
10189 hres = LoadTypeLib(stdole2tlb, &stdole);
10190 if(FAILED(hres))
10191 return hres;
10193 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
10194 ITypeLib_Release(stdole);
10195 if(FAILED(hres))
10196 return hres;
10198 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
10199 ITypeInfo_Release(dispatch);
10200 if(FAILED(hres))
10201 return hres;
10204 old_flags = This->typeattr.wTypeFlags;
10205 This->typeattr.wTypeFlags = typeFlags;
10207 hres = ICreateTypeInfo2_LayOut(iface);
10208 if (FAILED(hres)) {
10209 This->typeattr.wTypeFlags = old_flags;
10210 return hres;
10213 return S_OK;
10216 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
10217 LPOLESTR doc)
10219 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10221 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
10223 if (!doc)
10224 return E_INVALIDARG;
10226 This->DocString = TLB_append_str(&This->pTypeLib->string_list, doc);
10228 return S_OK;
10231 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
10232 DWORD helpContext)
10234 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10236 TRACE("%p %d\n", This, helpContext);
10238 This->dwHelpContext = helpContext;
10240 return S_OK;
10243 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
10244 WORD majorVerNum, WORD minorVerNum)
10246 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10248 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
10250 This->typeattr.wMajorVerNum = majorVerNum;
10251 This->typeattr.wMinorVerNum = minorVerNum;
10253 return S_OK;
10256 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
10257 ITypeInfo *typeInfo, HREFTYPE *refType)
10259 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10260 UINT index;
10261 ITypeLib *container;
10262 TLBRefType *ref_type;
10263 TLBImpLib *implib;
10264 TYPEATTR *typeattr;
10265 TLIBATTR *libattr;
10266 HRESULT hres;
10268 TRACE("%p %p %p\n", This, typeInfo, refType);
10270 if (!typeInfo || !refType)
10271 return E_INVALIDARG;
10273 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
10274 if (FAILED(hres))
10275 return hres;
10277 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
10278 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
10280 ITypeLib_Release(container);
10282 *refType = target->hreftype;
10284 return S_OK;
10287 hres = ITypeLib_GetLibAttr(container, &libattr);
10288 if (FAILED(hres)) {
10289 ITypeLib_Release(container);
10290 return hres;
10293 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
10294 if(IsEqualGUID(&implib->guid->guid, &libattr->guid) &&
10295 implib->lcid == libattr->lcid &&
10296 implib->wVersionMajor == libattr->wMajorVerNum &&
10297 implib->wVersionMinor == libattr->wMinorVerNum)
10298 break;
10301 if(&implib->entry == &This->pTypeLib->implib_list){
10302 implib = heap_alloc_zero(sizeof(TLBImpLib));
10304 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
10305 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
10306 implib->name = SysAllocString(our_container->path);
10307 }else{
10308 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
10309 libattr->wMinorVerNum, libattr->lcid, &implib->name);
10310 if(FAILED(hres)){
10311 implib->name = NULL;
10312 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres);
10316 implib->guid = TLB_append_guid(&This->pTypeLib->guid_list, &libattr->guid, 2);
10317 implib->lcid = libattr->lcid;
10318 implib->wVersionMajor = libattr->wMajorVerNum;
10319 implib->wVersionMinor = libattr->wMinorVerNum;
10321 list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
10324 ITypeLib_ReleaseTLibAttr(container, libattr);
10325 ITypeLib_Release(container);
10327 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
10328 if (FAILED(hres))
10329 return hres;
10331 index = 0;
10332 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
10333 if(ref_type->index == TLB_REF_USE_GUID &&
10334 IsEqualGUID(&ref_type->guid->guid, &typeattr->guid) &&
10335 ref_type->tkind == typeattr->typekind)
10336 break;
10337 ++index;
10340 if(&ref_type->entry == &This->pTypeLib->ref_list){
10341 ref_type = heap_alloc_zero(sizeof(TLBRefType));
10343 ref_type->tkind = typeattr->typekind;
10344 ref_type->pImpTLInfo = implib;
10345 ref_type->reference = index * sizeof(MSFT_ImpInfo);
10347 ref_type->index = TLB_REF_USE_GUID;
10349 ref_type->guid = TLB_append_guid(&This->pTypeLib->guid_list, &typeattr->guid, ref_type->reference+1);
10351 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
10354 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
10356 *refType = ref_type->reference | 0x1;
10358 if(IsEqualGUID(&ref_type->guid->guid, &IID_IDispatch))
10359 This->pTypeLib->dispatch_href = *refType;
10361 return S_OK;
10364 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
10365 UINT index, FUNCDESC *funcDesc)
10367 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10368 TLBFuncDesc tmp_func_desc, *func_desc;
10369 int buf_size, i;
10370 char *buffer;
10371 HRESULT hres;
10373 TRACE("%p %u %p\n", This, index, funcDesc);
10375 if (!funcDesc || funcDesc->oVft & 3)
10376 return E_INVALIDARG;
10378 switch (This->typeattr.typekind) {
10379 case TKIND_MODULE:
10380 if (funcDesc->funckind != FUNC_STATIC)
10381 return TYPE_E_BADMODULEKIND;
10382 break;
10383 case TKIND_DISPATCH:
10384 if (funcDesc->funckind != FUNC_DISPATCH)
10385 return TYPE_E_BADMODULEKIND;
10386 break;
10387 default:
10388 if (funcDesc->funckind != FUNC_PUREVIRTUAL)
10389 return TYPE_E_BADMODULEKIND;
10392 if (index > This->typeattr.cFuncs)
10393 return TYPE_E_ELEMENTNOTFOUND;
10395 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) &&
10396 !funcDesc->cParams)
10397 return TYPE_E_INCONSISTENTPROPFUNCS;
10399 #ifdef _WIN64
10400 if(This->pTypeLib->syskind == SYS_WIN64 &&
10401 funcDesc->oVft % 8 != 0)
10402 return E_INVALIDARG;
10403 #endif
10405 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc));
10406 TLBFuncDesc_Constructor(&tmp_func_desc);
10408 tmp_func_desc.funcdesc = *funcDesc;
10410 if (tmp_func_desc.funcdesc.oVft != 0)
10411 tmp_func_desc.funcdesc.oVft |= 1;
10413 if (funcDesc->cScodes && funcDesc->lprgscode) {
10414 tmp_func_desc.funcdesc.lprgscode = heap_alloc(sizeof(SCODE) * funcDesc->cScodes);
10415 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes);
10416 } else {
10417 tmp_func_desc.funcdesc.lprgscode = NULL;
10418 tmp_func_desc.funcdesc.cScodes = 0;
10421 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc);
10422 for (i = 0; i < funcDesc->cParams; ++i) {
10423 buf_size += sizeof(ELEMDESC);
10424 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i);
10426 tmp_func_desc.funcdesc.lprgelemdescParam = heap_alloc(buf_size);
10427 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams);
10429 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer);
10430 if (FAILED(hres)) {
10431 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10432 heap_free(tmp_func_desc.funcdesc.lprgscode);
10433 return hres;
10436 for (i = 0; i < funcDesc->cParams; ++i) {
10437 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i,
10438 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer);
10439 if (FAILED(hres)) {
10440 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10441 heap_free(tmp_func_desc.funcdesc.lprgscode);
10442 return hres;
10444 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT &&
10445 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT &&
10446 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){
10447 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
10448 if (FAILED(hres)) {
10449 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10450 heap_free(tmp_func_desc.funcdesc.lprgscode);
10451 return hres;
10456 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams);
10458 if (This->funcdescs) {
10459 This->funcdescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->funcdescs,
10460 sizeof(TLBFuncDesc) * (This->typeattr.cFuncs + 1));
10462 if (index < This->typeattr.cFuncs) {
10463 memmove(This->funcdescs + index + 1, This->funcdescs + index,
10464 (This->typeattr.cFuncs - index) * sizeof(TLBFuncDesc));
10465 func_desc = This->funcdescs + index;
10466 } else
10467 func_desc = This->funcdescs + This->typeattr.cFuncs;
10469 /* move custdata lists to the new memory location */
10470 for(i = 0; i < This->typeattr.cFuncs + 1; ++i){
10471 if(index != i){
10472 TLBFuncDesc *fd = &This->funcdescs[i];
10473 if(fd->custdata_list.prev == fd->custdata_list.next)
10474 list_init(&fd->custdata_list);
10475 else{
10476 fd->custdata_list.prev->next = &fd->custdata_list;
10477 fd->custdata_list.next->prev = &fd->custdata_list;
10481 } else
10482 func_desc = This->funcdescs = heap_alloc(sizeof(TLBFuncDesc));
10484 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc));
10485 list_init(&func_desc->custdata_list);
10487 ++This->typeattr.cFuncs;
10489 This->needs_layout = TRUE;
10491 return S_OK;
10494 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
10495 UINT index, HREFTYPE refType)
10497 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10498 TLBImplType *impl_type;
10499 HRESULT hres;
10501 TRACE("%p %u %d\n", This, index, refType);
10503 switch(This->typeattr.typekind){
10504 case TKIND_COCLASS: {
10505 if (index == -1) {
10506 FIXME("Unhandled index: -1\n");
10507 return E_NOTIMPL;
10510 if(index != This->typeattr.cImplTypes)
10511 return TYPE_E_ELEMENTNOTFOUND;
10513 break;
10515 case TKIND_INTERFACE:
10516 case TKIND_DISPATCH:
10517 if (index != 0 || This->typeattr.cImplTypes)
10518 return TYPE_E_ELEMENTNOTFOUND;
10519 break;
10520 default:
10521 FIXME("Unimplemented typekind: %d\n", This->typeattr.typekind);
10522 return E_NOTIMPL;
10525 if (This->impltypes){
10526 UINT i;
10528 This->impltypes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->impltypes,
10529 sizeof(TLBImplType) * (This->typeattr.cImplTypes + 1));
10531 if (index < This->typeattr.cImplTypes) {
10532 memmove(This->impltypes + index + 1, This->impltypes + index,
10533 (This->typeattr.cImplTypes - index) * sizeof(TLBImplType));
10534 impl_type = This->impltypes + index;
10535 } else
10536 impl_type = This->impltypes + This->typeattr.cImplTypes;
10538 /* move custdata lists to the new memory location */
10539 for(i = 0; i < This->typeattr.cImplTypes + 1; ++i){
10540 if(index != i){
10541 TLBImplType *it = &This->impltypes[i];
10542 if(it->custdata_list.prev == it->custdata_list.next)
10543 list_init(&it->custdata_list);
10544 else{
10545 it->custdata_list.prev->next = &it->custdata_list;
10546 it->custdata_list.next->prev = &it->custdata_list;
10550 } else
10551 impl_type = This->impltypes = heap_alloc(sizeof(TLBImplType));
10553 memset(impl_type, 0, sizeof(TLBImplType));
10554 TLBImplType_Constructor(impl_type);
10555 impl_type->hRef = refType;
10557 ++This->typeattr.cImplTypes;
10559 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
10560 This->typeattr.wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
10562 hres = ICreateTypeInfo2_LayOut(iface);
10563 if (FAILED(hres))
10564 return hres;
10566 return S_OK;
10569 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
10570 UINT index, INT implTypeFlags)
10572 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10573 TLBImplType *impl_type = &This->impltypes[index];
10575 TRACE("%p %u %x\n", This, index, implTypeFlags);
10577 if (This->typeattr.typekind != TKIND_COCLASS)
10578 return TYPE_E_BADMODULEKIND;
10580 if (index >= This->typeattr.cImplTypes)
10581 return TYPE_E_ELEMENTNOTFOUND;
10583 impl_type->implflags = implTypeFlags;
10585 return S_OK;
10588 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
10589 WORD alignment)
10591 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10593 TRACE("%p %d\n", This, alignment);
10595 This->typeattr.cbAlignment = alignment;
10597 return S_OK;
10600 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
10601 LPOLESTR schema)
10603 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10605 TRACE("%p %s\n", This, wine_dbgstr_w(schema));
10607 if (!schema)
10608 return E_INVALIDARG;
10610 This->Schema = TLB_append_str(&This->pTypeLib->string_list, schema);
10612 This->typeattr.lpstrSchema = This->Schema->str;
10614 return S_OK;
10617 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
10618 UINT index, VARDESC *varDesc)
10620 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10621 TLBVarDesc *var_desc;
10623 TRACE("%p %u %p\n", This, index, varDesc);
10625 if (This->vardescs){
10626 UINT i;
10628 This->vardescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->vardescs,
10629 sizeof(TLBVarDesc) * (This->typeattr.cVars + 1));
10631 if (index < This->typeattr.cVars) {
10632 memmove(This->vardescs + index + 1, This->vardescs + index,
10633 (This->typeattr.cVars - index) * sizeof(TLBVarDesc));
10634 var_desc = This->vardescs + index;
10635 } else
10636 var_desc = This->vardescs + This->typeattr.cVars;
10638 /* move custdata lists to the new memory location */
10639 for(i = 0; i < This->typeattr.cVars + 1; ++i){
10640 if(index != i){
10641 TLBVarDesc *var = &This->vardescs[i];
10642 if(var->custdata_list.prev == var->custdata_list.next)
10643 list_init(&var->custdata_list);
10644 else{
10645 var->custdata_list.prev->next = &var->custdata_list;
10646 var->custdata_list.next->prev = &var->custdata_list;
10650 } else
10651 var_desc = This->vardescs = heap_alloc_zero(sizeof(TLBVarDesc));
10653 TLBVarDesc_Constructor(var_desc);
10654 TLB_AllocAndInitVarDesc(varDesc, &var_desc->vardesc_create);
10655 var_desc->vardesc = *var_desc->vardesc_create;
10657 ++This->typeattr.cVars;
10659 This->needs_layout = TRUE;
10661 return S_OK;
10664 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
10665 UINT index, LPOLESTR *names, UINT numNames)
10667 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10668 TLBFuncDesc *func_desc = &This->funcdescs[index];
10669 int i;
10671 TRACE("%p %u %p %u\n", This, index, names, numNames);
10673 if (!names)
10674 return E_INVALIDARG;
10676 if (index >= This->typeattr.cFuncs || numNames == 0)
10677 return TYPE_E_ELEMENTNOTFOUND;
10679 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){
10680 if(numNames > func_desc->funcdesc.cParams)
10681 return TYPE_E_ELEMENTNOTFOUND;
10682 } else
10683 if(numNames > func_desc->funcdesc.cParams + 1)
10684 return TYPE_E_ELEMENTNOTFOUND;
10686 for(i = 0; i < This->typeattr.cFuncs; ++i) {
10687 TLBFuncDesc *iter = &This->funcdescs[i];
10688 if (iter->Name && !strcmpW(TLB_get_bstr(iter->Name), *names)) {
10689 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10690 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10691 func_desc->funcdesc.invkind != iter->funcdesc.invkind)
10692 continue;
10693 return TYPE_E_AMBIGUOUSNAME;
10697 func_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *names);
10699 for (i = 1; i < numNames; ++i) {
10700 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1;
10701 par_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *(names + i));
10704 return S_OK;
10707 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
10708 UINT index, LPOLESTR name)
10710 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10712 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(name));
10714 if(!name)
10715 return E_INVALIDARG;
10717 if(index >= This->typeattr.cVars)
10718 return TYPE_E_ELEMENTNOTFOUND;
10720 This->vardescs[index].Name = TLB_append_str(&This->pTypeLib->name_list, name);
10721 return S_OK;
10724 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
10725 TYPEDESC *tdescAlias)
10727 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10728 HRESULT hr;
10730 TRACE("%p %p\n", This, tdescAlias);
10732 if(!tdescAlias)
10733 return E_INVALIDARG;
10735 if(This->typeattr.typekind != TKIND_ALIAS)
10736 return TYPE_E_BADMODULEKIND;
10738 hr = TLB_size_instance(This, This->pTypeLib->syskind, tdescAlias, &This->typeattr.cbSizeInstance, &This->typeattr.cbAlignment);
10739 if(FAILED(hr))
10740 return hr;
10742 heap_free(This->tdescAlias);
10743 This->tdescAlias = heap_alloc(TLB_SizeTypeDesc(tdescAlias, TRUE));
10744 TLB_CopyTypeDesc(NULL, tdescAlias, This->tdescAlias);
10746 return S_OK;
10749 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
10750 UINT index, LPOLESTR dllName, LPOLESTR procName)
10752 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10753 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
10754 return E_NOTIMPL;
10757 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
10758 UINT index, LPOLESTR docString)
10760 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10761 TLBFuncDesc *func_desc = &This->funcdescs[index];
10763 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10765 if(!docString)
10766 return E_INVALIDARG;
10768 if(index >= This->typeattr.cFuncs)
10769 return TYPE_E_ELEMENTNOTFOUND;
10771 func_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10773 return S_OK;
10776 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
10777 UINT index, LPOLESTR docString)
10779 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10780 TLBVarDesc *var_desc = &This->vardescs[index];
10782 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10784 if(!docString)
10785 return E_INVALIDARG;
10787 if(index >= This->typeattr.cVars)
10788 return TYPE_E_ELEMENTNOTFOUND;
10790 var_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10792 return S_OK;
10795 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
10796 UINT index, DWORD helpContext)
10798 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10799 TLBFuncDesc *func_desc = &This->funcdescs[index];
10801 TRACE("%p %u %d\n", This, index, helpContext);
10803 if(index >= This->typeattr.cFuncs)
10804 return TYPE_E_ELEMENTNOTFOUND;
10806 func_desc->helpcontext = helpContext;
10808 return S_OK;
10811 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
10812 UINT index, DWORD helpContext)
10814 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10815 TLBVarDesc *var_desc = &This->vardescs[index];
10817 TRACE("%p %u %d\n", This, index, helpContext);
10819 if(index >= This->typeattr.cVars)
10820 return TYPE_E_ELEMENTNOTFOUND;
10822 var_desc->HelpContext = helpContext;
10824 return S_OK;
10827 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
10828 UINT index, BSTR bstrMops)
10830 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10831 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
10832 return E_NOTIMPL;
10835 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
10836 IDLDESC *idlDesc)
10838 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10840 TRACE("%p %p\n", This, idlDesc);
10842 if (!idlDesc)
10843 return E_INVALIDARG;
10845 This->typeattr.idldescType.dwReserved = idlDesc->dwReserved;
10846 This->typeattr.idldescType.wIDLFlags = idlDesc->wIDLFlags;
10848 return S_OK;
10851 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
10853 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10854 ITypeInfo *tinfo;
10855 TLBFuncDesc *func_desc;
10856 UINT user_vft = 0, i, depth = 0;
10857 HRESULT hres = S_OK;
10859 TRACE("%p\n", This);
10861 This->needs_layout = FALSE;
10863 hres = ICreateTypeInfo2_QueryInterface(iface, &IID_ITypeInfo, (LPVOID*)&tinfo);
10864 if (FAILED(hres))
10865 return hres;
10867 if (This->typeattr.typekind == TKIND_INTERFACE) {
10868 ITypeInfo *inh;
10869 TYPEATTR *attr;
10870 HREFTYPE inh_href;
10872 hres = ITypeInfo_GetRefTypeOfImplType(tinfo, 0, &inh_href);
10874 if (SUCCEEDED(hres)) {
10875 hres = ITypeInfo_GetRefTypeInfo(tinfo, inh_href, &inh);
10877 if (SUCCEEDED(hres)) {
10878 hres = ITypeInfo_GetTypeAttr(inh, &attr);
10879 if (FAILED(hres)) {
10880 ITypeInfo_Release(inh);
10881 ITypeInfo_Release(tinfo);
10882 return hres;
10884 This->typeattr.cbSizeVft = attr->cbSizeVft;
10885 ITypeInfo_ReleaseTypeAttr(inh, attr);
10888 ++depth;
10889 hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href);
10890 if(SUCCEEDED(hres)){
10891 ITypeInfo *next;
10892 hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next);
10893 if(SUCCEEDED(hres)){
10894 ITypeInfo_Release(inh);
10895 inh = next;
10898 }while(SUCCEEDED(hres));
10899 hres = S_OK;
10901 ITypeInfo_Release(inh);
10902 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10903 This->typeattr.cbSizeVft = 0;
10904 hres = S_OK;
10905 } else {
10906 ITypeInfo_Release(tinfo);
10907 return hres;
10909 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10910 This->typeattr.cbSizeVft = 0;
10911 hres = S_OK;
10912 } else {
10913 ITypeInfo_Release(tinfo);
10914 return hres;
10916 } else if (This->typeattr.typekind == TKIND_DISPATCH)
10917 This->typeattr.cbSizeVft = 7 * This->pTypeLib->ptr_size;
10918 else
10919 This->typeattr.cbSizeVft = 0;
10921 func_desc = This->funcdescs;
10922 i = 0;
10923 while (i < This->typeattr.cFuncs) {
10924 if (!(func_desc->funcdesc.oVft & 0x1))
10925 func_desc->funcdesc.oVft = This->typeattr.cbSizeVft;
10927 if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft)
10928 user_vft = func_desc->funcdesc.oVft & 0xFFFC;
10930 This->typeattr.cbSizeVft += This->pTypeLib->ptr_size;
10932 if (func_desc->funcdesc.memid == MEMBERID_NIL) {
10933 TLBFuncDesc *iter;
10934 UINT j = 0;
10935 BOOL reset = FALSE;
10937 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i;
10939 iter = This->funcdescs;
10940 while (j < This->typeattr.cFuncs) {
10941 if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) {
10942 if (!reset) {
10943 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->typeattr.cFuncs;
10944 reset = TRUE;
10945 } else
10946 ++func_desc->funcdesc.memid;
10947 iter = This->funcdescs;
10948 j = 0;
10949 } else {
10950 ++iter;
10951 ++j;
10956 ++func_desc;
10957 ++i;
10960 if (user_vft > This->typeattr.cbSizeVft)
10961 This->typeattr.cbSizeVft = user_vft + This->pTypeLib->ptr_size;
10963 for(i = 0; i < This->typeattr.cVars; ++i){
10964 TLBVarDesc *var_desc = &This->vardescs[i];
10965 if(var_desc->vardesc.memid == MEMBERID_NIL){
10966 UINT j = 0;
10967 BOOL reset = FALSE;
10968 TLBVarDesc *iter;
10970 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + i;
10972 iter = This->vardescs;
10973 while (j < This->typeattr.cVars) {
10974 if (iter != var_desc && iter->vardesc.memid == var_desc->vardesc.memid) {
10975 if (!reset) {
10976 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + This->typeattr.cVars;
10977 reset = TRUE;
10978 } else
10979 ++var_desc->vardesc.memid;
10980 iter = This->vardescs;
10981 j = 0;
10982 } else {
10983 ++iter;
10984 ++j;
10990 ITypeInfo_Release(tinfo);
10991 return hres;
10994 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
10995 UINT index)
10997 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10998 FIXME("%p %u - stub\n", This, index);
10999 return E_NOTIMPL;
11002 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
11003 MEMBERID memid, INVOKEKIND invKind)
11005 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11006 FIXME("%p %x %d - stub\n", This, memid, invKind);
11007 return E_NOTIMPL;
11010 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
11011 UINT index)
11013 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11014 FIXME("%p %u - stub\n", This, index);
11015 return E_NOTIMPL;
11018 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
11019 MEMBERID memid)
11021 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11022 FIXME("%p %x - stub\n", This, memid);
11023 return E_NOTIMPL;
11026 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
11027 UINT index)
11029 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11030 FIXME("%p %u - stub\n", This, index);
11031 return E_NOTIMPL;
11034 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
11035 REFGUID guid, VARIANT *varVal)
11037 TLBGuid *tlbguid;
11039 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11041 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
11043 if (!guid || !varVal)
11044 return E_INVALIDARG;
11046 tlbguid = TLB_append_guid(&This->pTypeLib->guid_list, guid, -1);
11048 return TLB_set_custdata(This->pcustdata_list, tlbguid, varVal);
11051 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
11052 UINT index, REFGUID guid, VARIANT *varVal)
11054 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11055 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11056 return E_NOTIMPL;
11059 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
11060 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
11062 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11063 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
11064 return E_NOTIMPL;
11067 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
11068 UINT index, REFGUID guid, VARIANT *varVal)
11070 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11071 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11072 return E_NOTIMPL;
11075 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
11076 UINT index, REFGUID guid, VARIANT *varVal)
11078 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11079 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11080 return E_NOTIMPL;
11083 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
11084 ULONG helpStringContext)
11086 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11088 TRACE("%p %u\n", This, helpStringContext);
11090 This->dwHelpStringContext = helpStringContext;
11092 return S_OK;
11095 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
11096 UINT index, ULONG helpStringContext)
11098 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11099 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11100 return E_NOTIMPL;
11103 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
11104 UINT index, ULONG helpStringContext)
11106 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11107 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11108 return E_NOTIMPL;
11111 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
11113 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11114 FIXME("%p - stub\n", This);
11115 return E_NOTIMPL;
11118 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
11119 LPOLESTR name)
11121 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11123 TRACE("%p %s\n", This, wine_dbgstr_w(name));
11125 if (!name)
11126 return E_INVALIDARG;
11128 This->Name = TLB_append_str(&This->pTypeLib->name_list, name);
11130 return S_OK;
11133 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
11134 ICreateTypeInfo2_fnQueryInterface,
11135 ICreateTypeInfo2_fnAddRef,
11136 ICreateTypeInfo2_fnRelease,
11137 ICreateTypeInfo2_fnSetGuid,
11138 ICreateTypeInfo2_fnSetTypeFlags,
11139 ICreateTypeInfo2_fnSetDocString,
11140 ICreateTypeInfo2_fnSetHelpContext,
11141 ICreateTypeInfo2_fnSetVersion,
11142 ICreateTypeInfo2_fnAddRefTypeInfo,
11143 ICreateTypeInfo2_fnAddFuncDesc,
11144 ICreateTypeInfo2_fnAddImplType,
11145 ICreateTypeInfo2_fnSetImplTypeFlags,
11146 ICreateTypeInfo2_fnSetAlignment,
11147 ICreateTypeInfo2_fnSetSchema,
11148 ICreateTypeInfo2_fnAddVarDesc,
11149 ICreateTypeInfo2_fnSetFuncAndParamNames,
11150 ICreateTypeInfo2_fnSetVarName,
11151 ICreateTypeInfo2_fnSetTypeDescAlias,
11152 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
11153 ICreateTypeInfo2_fnSetFuncDocString,
11154 ICreateTypeInfo2_fnSetVarDocString,
11155 ICreateTypeInfo2_fnSetFuncHelpContext,
11156 ICreateTypeInfo2_fnSetVarHelpContext,
11157 ICreateTypeInfo2_fnSetMops,
11158 ICreateTypeInfo2_fnSetTypeIdldesc,
11159 ICreateTypeInfo2_fnLayOut,
11160 ICreateTypeInfo2_fnDeleteFuncDesc,
11161 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
11162 ICreateTypeInfo2_fnDeleteVarDesc,
11163 ICreateTypeInfo2_fnDeleteVarDescByMemId,
11164 ICreateTypeInfo2_fnDeleteImplType,
11165 ICreateTypeInfo2_fnSetCustData,
11166 ICreateTypeInfo2_fnSetFuncCustData,
11167 ICreateTypeInfo2_fnSetParamCustData,
11168 ICreateTypeInfo2_fnSetVarCustData,
11169 ICreateTypeInfo2_fnSetImplTypeCustData,
11170 ICreateTypeInfo2_fnSetHelpStringContext,
11171 ICreateTypeInfo2_fnSetFuncHelpStringContext,
11172 ICreateTypeInfo2_fnSetVarHelpStringContext,
11173 ICreateTypeInfo2_fnInvalidate,
11174 ICreateTypeInfo2_fnSetName
11177 /******************************************************************************
11178 * ClearCustData (OLEAUT32.171)
11180 * Clear a custom data type's data.
11182 * PARAMS
11183 * lpCust [I] The custom data type instance
11185 * RETURNS
11186 * Nothing.
11188 void WINAPI ClearCustData(CUSTDATA *lpCust)
11190 if (lpCust && lpCust->cCustData)
11192 if (lpCust->prgCustData)
11194 DWORD i;
11196 for (i = 0; i < lpCust->cCustData; i++)
11197 VariantClear(&lpCust->prgCustData[i].varValue);
11199 CoTaskMemFree(lpCust->prgCustData);
11200 lpCust->prgCustData = NULL;
11202 lpCust->cCustData = 0;