po: Fix a mistake in Dutch translation.
[wine.git] / dlls / oleaut32 / typelib.c
blobc6c539eb55858ebabed91806937a9e5fce6c2e34
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
61 #define NONAMELESSSTRUCT
63 #include "winerror.h"
64 #include "windef.h"
65 #include "winbase.h"
66 #include "winnls.h"
67 #include "winreg.h"
68 #include "winuser.h"
69 #include "winternl.h"
70 #include "lzexpand.h"
72 #include "wine/unicode.h"
73 #include "objbase.h"
74 #include "typelib.h"
75 #include "wine/debug.h"
76 #include "variant.h"
77 #include "wine/list.h"
79 WINE_DEFAULT_DEBUG_CHANNEL(ole);
80 WINE_DECLARE_DEBUG_CHANNEL(typelib);
82 typedef struct
84 WORD offset;
85 WORD length;
86 WORD flags;
87 WORD id;
88 WORD handle;
89 WORD usage;
90 } NE_NAMEINFO;
92 typedef struct
94 WORD type_id; /* Type identifier */
95 WORD count; /* Number of resources of this type */
96 DWORD resloader; /* SetResourceHandler() */
98 * Name info array.
100 } NE_TYPEINFO;
102 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
103 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
104 static void TLB_FreeVarDesc(VARDESC*);
106 /****************************************************************************
107 * FromLExxx
109 * Takes p_iVal (which is in little endian) and returns it
110 * in the host machine's byte order.
112 #ifdef WORDS_BIGENDIAN
113 static WORD FromLEWord(WORD p_iVal)
115 return (((p_iVal & 0x00FF) << 8) |
116 ((p_iVal & 0xFF00) >> 8));
120 static DWORD FromLEDWord(DWORD p_iVal)
122 return (((p_iVal & 0x000000FF) << 24) |
123 ((p_iVal & 0x0000FF00) << 8) |
124 ((p_iVal & 0x00FF0000) >> 8) |
125 ((p_iVal & 0xFF000000) >> 24));
127 #else
128 #define FromLEWord(X) (X)
129 #define FromLEDWord(X) (X)
130 #endif
132 #define DISPATCH_HREF_OFFSET 0x01000000
133 #define DISPATCH_HREF_MASK 0xff000000
135 /****************************************************************************
136 * FromLExxx
138 * Fix byte order in any structure if necessary
140 #ifdef WORDS_BIGENDIAN
141 static void FromLEWords(void *p_Val, int p_iSize)
143 WORD *Val = p_Val;
145 p_iSize /= sizeof(WORD);
147 while (p_iSize) {
148 *Val = FromLEWord(*Val);
149 Val++;
150 p_iSize--;
155 static void FromLEDWords(void *p_Val, int p_iSize)
157 DWORD *Val = p_Val;
159 p_iSize /= sizeof(DWORD);
161 while (p_iSize) {
162 *Val = FromLEDWord(*Val);
163 Val++;
164 p_iSize--;
167 #else
168 #define FromLEWords(X,Y) /*nothing*/
169 #define FromLEDWords(X,Y) /*nothing*/
170 #endif
173 * Find a typelib key which matches a requested maj.min version.
175 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
177 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
178 WCHAR buffer[60];
179 char key_name[16];
180 DWORD len, i;
181 INT best_maj = -1, best_min = -1;
182 HKEY hkey;
184 memcpy( buffer, typelibW, sizeof(typelibW) );
185 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
187 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
188 return FALSE;
190 len = sizeof(key_name);
191 i = 0;
192 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
194 INT v_maj, v_min;
196 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
198 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
200 if (*wMaj == 0xffff && *wMin == 0xffff)
202 if (v_maj > best_maj) best_maj = v_maj;
203 if (v_min > best_min) best_min = v_min;
205 else if (*wMaj == v_maj)
207 best_maj = v_maj;
209 if (*wMin == v_min)
211 best_min = v_min;
212 break; /* exact match */
214 if (*wMin != 0xffff && v_min > best_min) best_min = v_min;
217 len = sizeof(key_name);
219 RegCloseKey( hkey );
221 TRACE("found best_maj %d, best_min %d\n", best_maj, best_min);
223 if (*wMaj == 0xffff && *wMin == 0xffff)
225 if (best_maj >= 0 && best_min >= 0)
227 *wMaj = best_maj;
228 *wMin = best_min;
229 return TRUE;
233 if (*wMaj == best_maj && best_min >= 0)
235 *wMin = best_min;
236 return TRUE;
238 return FALSE;
241 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
242 /* buffer must be at least 60 characters long */
243 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
245 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
246 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
248 memcpy( buffer, TypelibW, sizeof(TypelibW) );
249 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
250 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
251 return buffer;
254 /* get the path of an interface key, in the form "Interface\\<guid>" */
255 /* buffer must be at least 50 characters long */
256 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
258 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
260 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
261 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
262 return buffer;
265 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
266 /* buffer must be at least 16 characters long */
267 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
269 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
270 static const WCHAR win16W[] = {'w','i','n','1','6',0};
271 static const WCHAR win32W[] = {'w','i','n','3','2',0};
272 static const WCHAR win64W[] = {'w','i','n','6','4',0};
274 sprintfW( buffer, LcidFormatW, lcid );
275 switch(syskind)
277 case SYS_WIN16: strcatW( buffer, win16W ); break;
278 case SYS_WIN32: strcatW( buffer, win32W ); break;
279 case SYS_WIN64: strcatW( buffer, win64W ); break;
280 default:
281 TRACE("Typelib is for unsupported syskind %i\n", syskind);
282 return NULL;
284 return buffer;
287 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
289 struct tlibredirect_data
291 ULONG size;
292 DWORD res;
293 ULONG name_len;
294 ULONG name_offset;
295 LANGID langid;
296 WORD flags;
297 ULONG help_len;
298 ULONG help_offset;
299 WORD major_version;
300 WORD minor_version;
303 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
304 static HRESULT query_typelib_path( REFGUID guid, WORD wMaj, WORD wMin,
305 SYSKIND syskind, LCID lcid, BSTR *path, BOOL redir )
307 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
308 LCID myLCID = lcid;
309 HKEY hkey;
310 WCHAR buffer[60];
311 WCHAR Path[MAX_PATH];
312 LONG res;
314 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
316 if (redir)
318 ACTCTX_SECTION_KEYED_DATA data;
320 data.cbSize = sizeof(data);
321 if (FindActCtxSectionGuid( 0, NULL, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION, guid, &data ))
323 struct tlibredirect_data *tlib = (struct tlibredirect_data*)data.lpData;
324 WCHAR *nameW;
325 DWORD len;
327 if (tlib->major_version != wMaj || tlib->minor_version < wMin)
328 return TYPE_E_LIBNOTREGISTERED;
330 nameW = (WCHAR*)((BYTE*)data.lpSectionBase + tlib->name_offset);
331 len = SearchPathW( NULL, nameW, NULL, sizeof(Path)/sizeof(WCHAR), Path, NULL );
332 if (!len) return TYPE_E_LIBNOTREGISTERED;
334 TRACE_(typelib)("got path from context %s\n", debugstr_w(Path));
335 *path = SysAllocString( Path );
336 return S_OK;
340 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
341 get_typelib_key( guid, wMaj, wMin, buffer );
343 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
344 if (res == ERROR_FILE_NOT_FOUND)
346 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
347 return TYPE_E_LIBNOTREGISTERED;
349 else if (res != ERROR_SUCCESS)
351 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
352 return TYPE_E_REGISTRYACCESS;
355 while (hr != S_OK)
357 LONG dwPathLen = sizeof(Path);
359 get_lcid_subkey( myLCID, syskind, buffer );
361 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
363 if (!lcid)
364 break;
365 else if (myLCID == lcid)
367 /* try with sub-langid */
368 myLCID = SUBLANGID(lcid);
370 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
372 /* try with system langid */
373 myLCID = 0;
375 else
377 break;
380 else
382 *path = SysAllocString( Path );
383 hr = S_OK;
386 RegCloseKey( hkey );
387 TRACE_(typelib)("-- 0x%08x\n", hr);
388 return hr;
391 /****************************************************************************
392 * QueryPathOfRegTypeLib [OLEAUT32.164]
394 * Gets the path to a registered type library.
396 * PARAMS
397 * guid [I] referenced guid
398 * wMaj [I] major version
399 * wMin [I] minor version
400 * lcid [I] locale id
401 * path [O] path of typelib
403 * RETURNS
404 * Success: S_OK.
405 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
406 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
407 * opened.
409 HRESULT WINAPI QueryPathOfRegTypeLib( REFGUID guid, WORD wMaj, WORD wMin, LCID lcid, LPBSTR path )
411 BOOL redir = TRUE;
412 #ifdef _WIN64
413 HRESULT hres = query_typelib_path( guid, wMaj, wMin, SYS_WIN64, lcid, path, TRUE );
414 if(SUCCEEDED(hres))
415 return hres;
416 redir = FALSE;
417 #endif
418 return query_typelib_path( guid, wMaj, wMin, SYS_WIN32, lcid, path, redir );
421 /******************************************************************************
422 * CreateTypeLib [OLEAUT32.160] creates a typelib
424 * RETURNS
425 * Success: S_OK
426 * Failure: Status
428 HRESULT WINAPI CreateTypeLib(
429 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
431 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
432 return E_FAIL;
435 /******************************************************************************
436 * LoadTypeLib [OLEAUT32.161]
438 * Loads a type library
440 * PARAMS
441 * szFile [I] Name of file to load from.
442 * pptLib [O] Pointer that receives ITypeLib object on success.
444 * RETURNS
445 * Success: S_OK
446 * Failure: Status
448 * SEE
449 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
451 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
453 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
454 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
457 /******************************************************************************
458 * LoadTypeLibEx [OLEAUT32.183]
460 * Loads and optionally registers a type library
462 * RETURNS
463 * Success: S_OK
464 * Failure: Status
466 HRESULT WINAPI LoadTypeLibEx(
467 LPCOLESTR szFile, /* [in] Name of file to load from */
468 REGKIND regkind, /* [in] Specify kind of registration */
469 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
471 WCHAR szPath[MAX_PATH+1];
472 HRESULT res;
474 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
476 *pptLib = NULL;
478 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
480 if (SUCCEEDED(res))
481 switch(regkind)
483 case REGKIND_DEFAULT:
484 /* don't register typelibs supplied with full path. Experimentation confirms the following */
485 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
486 (szFile[0] && (szFile[1] == ':'))) break;
487 /* else fall-through */
489 case REGKIND_REGISTER:
490 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
492 ITypeLib_Release(*pptLib);
493 *pptLib = 0;
495 break;
496 case REGKIND_NONE:
497 break;
500 TRACE(" returns %08x\n",res);
501 return res;
504 /******************************************************************************
505 * LoadRegTypeLib [OLEAUT32.162]
507 * Loads a registered type library.
509 * PARAMS
510 * rguid [I] GUID of the registered type library.
511 * wVerMajor [I] major version.
512 * wVerMinor [I] minor version.
513 * lcid [I] locale ID.
514 * ppTLib [O] pointer that receives an ITypeLib object on success.
516 * RETURNS
517 * Success: S_OK.
518 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
519 * LoadTypeLib.
521 HRESULT WINAPI LoadRegTypeLib(
522 REFGUID rguid,
523 WORD wVerMajor,
524 WORD wVerMinor,
525 LCID lcid,
526 ITypeLib **ppTLib)
528 BSTR bstr=NULL;
529 HRESULT res;
531 *ppTLib = NULL;
533 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
535 if(SUCCEEDED(res))
537 res= LoadTypeLib(bstr, ppTLib);
538 SysFreeString(bstr);
540 if (*ppTLib)
542 TLIBATTR *attr;
544 res = ITypeLib_GetLibAttr(*ppTLib, &attr);
545 if (res == S_OK)
547 BOOL mismatch = attr->wMajorVerNum != wVerMajor || attr->wMinorVerNum < wVerMinor;
548 ITypeLib_ReleaseTLibAttr(*ppTLib, attr);
550 if (mismatch)
552 ITypeLib_Release(*ppTLib);
553 *ppTLib = NULL;
554 res = TYPE_E_LIBNOTREGISTERED;
560 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
562 return res;
566 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
567 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
568 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
569 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
570 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
571 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
573 static void TLB_register_interface(TLIBATTR *libattr, LPOLESTR name, TYPEATTR *tattr, DWORD flag)
575 WCHAR keyName[60];
576 HKEY key, subKey;
578 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
579 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
580 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
582 get_interface_key( &tattr->guid, keyName );
583 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
584 KEY_WRITE | flag, NULL, &key, NULL) == ERROR_SUCCESS)
586 if (name)
587 RegSetValueExW(key, NULL, 0, REG_SZ,
588 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
590 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
591 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS) {
592 RegSetValueExW(subKey, NULL, 0, REG_SZ,
593 (const BYTE *)PSOA, sizeof PSOA);
594 RegCloseKey(subKey);
597 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
598 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS) {
599 RegSetValueExW(subKey, NULL, 0, REG_SZ,
600 (const BYTE *)PSOA, sizeof PSOA);
601 RegCloseKey(subKey);
604 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
605 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS)
607 WCHAR buffer[40];
608 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
609 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
611 StringFromGUID2(&libattr->guid, buffer, 40);
612 RegSetValueExW(subKey, NULL, 0, REG_SZ,
613 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
614 sprintfW(buffer, fmtver, libattr->wMajorVerNum, libattr->wMinorVerNum);
615 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
616 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
617 RegCloseKey(subKey);
620 RegCloseKey(key);
624 /******************************************************************************
625 * RegisterTypeLib [OLEAUT32.163]
626 * Adds information about a type library to the System Registry
627 * NOTES
628 * Docs: ITypeLib FAR * ptlib
629 * Docs: OLECHAR FAR* szFullPath
630 * Docs: OLECHAR FAR* szHelpDir
632 * RETURNS
633 * Success: S_OK
634 * Failure: Status
636 HRESULT WINAPI RegisterTypeLib(
637 ITypeLib * ptlib, /* [in] Pointer to the library*/
638 OLECHAR * szFullPath, /* [in] full Path of the library*/
639 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
640 may be NULL*/
642 HRESULT res;
643 TLIBATTR *attr;
644 WCHAR keyName[60];
645 WCHAR tmp[16];
646 HKEY key, subKey;
647 UINT types, tidx;
648 TYPEKIND kind;
649 DWORD disposition;
651 if (ptlib == NULL || szFullPath == NULL)
652 return E_INVALIDARG;
654 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
655 return E_FAIL;
657 #ifndef _WIN64
658 if (attr->syskind == SYS_WIN64) return TYPE_E_BADMODULEKIND;
659 #endif
661 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
663 res = S_OK;
664 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
665 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
667 LPOLESTR doc;
669 /* Set the human-readable name of the typelib */
670 if (FAILED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
671 res = E_FAIL;
672 else if (doc)
674 if (RegSetValueExW(key, NULL, 0, REG_SZ,
675 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
676 res = E_FAIL;
678 SysFreeString(doc);
681 /* Make up the name of the typelib path subkey */
682 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
684 /* Create the typelib path subkey */
685 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
686 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
688 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
689 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
690 res = E_FAIL;
692 RegCloseKey(subKey);
694 else
695 res = E_FAIL;
697 /* Create the flags subkey */
698 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
699 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
701 /* FIXME: is %u correct? */
702 static const WCHAR formatW[] = {'%','u',0};
703 WCHAR buf[20];
704 sprintfW(buf, formatW, attr->wLibFlags);
705 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
706 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
707 res = E_FAIL;
709 RegCloseKey(subKey);
711 else
712 res = E_FAIL;
714 /* create the helpdir subkey */
715 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
716 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
718 BOOL freeHelpDir = FALSE;
719 OLECHAR* pIndexStr;
721 /* if we created a new key, and helpDir was null, set the helpdir
722 to the directory which contains the typelib. However,
723 if we just opened an existing key, we leave the helpdir alone */
724 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
725 szHelpDir = SysAllocString(szFullPath);
726 pIndexStr = strrchrW(szHelpDir, '\\');
727 if (pIndexStr) {
728 *pIndexStr = 0;
730 freeHelpDir = TRUE;
733 /* if we have an szHelpDir, set it! */
734 if (szHelpDir != NULL) {
735 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
736 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
737 res = E_FAIL;
741 /* tidy up */
742 if (freeHelpDir) SysFreeString(szHelpDir);
743 RegCloseKey(subKey);
745 } else {
746 res = E_FAIL;
749 RegCloseKey(key);
751 else
752 res = E_FAIL;
754 /* register OLE Automation-compatible interfaces for this typelib */
755 types = ITypeLib_GetTypeInfoCount(ptlib);
756 for (tidx=0; tidx<types; tidx++) {
757 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
758 LPOLESTR name = NULL;
759 ITypeInfo *tinfo = NULL;
761 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
763 switch (kind) {
764 case TKIND_INTERFACE:
765 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
766 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
767 break;
769 case TKIND_DISPATCH:
770 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
771 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
772 break;
774 default:
775 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
776 break;
779 if (tinfo) {
780 TYPEATTR *tattr = NULL;
781 ITypeInfo_GetTypeAttr(tinfo, &tattr);
783 if (tattr) {
784 TRACE_(typelib)("guid=%s, flags=%04x (",
785 debugstr_guid(&tattr->guid),
786 tattr->wTypeFlags);
788 if (TRACE_ON(typelib)) {
789 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
790 XX(FAPPOBJECT);
791 XX(FCANCREATE);
792 XX(FLICENSED);
793 XX(FPREDECLID);
794 XX(FHIDDEN);
795 XX(FCONTROL);
796 XX(FDUAL);
797 XX(FNONEXTENSIBLE);
798 XX(FOLEAUTOMATION);
799 XX(FRESTRICTED);
800 XX(FAGGREGATABLE);
801 XX(FREPLACEABLE);
802 XX(FDISPATCHABLE);
803 XX(FREVERSEBIND);
804 XX(FPROXY);
805 #undef XX
806 MESSAGE("\n");
809 /* Register all dispinterfaces (which includes dual interfaces) and
810 oleautomation interfaces */
811 if ((kind == TKIND_INTERFACE && (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
812 kind == TKIND_DISPATCH)
814 BOOL is_wow64;
815 DWORD opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
817 /* register interface<->typelib coupling */
818 TLB_register_interface(attr, name, tattr, 0);
820 /* register TLBs into the opposite registry view, too */
821 if(opposite == KEY_WOW64_32KEY ||
822 (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64))
823 TLB_register_interface(attr, name, tattr, opposite);
826 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
829 ITypeInfo_Release(tinfo);
832 SysFreeString(name);
836 ITypeLib_ReleaseTLibAttr(ptlib, attr);
838 return res;
841 static void TLB_unregister_interface(GUID *guid, REGSAM flag)
843 WCHAR subKeyName[50];
844 HKEY subKey;
846 /* the path to the type */
847 get_interface_key( guid, subKeyName );
849 /* Delete its bits */
850 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE | flag, &subKey) != ERROR_SUCCESS)
851 return;
853 RegDeleteKeyW(subKey, ProxyStubClsidW);
854 RegDeleteKeyW(subKey, ProxyStubClsid32W);
855 RegDeleteKeyW(subKey, TypeLibW);
856 RegCloseKey(subKey);
857 RegDeleteKeyExW(HKEY_CLASSES_ROOT, subKeyName, flag, 0);
860 /******************************************************************************
861 * UnRegisterTypeLib [OLEAUT32.186]
862 * Removes information about a type library from the System Registry
863 * NOTES
865 * RETURNS
866 * Success: S_OK
867 * Failure: Status
869 HRESULT WINAPI UnRegisterTypeLib(
870 REFGUID libid, /* [in] Guid of the library */
871 WORD wVerMajor, /* [in] major version */
872 WORD wVerMinor, /* [in] minor version */
873 LCID lcid, /* [in] locale id */
874 SYSKIND syskind)
876 BSTR tlibPath = NULL;
877 DWORD tmpLength;
878 WCHAR keyName[60];
879 WCHAR subKeyName[50];
880 int result = S_OK;
881 DWORD i = 0;
882 BOOL deleteOtherStuff;
883 HKEY key = NULL;
884 TYPEATTR* typeAttr = NULL;
885 TYPEKIND kind;
886 ITypeInfo* typeInfo = NULL;
887 ITypeLib* typeLib = NULL;
888 int numTypes;
890 TRACE("(IID: %s)\n",debugstr_guid(libid));
892 /* Create the path to the key */
893 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
895 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
897 TRACE("Unsupported syskind %i\n", syskind);
898 result = E_INVALIDARG;
899 goto end;
902 /* get the path to the typelib on disk */
903 if (query_typelib_path(libid, wVerMajor, wVerMinor, syskind, lcid, &tlibPath, FALSE) != S_OK) {
904 result = E_INVALIDARG;
905 goto end;
908 /* Try and open the key to the type library. */
909 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
910 result = E_INVALIDARG;
911 goto end;
914 /* Try and load the type library */
915 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib) != S_OK) {
916 result = TYPE_E_INVALIDSTATE;
917 goto end;
920 /* remove any types registered with this typelib */
921 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
922 for (i=0; i<numTypes; i++) {
923 /* get the kind of type */
924 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
925 goto enddeleteloop;
928 /* skip non-interfaces, and get type info for the type */
929 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
930 goto enddeleteloop;
932 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
933 goto enddeleteloop;
935 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
936 goto enddeleteloop;
939 if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
940 kind == TKIND_DISPATCH)
942 BOOL is_wow64;
943 REGSAM opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
945 TLB_unregister_interface(&typeAttr->guid, 0);
947 /* unregister TLBs into the opposite registry view, too */
948 if(opposite == KEY_WOW64_32KEY ||
949 (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64)) {
950 TLB_unregister_interface(&typeAttr->guid, opposite);
954 enddeleteloop:
955 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
956 typeAttr = NULL;
957 if (typeInfo) ITypeInfo_Release(typeInfo);
958 typeInfo = NULL;
961 /* Now, delete the type library path subkey */
962 get_lcid_subkey( lcid, syskind, subKeyName );
963 RegDeleteKeyW(key, subKeyName);
964 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
965 RegDeleteKeyW(key, subKeyName);
967 /* check if there is anything besides the FLAGS/HELPDIR keys.
968 If there is, we don't delete them */
969 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
970 deleteOtherStuff = TRUE;
971 i = 0;
972 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
973 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
975 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
976 if (!strcmpW(subKeyName, FLAGSW)) continue;
977 if (!strcmpW(subKeyName, HELPDIRW)) continue;
978 deleteOtherStuff = FALSE;
979 break;
982 /* only delete the other parts of the key if we're absolutely sure */
983 if (deleteOtherStuff) {
984 RegDeleteKeyW(key, FLAGSW);
985 RegDeleteKeyW(key, HELPDIRW);
986 RegCloseKey(key);
987 key = NULL;
989 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
990 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
991 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
994 end:
995 SysFreeString(tlibPath);
996 if (typeLib) ITypeLib_Release(typeLib);
997 if (key) RegCloseKey(key);
998 return result;
1001 /******************************************************************************
1002 * RegisterTypeLibForUser [OLEAUT32.442]
1003 * Adds information about a type library to the user registry
1004 * NOTES
1005 * Docs: ITypeLib FAR * ptlib
1006 * Docs: OLECHAR FAR* szFullPath
1007 * Docs: OLECHAR FAR* szHelpDir
1009 * RETURNS
1010 * Success: S_OK
1011 * Failure: Status
1013 HRESULT WINAPI RegisterTypeLibForUser(
1014 ITypeLib * ptlib, /* [in] Pointer to the library*/
1015 OLECHAR * szFullPath, /* [in] full Path of the library*/
1016 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
1017 may be NULL*/
1019 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib,
1020 debugstr_w(szFullPath), debugstr_w(szHelpDir));
1021 return RegisterTypeLib(ptlib, szFullPath, szHelpDir);
1024 /******************************************************************************
1025 * UnRegisterTypeLibForUser [OLEAUT32.443]
1026 * Removes information about a type library from the user registry
1028 * RETURNS
1029 * Success: S_OK
1030 * Failure: Status
1032 HRESULT WINAPI UnRegisterTypeLibForUser(
1033 REFGUID libid, /* [in] GUID of the library */
1034 WORD wVerMajor, /* [in] major version */
1035 WORD wVerMinor, /* [in] minor version */
1036 LCID lcid, /* [in] locale id */
1037 SYSKIND syskind)
1039 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
1040 debugstr_guid(libid), wVerMajor, wVerMinor, lcid, syskind);
1041 return UnRegisterTypeLib(libid, wVerMajor, wVerMinor, lcid, syskind);
1044 /*======================= ITypeLib implementation =======================*/
1046 typedef struct tagTLBGuid {
1047 GUID guid;
1048 INT hreftype;
1049 UINT offset;
1050 struct list entry;
1051 } TLBGuid;
1053 typedef struct tagTLBCustData
1055 TLBGuid *guid;
1056 VARIANT data;
1057 struct list entry;
1058 } TLBCustData;
1060 /* data structure for import typelibs */
1061 typedef struct tagTLBImpLib
1063 int offset; /* offset in the file (MSFT)
1064 offset in nametable (SLTG)
1065 just used to identify library while reading
1066 data from file */
1067 TLBGuid *guid; /* libid */
1068 BSTR name; /* name */
1070 LCID lcid; /* lcid of imported typelib */
1072 WORD wVersionMajor; /* major version number */
1073 WORD wVersionMinor; /* minor version number */
1075 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
1076 NULL if not yet loaded */
1077 struct list entry;
1078 } TLBImpLib;
1080 typedef struct tagTLBString {
1081 BSTR str;
1082 UINT offset;
1083 struct list entry;
1084 } TLBString;
1086 /* internal ITypeLib data */
1087 typedef struct tagITypeLibImpl
1089 ITypeLib2 ITypeLib2_iface;
1090 ITypeComp ITypeComp_iface;
1091 ICreateTypeLib2 ICreateTypeLib2_iface;
1092 LONG ref;
1093 TLBGuid *guid;
1094 LCID lcid;
1095 SYSKIND syskind;
1096 int ptr_size;
1097 WORD ver_major;
1098 WORD ver_minor;
1099 WORD libflags;
1100 LCID set_lcid;
1102 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1103 * exported to the application as a UNICODE string.
1105 struct list string_list;
1106 struct list name_list;
1107 struct list guid_list;
1109 const TLBString *Name;
1110 const TLBString *DocString;
1111 const TLBString *HelpFile;
1112 const TLBString *HelpStringDll;
1113 DWORD dwHelpContext;
1114 int TypeInfoCount; /* nr of typeinfo's in librarry */
1115 struct tagITypeInfoImpl **typeinfos;
1116 struct list custdata_list;
1117 struct list implib_list;
1118 int ctTypeDesc; /* number of items in type desc array */
1119 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1120 library. Only used while reading MSFT
1121 typelibs */
1122 struct list ref_list; /* list of ref types in this typelib */
1123 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1126 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1127 struct list entry;
1128 WCHAR *path;
1129 INT index;
1130 } ITypeLibImpl;
1132 static const ITypeLib2Vtbl tlbvt;
1133 static const ITypeCompVtbl tlbtcvt;
1134 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl;
1136 static inline ITypeLibImpl *impl_from_ITypeLib2(ITypeLib2 *iface)
1138 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeLib2_iface);
1141 static inline ITypeLibImpl *impl_from_ITypeLib(ITypeLib *iface)
1143 return impl_from_ITypeLib2((ITypeLib2*)iface);
1146 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1148 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeComp_iface);
1151 static inline ITypeLibImpl *impl_from_ICreateTypeLib2( ICreateTypeLib2 *iface )
1153 return CONTAINING_RECORD(iface, ITypeLibImpl, ICreateTypeLib2_iface);
1156 /* ITypeLib methods */
1157 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1158 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1160 /*======================= ITypeInfo implementation =======================*/
1162 /* data for referenced types */
1163 typedef struct tagTLBRefType
1165 INT index; /* Type index for internal ref or for external ref
1166 it the format is SLTG. -2 indicates to
1167 use guid */
1169 TYPEKIND tkind;
1170 TLBGuid *guid; /* guid of the referenced type */
1171 /* if index == TLB_REF_USE_GUID */
1173 HREFTYPE reference; /* The href of this ref */
1174 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1175 TLB_REF_INTERNAL for internal refs
1176 TLB_REF_NOT_FOUND for broken refs */
1178 struct list entry;
1179 } TLBRefType;
1181 #define TLB_REF_USE_GUID -2
1183 #define TLB_REF_INTERNAL (void*)-2
1184 #define TLB_REF_NOT_FOUND (void*)-1
1186 /* internal Parameter data */
1187 typedef struct tagTLBParDesc
1189 const TLBString *Name;
1190 struct list custdata_list;
1191 } TLBParDesc;
1193 /* internal Function data */
1194 typedef struct tagTLBFuncDesc
1196 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1197 const TLBString *Name; /* the name of this function */
1198 TLBParDesc *pParamDesc; /* array with param names and custom data */
1199 int helpcontext;
1200 int HelpStringContext;
1201 const TLBString *HelpString;
1202 const TLBString *Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1203 struct list custdata_list;
1204 } TLBFuncDesc;
1206 /* internal Variable data */
1207 typedef struct tagTLBVarDesc
1209 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1210 VARDESC *vardesc_create; /* additional data needed for storing VARDESC */
1211 const TLBString *Name; /* the name of this variable */
1212 int HelpContext;
1213 int HelpStringContext;
1214 const TLBString *HelpString;
1215 struct list custdata_list;
1216 } TLBVarDesc;
1218 /* internal implemented interface data */
1219 typedef struct tagTLBImplType
1221 HREFTYPE hRef; /* hRef of interface */
1222 int implflags; /* IMPLFLAG_*s */
1223 struct list custdata_list;
1224 } TLBImplType;
1226 /* internal TypeInfo data */
1227 typedef struct tagITypeInfoImpl
1229 ITypeInfo2 ITypeInfo2_iface;
1230 ITypeComp ITypeComp_iface;
1231 ICreateTypeInfo2 ICreateTypeInfo2_iface;
1232 LONG ref;
1233 BOOL not_attached_to_typelib;
1234 BOOL needs_layout;
1236 TLBGuid *guid;
1237 LCID lcid;
1238 MEMBERID memidConstructor;
1239 MEMBERID memidDestructor;
1240 LPOLESTR lpstrSchema;
1241 ULONG cbSizeInstance;
1242 TYPEKIND typekind;
1243 WORD cFuncs;
1244 WORD cVars;
1245 WORD cImplTypes;
1246 WORD cbSizeVft;
1247 WORD cbAlignment;
1248 WORD wTypeFlags;
1249 WORD wMajorVerNum;
1250 WORD wMinorVerNum;
1251 TYPEDESC *tdescAlias;
1252 IDLDESC idldescType;
1254 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1255 int index; /* index in this typelib; */
1256 HREFTYPE hreftype; /* hreftype for app object binding */
1257 /* type libs seem to store the doc strings in ascii
1258 * so why should we do it in unicode?
1260 const TLBString *Name;
1261 const TLBString *DocString;
1262 const TLBString *DllName;
1263 const TLBString *Schema;
1264 DWORD dwHelpContext;
1265 DWORD dwHelpStringContext;
1267 /* functions */
1268 TLBFuncDesc *funcdescs;
1270 /* variables */
1271 TLBVarDesc *vardescs;
1273 /* Implemented Interfaces */
1274 TLBImplType *impltypes;
1276 struct list *pcustdata_list;
1277 struct list custdata_list;
1278 } ITypeInfoImpl;
1280 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1282 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeComp_iface);
1285 static inline ITypeInfoImpl *impl_from_ITypeInfo2( ITypeInfo2 *iface )
1287 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeInfo2_iface);
1290 static inline ITypeInfoImpl *impl_from_ITypeInfo( ITypeInfo *iface )
1292 return impl_from_ITypeInfo2((ITypeInfo2*)iface);
1295 static inline ITypeInfoImpl *info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2 *iface )
1297 return CONTAINING_RECORD(iface, ITypeInfoImpl, ICreateTypeInfo2_iface);
1300 static const ITypeInfo2Vtbl tinfvt;
1301 static const ITypeCompVtbl tcompvt;
1302 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl;
1304 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1305 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1307 typedef struct tagTLBContext
1309 unsigned int oStart; /* start of TLB in file */
1310 unsigned int pos; /* current pos */
1311 unsigned int length; /* total length */
1312 void *mapping; /* memory mapping */
1313 MSFT_SegDir * pTblDir;
1314 ITypeLibImpl* pLibInfo;
1315 } TLBContext;
1318 static inline BSTR TLB_get_bstr(const TLBString *str)
1320 return str != NULL ? str->str : NULL;
1323 static inline int TLB_str_memcmp(void *left, const TLBString *str, DWORD len)
1325 if(!str)
1326 return 1;
1327 return memcmp(left, str->str, len);
1330 static inline const GUID *TLB_get_guidref(const TLBGuid *guid)
1332 return guid != NULL ? &guid->guid : NULL;
1335 static inline const GUID *TLB_get_guid_null(const TLBGuid *guid)
1337 return guid != NULL ? &guid->guid : &GUID_NULL;
1340 static int get_ptr_size(SYSKIND syskind)
1342 switch(syskind){
1343 case SYS_WIN64:
1344 return 8;
1345 case SYS_WIN32:
1346 case SYS_MAC:
1347 case SYS_WIN16:
1348 return 4;
1350 WARN("Unhandled syskind: 0x%x\n", syskind);
1351 return 4;
1355 debug
1357 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1358 if (pTD->vt & VT_RESERVED)
1359 szVarType += strlen(strcpy(szVarType, "reserved | "));
1360 if (pTD->vt & VT_BYREF)
1361 szVarType += strlen(strcpy(szVarType, "ref to "));
1362 if (pTD->vt & VT_ARRAY)
1363 szVarType += strlen(strcpy(szVarType, "array of "));
1364 if (pTD->vt & VT_VECTOR)
1365 szVarType += strlen(strcpy(szVarType, "vector of "));
1366 switch(pTD->vt & VT_TYPEMASK) {
1367 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1368 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1369 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1370 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1371 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1372 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1373 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1374 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1375 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1376 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1377 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1378 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1379 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1380 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1381 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1382 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1383 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1384 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1385 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1386 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1387 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1388 pTD->u.hreftype); break;
1389 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1390 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1391 case VT_PTR: sprintf(szVarType, "ptr to ");
1392 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1393 break;
1394 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1395 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1396 break;
1397 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1398 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1399 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1400 break;
1402 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1406 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1407 char buf[200];
1408 USHORT flags = edesc->u.paramdesc.wParamFlags;
1409 dump_TypeDesc(&edesc->tdesc,buf);
1410 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1411 MESSAGE("\t\tu.paramdesc.wParamFlags");
1412 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1413 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1414 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1415 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1416 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1417 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1418 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1419 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1420 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1422 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1423 int i;
1424 MESSAGE("memid is %08x\n",funcdesc->memid);
1425 for (i=0;i<funcdesc->cParams;i++) {
1426 MESSAGE("Param %d:\n",i);
1427 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1429 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1430 switch (funcdesc->funckind) {
1431 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1432 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1433 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1434 case FUNC_STATIC: MESSAGE("static");break;
1435 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1436 default: MESSAGE("unknown");break;
1438 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1439 switch (funcdesc->invkind) {
1440 case INVOKE_FUNC: MESSAGE("func");break;
1441 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1442 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1443 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1445 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1446 switch (funcdesc->callconv) {
1447 case CC_CDECL: MESSAGE("cdecl");break;
1448 case CC_PASCAL: MESSAGE("pascal");break;
1449 case CC_STDCALL: MESSAGE("stdcall");break;
1450 case CC_SYSCALL: MESSAGE("syscall");break;
1451 default:break;
1453 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1454 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1455 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1457 MESSAGE("\telemdescFunc (return value type):\n");
1458 dump_ELEMDESC(&funcdesc->elemdescFunc);
1461 static const char * const typekind_desc[] =
1463 "TKIND_ENUM",
1464 "TKIND_RECORD",
1465 "TKIND_MODULE",
1466 "TKIND_INTERFACE",
1467 "TKIND_DISPATCH",
1468 "TKIND_COCLASS",
1469 "TKIND_ALIAS",
1470 "TKIND_UNION",
1471 "TKIND_MAX"
1474 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1476 int i;
1477 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd->Name)), pfd->funcdesc.cParams);
1478 for (i=0;i<pfd->funcdesc.cParams;i++)
1479 MESSAGE("\tparm%d: %s\n",i,debugstr_w(TLB_get_bstr(pfd->pParamDesc[i].Name)));
1482 dump_FUNCDESC(&(pfd->funcdesc));
1484 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd->HelpString)));
1485 if(pfd->Entry == NULL)
1486 MESSAGE("\tentry: (null)\n");
1487 else if(pfd->Entry == (void*)-1)
1488 MESSAGE("\tentry: invalid\n");
1489 else if(IS_INTRESOURCE(pfd->Entry))
1490 MESSAGE("\tentry: %p\n", pfd->Entry);
1491 else
1492 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd->Entry)));
1494 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1496 while (n)
1498 dump_TLBFuncDescOne(pfd);
1499 ++pfd;
1500 --n;
1503 static void dump_TLBVarDesc(const TLBVarDesc * pvd, UINT n)
1505 while (n)
1507 TRACE_(typelib)("%s\n", debugstr_w(TLB_get_bstr(pvd->Name)));
1508 ++pvd;
1509 --n;
1513 static void dump_TLBImpLib(const TLBImpLib *import)
1515 TRACE_(typelib)("%s %s\n", debugstr_guid(TLB_get_guidref(import->guid)),
1516 debugstr_w(import->name));
1517 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1518 import->wVersionMinor, import->lcid, import->offset);
1521 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1523 TLBRefType *ref;
1525 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1527 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1528 if(ref->index == -1)
1529 TRACE_(typelib)("%s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
1530 else
1531 TRACE_(typelib)("type no: %d\n", ref->index);
1533 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1535 TRACE_(typelib)("in lib\n");
1536 dump_TLBImpLib(ref->pImpTLInfo);
1541 static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1543 if(!impl)
1544 return;
1545 while (n) {
1546 TRACE_(typelib)("implementing/inheriting interface hRef = %x implflags %x\n",
1547 impl->hRef, impl->implflags);
1548 ++impl;
1549 --n;
1553 static void dump_DispParms(const DISPPARAMS * pdp)
1555 unsigned int index;
1557 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1559 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1561 TRACE("named args:\n");
1562 for (index = 0; index < pdp->cNamedArgs; index++)
1563 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1566 if (pdp->cArgs && pdp->rgvarg)
1568 TRACE("args:\n");
1569 for (index = 0; index < pdp->cArgs; index++)
1570 TRACE(" [%d] %s\n", index, debugstr_variant(pdp->rgvarg+index));
1574 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1576 TRACE("%p ref=%u\n", pty, pty->ref);
1577 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty->Name)), debugstr_w(TLB_get_bstr(pty->DocString)));
1578 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty->guid)));
1579 TRACE("kind:%s\n", typekind_desc[pty->typekind]);
1580 TRACE("fct:%u var:%u impl:%u\n", pty->cFuncs, pty->cVars, pty->cImplTypes);
1581 TRACE("wTypeFlags: 0x%04x\n", pty->wTypeFlags);
1582 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1583 if (pty->typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty->DllName)));
1584 if (TRACE_ON(ole))
1585 dump_TLBFuncDesc(pty->funcdescs, pty->cFuncs);
1586 dump_TLBVarDesc(pty->vardescs, pty->cVars);
1587 dump_TLBImplType(pty->impltypes, pty->cImplTypes);
1590 static void dump_VARDESC(const VARDESC *v)
1592 MESSAGE("memid %d\n",v->memid);
1593 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1594 MESSAGE("oInst %d\n",v->u.oInst);
1595 dump_ELEMDESC(&(v->elemdescVar));
1596 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1597 MESSAGE("varkind %d\n",v->varkind);
1600 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1602 /* VT_LPWSTR is largest type that, may appear in type description */
1603 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1604 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1605 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1606 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1607 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1608 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1609 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1610 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1613 static void TLB_abort(void)
1615 DebugBreak();
1618 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size)
1620 void *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
1621 if (!ret) ERR("cannot allocate memory\n");
1622 return ret;
1625 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size)
1627 void *ret = HeapAlloc(GetProcessHeap(), 0, size);
1628 if (!ret) ERR("cannot allocate memory\n");
1629 return ret;
1632 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr, unsigned size)
1634 return HeapReAlloc(GetProcessHeap(), 0, ptr, size);
1637 void heap_free(void *ptr)
1639 HeapFree(GetProcessHeap(), 0, ptr);
1642 /* returns the size required for a deep copy of a typedesc into a
1643 * flat buffer */
1644 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1646 SIZE_T size = 0;
1648 if (alloc_initial_space)
1649 size += sizeof(TYPEDESC);
1651 switch (tdesc->vt)
1653 case VT_PTR:
1654 case VT_SAFEARRAY:
1655 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1656 break;
1657 case VT_CARRAY:
1658 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1659 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1660 break;
1662 return size;
1665 /* deep copy a typedesc into a flat buffer */
1666 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1668 if (!dest)
1670 dest = buffer;
1671 buffer = (char *)buffer + sizeof(TYPEDESC);
1674 *dest = *src;
1676 switch (src->vt)
1678 case VT_PTR:
1679 case VT_SAFEARRAY:
1680 dest->u.lptdesc = buffer;
1681 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1682 break;
1683 case VT_CARRAY:
1684 dest->u.lpadesc = buffer;
1685 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1686 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1687 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1688 break;
1690 return buffer;
1693 /* free custom data allocated by MSFT_CustData */
1694 static inline void TLB_FreeCustData(struct list *custdata_list)
1696 TLBCustData *cd, *cdn;
1697 LIST_FOR_EACH_ENTRY_SAFE(cd, cdn, custdata_list, TLBCustData, entry)
1699 list_remove(&cd->entry);
1700 VariantClear(&cd->data);
1701 heap_free(cd);
1705 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1707 DWORD len;
1708 BSTR ret;
1710 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1711 ret = SysAllocStringLen(NULL, len - 1);
1712 if (!ret) return ret;
1713 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1714 return ret;
1717 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(TLBFuncDesc *funcdescs,
1718 UINT n, MEMBERID memid)
1720 while(n){
1721 if(funcdescs->funcdesc.memid == memid)
1722 return funcdescs;
1723 ++funcdescs;
1724 --n;
1726 return NULL;
1729 static inline TLBVarDesc *TLB_get_vardesc_by_memberid(TLBVarDesc *vardescs,
1730 UINT n, MEMBERID memid)
1732 while(n){
1733 if(vardescs->vardesc.memid == memid)
1734 return vardescs;
1735 ++vardescs;
1736 --n;
1738 return NULL;
1741 static inline TLBVarDesc *TLB_get_vardesc_by_name(TLBVarDesc *vardescs,
1742 UINT n, const OLECHAR *name)
1744 while(n){
1745 if(!lstrcmpiW(TLB_get_bstr(vardescs->Name), name))
1746 return vardescs;
1747 ++vardescs;
1748 --n;
1750 return NULL;
1753 static inline TLBCustData *TLB_get_custdata_by_guid(struct list *custdata_list, REFGUID guid)
1755 TLBCustData *cust_data;
1756 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1757 if(IsEqualIID(TLB_get_guid_null(cust_data->guid), guid))
1758 return cust_data;
1759 return NULL;
1762 static inline ITypeInfoImpl *TLB_get_typeinfo_by_name(ITypeInfoImpl **typeinfos,
1763 UINT n, const OLECHAR *name)
1765 while(n){
1766 if(!lstrcmpiW(TLB_get_bstr((*typeinfos)->Name), name))
1767 return *typeinfos;
1768 ++typeinfos;
1769 --n;
1771 return NULL;
1774 static void TLBVarDesc_Constructor(TLBVarDesc *var_desc)
1776 list_init(&var_desc->custdata_list);
1779 static TLBVarDesc *TLBVarDesc_Alloc(UINT n)
1781 TLBVarDesc *ret;
1783 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1784 if(!ret)
1785 return NULL;
1787 while(n){
1788 TLBVarDesc_Constructor(&ret[n-1]);
1789 --n;
1792 return ret;
1795 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1797 TLBParDesc *ret;
1799 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1800 if(!ret)
1801 return NULL;
1803 while(n){
1804 list_init(&ret[n-1].custdata_list);
1805 --n;
1808 return ret;
1811 static void TLBFuncDesc_Constructor(TLBFuncDesc *func_desc)
1813 list_init(&func_desc->custdata_list);
1816 static TLBFuncDesc *TLBFuncDesc_Alloc(UINT n)
1818 TLBFuncDesc *ret;
1820 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1821 if(!ret)
1822 return NULL;
1824 while(n){
1825 TLBFuncDesc_Constructor(&ret[n-1]);
1826 --n;
1829 return ret;
1832 static void TLBImplType_Constructor(TLBImplType *impl)
1834 list_init(&impl->custdata_list);
1837 static TLBImplType *TLBImplType_Alloc(UINT n)
1839 TLBImplType *ret;
1841 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1842 if(!ret)
1843 return NULL;
1845 while(n){
1846 TLBImplType_Constructor(&ret[n-1]);
1847 --n;
1850 return ret;
1853 static TLBGuid *TLB_append_guid(struct list *guid_list,
1854 const GUID *new_guid, HREFTYPE hreftype)
1856 TLBGuid *guid;
1858 LIST_FOR_EACH_ENTRY(guid, guid_list, TLBGuid, entry) {
1859 if (IsEqualGUID(&guid->guid, new_guid))
1860 return guid;
1863 guid = heap_alloc(sizeof(TLBGuid));
1864 if (!guid)
1865 return NULL;
1867 memcpy(&guid->guid, new_guid, sizeof(GUID));
1868 guid->hreftype = hreftype;
1870 list_add_tail(guid_list, &guid->entry);
1872 return guid;
1875 static HRESULT TLB_set_custdata(struct list *custdata_list, TLBGuid *tlbguid, VARIANT *var)
1877 TLBCustData *cust_data;
1879 switch(V_VT(var)){
1880 case VT_I4:
1881 case VT_R4:
1882 case VT_UI4:
1883 case VT_INT:
1884 case VT_UINT:
1885 case VT_HRESULT:
1886 case VT_BSTR:
1887 break;
1888 default:
1889 return DISP_E_BADVARTYPE;
1892 cust_data = TLB_get_custdata_by_guid(custdata_list, TLB_get_guid_null(tlbguid));
1894 if (!cust_data) {
1895 cust_data = heap_alloc(sizeof(TLBCustData));
1896 if (!cust_data)
1897 return E_OUTOFMEMORY;
1899 cust_data->guid = tlbguid;
1900 VariantInit(&cust_data->data);
1902 list_add_tail(custdata_list, &cust_data->entry);
1903 }else
1904 VariantClear(&cust_data->data);
1906 return VariantCopy(&cust_data->data, var);
1909 static TLBString *TLB_append_str(struct list *string_list, BSTR new_str)
1911 TLBString *str;
1913 if(!new_str)
1914 return NULL;
1916 LIST_FOR_EACH_ENTRY(str, string_list, TLBString, entry) {
1917 if (strcmpW(str->str, new_str) == 0)
1918 return str;
1921 str = heap_alloc(sizeof(TLBString));
1922 if (!str)
1923 return NULL;
1925 str->str = SysAllocString(new_str);
1926 if (!str->str) {
1927 heap_free(str);
1928 return NULL;
1931 list_add_tail(string_list, &str->entry);
1933 return str;
1936 static HRESULT TLB_get_size_from_hreftype(ITypeInfoImpl *info, HREFTYPE href,
1937 ULONG *size, WORD *align)
1939 ITypeInfo *other;
1940 TYPEATTR *attr;
1941 HRESULT hr;
1943 hr = ITypeInfo2_GetRefTypeInfo(&info->ITypeInfo2_iface, href, &other);
1944 if(FAILED(hr))
1945 return hr;
1947 hr = ITypeInfo_GetTypeAttr(other, &attr);
1948 if(FAILED(hr)){
1949 ITypeInfo_Release(other);
1950 return hr;
1953 if(size)
1954 *size = attr->cbSizeInstance;
1955 if(align)
1956 *align = attr->cbAlignment;
1958 ITypeInfo_ReleaseTypeAttr(other, attr);
1959 ITypeInfo_Release(other);
1961 return S_OK;
1964 static HRESULT TLB_size_instance(ITypeInfoImpl *info, SYSKIND sys,
1965 TYPEDESC *tdesc, ULONG *size, WORD *align)
1967 ULONG i, sub, ptr_size;
1968 HRESULT hr;
1970 ptr_size = get_ptr_size(sys);
1972 switch(tdesc->vt){
1973 case VT_VOID:
1974 *size = 0;
1975 break;
1976 case VT_I1:
1977 case VT_UI1:
1978 *size = 1;
1979 break;
1980 case VT_I2:
1981 case VT_BOOL:
1982 case VT_UI2:
1983 *size = 2;
1984 break;
1985 case VT_I4:
1986 case VT_R4:
1987 case VT_ERROR:
1988 case VT_UI4:
1989 case VT_INT:
1990 case VT_UINT:
1991 case VT_HRESULT:
1992 *size = 4;
1993 break;
1994 case VT_R8:
1995 case VT_I8:
1996 case VT_UI8:
1997 *size = 8;
1998 break;
1999 case VT_BSTR:
2000 case VT_DISPATCH:
2001 case VT_UNKNOWN:
2002 case VT_PTR:
2003 case VT_SAFEARRAY:
2004 case VT_LPSTR:
2005 case VT_LPWSTR:
2006 *size = ptr_size;
2007 break;
2008 case VT_DATE:
2009 *size = sizeof(DATE);
2010 break;
2011 case VT_VARIANT:
2012 *size = sizeof(VARIANT);
2013 #ifdef _WIN64
2014 if(sys == SYS_WIN32)
2015 *size -= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
2016 #endif
2017 break;
2018 case VT_DECIMAL:
2019 *size = sizeof(DECIMAL);
2020 break;
2021 case VT_CY:
2022 *size = sizeof(CY);
2023 break;
2024 case VT_CARRAY:
2025 *size = 0;
2026 for(i = 0; i < tdesc->u.lpadesc->cDims; ++i)
2027 *size += tdesc->u.lpadesc->rgbounds[i].cElements;
2028 hr = TLB_size_instance(info, sys, &tdesc->u.lpadesc->tdescElem, &sub, align);
2029 if(FAILED(hr))
2030 return hr;
2031 *size *= sub;
2032 return S_OK;
2033 case VT_USERDEFINED:
2034 return TLB_get_size_from_hreftype(info, tdesc->u.hreftype, size, align);
2035 default:
2036 FIXME("Unsized VT: 0x%x\n", tdesc->vt);
2037 return E_FAIL;
2040 if(align){
2041 if(*size < 4)
2042 *align = *size;
2043 else
2044 *align = 4;
2047 return S_OK;
2050 /**********************************************************************
2052 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2055 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
2057 if (where != DO_NOT_SEEK)
2059 where += pcx->oStart;
2060 if (where > pcx->length)
2062 /* FIXME */
2063 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
2064 TLB_abort();
2066 pcx->pos = where;
2070 /* read function */
2071 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
2073 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2074 pcx->pos, count, pcx->oStart, pcx->length, where);
2076 MSFT_Seek(pcx, where);
2077 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
2078 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
2079 pcx->pos += count;
2080 return count;
2083 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
2084 LONG where )
2086 DWORD ret;
2088 ret = MSFT_Read(buffer, count, pcx, where);
2089 FromLEDWords(buffer, ret);
2091 return ret;
2094 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
2095 LONG where )
2097 DWORD ret;
2099 ret = MSFT_Read(buffer, count, pcx, where);
2100 FromLEWords(buffer, ret);
2102 return ret;
2105 static HRESULT MSFT_ReadAllGuids(TLBContext *pcx)
2107 TLBGuid *guid;
2108 MSFT_GuidEntry entry;
2109 int offs = 0;
2111 MSFT_Seek(pcx, pcx->pTblDir->pGuidTab.offset);
2112 while (1) {
2113 if (offs >= pcx->pTblDir->pGuidTab.length)
2114 return S_OK;
2116 MSFT_ReadLEWords(&entry, sizeof(MSFT_GuidEntry), pcx, DO_NOT_SEEK);
2118 guid = heap_alloc(sizeof(TLBGuid));
2120 guid->offset = offs;
2121 guid->guid = entry.guid;
2122 guid->hreftype = entry.hreftype;
2124 list_add_tail(&pcx->pLibInfo->guid_list, &guid->entry);
2126 offs += sizeof(MSFT_GuidEntry);
2130 static TLBGuid *MSFT_ReadGuid( int offset, TLBContext *pcx)
2132 TLBGuid *ret;
2134 LIST_FOR_EACH_ENTRY(ret, &pcx->pLibInfo->guid_list, TLBGuid, entry){
2135 if(ret->offset == offset){
2136 TRACE_(typelib)("%s\n", debugstr_guid(&ret->guid));
2137 return ret;
2141 return NULL;
2144 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
2146 MSFT_NameIntro niName;
2148 if (offset < 0)
2150 ERR_(typelib)("bad offset %d\n", offset);
2151 return -1;
2154 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
2155 pcx->pTblDir->pNametab.offset+offset);
2157 return niName.hreftype;
2160 static HRESULT MSFT_ReadAllNames(TLBContext *pcx)
2162 char *string;
2163 MSFT_NameIntro intro;
2164 INT16 len_piece;
2165 int offs = 0, lengthInChars;
2167 MSFT_Seek(pcx, pcx->pTblDir->pNametab.offset);
2168 while (1) {
2169 TLBString *tlbstr;
2171 if (offs >= pcx->pTblDir->pNametab.length)
2172 return S_OK;
2174 MSFT_ReadLEWords(&intro, sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2175 intro.namelen &= 0xFF;
2176 len_piece = intro.namelen + sizeof(MSFT_NameIntro);
2177 if(len_piece % 4)
2178 len_piece = (len_piece + 4) & ~0x3;
2179 if(len_piece < 8)
2180 len_piece = 8;
2182 string = heap_alloc(len_piece + 1);
2183 MSFT_Read(string, len_piece - sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2184 string[intro.namelen] = '\0';
2186 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2187 string, -1, NULL, 0);
2188 if (!lengthInChars) {
2189 heap_free(string);
2190 return E_UNEXPECTED;
2193 tlbstr = heap_alloc(sizeof(TLBString));
2195 tlbstr->offset = offs;
2196 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2197 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2199 heap_free(string);
2201 list_add_tail(&pcx->pLibInfo->name_list, &tlbstr->entry);
2203 offs += len_piece;
2207 static TLBString *MSFT_ReadName( TLBContext *pcx, int offset)
2209 TLBString *tlbstr;
2211 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->name_list, TLBString, entry) {
2212 if (tlbstr->offset == offset) {
2213 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2214 return tlbstr;
2218 return NULL;
2221 static TLBString *MSFT_ReadString( TLBContext *pcx, int offset)
2223 TLBString *tlbstr;
2225 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->string_list, TLBString, entry) {
2226 if (tlbstr->offset == offset) {
2227 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2228 return tlbstr;
2232 return NULL;
2236 * read a value and fill a VARIANT structure
2238 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
2240 int size;
2242 TRACE_(typelib)("\n");
2244 if(offset <0) { /* data are packed in here */
2245 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
2246 V_I4(pVar) = offset & 0x3ffffff;
2247 return;
2249 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
2250 pcx->pTblDir->pCustData.offset + offset );
2251 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
2252 switch (V_VT(pVar)){
2253 case VT_EMPTY: /* FIXME: is this right? */
2254 case VT_NULL: /* FIXME: is this right? */
2255 case VT_I2 : /* this should not happen */
2256 case VT_I4 :
2257 case VT_R4 :
2258 case VT_ERROR :
2259 case VT_BOOL :
2260 case VT_I1 :
2261 case VT_UI1 :
2262 case VT_UI2 :
2263 case VT_UI4 :
2264 case VT_INT :
2265 case VT_UINT :
2266 case VT_VOID : /* FIXME: is this right? */
2267 case VT_HRESULT :
2268 size=4; break;
2269 case VT_R8 :
2270 case VT_CY :
2271 case VT_DATE :
2272 case VT_I8 :
2273 case VT_UI8 :
2274 case VT_DECIMAL : /* FIXME: is this right? */
2275 case VT_FILETIME :
2276 size=8;break;
2277 /* pointer types with known behaviour */
2278 case VT_BSTR :{
2279 char * ptr;
2280 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
2281 if(size == -1){
2282 V_BSTR(pVar) = NULL;
2283 }else{
2284 ptr = heap_alloc_zero(size);
2285 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);
2286 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
2287 /* FIXME: do we need a AtoW conversion here? */
2288 V_UNION(pVar, bstrVal[size])='\0';
2289 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
2290 heap_free(ptr);
2293 size=-4; break;
2294 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2295 case VT_DISPATCH :
2296 case VT_VARIANT :
2297 case VT_UNKNOWN :
2298 case VT_PTR :
2299 case VT_SAFEARRAY :
2300 case VT_CARRAY :
2301 case VT_USERDEFINED :
2302 case VT_LPSTR :
2303 case VT_LPWSTR :
2304 case VT_BLOB :
2305 case VT_STREAM :
2306 case VT_STORAGE :
2307 case VT_STREAMED_OBJECT :
2308 case VT_STORED_OBJECT :
2309 case VT_BLOB_OBJECT :
2310 case VT_CF :
2311 case VT_CLSID :
2312 default:
2313 size=0;
2314 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2315 V_VT(pVar));
2318 if(size>0) /* (big|small) endian correct? */
2319 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
2320 return;
2323 * create a linked list with custom data
2325 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
2327 MSFT_CDGuid entry;
2328 TLBCustData* pNew;
2329 int count=0;
2331 TRACE_(typelib)("\n");
2333 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
2335 while(offset >=0){
2336 count++;
2337 pNew=heap_alloc_zero(sizeof(TLBCustData));
2338 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
2339 pNew->guid = MSFT_ReadGuid(entry.GuidOffset, pcx);
2340 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
2341 list_add_head(custdata_list, &pNew->entry);
2342 offset = entry.next;
2344 return count;
2347 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd)
2349 if(type <0)
2350 pTd->vt=type & VT_TYPEMASK;
2351 else
2352 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
2354 TRACE_(typelib)("vt type = %X\n", pTd->vt);
2357 static BOOL TLB_is_propgetput(INVOKEKIND invkind)
2359 return (invkind == INVOKE_PROPERTYGET ||
2360 invkind == INVOKE_PROPERTYPUT ||
2361 invkind == INVOKE_PROPERTYPUTREF);
2364 static void
2365 MSFT_DoFuncs(TLBContext* pcx,
2366 ITypeInfoImpl* pTI,
2367 int cFuncs,
2368 int cVars,
2369 int offset,
2370 TLBFuncDesc** pptfd)
2373 * member information is stored in a data structure at offset
2374 * indicated by the memoffset field of the typeinfo structure
2375 * There are several distinctive parts.
2376 * The first part starts with a field that holds the total length
2377 * of this (first) part excluding this field. Then follow the records,
2378 * for each member there is one record.
2380 * The first entry is always the length of the record (including this
2381 * length word).
2382 * The rest of the record depends on the type of the member. If there is
2383 * a field indicating the member type (function, variable, interface, etc)
2384 * I have not found it yet. At this time we depend on the information
2385 * in the type info and the usual order how things are stored.
2387 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2388 * for each member;
2390 * Third is an equal sized array with file offsets to the name entry
2391 * of each member.
2393 * The fourth and last (?) part is an array with offsets to the records
2394 * in the first part of this file segment.
2397 int infolen, nameoffset, reclength, i;
2398 int recoffset = offset + sizeof(INT);
2400 char *recbuf = heap_alloc(0xffff);
2401 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2402 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2404 TRACE_(typelib)("\n");
2406 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2408 *pptfd = TLBFuncDesc_Alloc(cFuncs);
2409 ptfd = *pptfd;
2410 for ( i = 0; i < cFuncs ; i++ )
2412 int optional;
2414 /* name, eventually add to a hash table */
2415 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2416 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2418 /* read the function information record */
2419 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2421 reclength &= 0xffff;
2423 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2425 /* size without argument data */
2426 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2427 if (pFuncRec->FKCCIC & 0x1000)
2428 optional -= pFuncRec->nrargs * sizeof(INT);
2430 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2431 ptfd->helpcontext = pFuncRec->HelpContext;
2433 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2434 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2436 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2438 if (pFuncRec->FKCCIC & 0x2000 )
2440 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2441 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2442 ptfd->Entry = (TLBString*)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2444 else
2445 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2447 else
2448 ptfd->Entry = (TLBString*)-1;
2450 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2451 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2453 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2454 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2456 /* fill the FuncDesc Structure */
2457 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2458 offset + infolen + ( i + 1) * sizeof(INT));
2460 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2461 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2462 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2463 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2464 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2465 ptfd->funcdesc.oVft = pFuncRec->VtableOffset & ~1;
2466 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2468 /* nameoffset is sometimes -1 on the second half of a propget/propput
2469 * pair of functions */
2470 if ((nameoffset == -1) && (i > 0) &&
2471 TLB_is_propgetput(ptfd_prev->funcdesc.invkind) &&
2472 TLB_is_propgetput(ptfd->funcdesc.invkind))
2473 ptfd->Name = ptfd_prev->Name;
2474 else
2475 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2477 MSFT_GetTdesc(pcx,
2478 pFuncRec->DataType,
2479 &ptfd->funcdesc.elemdescFunc.tdesc);
2481 /* do the parameters/arguments */
2482 if(pFuncRec->nrargs)
2484 int j = 0;
2485 MSFT_ParameterInfo paraminfo;
2487 ptfd->funcdesc.lprgelemdescParam =
2488 heap_alloc_zero(pFuncRec->nrargs * (sizeof(ELEMDESC) + sizeof(PARAMDESCEX)));
2490 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2492 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2493 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2495 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2497 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2499 MSFT_GetTdesc(pcx,
2500 paraminfo.DataType,
2501 &elemdesc->tdesc);
2503 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2505 /* name */
2506 if (paraminfo.oName != -1)
2507 ptfd->pParamDesc[j].Name =
2508 MSFT_ReadName( pcx, paraminfo.oName );
2509 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(TLB_get_bstr(ptfd->pParamDesc[j].Name)));
2511 /* default value */
2512 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2513 (pFuncRec->FKCCIC & 0x1000) )
2515 INT* pInt = (INT *)((char *)pFuncRec +
2516 reclength -
2517 (pFuncRec->nrargs * 4) * sizeof(INT) );
2519 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2521 pParamDesc->pparamdescex = (PARAMDESCEX*)(ptfd->funcdesc.lprgelemdescParam+pFuncRec->nrargs)+j;
2522 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2524 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2525 pInt[j], pcx);
2527 else
2528 elemdesc->u.paramdesc.pparamdescex = NULL;
2530 /* custom info */
2531 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2532 j*sizeof(pFuncRec->oArgCustData[0])) &&
2533 pFuncRec->FKCCIC & 0x80 )
2535 MSFT_CustData(pcx,
2536 pFuncRec->oArgCustData[j],
2537 &ptfd->pParamDesc[j].custdata_list);
2540 /* SEEK value = jump to offset,
2541 * from there jump to the end of record,
2542 * go back by (j-1) arguments
2544 MSFT_ReadLEDWords( &paraminfo ,
2545 sizeof(MSFT_ParameterInfo), pcx,
2546 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2547 * sizeof(MSFT_ParameterInfo)));
2551 /* scode is not used: archaic win16 stuff FIXME: right? */
2552 ptfd->funcdesc.cScodes = 0 ;
2553 ptfd->funcdesc.lprgscode = NULL ;
2555 ptfd_prev = ptfd;
2556 ++ptfd;
2557 recoffset += reclength;
2559 heap_free(recbuf);
2562 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2563 int cVars, int offset, TLBVarDesc ** pptvd)
2565 int infolen, nameoffset, reclength;
2566 char recbuf[256];
2567 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2568 TLBVarDesc *ptvd;
2569 int i;
2570 int recoffset;
2572 TRACE_(typelib)("\n");
2574 ptvd = *pptvd = TLBVarDesc_Alloc(cVars);
2575 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2576 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2577 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2578 recoffset += offset+sizeof(INT);
2579 for(i=0;i<cVars;i++, ++ptvd){
2580 /* name, eventually add to a hash table */
2581 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2582 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2583 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2584 /* read the variable information record */
2585 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2586 reclength &= 0xff;
2587 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2589 /* optional data */
2590 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2591 ptvd->HelpContext = pVarRec->HelpContext;
2593 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2594 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2596 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2597 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2599 /* fill the VarDesc Structure */
2600 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2601 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2602 ptvd->vardesc.varkind = pVarRec->VarKind;
2603 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2604 MSFT_GetTdesc(pcx, pVarRec->DataType,
2605 &ptvd->vardesc.elemdescVar.tdesc);
2606 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2607 if(pVarRec->VarKind == VAR_CONST ){
2608 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2609 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2610 pVarRec->OffsValue, pcx);
2611 } else
2612 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2613 recoffset += reclength;
2617 /* process Implemented Interfaces of a com class */
2618 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2619 int offset)
2621 int i;
2622 MSFT_RefRecord refrec;
2623 TLBImplType *pImpl;
2625 TRACE_(typelib)("\n");
2627 pTI->impltypes = TLBImplType_Alloc(count);
2628 pImpl = pTI->impltypes;
2629 for(i=0;i<count;i++){
2630 if(offset<0) break; /* paranoia */
2631 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2632 pImpl->hRef = refrec.reftype;
2633 pImpl->implflags=refrec.flags;
2634 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2635 offset=refrec.onext;
2636 ++pImpl;
2640 #ifdef _WIN64
2641 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2642 * and some structures, and fix the alignment */
2643 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl *info)
2645 if(info->typekind == TKIND_ALIAS){
2646 switch(info->tdescAlias->vt){
2647 case VT_BSTR:
2648 case VT_DISPATCH:
2649 case VT_UNKNOWN:
2650 case VT_PTR:
2651 case VT_SAFEARRAY:
2652 case VT_LPSTR:
2653 case VT_LPWSTR:
2654 info->cbSizeInstance = sizeof(void*);
2655 info->cbAlignment = sizeof(void*);
2656 break;
2657 case VT_CARRAY:
2658 case VT_USERDEFINED:
2659 TLB_size_instance(info, SYS_WIN64, info->tdescAlias, &info->cbSizeInstance, &info->cbAlignment);
2660 break;
2661 case VT_VARIANT:
2662 info->cbSizeInstance = sizeof(VARIANT);
2663 info->cbAlignment = 8;
2664 default:
2665 if(info->cbSizeInstance < sizeof(void*))
2666 info->cbAlignment = info->cbSizeInstance;
2667 else
2668 info->cbAlignment = sizeof(void*);
2669 break;
2671 }else if(info->typekind == TKIND_INTERFACE ||
2672 info->typekind == TKIND_DISPATCH ||
2673 info->typekind == TKIND_COCLASS){
2674 info->cbSizeInstance = sizeof(void*);
2675 info->cbAlignment = sizeof(void*);
2678 #endif
2681 * process a typeinfo record
2683 static ITypeInfoImpl * MSFT_DoTypeInfo(
2684 TLBContext *pcx,
2685 int count,
2686 ITypeLibImpl * pLibInfo)
2688 MSFT_TypeInfoBase tiBase;
2689 ITypeInfoImpl *ptiRet;
2691 TRACE_(typelib)("count=%u\n", count);
2693 ptiRet = ITypeInfoImpl_Constructor();
2694 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2695 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2697 /* this is where we are coming from */
2698 ptiRet->pTypeLib = pLibInfo;
2699 ptiRet->index=count;
2701 ptiRet->guid = MSFT_ReadGuid(tiBase.posguid, pcx);
2702 ptiRet->lcid=pLibInfo->set_lcid; /* FIXME: correct? */
2703 ptiRet->lpstrSchema=NULL; /* reserved */
2704 ptiRet->cbSizeInstance=tiBase.size;
2705 ptiRet->typekind=tiBase.typekind & 0xF;
2706 ptiRet->cFuncs=LOWORD(tiBase.cElement);
2707 ptiRet->cVars=HIWORD(tiBase.cElement);
2708 ptiRet->cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2709 ptiRet->wTypeFlags=tiBase.flags;
2710 ptiRet->wMajorVerNum=LOWORD(tiBase.version);
2711 ptiRet->wMinorVerNum=HIWORD(tiBase.version);
2712 ptiRet->cImplTypes=tiBase.cImplTypes;
2713 ptiRet->cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2714 if(ptiRet->typekind == TKIND_ALIAS){
2715 TYPEDESC tmp;
2716 MSFT_GetTdesc(pcx, tiBase.datatype1, &tmp);
2717 ptiRet->tdescAlias = heap_alloc(TLB_SizeTypeDesc(&tmp, TRUE));
2718 TLB_CopyTypeDesc(NULL, &tmp, ptiRet->tdescAlias);
2721 /* FIXME: */
2722 /* IDLDESC idldescType; *//* never saw this one != zero */
2724 /* name, eventually add to a hash table */
2725 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2726 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2727 TRACE_(typelib)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet->Name)));
2728 /* help info */
2729 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2730 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2731 ptiRet->dwHelpContext=tiBase.helpcontext;
2733 if (ptiRet->typekind == TKIND_MODULE)
2734 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2736 /* note: InfoType's Help file and HelpStringDll come from the containing
2737 * library. Further HelpString and Docstring appear to be the same thing :(
2739 /* functions */
2740 if(ptiRet->cFuncs >0 )
2741 MSFT_DoFuncs(pcx, ptiRet, ptiRet->cFuncs,
2742 ptiRet->cVars,
2743 tiBase.memoffset, &ptiRet->funcdescs);
2744 /* variables */
2745 if(ptiRet->cVars >0 )
2746 MSFT_DoVars(pcx, ptiRet, ptiRet->cFuncs,
2747 ptiRet->cVars,
2748 tiBase.memoffset, &ptiRet->vardescs);
2749 if(ptiRet->cImplTypes >0 ) {
2750 switch(ptiRet->typekind)
2752 case TKIND_COCLASS:
2753 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->cImplTypes,
2754 tiBase.datatype1);
2755 break;
2756 case TKIND_DISPATCH:
2757 /* This is not -1 when the interface is a non-base dual interface or
2758 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2759 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2760 not this interface.
2763 if (tiBase.datatype1 != -1)
2765 ptiRet->impltypes = TLBImplType_Alloc(1);
2766 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2768 break;
2769 default:
2770 ptiRet->impltypes = TLBImplType_Alloc(1);
2771 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2772 break;
2775 MSFT_CustData(pcx, tiBase.oCustData, ptiRet->pcustdata_list);
2777 TRACE_(typelib)("%s guid: %s kind:%s\n",
2778 debugstr_w(TLB_get_bstr(ptiRet->Name)),
2779 debugstr_guid(TLB_get_guidref(ptiRet->guid)),
2780 typekind_desc[ptiRet->typekind]);
2781 if (TRACE_ON(typelib))
2782 dump_TypeInfo(ptiRet);
2784 return ptiRet;
2787 static HRESULT MSFT_ReadAllStrings(TLBContext *pcx)
2789 char *string;
2790 INT16 len_str, len_piece;
2791 int offs = 0, lengthInChars;
2793 MSFT_Seek(pcx, pcx->pTblDir->pStringtab.offset);
2794 while (1) {
2795 TLBString *tlbstr;
2797 if (offs >= pcx->pTblDir->pStringtab.length)
2798 return S_OK;
2800 MSFT_ReadLEWords(&len_str, sizeof(INT16), pcx, DO_NOT_SEEK);
2801 len_piece = len_str + sizeof(INT16);
2802 if(len_piece % 4)
2803 len_piece = (len_piece + 4) & ~0x3;
2804 if(len_piece < 8)
2805 len_piece = 8;
2807 string = heap_alloc(len_piece + 1);
2808 MSFT_Read(string, len_piece - sizeof(INT16), pcx, DO_NOT_SEEK);
2809 string[len_str] = '\0';
2811 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2812 string, -1, NULL, 0);
2813 if (!lengthInChars) {
2814 heap_free(string);
2815 return E_UNEXPECTED;
2818 tlbstr = heap_alloc(sizeof(TLBString));
2820 tlbstr->offset = offs;
2821 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2822 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2824 heap_free(string);
2826 list_add_tail(&pcx->pLibInfo->string_list, &tlbstr->entry);
2828 offs += len_piece;
2832 static HRESULT MSFT_ReadAllRefs(TLBContext *pcx)
2834 TLBRefType *ref;
2835 int offs = 0;
2837 MSFT_Seek(pcx, pcx->pTblDir->pImpInfo.offset);
2838 while (offs < pcx->pTblDir->pImpInfo.length) {
2839 MSFT_ImpInfo impinfo;
2840 TLBImpLib *pImpLib;
2842 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx, DO_NOT_SEEK);
2844 ref = heap_alloc_zero(sizeof(TLBRefType));
2845 list_add_tail(&pcx->pLibInfo->ref_list, &ref->entry);
2847 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2848 if(pImpLib->offset==impinfo.oImpFile)
2849 break;
2851 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2852 ref->reference = offs;
2853 ref->pImpTLInfo = pImpLib;
2854 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2855 ref->guid = MSFT_ReadGuid(impinfo.oGuid, pcx);
2856 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
2857 ref->index = TLB_REF_USE_GUID;
2858 } else
2859 ref->index = impinfo.oGuid;
2860 }else{
2861 ERR("Cannot find a reference\n");
2862 ref->reference = -1;
2863 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2866 offs += sizeof(impinfo);
2869 return S_OK;
2872 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2873 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2874 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2875 * tradeoff here.
2877 static struct list tlb_cache = LIST_INIT(tlb_cache);
2878 static CRITICAL_SECTION cache_section;
2879 static CRITICAL_SECTION_DEBUG cache_section_debug =
2881 0, 0, &cache_section,
2882 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2883 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2885 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2888 typedef struct TLB_PEFile
2890 IUnknown IUnknown_iface;
2891 LONG refs;
2892 HMODULE dll;
2893 HRSRC typelib_resource;
2894 HGLOBAL typelib_global;
2895 LPVOID typelib_base;
2896 } TLB_PEFile;
2898 static inline TLB_PEFile *pefile_impl_from_IUnknown(IUnknown *iface)
2900 return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2903 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2905 if (IsEqualIID(riid, &IID_IUnknown))
2907 *ppv = iface;
2908 IUnknown_AddRef(iface);
2909 return S_OK;
2911 *ppv = NULL;
2912 return E_NOINTERFACE;
2915 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2917 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2918 return InterlockedIncrement(&This->refs);
2921 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2923 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2924 ULONG refs = InterlockedDecrement(&This->refs);
2925 if (!refs)
2927 if (This->typelib_global)
2928 FreeResource(This->typelib_global);
2929 if (This->dll)
2930 FreeLibrary(This->dll);
2931 heap_free(This);
2933 return refs;
2936 static const IUnknownVtbl TLB_PEFile_Vtable =
2938 TLB_PEFile_QueryInterface,
2939 TLB_PEFile_AddRef,
2940 TLB_PEFile_Release
2943 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2945 TLB_PEFile *This;
2946 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2948 This = heap_alloc(sizeof(TLB_PEFile));
2949 if (!This)
2950 return E_OUTOFMEMORY;
2952 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
2953 This->refs = 1;
2954 This->dll = NULL;
2955 This->typelib_resource = NULL;
2956 This->typelib_global = NULL;
2957 This->typelib_base = NULL;
2959 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2960 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2962 if (This->dll)
2964 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2965 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2966 if (This->typelib_resource)
2968 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2969 if (This->typelib_global)
2971 This->typelib_base = LockResource(This->typelib_global);
2973 if (This->typelib_base)
2975 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2976 *ppBase = This->typelib_base;
2977 *ppFile = &This->IUnknown_iface;
2978 return S_OK;
2983 TRACE("No TYPELIB resource found\n");
2984 hr = E_FAIL;
2987 TLB_PEFile_Release(&This->IUnknown_iface);
2988 return hr;
2991 typedef struct TLB_NEFile
2993 IUnknown IUnknown_iface;
2994 LONG refs;
2995 LPVOID typelib_base;
2996 } TLB_NEFile;
2998 static inline TLB_NEFile *nefile_impl_from_IUnknown(IUnknown *iface)
3000 return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
3003 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3005 if (IsEqualIID(riid, &IID_IUnknown))
3007 *ppv = iface;
3008 IUnknown_AddRef(iface);
3009 return S_OK;
3011 *ppv = NULL;
3012 return E_NOINTERFACE;
3015 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
3017 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
3018 return InterlockedIncrement(&This->refs);
3021 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
3023 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
3024 ULONG refs = InterlockedDecrement(&This->refs);
3025 if (!refs)
3027 heap_free(This->typelib_base);
3028 heap_free(This);
3030 return refs;
3033 static const IUnknownVtbl TLB_NEFile_Vtable =
3035 TLB_NEFile_QueryInterface,
3036 TLB_NEFile_AddRef,
3037 TLB_NEFile_Release
3040 /***********************************************************************
3041 * read_xx_header [internal]
3043 static int read_xx_header( HFILE lzfd )
3045 IMAGE_DOS_HEADER mzh;
3046 char magic[3];
3048 LZSeek( lzfd, 0, SEEK_SET );
3049 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
3050 return 0;
3051 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
3052 return 0;
3054 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3055 if ( 2 != LZRead( lzfd, magic, 2 ) )
3056 return 0;
3058 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3060 if ( magic[0] == 'N' && magic[1] == 'E' )
3061 return IMAGE_OS2_SIGNATURE;
3062 if ( magic[0] == 'P' && magic[1] == 'E' )
3063 return IMAGE_NT_SIGNATURE;
3065 magic[2] = '\0';
3066 WARN("Can't handle %s files.\n", magic );
3067 return 0;
3071 /***********************************************************************
3072 * find_ne_resource [internal]
3074 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
3075 DWORD *resLen, DWORD *resOff )
3077 IMAGE_OS2_HEADER nehd;
3078 NE_TYPEINFO *typeInfo;
3079 NE_NAMEINFO *nameInfo;
3080 DWORD nehdoffset;
3081 LPBYTE resTab;
3082 DWORD resTabSize;
3083 int count;
3085 /* Read in NE header */
3086 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
3087 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return FALSE;
3089 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
3090 if ( !resTabSize )
3092 TRACE("No resources in NE dll\n" );
3093 return FALSE;
3096 /* Read in resource table */
3097 resTab = heap_alloc( resTabSize );
3098 if ( !resTab ) return FALSE;
3100 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
3101 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
3103 heap_free( resTab );
3104 return FALSE;
3107 /* Find resource */
3108 typeInfo = (NE_TYPEINFO *)(resTab + 2);
3110 if (!IS_INTRESOURCE(typeid)) /* named type */
3112 BYTE len = strlen( typeid );
3113 while (typeInfo->type_id)
3115 if (!(typeInfo->type_id & 0x8000))
3117 BYTE *p = resTab + typeInfo->type_id;
3118 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
3120 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3121 typeInfo->count * sizeof(NE_NAMEINFO));
3124 else /* numeric type id */
3126 WORD id = LOWORD(typeid) | 0x8000;
3127 while (typeInfo->type_id)
3129 if (typeInfo->type_id == id) goto found_type;
3130 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3131 typeInfo->count * sizeof(NE_NAMEINFO));
3134 TRACE("No typeid entry found for %p\n", typeid );
3135 heap_free( resTab );
3136 return FALSE;
3138 found_type:
3139 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
3141 if (!IS_INTRESOURCE(resid)) /* named resource */
3143 BYTE len = strlen( resid );
3144 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3146 BYTE *p = resTab + nameInfo->id;
3147 if (nameInfo->id & 0x8000) continue;
3148 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
3151 else /* numeric resource id */
3153 WORD id = LOWORD(resid) | 0x8000;
3154 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3155 if (nameInfo->id == id) goto found_name;
3157 TRACE("No resid entry found for %p\n", typeid );
3158 heap_free( resTab );
3159 return FALSE;
3161 found_name:
3162 /* Return resource data */
3163 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
3164 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
3166 heap_free( resTab );
3167 return TRUE;
3170 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
3172 HFILE lzfd = -1;
3173 OFSTRUCT ofs;
3174 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
3175 TLB_NEFile *This;
3177 This = heap_alloc(sizeof(TLB_NEFile));
3178 if (!This) return E_OUTOFMEMORY;
3180 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
3181 This->refs = 1;
3182 This->typelib_base = NULL;
3184 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
3185 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
3187 DWORD reslen, offset;
3188 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
3190 This->typelib_base = heap_alloc(reslen);
3191 if( !This->typelib_base )
3192 hr = E_OUTOFMEMORY;
3193 else
3195 LZSeek( lzfd, offset, SEEK_SET );
3196 reslen = LZRead( lzfd, This->typelib_base, reslen );
3197 LZClose( lzfd );
3198 *ppBase = This->typelib_base;
3199 *pdwTLBLength = reslen;
3200 *ppFile = &This->IUnknown_iface;
3201 return S_OK;
3206 if( lzfd >= 0) LZClose( lzfd );
3207 TLB_NEFile_Release(&This->IUnknown_iface);
3208 return hr;
3211 typedef struct TLB_Mapping
3213 IUnknown IUnknown_iface;
3214 LONG refs;
3215 HANDLE file;
3216 HANDLE mapping;
3217 LPVOID typelib_base;
3218 } TLB_Mapping;
3220 static inline TLB_Mapping *mapping_impl_from_IUnknown(IUnknown *iface)
3222 return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
3225 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3227 if (IsEqualIID(riid, &IID_IUnknown))
3229 *ppv = iface;
3230 IUnknown_AddRef(iface);
3231 return S_OK;
3233 *ppv = NULL;
3234 return E_NOINTERFACE;
3237 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
3239 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3240 return InterlockedIncrement(&This->refs);
3243 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
3245 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3246 ULONG refs = InterlockedDecrement(&This->refs);
3247 if (!refs)
3249 if (This->typelib_base)
3250 UnmapViewOfFile(This->typelib_base);
3251 if (This->mapping)
3252 CloseHandle(This->mapping);
3253 if (This->file != INVALID_HANDLE_VALUE)
3254 CloseHandle(This->file);
3255 heap_free(This);
3257 return refs;
3260 static const IUnknownVtbl TLB_Mapping_Vtable =
3262 TLB_Mapping_QueryInterface,
3263 TLB_Mapping_AddRef,
3264 TLB_Mapping_Release
3267 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
3269 TLB_Mapping *This;
3271 This = heap_alloc(sizeof(TLB_Mapping));
3272 if (!This)
3273 return E_OUTOFMEMORY;
3275 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
3276 This->refs = 1;
3277 This->file = INVALID_HANDLE_VALUE;
3278 This->mapping = NULL;
3279 This->typelib_base = NULL;
3281 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3282 if (INVALID_HANDLE_VALUE != This->file)
3284 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
3285 if (This->mapping)
3287 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
3288 if(This->typelib_base)
3290 /* retrieve file size */
3291 *pdwTLBLength = GetFileSize(This->file, NULL);
3292 *ppBase = This->typelib_base;
3293 *ppFile = &This->IUnknown_iface;
3294 return S_OK;
3299 IUnknown_Release(&This->IUnknown_iface);
3300 return TYPE_E_CANTLOADLIBRARY;
3303 /****************************************************************************
3304 * TLB_ReadTypeLib
3306 * find the type of the typelib file and map the typelib resource into
3307 * the memory
3310 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3311 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
3313 ITypeLibImpl *entry;
3314 HRESULT ret;
3315 INT index = 1;
3316 LPWSTR index_str, file = (LPWSTR)pszFileName;
3317 LPVOID pBase = NULL;
3318 DWORD dwTLBLength = 0;
3319 IUnknown *pFile = NULL;
3320 HANDLE h;
3322 *ppTypeLib = NULL;
3324 index_str = strrchrW(pszFileName, '\\');
3325 if(index_str && *++index_str != '\0')
3327 LPWSTR end_ptr;
3328 LONG idx = strtolW(index_str, &end_ptr, 10);
3329 if(*end_ptr == '\0')
3331 int str_len = index_str - pszFileName - 1;
3332 index = idx;
3333 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
3334 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
3335 file[str_len] = 0;
3339 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
3341 if(strchrW(file, '\\'))
3343 lstrcpyW(pszPath, file);
3345 else
3347 int len = GetSystemDirectoryW(pszPath, cchPath);
3348 pszPath[len] = '\\';
3349 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
3353 if(file != pszFileName) heap_free(file);
3355 h = CreateFileW(pszPath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
3356 if(h != INVALID_HANDLE_VALUE){
3357 FILE_NAME_INFORMATION *info;
3358 char data[MAX_PATH * sizeof(WCHAR) + sizeof(info->FileNameLength)];
3359 BOOL br;
3361 info = (FILE_NAME_INFORMATION*)data;
3362 /* GetFileInformationByHandleEx returns the path of the file without
3363 * WOW64 redirection */
3364 br = GetFileInformationByHandleEx(h, FileNameInfo, data, sizeof(data));
3365 if(br){
3366 info->FileName[info->FileNameLength / sizeof(WCHAR)] = 0;
3367 lstrcpynW(pszPath + 2, info->FileName, cchPath - 2);
3369 CloseHandle(h);
3372 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
3374 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3375 EnterCriticalSection(&cache_section);
3376 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
3378 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
3380 TRACE("cache hit\n");
3381 *ppTypeLib = &entry->ITypeLib2_iface;
3382 ITypeLib2_AddRef(*ppTypeLib);
3383 LeaveCriticalSection(&cache_section);
3384 return S_OK;
3387 LeaveCriticalSection(&cache_section);
3389 /* now actually load and parse the typelib */
3391 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3392 if (ret == TYPE_E_CANTLOADLIBRARY)
3393 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3394 if (ret == TYPE_E_CANTLOADLIBRARY)
3395 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
3396 if (SUCCEEDED(ret))
3398 if (dwTLBLength >= 4)
3400 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
3401 if (dwSignature == MSFT_SIGNATURE)
3402 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
3403 else if (dwSignature == SLTG_SIGNATURE)
3404 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
3405 else
3407 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
3408 ret = TYPE_E_CANTLOADLIBRARY;
3411 else
3412 ret = TYPE_E_CANTLOADLIBRARY;
3413 IUnknown_Release(pFile);
3416 if(*ppTypeLib) {
3417 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
3419 TRACE("adding to cache\n");
3420 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
3421 lstrcpyW(impl->path, pszPath);
3422 /* We should really canonicalise the path here. */
3423 impl->index = index;
3425 /* FIXME: check if it has added already in the meantime */
3426 EnterCriticalSection(&cache_section);
3427 list_add_head(&tlb_cache, &impl->entry);
3428 LeaveCriticalSection(&cache_section);
3429 ret = S_OK;
3431 else
3433 if(ret != E_FAIL)
3434 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
3436 ret = TYPE_E_CANTLOADLIBRARY;
3440 return ret;
3443 /*================== ITypeLib(2) Methods ===================================*/
3445 static ITypeLibImpl* TypeLibImpl_Constructor(void)
3447 ITypeLibImpl* pTypeLibImpl;
3449 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
3450 if (!pTypeLibImpl) return NULL;
3452 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3453 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3454 pTypeLibImpl->ICreateTypeLib2_iface.lpVtbl = &CreateTypeLib2Vtbl;
3455 pTypeLibImpl->ref = 1;
3457 list_init(&pTypeLibImpl->implib_list);
3458 list_init(&pTypeLibImpl->custdata_list);
3459 list_init(&pTypeLibImpl->name_list);
3460 list_init(&pTypeLibImpl->string_list);
3461 list_init(&pTypeLibImpl->guid_list);
3462 list_init(&pTypeLibImpl->ref_list);
3463 pTypeLibImpl->dispatch_href = -1;
3465 return pTypeLibImpl;
3468 /****************************************************************************
3469 * ITypeLib2_Constructor_MSFT
3471 * loading an MSFT typelib from an in-memory image
3473 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3475 TLBContext cx;
3476 LONG lPSegDir;
3477 MSFT_Header tlbHeader;
3478 MSFT_SegDir tlbSegDir;
3479 ITypeLibImpl * pTypeLibImpl;
3480 int i;
3482 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3484 pTypeLibImpl = TypeLibImpl_Constructor();
3485 if (!pTypeLibImpl) return NULL;
3487 /* get pointer to beginning of typelib data */
3488 cx.pos = 0;
3489 cx.oStart=0;
3490 cx.mapping = pLib;
3491 cx.pLibInfo = pTypeLibImpl;
3492 cx.length = dwTLBLength;
3494 /* read header */
3495 MSFT_ReadLEDWords(&tlbHeader, sizeof(tlbHeader), &cx, 0);
3496 TRACE_(typelib)("header:\n");
3497 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3498 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3499 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3500 return NULL;
3502 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3504 /* there is a small amount of information here until the next important
3505 * part:
3506 * the segment directory . Try to calculate the amount of data */
3507 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3509 /* now read the segment directory */
3510 TRACE("read segment directory (at %d)\n",lPSegDir);
3511 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3512 cx.pTblDir = &tlbSegDir;
3514 /* just check two entries */
3515 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3517 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3518 heap_free(pTypeLibImpl);
3519 return NULL;
3522 MSFT_ReadAllNames(&cx);
3523 MSFT_ReadAllStrings(&cx);
3524 MSFT_ReadAllGuids(&cx);
3526 /* now fill our internal data */
3527 /* TLIBATTR fields */
3528 pTypeLibImpl->guid = MSFT_ReadGuid(tlbHeader.posguid, &cx);
3530 pTypeLibImpl->syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3531 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3532 pTypeLibImpl->ver_major = LOWORD(tlbHeader.version);
3533 pTypeLibImpl->ver_minor = HIWORD(tlbHeader.version);
3534 pTypeLibImpl->libflags = ((WORD) tlbHeader.flags & 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE;
3536 pTypeLibImpl->set_lcid = tlbHeader.lcid2;
3537 pTypeLibImpl->lcid = tlbHeader.lcid;
3539 /* name, eventually add to a hash table */
3540 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3542 /* help info */
3543 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3544 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3546 if( tlbHeader.varflags & HELPDLLFLAG)
3548 int offset;
3549 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3550 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3553 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3555 /* custom data */
3556 if(tlbHeader.CustomDataOffset >= 0)
3558 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3561 /* fill in type descriptions */
3562 if(tlbSegDir.pTypdescTab.length > 0)
3564 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3565 INT16 td[4];
3566 pTypeLibImpl->ctTypeDesc = cTD;
3567 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3568 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3569 for(i=0; i<cTD; )
3571 /* FIXME: add several sanity checks here */
3572 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3573 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3575 /* FIXME: check safearray */
3576 if(td[3] < 0)
3577 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3578 else
3579 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3581 else if(td[0] == VT_CARRAY)
3583 /* array descr table here */
3584 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3586 else if(td[0] == VT_USERDEFINED)
3588 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3590 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3593 /* second time around to fill the array subscript info */
3594 for(i=0;i<cTD;i++)
3596 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3597 if(tlbSegDir.pArrayDescriptions.offset>0)
3599 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3600 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3602 if(td[1]<0)
3603 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3604 else
3605 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3607 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3609 for(j = 0; j<td[2]; j++)
3611 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3612 sizeof(INT), &cx, DO_NOT_SEEK);
3613 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3614 sizeof(INT), &cx, DO_NOT_SEEK);
3617 else
3619 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3620 ERR("didn't find array description data\n");
3625 /* imported type libs */
3626 if(tlbSegDir.pImpFiles.offset>0)
3628 TLBImpLib *pImpLib;
3629 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3630 UINT16 size;
3632 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3634 char *name;
3636 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3637 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3638 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3640 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3641 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3642 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3643 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3645 size >>= 2;
3646 name = heap_alloc_zero(size+1);
3647 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3648 pImpLib->name = TLB_MultiByteToBSTR(name);
3649 heap_free(name);
3651 pImpLib->guid = MSFT_ReadGuid(oGuid, &cx);
3652 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3654 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3658 MSFT_ReadAllRefs(&cx);
3660 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3662 /* type infos */
3663 if(tlbHeader.nrtypeinfos >= 0 )
3665 ITypeInfoImpl **ppTI;
3667 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3669 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3671 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3673 ++ppTI;
3674 (pTypeLibImpl->TypeInfoCount)++;
3678 #ifdef _WIN64
3679 if(pTypeLibImpl->syskind == SYS_WIN32){
3680 for(i = 0; i < pTypeLibImpl->TypeInfoCount; ++i)
3681 TLB_fix_32on64_typeinfo(pTypeLibImpl->typeinfos[i]);
3683 #endif
3685 TRACE("(%p)\n", pTypeLibImpl);
3686 return &pTypeLibImpl->ITypeLib2_iface;
3690 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3692 char b[3];
3693 int i;
3694 short s;
3696 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3697 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3698 return FALSE;
3701 guid->Data4[0] = s >> 8;
3702 guid->Data4[1] = s & 0xff;
3704 b[2] = '\0';
3705 for(i = 0; i < 6; i++) {
3706 memcpy(b, str + 24 + 2 * i, 2);
3707 guid->Data4[i + 2] = strtol(b, NULL, 16);
3709 return TRUE;
3712 static WORD SLTG_ReadString(const char *ptr, const TLBString **pStr, ITypeLibImpl *lib)
3714 WORD bytelen;
3715 DWORD len;
3716 BSTR tmp_str;
3718 *pStr = NULL;
3719 bytelen = *(const WORD*)ptr;
3720 if(bytelen == 0xffff) return 2;
3722 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3723 tmp_str = SysAllocStringLen(NULL, len);
3724 if (tmp_str) {
3725 MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, tmp_str, len);
3726 *pStr = TLB_append_str(&lib->string_list, tmp_str);
3727 SysFreeString(tmp_str);
3729 return bytelen + 2;
3732 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3734 WORD bytelen;
3736 *str = NULL;
3737 bytelen = *(const WORD*)ptr;
3738 if(bytelen == 0xffff) return 2;
3739 *str = heap_alloc(bytelen + 1);
3740 memcpy(*str, ptr + 2, bytelen);
3741 (*str)[bytelen] = '\0';
3742 return bytelen + 2;
3745 static TLBString *SLTG_ReadName(const char *pNameTable, int offset, ITypeLibImpl *lib)
3747 BSTR tmp_str;
3748 TLBString *tlbstr;
3750 LIST_FOR_EACH_ENTRY(tlbstr, &lib->name_list, TLBString, entry) {
3751 if (tlbstr->offset == offset)
3752 return tlbstr;
3755 tmp_str = TLB_MultiByteToBSTR(pNameTable + offset);
3756 tlbstr = TLB_append_str(&lib->name_list, tmp_str);
3757 SysFreeString(tmp_str);
3759 return tlbstr;
3762 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3764 char *ptr = pLibBlk;
3765 WORD w;
3767 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3768 FIXME("libblk magic = %04x\n", w);
3769 return 0;
3772 ptr += 6;
3773 if((w = *(WORD*)ptr) != 0xffff) {
3774 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3775 ptr += w;
3777 ptr += 2;
3779 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString, pTypeLibImpl);
3781 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile, pTypeLibImpl);
3783 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3784 ptr += 4;
3786 pTypeLibImpl->syskind = *(WORD*)ptr;
3787 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3788 ptr += 2;
3790 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3791 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3792 else
3793 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = 0;
3794 ptr += 2;
3796 ptr += 4; /* skip res12 */
3798 pTypeLibImpl->libflags = *(WORD*)ptr;
3799 ptr += 2;
3801 pTypeLibImpl->ver_major = *(WORD*)ptr;
3802 ptr += 2;
3804 pTypeLibImpl->ver_minor = *(WORD*)ptr;
3805 ptr += 2;
3807 pTypeLibImpl->guid = TLB_append_guid(&pTypeLibImpl->guid_list, (GUID*)ptr, -2);
3808 ptr += sizeof(GUID);
3810 return ptr - (char*)pLibBlk;
3813 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3814 typedef struct
3816 unsigned int num;
3817 HREFTYPE refs[1];
3818 } sltg_ref_lookup_t;
3820 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3821 HREFTYPE *typelib_ref)
3823 if(table && typeinfo_ref < table->num)
3825 *typelib_ref = table->refs[typeinfo_ref];
3826 return S_OK;
3829 ERR_(typelib)("Unable to find reference\n");
3830 *typelib_ref = -1;
3831 return E_FAIL;
3834 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3836 BOOL done = FALSE;
3838 while(!done) {
3839 if((*pType & 0xe00) == 0xe00) {
3840 pTD->vt = VT_PTR;
3841 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3842 pTD = pTD->u.lptdesc;
3844 switch(*pType & 0x3f) {
3845 case VT_PTR:
3846 pTD->vt = VT_PTR;
3847 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3848 pTD = pTD->u.lptdesc;
3849 break;
3851 case VT_USERDEFINED:
3852 pTD->vt = VT_USERDEFINED;
3853 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3854 done = TRUE;
3855 break;
3857 case VT_CARRAY:
3859 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3860 array */
3862 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3864 pTD->vt = VT_CARRAY;
3865 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3866 pTD->u.lpadesc->cDims = pSA->cDims;
3867 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3868 pSA->cDims * sizeof(SAFEARRAYBOUND));
3870 pTD = &pTD->u.lpadesc->tdescElem;
3871 break;
3874 case VT_SAFEARRAY:
3876 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3877 useful? */
3879 pType++;
3880 pTD->vt = VT_SAFEARRAY;
3881 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3882 pTD = pTD->u.lptdesc;
3883 break;
3885 default:
3886 pTD->vt = *pType & 0x3f;
3887 done = TRUE;
3888 break;
3890 pType++;
3892 return pType;
3895 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3896 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3898 /* Handle [in/out] first */
3899 if((*pType & 0xc000) == 0xc000)
3900 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3901 else if(*pType & 0x8000)
3902 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3903 else if(*pType & 0x4000)
3904 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3905 else
3906 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3908 if(*pType & 0x2000)
3909 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3911 if(*pType & 0x80)
3912 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3914 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3918 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3919 char *pNameTable)
3921 unsigned int ref;
3922 char *name;
3923 TLBRefType *ref_type;
3924 sltg_ref_lookup_t *table;
3925 HREFTYPE typelib_ref;
3927 if(pRef->magic != SLTG_REF_MAGIC) {
3928 FIXME("Ref magic = %x\n", pRef->magic);
3929 return NULL;
3931 name = ( (char*)pRef->names + pRef->number);
3933 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3934 table->num = pRef->number >> 3;
3936 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3938 /* We don't want the first href to be 0 */
3939 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3941 for(ref = 0; ref < pRef->number >> 3; ref++) {
3942 char *refname;
3943 unsigned int lib_offs, type_num;
3945 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3947 name += SLTG_ReadStringA(name, &refname);
3948 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3949 FIXME_(typelib)("Can't sscanf ref\n");
3950 if(lib_offs != 0xffff) {
3951 TLBImpLib *import;
3953 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
3954 if(import->offset == lib_offs)
3955 break;
3957 if(&import->entry == &pTL->implib_list) {
3958 char fname[MAX_PATH+1];
3959 int len;
3960 GUID tmpguid;
3962 import = heap_alloc_zero(sizeof(*import));
3963 import->offset = lib_offs;
3964 TLB_GUIDFromString( pNameTable + lib_offs + 4, &tmpguid);
3965 import->guid = TLB_append_guid(&pTL->guid_list, &tmpguid, 2);
3966 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3967 &import->wVersionMajor,
3968 &import->wVersionMinor,
3969 &import->lcid, fname) != 4) {
3970 FIXME_(typelib)("can't sscanf ref %s\n",
3971 pNameTable + lib_offs + 40);
3973 len = strlen(fname);
3974 if(fname[len-1] != '#')
3975 FIXME("fname = %s\n", fname);
3976 fname[len-1] = '\0';
3977 import->name = TLB_MultiByteToBSTR(fname);
3978 list_add_tail(&pTL->implib_list, &import->entry);
3980 ref_type->pImpTLInfo = import;
3982 /* Store a reference to IDispatch */
3983 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid->guid, &IID_StdOle) && type_num == 4)
3984 pTL->dispatch_href = typelib_ref;
3986 } else { /* internal ref */
3987 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3989 ref_type->reference = typelib_ref;
3990 ref_type->index = type_num;
3992 heap_free(refname);
3993 list_add_tail(&pTL->ref_list, &ref_type->entry);
3995 table->refs[ref] = typelib_ref;
3996 typelib_ref += 4;
3998 if((BYTE)*name != SLTG_REF_MAGIC)
3999 FIXME_(typelib)("End of ref block magic = %x\n", *name);
4000 dump_TLBRefType(pTL);
4001 return table;
4004 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
4005 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
4007 SLTG_ImplInfo *info;
4008 TLBImplType *pImplType;
4009 /* I don't really get this structure, usually it's 0x16 bytes
4010 long, but iuser.tlb contains some that are 0x18 bytes long.
4011 That's ok because we can use the next ptr to jump to the next
4012 one. But how do we know the length of the last one? The WORD
4013 at offs 0x8 might be the clue. For now I'm just assuming that
4014 the last one is the regular 0x16 bytes. */
4016 info = (SLTG_ImplInfo*)pBlk;
4017 while(1){
4018 pTI->cImplTypes++;
4019 if(info->next == 0xffff)
4020 break;
4021 info = (SLTG_ImplInfo*)(pBlk + info->next);
4024 info = (SLTG_ImplInfo*)pBlk;
4025 pTI->impltypes = TLBImplType_Alloc(pTI->cImplTypes);
4026 pImplType = pTI->impltypes;
4027 while(1) {
4028 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
4029 pImplType->implflags = info->impltypeflags;
4030 ++pImplType;
4032 if(info->next == 0xffff)
4033 break;
4034 if(OneOnly)
4035 FIXME_(typelib)("Interface inheriting more than one interface\n");
4036 info = (SLTG_ImplInfo*)(pBlk + info->next);
4038 info++; /* see comment at top of function */
4039 return (char*)info;
4042 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
4043 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4045 TLBVarDesc *pVarDesc;
4046 const TLBString *prevName = NULL;
4047 SLTG_Variable *pItem;
4048 unsigned short i;
4049 WORD *pType;
4051 pVarDesc = pTI->vardescs = TLBVarDesc_Alloc(cVars);
4053 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
4054 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
4056 pVarDesc->vardesc.memid = pItem->memid;
4058 if (pItem->magic != SLTG_VAR_MAGIC &&
4059 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
4060 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
4061 return;
4064 if (pItem->name == 0xfffe)
4065 pVarDesc->Name = prevName;
4066 else
4067 pVarDesc->Name = SLTG_ReadName(pNameTable, pItem->name, pTI->pTypeLib);
4069 TRACE_(typelib)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc->Name)));
4070 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
4071 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
4073 if(pItem->flags & 0x02)
4074 pType = &pItem->type;
4075 else
4076 pType = (WORD*)(pBlk + pItem->type);
4078 if (pItem->flags & ~0xda)
4079 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
4081 SLTG_DoElem(pType, pBlk,
4082 &pVarDesc->vardesc.elemdescVar, ref_lookup);
4084 if (TRACE_ON(typelib)) {
4085 char buf[300];
4086 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
4087 TRACE_(typelib)("elemdescVar: %s\n", buf);
4090 if (pItem->flags & 0x40) {
4091 TRACE_(typelib)("VAR_DISPATCH\n");
4092 pVarDesc->vardesc.varkind = VAR_DISPATCH;
4094 else if (pItem->flags & 0x10) {
4095 TRACE_(typelib)("VAR_CONST\n");
4096 pVarDesc->vardesc.varkind = VAR_CONST;
4097 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
4098 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
4099 if (pItem->flags & 0x08)
4100 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
4101 else {
4102 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
4104 case VT_LPSTR:
4105 case VT_LPWSTR:
4106 case VT_BSTR:
4108 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
4109 BSTR str;
4110 TRACE_(typelib)("len = %u\n", len);
4111 if (len == 0xffff) {
4112 str = NULL;
4113 } else {
4114 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
4115 str = SysAllocStringLen(NULL, alloc_len);
4116 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
4118 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
4119 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
4120 break;
4122 case VT_I2:
4123 case VT_UI2:
4124 case VT_I4:
4125 case VT_UI4:
4126 case VT_INT:
4127 case VT_UINT:
4128 V_INT(pVarDesc->vardesc.u.lpvarValue) =
4129 *(INT*)(pBlk + pItem->byte_offs);
4130 break;
4131 default:
4132 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
4136 else {
4137 TRACE_(typelib)("VAR_PERINSTANCE\n");
4138 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
4139 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
4142 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
4143 pVarDesc->vardesc.wVarFlags = pItem->varflags;
4145 if (pItem->flags & 0x80)
4146 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
4148 prevName = pVarDesc->Name;
4150 pTI->cVars = cVars;
4153 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
4154 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4156 SLTG_Function *pFunc;
4157 unsigned short i;
4158 TLBFuncDesc *pFuncDesc;
4160 pTI->funcdescs = TLBFuncDesc_Alloc(cFuncs);
4162 pFuncDesc = pTI->funcdescs;
4163 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
4164 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
4166 int param;
4167 WORD *pType, *pArg;
4169 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
4170 case SLTG_FUNCTION_MAGIC:
4171 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
4172 break;
4173 case SLTG_DISPATCH_FUNCTION_MAGIC:
4174 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
4175 break;
4176 case SLTG_STATIC_FUNCTION_MAGIC:
4177 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
4178 break;
4179 default:
4180 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
4181 continue;
4183 pFuncDesc->Name = SLTG_ReadName(pNameTable, pFunc->name, pTI->pTypeLib);
4185 pFuncDesc->funcdesc.memid = pFunc->dispid;
4186 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
4187 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
4188 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
4189 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
4190 pFuncDesc->funcdesc.oVft = pFunc->vtblpos & ~1;
4192 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
4193 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
4195 if(pFunc->retnextopt & 0x80)
4196 pType = &pFunc->rettype;
4197 else
4198 pType = (WORD*)(pBlk + pFunc->rettype);
4200 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
4202 pFuncDesc->funcdesc.lprgelemdescParam =
4203 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
4204 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
4206 pArg = (WORD*)(pBlk + pFunc->arg_off);
4208 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
4209 char *paramName = pNameTable + *pArg;
4210 BOOL HaveOffs;
4211 /* If arg type follows then paramName points to the 2nd
4212 letter of the name, else the next WORD is an offset to
4213 the arg type and paramName points to the first letter.
4214 So let's take one char off paramName and see if we're
4215 pointing at an alpha-numeric char. However if *pArg is
4216 0xffff or 0xfffe then the param has no name, the former
4217 meaning that the next WORD is the type, the latter
4218 meaning that the next WORD is an offset to the type. */
4220 HaveOffs = FALSE;
4221 if(*pArg == 0xffff)
4222 paramName = NULL;
4223 else if(*pArg == 0xfffe) {
4224 paramName = NULL;
4225 HaveOffs = TRUE;
4227 else if(paramName[-1] && !isalnum(paramName[-1]))
4228 HaveOffs = TRUE;
4230 pArg++;
4232 if(HaveOffs) { /* the next word is an offset to type */
4233 pType = (WORD*)(pBlk + *pArg);
4234 SLTG_DoElem(pType, pBlk,
4235 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4236 pArg++;
4237 } else {
4238 if(paramName)
4239 paramName--;
4240 pArg = SLTG_DoElem(pArg, pBlk,
4241 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4244 /* Are we an optional param ? */
4245 if(pFuncDesc->funcdesc.cParams - param <=
4246 pFuncDesc->funcdesc.cParamsOpt)
4247 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
4249 if(paramName) {
4250 pFuncDesc->pParamDesc[param].Name = SLTG_ReadName(pNameTable,
4251 paramName - pNameTable, pTI->pTypeLib);
4252 } else {
4253 pFuncDesc->pParamDesc[param].Name = pFuncDesc->Name;
4257 pTI->cFuncs = cFuncs;
4260 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
4261 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4262 SLTG_TypeInfoTail *pTITail)
4264 char *pFirstItem;
4265 sltg_ref_lookup_t *ref_lookup = NULL;
4267 if(pTIHeader->href_table != 0xffffffff) {
4268 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4269 pNameTable);
4272 pFirstItem = pBlk;
4274 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4275 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
4277 heap_free(ref_lookup);
4281 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
4282 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4283 const SLTG_TypeInfoTail *pTITail)
4285 char *pFirstItem;
4286 sltg_ref_lookup_t *ref_lookup = NULL;
4288 if(pTIHeader->href_table != 0xffffffff) {
4289 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4290 pNameTable);
4293 pFirstItem = pBlk;
4295 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4296 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
4299 if (pTITail->funcs_off != 0xffff)
4300 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4302 heap_free(ref_lookup);
4304 if (TRACE_ON(typelib))
4305 dump_TLBFuncDesc(pTI->funcdescs, pTI->cFuncs);
4308 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
4309 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4310 const SLTG_TypeInfoTail *pTITail)
4312 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4315 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
4316 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4317 const SLTG_TypeInfoTail *pTITail)
4319 WORD *pType;
4320 sltg_ref_lookup_t *ref_lookup = NULL;
4322 if (pTITail->simple_alias) {
4323 /* if simple alias, no more processing required */
4324 pTI->tdescAlias = heap_alloc_zero(sizeof(TYPEDESC));
4325 pTI->tdescAlias->vt = pTITail->tdescalias_vt;
4326 return;
4329 if(pTIHeader->href_table != 0xffffffff) {
4330 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4331 pNameTable);
4334 /* otherwise it is an offset to a type */
4335 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
4337 pTI->tdescAlias = heap_alloc(sizeof(TYPEDESC));
4338 SLTG_DoType(pType, pBlk, pTI->tdescAlias, ref_lookup);
4340 heap_free(ref_lookup);
4343 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
4344 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4345 const SLTG_TypeInfoTail *pTITail)
4347 sltg_ref_lookup_t *ref_lookup = NULL;
4348 if (pTIHeader->href_table != 0xffffffff)
4349 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4350 pNameTable);
4352 if (pTITail->vars_off != 0xffff)
4353 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4355 if (pTITail->funcs_off != 0xffff)
4356 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4358 if (pTITail->impls_off != 0xffff)
4359 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
4361 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4362 * of dispinterface functions including the IDispatch ones, so
4363 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4364 pTI->cbSizeVft = pTI->cFuncs * pTI->pTypeLib->ptr_size;
4366 heap_free(ref_lookup);
4367 if (TRACE_ON(typelib))
4368 dump_TLBFuncDesc(pTI->funcdescs, pTI->cFuncs);
4371 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
4372 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4373 const SLTG_TypeInfoTail *pTITail)
4375 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4378 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
4379 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4380 const SLTG_TypeInfoTail *pTITail)
4382 sltg_ref_lookup_t *ref_lookup = NULL;
4383 if (pTIHeader->href_table != 0xffffffff)
4384 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4385 pNameTable);
4387 if (pTITail->vars_off != 0xffff)
4388 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4390 if (pTITail->funcs_off != 0xffff)
4391 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4392 heap_free(ref_lookup);
4393 if (TRACE_ON(typelib))
4394 dump_TypeInfo(pTI);
4397 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4398 manageable copy of it into this */
4399 typedef struct {
4400 WORD small_no;
4401 char *index_name;
4402 char *other_name;
4403 WORD res1a;
4404 WORD name_offs;
4405 WORD more_bytes;
4406 char *extra;
4407 WORD res20;
4408 DWORD helpcontext;
4409 WORD res26;
4410 GUID uuid;
4411 } SLTG_InternalOtherTypeInfo;
4413 /****************************************************************************
4414 * ITypeLib2_Constructor_SLTG
4416 * loading a SLTG typelib from an in-memory image
4418 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
4420 ITypeLibImpl *pTypeLibImpl;
4421 SLTG_Header *pHeader;
4422 SLTG_BlkEntry *pBlkEntry;
4423 SLTG_Magic *pMagic;
4424 SLTG_Index *pIndex;
4425 SLTG_Pad9 *pPad9;
4426 LPVOID pBlk, pFirstBlk;
4427 SLTG_LibBlk *pLibBlk;
4428 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
4429 char *pAfterOTIBlks = NULL;
4430 char *pNameTable, *ptr;
4431 int i;
4432 DWORD len, order;
4433 ITypeInfoImpl **ppTypeInfoImpl;
4435 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
4438 pTypeLibImpl = TypeLibImpl_Constructor();
4439 if (!pTypeLibImpl) return NULL;
4441 pHeader = pLib;
4443 TRACE_(typelib)("header:\n");
4444 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
4445 pHeader->nrOfFileBlks );
4446 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
4447 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
4448 pHeader->SLTG_magic);
4449 return NULL;
4452 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4453 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
4455 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4456 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
4458 /* Next we have a magic block */
4459 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
4461 /* Let's see if we're still in sync */
4462 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
4463 sizeof(SLTG_COMPOBJ_MAGIC))) {
4464 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
4465 return NULL;
4467 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
4468 sizeof(SLTG_DIR_MAGIC))) {
4469 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
4470 return NULL;
4473 pIndex = (SLTG_Index*)(pMagic+1);
4475 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
4477 pFirstBlk = pPad9 + 1;
4479 /* We'll set up a ptr to the main library block, which is the last one. */
4481 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4482 pBlkEntry[order].next != 0;
4483 order = pBlkEntry[order].next - 1, i++) {
4484 pBlk = (char*)pBlk + pBlkEntry[order].len;
4486 pLibBlk = pBlk;
4488 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
4490 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4491 interspersed */
4493 len += 0x40;
4495 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4497 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
4500 ptr = (char*)pLibBlk + len;
4502 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4503 WORD w, extra;
4504 len = 0;
4506 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
4508 w = *(WORD*)(ptr + 2);
4509 if(w != 0xffff) {
4510 len += w;
4511 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
4512 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4513 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4515 w = *(WORD*)(ptr + 4 + len);
4516 if(w != 0xffff) {
4517 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4518 len += w;
4519 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4520 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4521 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4523 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4524 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4525 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4526 if(extra) {
4527 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4528 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4529 len += extra;
4531 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4532 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4533 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4534 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4535 len += sizeof(SLTG_OtherTypeInfo);
4536 ptr += len;
4539 pAfterOTIBlks = ptr;
4541 /* Skip this WORD and get the next DWORD */
4542 len = *(DWORD*)(pAfterOTIBlks + 2);
4544 /* Now add this to pLibBLk look at what we're pointing at and
4545 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4546 dust and we should be pointing at the beginning of the name
4547 table */
4549 pNameTable = (char*)pLibBlk + len;
4551 switch(*(WORD*)pNameTable) {
4552 case 0xffff:
4553 break;
4554 case 0x0200:
4555 pNameTable += 0x20;
4556 break;
4557 default:
4558 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4559 break;
4562 pNameTable += 0x216;
4564 pNameTable += 2;
4566 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4568 pTypeLibImpl->Name = SLTG_ReadName(pNameTable, pLibBlk->name, pTypeLibImpl);
4571 /* Hopefully we now have enough ptrs set up to actually read in
4572 some TypeInfos. It's not clear which order to do them in, so
4573 I'll just follow the links along the BlkEntry chain and read
4574 them in the order in which they are in the file */
4576 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4577 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4579 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4580 pBlkEntry[order].next != 0;
4581 order = pBlkEntry[order].next - 1, i++) {
4583 SLTG_TypeInfoHeader *pTIHeader;
4584 SLTG_TypeInfoTail *pTITail;
4585 SLTG_MemberHeader *pMemHeader;
4587 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4588 FIXME_(typelib)("Index strings don't match\n");
4589 heap_free(pOtherTypeInfoBlks);
4590 return NULL;
4593 pTIHeader = pBlk;
4594 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4595 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4596 heap_free(pOtherTypeInfoBlks);
4597 return NULL;
4599 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4600 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4601 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4603 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4604 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4605 (*ppTypeInfoImpl)->index = i;
4606 (*ppTypeInfoImpl)->Name = SLTG_ReadName(pNameTable, pOtherTypeInfoBlks[i].name_offs, pTypeLibImpl);
4607 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4608 (*ppTypeInfoImpl)->guid = TLB_append_guid(&pTypeLibImpl->guid_list, &pOtherTypeInfoBlks[i].uuid, 2);
4609 (*ppTypeInfoImpl)->typekind = pTIHeader->typekind;
4610 (*ppTypeInfoImpl)->wMajorVerNum = pTIHeader->major_version;
4611 (*ppTypeInfoImpl)->wMinorVerNum = pTIHeader->minor_version;
4612 (*ppTypeInfoImpl)->wTypeFlags =
4613 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4615 if((*ppTypeInfoImpl)->wTypeFlags & TYPEFLAG_FDUAL)
4616 (*ppTypeInfoImpl)->typekind = TKIND_DISPATCH;
4618 if((pTIHeader->typeflags1 & 7) != 2)
4619 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4620 if(pTIHeader->typeflags3 != 2)
4621 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4623 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4624 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl)->Name)),
4625 typekind_desc[pTIHeader->typekind],
4626 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl)->guid)),
4627 (*ppTypeInfoImpl)->wTypeFlags);
4629 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4631 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4633 (*ppTypeInfoImpl)->cbAlignment = pTITail->cbAlignment;
4634 (*ppTypeInfoImpl)->cbSizeInstance = pTITail->cbSizeInstance;
4635 (*ppTypeInfoImpl)->cbSizeVft = pTITail->cbSizeVft;
4637 switch(pTIHeader->typekind) {
4638 case TKIND_ENUM:
4639 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4640 pTIHeader, pTITail);
4641 break;
4643 case TKIND_RECORD:
4644 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4645 pTIHeader, pTITail);
4646 break;
4648 case TKIND_INTERFACE:
4649 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4650 pTIHeader, pTITail);
4651 break;
4653 case TKIND_COCLASS:
4654 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4655 pTIHeader, pTITail);
4656 break;
4658 case TKIND_ALIAS:
4659 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4660 pTIHeader, pTITail);
4661 break;
4663 case TKIND_DISPATCH:
4664 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4665 pTIHeader, pTITail);
4666 break;
4668 case TKIND_MODULE:
4669 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4670 pTIHeader, pTITail);
4671 break;
4673 default:
4674 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4675 break;
4679 /* could get cFuncs, cVars and cImplTypes from here
4680 but we've already set those */
4681 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4682 X(06);
4683 X(16);
4684 X(18);
4685 X(1a);
4686 X(1e);
4687 X(24);
4688 X(26);
4689 X(2a);
4690 X(2c);
4691 X(2e);
4692 X(30);
4693 X(32);
4694 X(34);
4695 #undef X
4696 ++ppTypeInfoImpl;
4697 pBlk = (char*)pBlk + pBlkEntry[order].len;
4700 if(i != pTypeLibImpl->TypeInfoCount) {
4701 FIXME("Somehow processed %d TypeInfos\n", i);
4702 heap_free(pOtherTypeInfoBlks);
4703 return NULL;
4706 heap_free(pOtherTypeInfoBlks);
4707 return &pTypeLibImpl->ITypeLib2_iface;
4710 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4712 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4714 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4716 if(IsEqualIID(riid, &IID_IUnknown) ||
4717 IsEqualIID(riid,&IID_ITypeLib)||
4718 IsEqualIID(riid,&IID_ITypeLib2))
4720 *ppv = &This->ITypeLib2_iface;
4722 else if(IsEqualIID(riid, &IID_ICreateTypeLib) ||
4723 IsEqualIID(riid, &IID_ICreateTypeLib2))
4725 *ppv = &This->ICreateTypeLib2_iface;
4727 else
4729 *ppv = NULL;
4730 TRACE("-- Interface: E_NOINTERFACE\n");
4731 return E_NOINTERFACE;
4734 IUnknown_AddRef((IUnknown*)*ppv);
4735 return S_OK;
4738 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4740 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4741 ULONG ref = InterlockedIncrement(&This->ref);
4743 TRACE("(%p) ref=%u\n", This, ref);
4745 return ref;
4748 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4750 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4751 ULONG ref = InterlockedDecrement(&This->ref);
4753 TRACE("(%p) ref=%u\n",This, ref);
4755 if (!ref)
4757 TLBImpLib *pImpLib, *pImpLibNext;
4758 TLBRefType *ref_type;
4759 TLBString *tlbstr, *tlbstr_next;
4760 TLBGuid *tlbguid, *tlbguid_next;
4761 void *cursor2;
4762 int i;
4764 /* remove cache entry */
4765 if(This->path)
4767 TRACE("removing from cache list\n");
4768 EnterCriticalSection(&cache_section);
4769 if(This->entry.next)
4770 list_remove(&This->entry);
4771 LeaveCriticalSection(&cache_section);
4772 heap_free(This->path);
4774 TRACE(" destroying ITypeLib(%p)\n",This);
4776 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->string_list, TLBString, entry) {
4777 list_remove(&tlbstr->entry);
4778 SysFreeString(tlbstr->str);
4779 heap_free(tlbstr);
4782 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->name_list, TLBString, entry) {
4783 list_remove(&tlbstr->entry);
4784 SysFreeString(tlbstr->str);
4785 heap_free(tlbstr);
4788 LIST_FOR_EACH_ENTRY_SAFE(tlbguid, tlbguid_next, &This->guid_list, TLBGuid, entry) {
4789 list_remove(&tlbguid->entry);
4790 heap_free(tlbguid);
4793 TLB_FreeCustData(&This->custdata_list);
4795 for (i = 0; i < This->ctTypeDesc; i++)
4796 if (This->pTypeDesc[i].vt == VT_CARRAY)
4797 heap_free(This->pTypeDesc[i].u.lpadesc);
4799 heap_free(This->pTypeDesc);
4801 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4803 if (pImpLib->pImpTypeLib)
4804 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4805 SysFreeString(pImpLib->name);
4807 list_remove(&pImpLib->entry);
4808 heap_free(pImpLib);
4811 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4813 list_remove(&ref_type->entry);
4814 heap_free(ref_type);
4817 for (i = 0; i < This->TypeInfoCount; ++i){
4818 heap_free(This->typeinfos[i]->tdescAlias);
4819 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4821 heap_free(This->typeinfos);
4822 heap_free(This);
4823 return 0;
4826 return ref;
4829 /* ITypeLib::GetTypeInfoCount
4831 * Returns the number of type descriptions in the type library
4833 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4835 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4836 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4837 return This->TypeInfoCount;
4840 /* ITypeLib::GetTypeInfo
4842 * retrieves the specified type description in the library.
4844 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4845 ITypeLib2 *iface,
4846 UINT index,
4847 ITypeInfo **ppTInfo)
4849 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4851 TRACE("%p %u %p\n", This, index, ppTInfo);
4853 if(!ppTInfo)
4854 return E_INVALIDARG;
4856 if(index >= This->TypeInfoCount)
4857 return TYPE_E_ELEMENTNOTFOUND;
4859 *ppTInfo = (ITypeInfo *)&This->typeinfos[index]->ITypeInfo2_iface;
4860 ITypeInfo_AddRef(*ppTInfo);
4862 return S_OK;
4866 /* ITypeLibs::GetTypeInfoType
4868 * Retrieves the type of a type description.
4870 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4871 ITypeLib2 *iface,
4872 UINT index,
4873 TYPEKIND *pTKind)
4875 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4877 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4879 if(!pTKind)
4880 return E_INVALIDARG;
4882 if(index >= This->TypeInfoCount)
4883 return TYPE_E_ELEMENTNOTFOUND;
4885 *pTKind = This->typeinfos[index]->typekind;
4887 return S_OK;
4890 /* ITypeLib::GetTypeInfoOfGuid
4892 * Retrieves the type description that corresponds to the specified GUID.
4895 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4896 ITypeLib2 *iface,
4897 REFGUID guid,
4898 ITypeInfo **ppTInfo)
4900 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4901 int i;
4903 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4905 for(i = 0; i < This->TypeInfoCount; ++i){
4906 if(IsEqualIID(TLB_get_guid_null(This->typeinfos[i]->guid), guid)){
4907 *ppTInfo = (ITypeInfo *)&This->typeinfos[i]->ITypeInfo2_iface;
4908 ITypeInfo_AddRef(*ppTInfo);
4909 return S_OK;
4913 return TYPE_E_ELEMENTNOTFOUND;
4916 /* ITypeLib::GetLibAttr
4918 * Retrieves the structure that contains the library's attributes.
4921 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4922 ITypeLib2 *iface,
4923 LPTLIBATTR *attr)
4925 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4927 TRACE("(%p, %p)\n", This, attr);
4929 if (!attr) return E_INVALIDARG;
4931 *attr = heap_alloc(sizeof(**attr));
4932 if (!*attr) return E_OUTOFMEMORY;
4934 (*attr)->guid = *TLB_get_guid_null(This->guid);
4935 (*attr)->lcid = This->set_lcid;
4936 (*attr)->syskind = This->syskind;
4937 (*attr)->wMajorVerNum = This->ver_major;
4938 (*attr)->wMinorVerNum = This->ver_minor;
4939 (*attr)->wLibFlags = This->libflags;
4941 return S_OK;
4944 /* ITypeLib::GetTypeComp
4946 * Enables a client compiler to bind to a library's types, variables,
4947 * constants, and global functions.
4950 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4951 ITypeLib2 *iface,
4952 ITypeComp **ppTComp)
4954 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4956 TRACE("(%p)->(%p)\n",This,ppTComp);
4957 *ppTComp = &This->ITypeComp_iface;
4958 ITypeComp_AddRef(*ppTComp);
4960 return S_OK;
4963 /* ITypeLib::GetDocumentation
4965 * Retrieves the library's documentation string, the complete Help file name
4966 * and path, and the context identifier for the library Help topic in the Help
4967 * file.
4969 * On a successful return all non-null BSTR pointers will have been set,
4970 * possibly to NULL.
4972 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4973 ITypeLib2 *iface,
4974 INT index,
4975 BSTR *pBstrName,
4976 BSTR *pBstrDocString,
4977 DWORD *pdwHelpContext,
4978 BSTR *pBstrHelpFile)
4980 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4981 HRESULT result = E_INVALIDARG;
4982 ITypeInfo *pTInfo;
4984 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4985 This, index,
4986 pBstrName, pBstrDocString,
4987 pdwHelpContext, pBstrHelpFile);
4989 if(index<0)
4991 /* documentation for the typelib */
4992 if(pBstrName)
4994 if (This->Name)
4996 if(!(*pBstrName = SysAllocString(TLB_get_bstr(This->Name))))
4997 goto memerr1;
4999 else
5000 *pBstrName = NULL;
5002 if(pBstrDocString)
5004 if (This->DocString)
5006 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->DocString))))
5007 goto memerr2;
5009 else
5010 *pBstrDocString = NULL;
5012 if(pdwHelpContext)
5014 *pdwHelpContext = This->dwHelpContext;
5016 if(pBstrHelpFile)
5018 if (This->HelpFile)
5020 if(!(*pBstrHelpFile = SysAllocString(TLB_get_bstr(This->HelpFile))))
5021 goto memerr3;
5023 else
5024 *pBstrHelpFile = NULL;
5027 result = S_OK;
5029 else
5031 /* for a typeinfo */
5032 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
5034 if(SUCCEEDED(result))
5036 result = ITypeInfo_GetDocumentation(pTInfo,
5037 MEMBERID_NIL,
5038 pBstrName,
5039 pBstrDocString,
5040 pdwHelpContext, pBstrHelpFile);
5042 ITypeInfo_Release(pTInfo);
5045 return result;
5046 memerr3:
5047 if (pBstrDocString) SysFreeString (*pBstrDocString);
5048 memerr2:
5049 if (pBstrName) SysFreeString (*pBstrName);
5050 memerr1:
5051 return STG_E_INSUFFICIENTMEMORY;
5054 /* ITypeLib::IsName
5056 * Indicates whether a passed-in string contains the name of a type or member
5057 * described in the library.
5060 static HRESULT WINAPI ITypeLib2_fnIsName(
5061 ITypeLib2 *iface,
5062 LPOLESTR szNameBuf,
5063 ULONG lHashVal,
5064 BOOL *pfName)
5066 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5067 int tic;
5068 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
5070 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
5071 pfName);
5073 *pfName=TRUE;
5074 for(tic = 0; tic < This->TypeInfoCount; ++tic){
5075 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5076 if(!TLB_str_memcmp(szNameBuf, pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5077 for(fdc = 0; fdc < pTInfo->cFuncs; ++fdc) {
5078 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
5079 int pc;
5080 if(!TLB_str_memcmp(szNameBuf, pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5081 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++){
5082 if(!TLB_str_memcmp(szNameBuf, pFInfo->pParamDesc[pc].Name, nNameBufLen))
5083 goto ITypeLib2_fnIsName_exit;
5086 for(vrc = 0; vrc < pTInfo->cVars; ++vrc){
5087 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
5088 if(!TLB_str_memcmp(szNameBuf, pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5092 *pfName=FALSE;
5094 ITypeLib2_fnIsName_exit:
5095 TRACE("(%p)slow! search for %s: %sfound!\n", This,
5096 debugstr_w(szNameBuf), *pfName ? "" : "NOT ");
5098 return S_OK;
5101 /* ITypeLib::FindName
5103 * Finds occurrences of a type description in a type library. This may be used
5104 * to quickly verify that a name exists in a type library.
5107 static HRESULT WINAPI ITypeLib2_fnFindName(
5108 ITypeLib2 *iface,
5109 LPOLESTR name,
5110 ULONG hash,
5111 ITypeInfo **ppTInfo,
5112 MEMBERID *memid,
5113 UINT16 *found)
5115 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5116 int tic;
5117 UINT count = 0;
5118 UINT len;
5120 TRACE("(%p)->(%s %u %p %p %p)\n", This, debugstr_w(name), hash, ppTInfo, memid, found);
5122 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
5123 return E_INVALIDARG;
5125 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
5126 for(tic = 0; count < *found && tic < This->TypeInfoCount; ++tic) {
5127 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5128 TLBVarDesc *var;
5129 UINT fdc;
5131 if(!TLB_str_memcmp(name, pTInfo->Name, len)) {
5132 memid[count] = MEMBERID_NIL;
5133 goto ITypeLib2_fnFindName_exit;
5136 for(fdc = 0; fdc < pTInfo->cFuncs; ++fdc) {
5137 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
5139 if(!TLB_str_memcmp(name, func->Name, len)) {
5140 memid[count] = func->funcdesc.memid;
5141 goto ITypeLib2_fnFindName_exit;
5145 var = TLB_get_vardesc_by_name(pTInfo->vardescs, pTInfo->cVars, name);
5146 if (var) {
5147 memid[count] = var->vardesc.memid;
5148 goto ITypeLib2_fnFindName_exit;
5151 continue;
5152 ITypeLib2_fnFindName_exit:
5153 ITypeInfo2_AddRef(&pTInfo->ITypeInfo2_iface);
5154 ppTInfo[count] = (ITypeInfo *)&pTInfo->ITypeInfo2_iface;
5155 count++;
5157 TRACE("found %d typeinfos\n", count);
5159 *found = count;
5161 return S_OK;
5164 /* ITypeLib::ReleaseTLibAttr
5166 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5169 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
5170 ITypeLib2 *iface,
5171 TLIBATTR *pTLibAttr)
5173 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5174 TRACE("(%p)->(%p)\n", This, pTLibAttr);
5175 heap_free(pTLibAttr);
5178 /* ITypeLib2::GetCustData
5180 * gets the custom data
5182 static HRESULT WINAPI ITypeLib2_fnGetCustData(
5183 ITypeLib2 * iface,
5184 REFGUID guid,
5185 VARIANT *pVarVal)
5187 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5188 TLBCustData *pCData;
5190 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
5192 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
5193 if(!pCData)
5194 return TYPE_E_ELEMENTNOTFOUND;
5196 VariantInit(pVarVal);
5197 VariantCopy(pVarVal, &pCData->data);
5199 return S_OK;
5202 /* ITypeLib2::GetLibStatistics
5204 * Returns statistics about a type library that are required for efficient
5205 * sizing of hash tables.
5208 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
5209 ITypeLib2 * iface,
5210 ULONG *pcUniqueNames,
5211 ULONG *pcchUniqueNames)
5213 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5215 FIXME("(%p): stub!\n", This);
5217 if(pcUniqueNames) *pcUniqueNames=1;
5218 if(pcchUniqueNames) *pcchUniqueNames=1;
5219 return S_OK;
5222 /* ITypeLib2::GetDocumentation2
5224 * Retrieves the library's documentation string, the complete Help file name
5225 * and path, the localization context to use, and the context ID for the
5226 * library Help topic in the Help file.
5229 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
5230 ITypeLib2 * iface,
5231 INT index,
5232 LCID lcid,
5233 BSTR *pbstrHelpString,
5234 DWORD *pdwHelpStringContext,
5235 BSTR *pbstrHelpStringDll)
5237 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5238 HRESULT result;
5239 ITypeInfo *pTInfo;
5241 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
5243 /* the help string should be obtained from the helpstringdll,
5244 * using the _DLLGetDocumentation function, based on the supplied
5245 * lcid. Nice to do sometime...
5247 if(index<0)
5249 /* documentation for the typelib */
5250 if(pbstrHelpString)
5251 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->DocString));
5252 if(pdwHelpStringContext)
5253 *pdwHelpStringContext=This->dwHelpContext;
5254 if(pbstrHelpStringDll)
5255 *pbstrHelpStringDll=SysAllocString(TLB_get_bstr(This->HelpStringDll));
5257 result = S_OK;
5259 else
5261 /* for a typeinfo */
5262 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
5264 if(SUCCEEDED(result))
5266 ITypeInfo2 * pTInfo2;
5267 result = ITypeInfo_QueryInterface(pTInfo,
5268 &IID_ITypeInfo2,
5269 (LPVOID*) &pTInfo2);
5271 if(SUCCEEDED(result))
5273 result = ITypeInfo2_GetDocumentation2(pTInfo2,
5274 MEMBERID_NIL,
5275 lcid,
5276 pbstrHelpString,
5277 pdwHelpStringContext,
5278 pbstrHelpStringDll);
5280 ITypeInfo2_Release(pTInfo2);
5283 ITypeInfo_Release(pTInfo);
5286 return result;
5289 static HRESULT TLB_copy_all_custdata(struct list *custdata_list, CUSTDATA *pCustData)
5291 TLBCustData *pCData;
5292 unsigned int ct;
5293 CUSTDATAITEM *cdi;
5295 ct = list_count(custdata_list);
5297 pCustData->prgCustData = CoTaskMemAlloc(ct * sizeof(CUSTDATAITEM));
5298 if(!pCustData->prgCustData)
5299 return E_OUTOFMEMORY;
5301 pCustData->cCustData = ct;
5303 cdi = pCustData->prgCustData;
5304 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
5305 cdi->guid = *TLB_get_guid_null(pCData->guid);
5306 VariantCopy(&cdi->varValue, &pCData->data);
5307 ++cdi;
5310 return S_OK;
5314 /* ITypeLib2::GetAllCustData
5316 * Gets all custom data items for the library.
5319 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
5320 ITypeLib2 * iface,
5321 CUSTDATA *pCustData)
5323 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5324 TRACE("(%p)->(%p)\n", This, pCustData);
5325 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
5328 static const ITypeLib2Vtbl tlbvt = {
5329 ITypeLib2_fnQueryInterface,
5330 ITypeLib2_fnAddRef,
5331 ITypeLib2_fnRelease,
5332 ITypeLib2_fnGetTypeInfoCount,
5333 ITypeLib2_fnGetTypeInfo,
5334 ITypeLib2_fnGetTypeInfoType,
5335 ITypeLib2_fnGetTypeInfoOfGuid,
5336 ITypeLib2_fnGetLibAttr,
5337 ITypeLib2_fnGetTypeComp,
5338 ITypeLib2_fnGetDocumentation,
5339 ITypeLib2_fnIsName,
5340 ITypeLib2_fnFindName,
5341 ITypeLib2_fnReleaseTLibAttr,
5343 ITypeLib2_fnGetCustData,
5344 ITypeLib2_fnGetLibStatistics,
5345 ITypeLib2_fnGetDocumentation2,
5346 ITypeLib2_fnGetAllCustData
5350 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5352 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5354 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
5357 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
5359 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5361 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
5364 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
5366 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5368 return ITypeLib2_Release(&This->ITypeLib2_iface);
5371 static HRESULT WINAPI ITypeLibComp_fnBind(
5372 ITypeComp * iface,
5373 OLECHAR * szName,
5374 ULONG lHash,
5375 WORD wFlags,
5376 ITypeInfo ** ppTInfo,
5377 DESCKIND * pDescKind,
5378 BINDPTR * pBindPtr)
5380 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5381 BOOL typemismatch = FALSE;
5382 int i;
5384 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5386 *pDescKind = DESCKIND_NONE;
5387 pBindPtr->lptcomp = NULL;
5388 *ppTInfo = NULL;
5390 for(i = 0; i < This->TypeInfoCount; ++i){
5391 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5392 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo->Name)));
5394 /* FIXME: check wFlags here? */
5395 /* FIXME: we should use a hash table to look this info up using lHash
5396 * instead of an O(n) search */
5397 if ((pTypeInfo->typekind == TKIND_ENUM) ||
5398 (pTypeInfo->typekind == TKIND_MODULE))
5400 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name->str, szName))
5402 *pDescKind = DESCKIND_TYPECOMP;
5403 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
5404 ITypeComp_AddRef(pBindPtr->lptcomp);
5405 TRACE("module or enum: %s\n", debugstr_w(szName));
5406 return S_OK;
5410 if ((pTypeInfo->typekind == TKIND_MODULE) ||
5411 (pTypeInfo->typekind == TKIND_ENUM))
5413 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5414 HRESULT hr;
5416 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5417 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
5419 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
5420 return S_OK;
5422 else if (hr == TYPE_E_TYPEMISMATCH)
5423 typemismatch = TRUE;
5426 if ((pTypeInfo->typekind == TKIND_COCLASS) &&
5427 (pTypeInfo->wTypeFlags & TYPEFLAG_FAPPOBJECT))
5429 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5430 HRESULT hr;
5431 ITypeInfo *subtypeinfo;
5432 BINDPTR subbindptr;
5433 DESCKIND subdesckind;
5435 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
5436 &subtypeinfo, &subdesckind, &subbindptr);
5437 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
5439 TYPEDESC tdesc_appobject;
5440 const VARDESC vardesc_appobject =
5442 -2, /* memid */
5443 NULL, /* lpstrSchema */
5445 0 /* oInst */
5448 /* ELEMDESC */
5450 /* TYPEDESC */
5452 &tdesc_appobject
5454 VT_PTR
5457 0, /* wVarFlags */
5458 VAR_STATIC /* varkind */
5461 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
5462 tdesc_appobject.vt = VT_USERDEFINED;
5464 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
5466 /* cleanup things filled in by Bind call so we can put our
5467 * application object data in there instead */
5468 switch (subdesckind)
5470 case DESCKIND_FUNCDESC:
5471 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
5472 break;
5473 case DESCKIND_VARDESC:
5474 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
5475 break;
5476 default:
5477 break;
5479 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
5481 if (pTypeInfo->hreftype == -1)
5482 FIXME("no hreftype for interface %p\n", pTypeInfo);
5484 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
5485 if (FAILED(hr))
5486 return hr;
5488 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5489 *ppTInfo = (ITypeInfo *)&pTypeInfo->ITypeInfo2_iface;
5490 ITypeInfo_AddRef(*ppTInfo);
5491 return S_OK;
5493 else if (hr == TYPE_E_TYPEMISMATCH)
5494 typemismatch = TRUE;
5498 if (typemismatch)
5500 TRACE("type mismatch %s\n", debugstr_w(szName));
5501 return TYPE_E_TYPEMISMATCH;
5503 else
5505 TRACE("name not found %s\n", debugstr_w(szName));
5506 return S_OK;
5510 static HRESULT WINAPI ITypeLibComp_fnBindType(
5511 ITypeComp * iface,
5512 OLECHAR * szName,
5513 ULONG lHash,
5514 ITypeInfo ** ppTInfo,
5515 ITypeComp ** ppTComp)
5517 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5518 ITypeInfoImpl *info;
5520 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5522 if(!szName || !ppTInfo || !ppTComp)
5523 return E_INVALIDARG;
5525 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, szName);
5526 if(!info){
5527 *ppTInfo = NULL;
5528 *ppTComp = NULL;
5529 return S_OK;
5532 *ppTInfo = (ITypeInfo *)&info->ITypeInfo2_iface;
5533 ITypeInfo_AddRef(*ppTInfo);
5534 *ppTComp = &info->ITypeComp_iface;
5535 ITypeComp_AddRef(*ppTComp);
5537 return S_OK;
5540 static const ITypeCompVtbl tlbtcvt =
5543 ITypeLibComp_fnQueryInterface,
5544 ITypeLibComp_fnAddRef,
5545 ITypeLibComp_fnRelease,
5547 ITypeLibComp_fnBind,
5548 ITypeLibComp_fnBindType
5551 /*================== ITypeInfo(2) Methods ===================================*/
5552 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5554 ITypeInfoImpl *pTypeInfoImpl;
5556 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5557 if (pTypeInfoImpl)
5559 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5560 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5561 pTypeInfoImpl->ICreateTypeInfo2_iface.lpVtbl = &CreateTypeInfo2Vtbl;
5562 pTypeInfoImpl->ref = 0;
5563 pTypeInfoImpl->hreftype = -1;
5564 pTypeInfoImpl->memidConstructor = MEMBERID_NIL;
5565 pTypeInfoImpl->memidDestructor = MEMBERID_NIL;
5566 pTypeInfoImpl->pcustdata_list = &pTypeInfoImpl->custdata_list;
5567 list_init(pTypeInfoImpl->pcustdata_list);
5569 TRACE("(%p)\n", pTypeInfoImpl);
5570 return pTypeInfoImpl;
5573 /* ITypeInfo::QueryInterface
5575 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5576 ITypeInfo2 *iface,
5577 REFIID riid,
5578 VOID **ppvObject)
5580 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5582 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5584 *ppvObject=NULL;
5585 if(IsEqualIID(riid, &IID_IUnknown) ||
5586 IsEqualIID(riid,&IID_ITypeInfo)||
5587 IsEqualIID(riid,&IID_ITypeInfo2))
5588 *ppvObject = This;
5589 else if(IsEqualIID(riid, &IID_ICreateTypeInfo) ||
5590 IsEqualIID(riid, &IID_ICreateTypeInfo2))
5591 *ppvObject = &This->ICreateTypeInfo2_iface;
5593 if(*ppvObject){
5594 ITypeInfo2_AddRef(iface);
5595 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5596 return S_OK;
5598 TRACE("-- Interface: E_NOINTERFACE\n");
5599 return E_NOINTERFACE;
5602 /* ITypeInfo::AddRef
5604 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5606 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5607 ULONG ref = InterlockedIncrement(&This->ref);
5609 TRACE("(%p)->ref is %u\n",This, ref);
5611 if (ref == 1 /* incremented from 0 */)
5612 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5614 return ref;
5617 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5619 UINT i;
5621 TRACE("destroying ITypeInfo(%p)\n",This);
5623 for (i = 0; i < This->cFuncs; ++i)
5625 int j;
5626 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5627 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5629 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5630 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5631 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5632 TLB_FreeCustData(&pFInfo->pParamDesc[j].custdata_list);
5634 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5635 heap_free(pFInfo->pParamDesc);
5636 TLB_FreeCustData(&pFInfo->custdata_list);
5638 heap_free(This->funcdescs);
5640 for(i = 0; i < This->cVars; ++i)
5642 TLBVarDesc *pVInfo = &This->vardescs[i];
5643 if (pVInfo->vardesc_create) {
5644 TLB_FreeVarDesc(pVInfo->vardesc_create);
5645 } else if (pVInfo->vardesc.varkind == VAR_CONST) {
5646 VariantClear(pVInfo->vardesc.u.lpvarValue);
5647 heap_free(pVInfo->vardesc.u.lpvarValue);
5649 TLB_FreeCustData(&pVInfo->custdata_list);
5651 heap_free(This->vardescs);
5653 if(This->impltypes){
5654 for (i = 0; i < This->cImplTypes; ++i){
5655 TLBImplType *pImpl = &This->impltypes[i];
5656 TLB_FreeCustData(&pImpl->custdata_list);
5658 heap_free(This->impltypes);
5661 TLB_FreeCustData(&This->custdata_list);
5663 heap_free(This);
5666 /* ITypeInfo::Release
5668 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5670 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5671 ULONG ref = InterlockedDecrement(&This->ref);
5673 TRACE("(%p)->(%u)\n",This, ref);
5675 if (!ref)
5677 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5678 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5679 if (not_attached_to_typelib)
5680 heap_free(This);
5681 /* otherwise This will be freed when typelib is freed */
5684 return ref;
5687 /* ITypeInfo::GetTypeAttr
5689 * Retrieves a TYPEATTR structure that contains the attributes of the type
5690 * description.
5693 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5694 LPTYPEATTR *ppTypeAttr)
5696 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5697 SIZE_T size;
5699 TRACE("(%p)\n",This);
5701 size = sizeof(**ppTypeAttr);
5702 if (This->typekind == TKIND_ALIAS && This->tdescAlias)
5703 size += TLB_SizeTypeDesc(This->tdescAlias, FALSE);
5705 *ppTypeAttr = heap_alloc(size);
5706 if (!*ppTypeAttr)
5707 return E_OUTOFMEMORY;
5709 (*ppTypeAttr)->guid = *TLB_get_guid_null(This->guid);
5710 (*ppTypeAttr)->lcid = This->lcid;
5711 (*ppTypeAttr)->memidConstructor = This->memidConstructor;
5712 (*ppTypeAttr)->memidDestructor = This->memidDestructor;
5713 (*ppTypeAttr)->lpstrSchema = This->lpstrSchema;
5714 (*ppTypeAttr)->cbSizeInstance = This->cbSizeInstance;
5715 (*ppTypeAttr)->typekind = This->typekind;
5716 (*ppTypeAttr)->cFuncs = This->cFuncs;
5717 (*ppTypeAttr)->cVars = This->cVars;
5718 (*ppTypeAttr)->cImplTypes = This->cImplTypes;
5719 (*ppTypeAttr)->cbSizeVft = This->cbSizeVft;
5720 (*ppTypeAttr)->cbAlignment = This->cbAlignment;
5721 (*ppTypeAttr)->wTypeFlags = This->wTypeFlags;
5722 (*ppTypeAttr)->wMajorVerNum = This->wMajorVerNum;
5723 (*ppTypeAttr)->wMinorVerNum = This->wMinorVerNum;
5724 (*ppTypeAttr)->idldescType = This->idldescType;
5726 if (This->tdescAlias)
5727 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5728 This->tdescAlias, *ppTypeAttr + 1);
5729 else{
5730 (*ppTypeAttr)->tdescAlias.vt = VT_EMPTY;
5731 (*ppTypeAttr)->tdescAlias.u.lptdesc = NULL;
5734 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5735 /* This should include all the inherited funcs */
5736 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / This->pTypeLib->ptr_size;
5737 /* This is always the size of IDispatch's vtbl */
5738 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5739 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5741 return S_OK;
5744 /* ITypeInfo::GetTypeComp
5746 * Retrieves the ITypeComp interface for the type description, which enables a
5747 * client compiler to bind to the type description's members.
5750 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5751 ITypeComp * *ppTComp)
5753 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5755 TRACE("(%p)->(%p)\n", This, ppTComp);
5757 *ppTComp = &This->ITypeComp_iface;
5758 ITypeComp_AddRef(*ppTComp);
5759 return S_OK;
5762 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5764 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5765 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5766 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5767 return size;
5770 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5772 *dest = *src;
5773 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5774 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5776 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5777 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5778 *buffer += sizeof(PARAMDESCEX);
5779 *pparamdescex_dest = *pparamdescex_src;
5780 pparamdescex_dest->cBytes = sizeof(PARAMDESCEX);
5781 VariantInit(&pparamdescex_dest->varDefaultValue);
5782 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5783 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5785 else
5786 dest->u.paramdesc.pparamdescex = NULL;
5787 return S_OK;
5790 static HRESULT TLB_SanitizeBSTR(BSTR str)
5792 UINT len = SysStringLen(str), i;
5793 for (i = 0; i < len; ++i)
5794 if (str[i] > 0x7f)
5795 str[i] = '?';
5796 return S_OK;
5799 static HRESULT TLB_SanitizeVariant(VARIANT *var)
5801 if (V_VT(var) == VT_INT)
5802 return VariantChangeType(var, var, 0, VT_I4);
5803 else if (V_VT(var) == VT_UINT)
5804 return VariantChangeType(var, var, 0, VT_UI4);
5805 else if (V_VT(var) == VT_BSTR)
5806 return TLB_SanitizeBSTR(V_BSTR(var));
5808 return S_OK;
5811 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5813 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5814 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5817 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5819 FUNCDESC *dest;
5820 char *buffer;
5821 SIZE_T size = sizeof(*src);
5822 SHORT i;
5823 HRESULT hr;
5825 size += sizeof(*src->lprgscode) * src->cScodes;
5826 size += TLB_SizeElemDesc(&src->elemdescFunc);
5827 for (i = 0; i < src->cParams; i++)
5829 size += sizeof(ELEMDESC);
5830 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5833 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5834 if (!dest) return E_OUTOFMEMORY;
5836 *dest = *src;
5837 if (dispinterface) /* overwrite funckind */
5838 dest->funckind = FUNC_DISPATCH;
5839 buffer = (char *)(dest + 1);
5841 dest->oVft = dest->oVft & 0xFFFC;
5843 if (dest->cScodes) {
5844 dest->lprgscode = (SCODE *)buffer;
5845 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5846 buffer += sizeof(*src->lprgscode) * src->cScodes;
5847 } else
5848 dest->lprgscode = NULL;
5850 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5851 if (FAILED(hr))
5853 SysFreeString((BSTR)dest);
5854 return hr;
5857 if (dest->cParams) {
5858 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5859 buffer += sizeof(ELEMDESC) * src->cParams;
5860 for (i = 0; i < src->cParams; i++)
5862 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5863 if (FAILED(hr))
5864 break;
5866 if (FAILED(hr))
5868 /* undo the above actions */
5869 for (i = i - 1; i >= 0; i--)
5870 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5871 TLB_FreeElemDesc(&dest->elemdescFunc);
5872 SysFreeString((BSTR)dest);
5873 return hr;
5875 } else
5876 dest->lprgelemdescParam = NULL;
5878 /* special treatment for dispinterfaces: this makes functions appear
5879 * to return their [retval] value when it is really returning an
5880 * HRESULT */
5881 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5883 if (dest->cParams &&
5884 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5886 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5887 if (elemdesc->tdesc.vt != VT_PTR)
5889 ERR("elemdesc should have started with VT_PTR instead of:\n");
5890 if (ERR_ON(ole))
5891 dump_ELEMDESC(elemdesc);
5892 return E_UNEXPECTED;
5895 /* copy last parameter to the return value. we are using a flat
5896 * buffer so there is no danger of leaking memory in
5897 * elemdescFunc */
5898 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5900 /* remove the last parameter */
5901 dest->cParams--;
5903 else
5904 /* otherwise this function is made to appear to have no return
5905 * value */
5906 dest->elemdescFunc.tdesc.vt = VT_VOID;
5910 *dest_ptr = dest;
5911 return S_OK;
5914 static void TLB_FreeVarDesc(VARDESC *var_desc)
5916 TLB_FreeElemDesc(&var_desc->elemdescVar);
5917 if (var_desc->varkind == VAR_CONST)
5918 VariantClear(var_desc->u.lpvarValue);
5919 SysFreeString((BSTR)var_desc);
5922 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5924 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5926 if (index >= This->cFuncs)
5927 return TYPE_E_ELEMENTNOTFOUND;
5929 *ppFuncDesc = &This->funcdescs[index].funcdesc;
5930 return S_OK;
5933 /* internal function to make the inherited interfaces' methods appear
5934 * part of the interface */
5935 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5936 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5938 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5939 HRESULT hr;
5940 UINT implemented_funcs = 0;
5942 if (funcs)
5943 *funcs = 0;
5944 else
5945 *hrefoffset = DISPATCH_HREF_OFFSET;
5947 if(This->impltypes)
5949 ITypeInfo *pSubTypeInfo;
5950 UINT sub_funcs;
5952 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5953 if (FAILED(hr))
5954 return hr;
5956 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5957 index,
5958 ppFuncDesc,
5959 &sub_funcs, hrefoffset);
5960 implemented_funcs += sub_funcs;
5961 ITypeInfo_Release(pSubTypeInfo);
5962 if (SUCCEEDED(hr))
5963 return hr;
5964 *hrefoffset += DISPATCH_HREF_OFFSET;
5967 if (funcs)
5968 *funcs = implemented_funcs + This->cFuncs;
5969 else
5970 *hrefoffset = 0;
5972 if (index < implemented_funcs)
5973 return E_INVALIDARG;
5974 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5975 ppFuncDesc);
5978 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5980 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5981 while (TRUE)
5983 switch (pTypeDesc->vt)
5985 case VT_USERDEFINED:
5986 pTypeDesc->u.hreftype += hrefoffset;
5987 return;
5988 case VT_PTR:
5989 case VT_SAFEARRAY:
5990 pTypeDesc = pTypeDesc->u.lptdesc;
5991 break;
5992 case VT_CARRAY:
5993 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5994 break;
5995 default:
5996 return;
6001 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
6003 SHORT i;
6004 for (i = 0; i < pFuncDesc->cParams; i++)
6005 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
6006 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
6009 /* ITypeInfo::GetFuncDesc
6011 * Retrieves the FUNCDESC structure that contains information about a
6012 * specified function.
6015 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
6016 LPFUNCDESC *ppFuncDesc)
6018 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6019 const FUNCDESC *internal_funcdesc;
6020 HRESULT hr;
6021 UINT hrefoffset = 0;
6023 TRACE("(%p) index %d\n", This, index);
6025 if (!ppFuncDesc)
6026 return E_INVALIDARG;
6028 if (This->needs_layout)
6029 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6031 if (This->typekind == TKIND_DISPATCH)
6032 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
6033 &internal_funcdesc, NULL,
6034 &hrefoffset);
6035 else
6036 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
6037 &internal_funcdesc);
6038 if (FAILED(hr))
6040 WARN("description for function %d not found\n", index);
6041 return hr;
6044 hr = TLB_AllocAndInitFuncDesc(
6045 internal_funcdesc,
6046 ppFuncDesc,
6047 This->typekind == TKIND_DISPATCH);
6049 if ((This->typekind == TKIND_DISPATCH) && hrefoffset)
6050 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
6052 TRACE("-- 0x%08x\n", hr);
6053 return hr;
6056 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
6058 VARDESC *dest;
6059 char *buffer;
6060 SIZE_T size = sizeof(*src);
6061 HRESULT hr;
6063 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
6064 if (src->varkind == VAR_CONST)
6065 size += sizeof(VARIANT);
6066 size += TLB_SizeElemDesc(&src->elemdescVar);
6068 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
6069 if (!dest) return E_OUTOFMEMORY;
6071 *dest = *src;
6072 buffer = (char *)(dest + 1);
6073 if (src->lpstrSchema)
6075 int len;
6076 dest->lpstrSchema = (LPOLESTR)buffer;
6077 len = strlenW(src->lpstrSchema);
6078 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
6079 buffer += (len + 1) * sizeof(WCHAR);
6082 if (src->varkind == VAR_CONST)
6084 HRESULT hr;
6086 dest->u.lpvarValue = (VARIANT *)buffer;
6087 *dest->u.lpvarValue = *src->u.lpvarValue;
6088 buffer += sizeof(VARIANT);
6089 VariantInit(dest->u.lpvarValue);
6090 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
6091 if (FAILED(hr))
6093 SysFreeString((BSTR)dest);
6094 return hr;
6097 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
6098 if (FAILED(hr))
6100 if (src->varkind == VAR_CONST)
6101 VariantClear(dest->u.lpvarValue);
6102 SysFreeString((BSTR)dest);
6103 return hr;
6105 *dest_ptr = dest;
6106 return S_OK;
6109 /* ITypeInfo::GetVarDesc
6111 * Retrieves a VARDESC structure that describes the specified variable.
6114 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
6115 LPVARDESC *ppVarDesc)
6117 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6118 const TLBVarDesc *pVDesc = &This->vardescs[index];
6120 TRACE("(%p) index %d\n", This, index);
6122 if(index >= This->cVars)
6123 return TYPE_E_ELEMENTNOTFOUND;
6125 if (This->needs_layout)
6126 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6128 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
6131 /* ITypeInfo_GetNames
6133 * Retrieves the variable with the specified member ID (or the name of the
6134 * property or method and its parameters) that correspond to the specified
6135 * function ID.
6137 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
6138 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
6140 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6141 const TLBFuncDesc *pFDesc;
6142 const TLBVarDesc *pVDesc;
6143 int i;
6144 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
6146 if(!rgBstrNames)
6147 return E_INVALIDARG;
6149 *pcNames = 0;
6151 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
6152 if(pFDesc)
6154 if(!cMaxNames || !pFDesc->Name)
6155 return S_OK;
6157 *rgBstrNames = SysAllocString(TLB_get_bstr(pFDesc->Name));
6158 ++(*pcNames);
6160 for(i = 0; i < pFDesc->funcdesc.cParams; ++i){
6161 if(*pcNames >= cMaxNames || !pFDesc->pParamDesc[i].Name)
6162 return S_OK;
6163 rgBstrNames[*pcNames] = SysAllocString(TLB_get_bstr(pFDesc->pParamDesc[i].Name));
6164 ++(*pcNames);
6166 return S_OK;
6169 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
6170 if(pVDesc)
6172 *rgBstrNames=SysAllocString(TLB_get_bstr(pVDesc->Name));
6173 *pcNames=1;
6175 else
6177 if(This->impltypes &&
6178 (This->typekind==TKIND_INTERFACE || This->typekind==TKIND_DISPATCH)) {
6179 /* recursive search */
6180 ITypeInfo *pTInfo;
6181 HRESULT result;
6182 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6183 if(SUCCEEDED(result))
6185 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
6186 ITypeInfo_Release(pTInfo);
6187 return result;
6189 WARN("Could not search inherited interface!\n");
6191 else
6193 WARN("no names found\n");
6195 *pcNames=0;
6196 return TYPE_E_ELEMENTNOTFOUND;
6198 return S_OK;
6202 /* ITypeInfo::GetRefTypeOfImplType
6204 * If a type description describes a COM class, it retrieves the type
6205 * description of the implemented interface types. For an interface,
6206 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6207 * if any exist.
6210 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
6211 ITypeInfo2 *iface,
6212 UINT index,
6213 HREFTYPE *pRefType)
6215 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6216 HRESULT hr = S_OK;
6218 TRACE("(%p) index %d\n", This, index);
6219 if (TRACE_ON(ole)) dump_TypeInfo(This);
6221 if(index==(UINT)-1)
6223 /* only valid on dual interfaces;
6224 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6227 if (This->wTypeFlags & TYPEFLAG_FDUAL)
6229 *pRefType = -2;
6231 else
6233 hr = TYPE_E_ELEMENTNOTFOUND;
6236 else if(index == 0 && This->typekind == TKIND_DISPATCH)
6238 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6239 *pRefType = This->pTypeLib->dispatch_href;
6241 else
6243 if(index >= This->cImplTypes)
6244 hr = TYPE_E_ELEMENTNOTFOUND;
6245 else{
6246 *pRefType = This->impltypes[index].hRef;
6247 if(This->typekind == TKIND_INTERFACE)
6248 *pRefType |= 0x2;
6252 if(TRACE_ON(ole))
6254 if(SUCCEEDED(hr))
6255 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
6256 else
6257 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
6260 return hr;
6263 /* ITypeInfo::GetImplTypeFlags
6265 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6266 * or base interface in a type description.
6268 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
6269 UINT index, INT *pImplTypeFlags)
6271 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6273 TRACE("(%p) index %d\n", This, index);
6275 if(!pImplTypeFlags)
6276 return E_INVALIDARG;
6278 if(This->typekind == TKIND_DISPATCH && index == 0){
6279 *pImplTypeFlags = 0;
6280 return S_OK;
6283 if(index >= This->cImplTypes)
6284 return TYPE_E_ELEMENTNOTFOUND;
6286 *pImplTypeFlags = This->impltypes[index].implflags;
6288 return S_OK;
6291 /* GetIDsOfNames
6292 * Maps between member names and member IDs, and parameter names and
6293 * parameter IDs.
6295 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
6296 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
6298 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6299 const TLBVarDesc *pVDesc;
6300 HRESULT ret=S_OK;
6301 UINT i, fdc;
6303 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
6304 cNames);
6306 /* init out parameters in case of failure */
6307 for (i = 0; i < cNames; i++)
6308 pMemId[i] = MEMBERID_NIL;
6310 for (fdc = 0; fdc < This->cFuncs; ++fdc) {
6311 int j;
6312 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
6313 if(!lstrcmpiW(*rgszNames, TLB_get_bstr(pFDesc->Name))) {
6314 if(cNames) *pMemId=pFDesc->funcdesc.memid;
6315 for(i=1; i < cNames; i++){
6316 for(j=0; j<pFDesc->funcdesc.cParams; j++)
6317 if(!lstrcmpiW(rgszNames[i],TLB_get_bstr(pFDesc->pParamDesc[j].Name)))
6318 break;
6319 if( j<pFDesc->funcdesc.cParams)
6320 pMemId[i]=j;
6321 else
6322 ret=DISP_E_UNKNOWNNAME;
6324 TRACE("-- 0x%08x\n", ret);
6325 return ret;
6328 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->cVars, *rgszNames);
6329 if(pVDesc){
6330 if(cNames)
6331 *pMemId = pVDesc->vardesc.memid;
6332 return ret;
6334 /* not found, see if it can be found in an inherited interface */
6335 if(This->impltypes) {
6336 /* recursive search */
6337 ITypeInfo *pTInfo;
6338 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6339 if(SUCCEEDED(ret)){
6340 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
6341 ITypeInfo_Release(pTInfo);
6342 return ret;
6344 WARN("Could not search inherited interface!\n");
6345 } else
6346 WARN("no names found\n");
6347 return DISP_E_UNKNOWNNAME;
6351 #ifdef __i386__
6353 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6354 __ASM_GLOBAL_FUNC( call_method,
6355 "pushl %ebp\n\t"
6356 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6357 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6358 "movl %esp,%ebp\n\t"
6359 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6360 "pushl %esi\n\t"
6361 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6362 "pushl %edi\n\t"
6363 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6364 "movl 12(%ebp),%edx\n\t"
6365 "movl %esp,%edi\n\t"
6366 "shll $2,%edx\n\t"
6367 "jz 1f\n\t"
6368 "subl %edx,%edi\n\t"
6369 "andl $~15,%edi\n\t"
6370 "movl %edi,%esp\n\t"
6371 "movl 12(%ebp),%ecx\n\t"
6372 "movl 16(%ebp),%esi\n\t"
6373 "cld\n\t"
6374 "rep; movsl\n"
6375 "1:\tcall *8(%ebp)\n\t"
6376 "subl %esp,%edi\n\t"
6377 "movl 20(%ebp),%ecx\n\t"
6378 "movl %edi,(%ecx)\n\t"
6379 "leal -8(%ebp),%esp\n\t"
6380 "popl %edi\n\t"
6381 __ASM_CFI(".cfi_same_value %edi\n\t")
6382 "popl %esi\n\t"
6383 __ASM_CFI(".cfi_same_value %esi\n\t")
6384 "popl %ebp\n\t"
6385 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6386 __ASM_CFI(".cfi_same_value %ebp\n\t")
6387 "ret" )
6389 /* same function but returning floating point */
6390 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
6392 /* ITypeInfo::Invoke
6394 * Invokes a method, or accesses a property of an object, that implements the
6395 * interface described by the type description.
6397 DWORD
6398 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
6399 DWORD res;
6400 int stack_offset;
6402 if (TRACE_ON(ole)) {
6403 int i;
6404 TRACE("Calling %p(",func);
6405 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
6406 if (nrargs > 30) TRACE("...");
6407 TRACE(")\n");
6410 switch (callconv) {
6411 case CC_STDCALL:
6412 case CC_CDECL:
6413 res = call_method( func, nrargs, args, &stack_offset );
6414 break;
6415 default:
6416 FIXME("unsupported calling convention %d\n",callconv);
6417 res = -1;
6418 break;
6420 TRACE("returns %08x\n",res);
6421 return res;
6424 #elif defined(__x86_64__)
6426 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
6427 __ASM_GLOBAL_FUNC( call_method,
6428 "pushq %rbp\n\t"
6429 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6430 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6431 "movq %rsp,%rbp\n\t"
6432 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6433 "pushq %rsi\n\t"
6434 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6435 "pushq %rdi\n\t"
6436 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6437 "movq %rcx,%rax\n\t"
6438 "movq $4,%rcx\n\t"
6439 "cmp %rcx,%rdx\n\t"
6440 "cmovgq %rdx,%rcx\n\t"
6441 "leaq 0(,%rcx,8),%rdx\n\t"
6442 "subq %rdx,%rsp\n\t"
6443 "andq $~15,%rsp\n\t"
6444 "movq %rsp,%rdi\n\t"
6445 "movq %r8,%rsi\n\t"
6446 "rep; movsq\n\t"
6447 "movq 0(%rsp),%rcx\n\t"
6448 "movq 8(%rsp),%rdx\n\t"
6449 "movq 16(%rsp),%r8\n\t"
6450 "movq 24(%rsp),%r9\n\t"
6451 "movq %rcx,%xmm0\n\t"
6452 "movq %rdx,%xmm1\n\t"
6453 "movq %r8,%xmm2\n\t"
6454 "movq %r9,%xmm3\n\t"
6455 "callq *%rax\n\t"
6456 "leaq -16(%rbp),%rsp\n\t"
6457 "popq %rdi\n\t"
6458 __ASM_CFI(".cfi_same_value %rdi\n\t")
6459 "popq %rsi\n\t"
6460 __ASM_CFI(".cfi_same_value %rsi\n\t")
6461 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6462 "popq %rbp\n\t"
6463 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6464 __ASM_CFI(".cfi_same_value %rbp\n\t")
6465 "ret")
6467 /* same function but returning floating point */
6468 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
6470 #endif /* __x86_64__ */
6472 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6474 HRESULT hr = S_OK;
6475 ITypeInfo *tinfo2 = NULL;
6476 TYPEATTR *tattr = NULL;
6478 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6479 if (hr)
6481 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6482 "hr = 0x%08x\n",
6483 tdesc->u.hreftype, hr);
6484 return hr;
6486 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6487 if (hr)
6489 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
6490 ITypeInfo_Release(tinfo2);
6491 return hr;
6494 switch (tattr->typekind)
6496 case TKIND_ENUM:
6497 *vt |= VT_I4;
6498 break;
6500 case TKIND_ALIAS:
6501 tdesc = &tattr->tdescAlias;
6502 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
6503 break;
6505 case TKIND_INTERFACE:
6506 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
6507 *vt |= VT_DISPATCH;
6508 else
6509 *vt |= VT_UNKNOWN;
6510 break;
6512 case TKIND_DISPATCH:
6513 *vt |= VT_DISPATCH;
6514 break;
6516 case TKIND_COCLASS:
6517 *vt |= VT_DISPATCH;
6518 break;
6520 case TKIND_RECORD:
6521 FIXME("TKIND_RECORD unhandled.\n");
6522 hr = E_NOTIMPL;
6523 break;
6525 case TKIND_UNION:
6526 FIXME("TKIND_UNION unhandled.\n");
6527 hr = E_NOTIMPL;
6528 break;
6530 default:
6531 FIXME("TKIND %d unhandled.\n",tattr->typekind);
6532 hr = E_NOTIMPL;
6533 break;
6535 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6536 ITypeInfo_Release(tinfo2);
6537 return hr;
6540 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6542 HRESULT hr = S_OK;
6544 /* enforce only one level of pointer indirection */
6545 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
6547 tdesc = tdesc->u.lptdesc;
6549 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6550 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6551 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6552 if ((tdesc->vt == VT_USERDEFINED) ||
6553 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
6555 VARTYPE vt_userdefined = 0;
6556 const TYPEDESC *tdesc_userdefined = tdesc;
6557 if (tdesc->vt == VT_PTR)
6559 vt_userdefined = VT_BYREF;
6560 tdesc_userdefined = tdesc->u.lptdesc;
6562 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
6563 if ((hr == S_OK) &&
6564 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
6565 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
6567 *vt |= vt_userdefined;
6568 return S_OK;
6571 *vt = VT_BYREF;
6574 switch (tdesc->vt)
6576 case VT_HRESULT:
6577 *vt |= VT_ERROR;
6578 break;
6579 case VT_USERDEFINED:
6580 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
6581 break;
6582 case VT_VOID:
6583 case VT_CARRAY:
6584 case VT_PTR:
6585 case VT_LPSTR:
6586 case VT_LPWSTR:
6587 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
6588 hr = DISP_E_BADVARTYPE;
6589 break;
6590 case VT_SAFEARRAY:
6591 *vt |= VT_ARRAY;
6592 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
6593 break;
6594 case VT_INT:
6595 *vt |= VT_I4;
6596 break;
6597 case VT_UINT:
6598 *vt |= VT_UI4;
6599 break;
6600 default:
6601 *vt |= tdesc->vt;
6602 break;
6604 return hr;
6607 static HRESULT get_iface_guid(ITypeInfo *tinfo, const TYPEDESC *tdesc, GUID *guid)
6609 ITypeInfo *tinfo2;
6610 TYPEATTR *tattr;
6611 HRESULT hres;
6613 hres = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6614 if(FAILED(hres))
6615 return hres;
6617 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6618 if(FAILED(hres)) {
6619 ITypeInfo_Release(tinfo2);
6620 return hres;
6623 switch(tattr->typekind) {
6624 case TKIND_ALIAS:
6625 hres = get_iface_guid(tinfo2, &tattr->tdescAlias, guid);
6626 break;
6628 case TKIND_INTERFACE:
6629 case TKIND_DISPATCH:
6630 *guid = tattr->guid;
6631 break;
6633 default:
6634 ERR("Unexpected typekind %d\n", tattr->typekind);
6635 hres = E_UNEXPECTED;
6638 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6639 ITypeInfo_Release(tinfo2);
6640 return hres;
6643 /***********************************************************************
6644 * DispCallFunc (OLEAUT32.@)
6646 * Invokes a function of the specified calling convention, passing the
6647 * specified arguments and returns the result.
6649 * PARAMS
6650 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6651 * oVft [I] The offset in the vtable. See notes.
6652 * cc [I] Calling convention of the function to call.
6653 * vtReturn [I] The return type of the function.
6654 * cActuals [I] Number of parameters.
6655 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6656 * prgpvarg [I] The arguments to pass.
6657 * pvargResult [O] The return value of the function. Can be NULL.
6659 * RETURNS
6660 * Success: S_OK.
6661 * Failure: HRESULT code.
6663 * NOTES
6664 * The HRESULT return value of this function is not affected by the return
6665 * value of the user supplied function, which is returned in pvargResult.
6667 * If pvInstance is NULL then a non-object function is to be called and oVft
6668 * is the address of the function to call.
6670 * The cc parameter can be one of the following values:
6671 *|CC_FASTCALL
6672 *|CC_CDECL
6673 *|CC_PASCAL
6674 *|CC_STDCALL
6675 *|CC_FPFASTCALL
6676 *|CC_SYSCALL
6677 *|CC_MPWCDECL
6678 *|CC_MPWPASCAL
6681 HRESULT WINAPI
6682 DispCallFunc(
6683 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
6684 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
6686 #ifdef __i386__
6687 int argspos, stack_offset;
6688 void *func;
6689 UINT i;
6690 DWORD *args;
6692 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6693 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6694 pvargResult, V_VT(pvargResult));
6696 if (cc != CC_STDCALL && cc != CC_CDECL)
6698 FIXME("unsupported calling convention %d\n",cc);
6699 return E_INVALIDARG;
6702 /* maximum size for an argument is sizeof(VARIANT) */
6703 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6705 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6706 argspos = 1;
6707 if (pvInstance)
6709 const FARPROC *vtable = *(FARPROC **)pvInstance;
6710 func = vtable[oVft/sizeof(void *)];
6711 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6713 else func = (void *)oVft;
6715 for (i = 0; i < cActuals; i++)
6717 VARIANT *arg = prgpvarg[i];
6719 switch (prgvt[i])
6721 case VT_EMPTY:
6722 break;
6723 case VT_I8:
6724 case VT_UI8:
6725 case VT_R8:
6726 case VT_DATE:
6727 case VT_CY:
6728 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6729 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6730 break;
6731 case VT_DECIMAL:
6732 case VT_VARIANT:
6733 memcpy( &args[argspos], arg, sizeof(*arg) );
6734 argspos += sizeof(*arg) / sizeof(DWORD);
6735 break;
6736 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6737 args[argspos++] = V_BOOL(arg);
6738 break;
6739 default:
6740 args[argspos++] = V_UI4(arg);
6741 break;
6743 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6746 switch (vtReturn)
6748 case VT_EMPTY:
6749 call_method( func, argspos - 1, args + 1, &stack_offset );
6750 break;
6751 case VT_R4:
6752 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6753 break;
6754 case VT_R8:
6755 case VT_DATE:
6756 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6757 break;
6758 case VT_DECIMAL:
6759 case VT_VARIANT:
6760 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6761 call_method( func, argspos, args, &stack_offset );
6762 break;
6763 case VT_I8:
6764 case VT_UI8:
6765 case VT_CY:
6766 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6767 break;
6768 case VT_HRESULT:
6769 WARN("invalid return type %u\n", vtReturn);
6770 heap_free( args );
6771 return E_INVALIDARG;
6772 default:
6773 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6774 break;
6776 heap_free( args );
6777 if (stack_offset && cc == CC_STDCALL)
6779 WARN( "stack pointer off by %d\n", stack_offset );
6780 return DISP_E_BADCALLEE;
6782 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6783 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6784 return S_OK;
6786 #elif defined(__x86_64__)
6787 int argspos;
6788 UINT i;
6789 DWORD_PTR *args;
6790 void *func;
6792 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6793 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6794 pvargResult, V_VT(pvargResult));
6796 if (cc != CC_STDCALL && cc != CC_CDECL)
6798 FIXME("unsupported calling convention %d\n",cc);
6799 return E_INVALIDARG;
6802 /* maximum size for an argument is sizeof(DWORD_PTR) */
6803 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6805 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6806 argspos = 1;
6807 if (pvInstance)
6809 const FARPROC *vtable = *(FARPROC **)pvInstance;
6810 func = vtable[oVft/sizeof(void *)];
6811 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6813 else func = (void *)oVft;
6815 for (i = 0; i < cActuals; i++)
6817 VARIANT *arg = prgpvarg[i];
6819 switch (prgvt[i])
6821 case VT_DECIMAL:
6822 case VT_VARIANT:
6823 args[argspos++] = (ULONG_PTR)arg;
6824 break;
6825 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6826 args[argspos++] = V_BOOL(arg);
6827 break;
6828 default:
6829 args[argspos++] = V_UI8(arg);
6830 break;
6832 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6835 switch (vtReturn)
6837 case VT_R4:
6838 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6839 break;
6840 case VT_R8:
6841 case VT_DATE:
6842 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6843 break;
6844 case VT_DECIMAL:
6845 case VT_VARIANT:
6846 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6847 call_method( func, argspos, args );
6848 break;
6849 case VT_HRESULT:
6850 WARN("invalid return type %u\n", vtReturn);
6851 heap_free( args );
6852 return E_INVALIDARG;
6853 default:
6854 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6855 break;
6857 heap_free( args );
6858 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6859 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6860 return S_OK;
6862 #else
6863 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6864 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6865 return E_NOTIMPL;
6866 #endif
6869 static inline BOOL func_restricted( const FUNCDESC *desc )
6871 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
6874 #define INVBUF_ELEMENT_SIZE \
6875 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6876 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6877 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6878 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6879 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6880 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6881 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6882 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6884 static HRESULT WINAPI ITypeInfo_fnInvoke(
6885 ITypeInfo2 *iface,
6886 VOID *pIUnk,
6887 MEMBERID memid,
6888 UINT16 wFlags,
6889 DISPPARAMS *pDispParams,
6890 VARIANT *pVarResult,
6891 EXCEPINFO *pExcepInfo,
6892 UINT *pArgErr)
6894 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6895 int i;
6896 unsigned int var_index;
6897 TYPEKIND type_kind;
6898 HRESULT hres;
6899 const TLBFuncDesc *pFuncInfo;
6900 UINT fdc;
6902 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6903 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6906 if( This->wTypeFlags & TYPEFLAG_FRESTRICTED )
6907 return DISP_E_MEMBERNOTFOUND;
6909 if (!pDispParams)
6911 ERR("NULL pDispParams not allowed\n");
6912 return E_INVALIDARG;
6915 dump_DispParms(pDispParams);
6917 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6919 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6920 pDispParams->cNamedArgs, pDispParams->cArgs);
6921 return E_INVALIDARG;
6924 /* we do this instead of using GetFuncDesc since it will return a fake
6925 * FUNCDESC for dispinterfaces and we want the real function description */
6926 for (fdc = 0; fdc < This->cFuncs; ++fdc){
6927 pFuncInfo = &This->funcdescs[fdc];
6928 if ((memid == pFuncInfo->funcdesc.memid) &&
6929 (wFlags & pFuncInfo->funcdesc.invkind) &&
6930 !func_restricted( &pFuncInfo->funcdesc ))
6931 break;
6934 if (fdc < This->cFuncs) {
6935 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6937 if (TRACE_ON(ole))
6939 TRACE("invoking:\n");
6940 dump_TLBFuncDescOne(pFuncInfo);
6943 switch (func_desc->funckind) {
6944 case FUNC_PUREVIRTUAL:
6945 case FUNC_VIRTUAL: {
6946 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
6947 VARIANT varresult;
6948 VARIANT retval; /* pointer for storing byref retvals in */
6949 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6950 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6951 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6952 UINT cNamedArgs = pDispParams->cNamedArgs;
6953 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6954 UINT vargs_converted=0;
6956 hres = S_OK;
6958 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6960 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6962 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6963 hres = DISP_E_PARAMNOTFOUND;
6964 goto func_fail;
6968 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6970 ERR("functions with the vararg attribute do not support named arguments\n");
6971 hres = DISP_E_NONAMEDARGS;
6972 goto func_fail;
6975 for (i = 0; i < func_desc->cParams; i++)
6977 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6978 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6979 if (FAILED(hres))
6980 goto func_fail;
6983 TRACE("changing args\n");
6984 for (i = 0; i < func_desc->cParams; i++)
6986 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6987 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6988 VARIANTARG *src_arg;
6990 if (wParamFlags & PARAMFLAG_FLCID)
6992 VARIANTARG *arg;
6993 arg = prgpvarg[i] = &rgvarg[i];
6994 V_VT(arg) = VT_I4;
6995 V_I4(arg) = This->pTypeLib->lcid;
6996 continue;
6999 src_arg = NULL;
7001 if (cNamedArgs)
7003 USHORT j;
7004 for (j = 0; j < cNamedArgs; j++)
7005 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
7007 src_arg = &pDispParams->rgvarg[j];
7008 break;
7012 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
7014 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7015 vargs_converted++;
7018 if (wParamFlags & PARAMFLAG_FRETVAL)
7020 /* under most conditions the caller is not allowed to
7021 * pass in a dispparam arg in the index of what would be
7022 * the retval parameter. however, there is an exception
7023 * where the extra parameter is used in an extra
7024 * IDispatch::Invoke below */
7025 if ((i < pDispParams->cArgs) &&
7026 ((func_desc->cParams != 1) || !pVarResult ||
7027 !(func_desc->invkind & INVOKE_PROPERTYGET)))
7029 hres = DISP_E_BADPARAMCOUNT;
7030 break;
7033 /* note: this check is placed so that if the caller passes
7034 * in a VARIANTARG for the retval we just ignore it, like
7035 * native does */
7036 if (i == func_desc->cParams - 1)
7038 VARIANTARG *arg;
7039 arg = prgpvarg[i] = &rgvarg[i];
7040 memset(arg, 0, sizeof(*arg));
7041 V_VT(arg) = rgvt[i];
7042 memset(&retval, 0, sizeof(retval));
7043 V_BYREF(arg) = &retval;
7045 else
7047 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
7048 hres = E_UNEXPECTED;
7049 break;
7052 else if (src_arg)
7054 TRACE("%s\n", debugstr_variant(src_arg));
7056 if(rgvt[i]!=V_VT(src_arg))
7058 if (rgvt[i] == VT_VARIANT)
7059 hres = VariantCopy(&rgvarg[i], src_arg);
7060 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
7062 if (rgvt[i] == V_VT(src_arg))
7063 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
7064 else
7066 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7067 if (wParamFlags & PARAMFLAG_FIN)
7068 hres = VariantCopy(&missing_arg[i], src_arg);
7069 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
7071 V_VT(&rgvarg[i]) = rgvt[i];
7073 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
7075 SAFEARRAY *a;
7076 SAFEARRAYBOUND bound;
7077 VARIANT *v;
7078 LONG j;
7079 bound.lLbound = 0;
7080 bound.cElements = pDispParams->cArgs-i;
7081 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
7083 ERR("SafeArrayCreate failed\n");
7084 break;
7086 hres = SafeArrayAccessData(a, (LPVOID)&v);
7087 if (hres != S_OK)
7089 ERR("SafeArrayAccessData failed with %x\n", hres);
7090 SafeArrayDestroy(a);
7091 break;
7093 for (j = 0; j < bound.cElements; j++)
7094 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
7095 hres = SafeArrayUnaccessData(a);
7096 if (hres != S_OK)
7098 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7099 SafeArrayDestroy(a);
7100 break;
7102 V_ARRAY(&rgvarg[i]) = a;
7103 V_VT(&rgvarg[i]) = rgvt[i];
7105 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
7107 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7108 if (wParamFlags & PARAMFLAG_FIN)
7109 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
7110 else
7111 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
7112 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
7113 V_VT(&rgvarg[i]) = rgvt[i];
7115 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
7117 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
7118 V_VT(&rgvarg[i]) = rgvt[i];
7120 else
7122 /* FIXME: this doesn't work for VT_BYREF arguments if
7123 * they are not the same type as in the paramdesc */
7124 V_VT(&rgvarg[i]) = V_VT(src_arg);
7125 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
7126 V_VT(&rgvarg[i]) = rgvt[i];
7129 if (FAILED(hres))
7131 ERR("failed to convert param %d to %s from %s\n", i,
7132 debugstr_vt(rgvt[i]), debugstr_variant(src_arg));
7133 break;
7135 prgpvarg[i] = &rgvarg[i];
7137 else
7139 prgpvarg[i] = src_arg;
7142 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
7143 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
7144 && V_UNKNOWN(prgpvarg[i])) {
7145 IUnknown *userdefined_iface;
7146 GUID guid;
7148 hres = get_iface_guid((ITypeInfo*)iface, tdesc->vt == VT_PTR ? tdesc->u.lptdesc : tdesc, &guid);
7149 if(FAILED(hres))
7150 break;
7152 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
7153 if(FAILED(hres)) {
7154 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
7155 break;
7158 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
7159 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
7162 else if (wParamFlags & PARAMFLAG_FOPT)
7164 VARIANTARG *arg;
7165 arg = prgpvarg[i] = &rgvarg[i];
7166 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7168 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
7169 if (FAILED(hres))
7170 break;
7172 else
7174 VARIANTARG *missing_arg;
7175 /* if the function wants a pointer to a variant then
7176 * set that up, otherwise just pass the VT_ERROR in
7177 * the argument by value */
7178 if (rgvt[i] & VT_BYREF)
7180 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
7181 V_VT(arg) = VT_VARIANT | VT_BYREF;
7182 V_VARIANTREF(arg) = missing_arg;
7184 else
7185 missing_arg = arg;
7186 V_VT(missing_arg) = VT_ERROR;
7187 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
7190 else
7192 hres = DISP_E_BADPARAMCOUNT;
7193 break;
7196 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7198 /* VT_VOID is a special case for return types, so it is not
7199 * handled in the general function */
7200 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
7201 V_VT(&varresult) = VT_EMPTY;
7202 else
7204 V_VT(&varresult) = 0;
7205 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
7206 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7209 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv,
7210 V_VT(&varresult), func_desc->cParams, rgvt,
7211 prgpvarg, &varresult);
7213 vargs_converted = 0;
7215 for (i = 0; i < func_desc->cParams; i++)
7217 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7218 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7220 if (wParamFlags & PARAMFLAG_FLCID)
7221 continue;
7222 else if (wParamFlags & PARAMFLAG_FRETVAL)
7224 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg[i]));
7226 if (pVarResult)
7228 VariantInit(pVarResult);
7229 /* deref return value */
7230 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
7233 VARIANT_ClearInd(prgpvarg[i]);
7235 else if (vargs_converted < pDispParams->cArgs)
7237 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7238 if (wParamFlags & PARAMFLAG_FOUT)
7240 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
7242 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
7244 if (FAILED(hres))
7246 ERR("failed to convert param %d to vt %d\n", i,
7247 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
7248 break;
7252 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
7253 func_desc->cParamsOpt < 0 &&
7254 i == func_desc->cParams-1)
7256 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
7257 LONG j, ubound;
7258 VARIANT *v;
7259 hres = SafeArrayGetUBound(a, 1, &ubound);
7260 if (hres != S_OK)
7262 ERR("SafeArrayGetUBound failed with %x\n", hres);
7263 break;
7265 hres = SafeArrayAccessData(a, (LPVOID)&v);
7266 if (hres != S_OK)
7268 ERR("SafeArrayAccessData failed with %x\n", hres);
7269 break;
7271 for (j = 0; j <= ubound; j++)
7272 VariantClear(&v[j]);
7273 hres = SafeArrayUnaccessData(a);
7274 if (hres != S_OK)
7276 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7277 break;
7280 VariantClear(&rgvarg[i]);
7281 vargs_converted++;
7283 else if (wParamFlags & PARAMFLAG_FOPT)
7285 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7286 VariantClear(&rgvarg[i]);
7289 VariantClear(&missing_arg[i]);
7292 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
7294 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
7295 hres = DISP_E_EXCEPTION;
7296 if (pExcepInfo)
7298 IErrorInfo *pErrorInfo;
7299 pExcepInfo->scode = V_ERROR(&varresult);
7300 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
7302 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
7303 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
7304 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
7305 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
7307 IErrorInfo_Release(pErrorInfo);
7311 if (V_VT(&varresult) != VT_ERROR)
7313 TRACE("varresult value: %s\n", debugstr_variant(&varresult));
7315 if (pVarResult)
7317 VariantClear(pVarResult);
7318 *pVarResult = varresult;
7320 else
7321 VariantClear(&varresult);
7324 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
7325 (func_desc->invkind & INVOKE_PROPERTYGET) &&
7326 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
7327 (pDispParams->cArgs != 0))
7329 if (V_VT(pVarResult) == VT_DISPATCH)
7331 IDispatch *pDispatch = V_DISPATCH(pVarResult);
7332 /* Note: not VariantClear; we still need the dispatch
7333 * pointer to be valid */
7334 VariantInit(pVarResult);
7335 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
7336 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
7337 pDispParams, pVarResult, pExcepInfo, pArgErr);
7338 IDispatch_Release(pDispatch);
7340 else
7342 VariantClear(pVarResult);
7343 hres = DISP_E_NOTACOLLECTION;
7347 func_fail:
7348 heap_free(buffer);
7349 break;
7351 case FUNC_DISPATCH: {
7352 IDispatch *disp;
7354 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
7355 if (SUCCEEDED(hres)) {
7356 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7357 hres = IDispatch_Invoke(
7358 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
7359 pVarResult,pExcepInfo,pArgErr
7361 if (FAILED(hres))
7362 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
7363 IDispatch_Release(disp);
7364 } else
7365 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7366 break;
7368 default:
7369 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
7370 hres = E_FAIL;
7371 break;
7374 TRACE("-- 0x%08x\n", hres);
7375 return hres;
7377 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
7378 VARDESC *var_desc;
7380 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
7381 if(FAILED(hres)) return hres;
7383 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7384 dump_VARDESC(var_desc);
7385 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
7386 return E_NOTIMPL;
7389 /* not found, look for it in inherited interfaces */
7390 ITypeInfo2_GetTypeKind(iface, &type_kind);
7391 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
7392 if(This->impltypes) {
7393 /* recursive search */
7394 ITypeInfo *pTInfo;
7395 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7396 if(SUCCEEDED(hres)){
7397 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
7398 ITypeInfo_Release(pTInfo);
7399 return hres;
7401 WARN("Could not search inherited interface!\n");
7404 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
7405 return DISP_E_MEMBERNOTFOUND;
7408 /* ITypeInfo::GetDocumentation
7410 * Retrieves the documentation string, the complete Help file name and path,
7411 * and the context ID for the Help topic for a specified type description.
7413 * (Can be tested by the Visual Basic Editor in Word for instance.)
7415 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
7416 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
7417 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
7419 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7420 const TLBFuncDesc *pFDesc;
7421 const TLBVarDesc *pVDesc;
7422 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7423 " HelpContext(%p) HelpFile(%p)\n",
7424 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
7425 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7426 if(pBstrName)
7427 *pBstrName=SysAllocString(TLB_get_bstr(This->Name));
7428 if(pBstrDocString)
7429 *pBstrDocString=SysAllocString(TLB_get_bstr(This->DocString));
7430 if(pdwHelpContext)
7431 *pdwHelpContext=This->dwHelpContext;
7432 if(pBstrHelpFile)
7433 *pBstrHelpFile=SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7434 return S_OK;
7435 }else {/* for a member */
7436 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7437 if(pFDesc){
7438 if(pBstrName)
7439 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Name));
7440 if(pBstrDocString)
7441 *pBstrDocString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7442 if(pdwHelpContext)
7443 *pdwHelpContext=pFDesc->helpcontext;
7444 if(pBstrHelpFile)
7445 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7446 return S_OK;
7448 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
7449 if(pVDesc){
7450 if(pBstrName)
7451 *pBstrName = SysAllocString(TLB_get_bstr(pVDesc->Name));
7452 if(pBstrDocString)
7453 *pBstrDocString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7454 if(pdwHelpContext)
7455 *pdwHelpContext=pVDesc->HelpContext;
7456 if(pBstrHelpFile)
7457 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7458 return S_OK;
7462 if(This->impltypes &&
7463 (This->typekind==TKIND_INTERFACE || This->typekind==TKIND_DISPATCH)) {
7464 /* recursive search */
7465 ITypeInfo *pTInfo;
7466 HRESULT result;
7467 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7468 if(SUCCEEDED(result)) {
7469 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
7470 pBstrDocString, pdwHelpContext, pBstrHelpFile);
7471 ITypeInfo_Release(pTInfo);
7472 return result;
7474 WARN("Could not search inherited interface!\n");
7477 WARN("member %d not found\n", memid);
7478 return TYPE_E_ELEMENTNOTFOUND;
7481 /* ITypeInfo::GetDllEntry
7483 * Retrieves a description or specification of an entry point for a function
7484 * in a DLL.
7486 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
7487 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
7488 WORD *pwOrdinal)
7490 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7491 const TLBFuncDesc *pFDesc;
7493 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
7495 if (pBstrDllName) *pBstrDllName = NULL;
7496 if (pBstrName) *pBstrName = NULL;
7497 if (pwOrdinal) *pwOrdinal = 0;
7499 if (This->typekind != TKIND_MODULE)
7500 return TYPE_E_BADMODULEKIND;
7502 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7503 if(pFDesc){
7504 dump_TypeInfo(This);
7505 if (TRACE_ON(ole))
7506 dump_TLBFuncDescOne(pFDesc);
7508 if (pBstrDllName)
7509 *pBstrDllName = SysAllocString(TLB_get_bstr(This->DllName));
7511 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
7512 if (pBstrName)
7513 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Entry));
7514 if (pwOrdinal)
7515 *pwOrdinal = -1;
7516 return S_OK;
7518 if (pBstrName)
7519 *pBstrName = NULL;
7520 if (pwOrdinal)
7521 *pwOrdinal = LOWORD(pFDesc->Entry);
7522 return S_OK;
7524 return TYPE_E_ELEMENTNOTFOUND;
7527 /* internal function to make the inherited interfaces' methods appear
7528 * part of the interface */
7529 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7530 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7532 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7533 HRESULT hr;
7535 TRACE("%p, 0x%x\n", iface, *hRefType);
7537 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7539 ITypeInfo *pSubTypeInfo;
7541 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7542 if (FAILED(hr))
7543 return hr;
7545 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7546 hRefType, ppTInfo);
7547 ITypeInfo_Release(pSubTypeInfo);
7548 if (SUCCEEDED(hr))
7549 return hr;
7551 *hRefType -= DISPATCH_HREF_OFFSET;
7553 if (!(*hRefType & DISPATCH_HREF_MASK))
7554 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7555 else
7556 return E_FAIL;
7559 struct search_res_tlb_params
7561 const GUID *guid;
7562 ITypeLib *pTLib;
7565 static BOOL CALLBACK search_res_tlb(HMODULE hModule, LPCWSTR lpszType, LPWSTR lpszName, LONG_PTR lParam)
7567 struct search_res_tlb_params *params = (LPVOID)lParam;
7568 static const WCHAR formatW[] = {'\\','%','d',0};
7569 WCHAR szPath[MAX_PATH+1];
7570 ITypeLib *pTLib = NULL;
7571 HRESULT ret;
7572 DWORD len;
7574 if (IS_INTRESOURCE(lpszName) == FALSE)
7575 return TRUE;
7577 if (!(len = GetModuleFileNameW(hModule, szPath, MAX_PATH)))
7578 return TRUE;
7580 if (snprintfW(szPath + len, sizeof(szPath)/sizeof(WCHAR) - len, formatW, LOWORD(lpszName)) < 0)
7581 return TRUE;
7583 ret = LoadTypeLibEx(szPath, REGKIND_NONE, &pTLib);
7584 if (SUCCEEDED(ret))
7586 ITypeLibImpl *impl = impl_from_ITypeLib(pTLib);
7587 if (IsEqualGUID(params->guid, impl->guid))
7589 params->pTLib = pTLib;
7590 return FALSE; /* stop enumeration */
7592 ITypeLib_Release(pTLib);
7595 return TRUE;
7598 /* ITypeInfo::GetRefTypeInfo
7600 * If a type description references other type descriptions, it retrieves
7601 * the referenced type descriptions.
7603 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7604 ITypeInfo2 *iface,
7605 HREFTYPE hRefType,
7606 ITypeInfo **ppTInfo)
7608 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7609 HRESULT result = E_FAIL;
7611 if(!ppTInfo)
7612 return E_INVALIDARG;
7614 if ((INT)hRefType < 0) {
7615 ITypeInfoImpl *pTypeInfoImpl;
7617 if (!(This->wTypeFlags & TYPEFLAG_FDUAL) ||
7618 !(This->typekind == TKIND_INTERFACE ||
7619 This->typekind == TKIND_DISPATCH))
7620 return TYPE_E_ELEMENTNOTFOUND;
7622 /* when we meet a DUAL typeinfo, we must create the alternate
7623 * version of it.
7625 pTypeInfoImpl = ITypeInfoImpl_Constructor();
7627 *pTypeInfoImpl = *This;
7628 pTypeInfoImpl->ref = 0;
7629 list_init(&pTypeInfoImpl->custdata_list);
7631 if (This->typekind == TKIND_INTERFACE)
7632 pTypeInfoImpl->typekind = TKIND_DISPATCH;
7633 else
7634 pTypeInfoImpl->typekind = TKIND_INTERFACE;
7636 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface;
7637 /* the AddRef implicitly adds a reference to the parent typelib, which
7638 * stops the copied data from being destroyed until the new typeinfo's
7639 * refcount goes to zero, but we need to signal to the new instance to
7640 * not free its data structures when it is destroyed */
7641 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7643 ITypeInfo_AddRef(*ppTInfo);
7645 result = S_OK;
7646 } else if ((hRefType & DISPATCH_HREF_MASK) &&
7647 (This->typekind == TKIND_DISPATCH))
7649 HREFTYPE href_dispatch = hRefType;
7650 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
7651 } else {
7652 TLBRefType *ref_type;
7653 ITypeLib *pTLib = NULL;
7654 UINT i;
7656 if(!(hRefType & 0x1)){
7657 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
7659 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
7661 result = S_OK;
7662 *ppTInfo = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
7663 ITypeInfo_AddRef(*ppTInfo);
7664 goto end;
7669 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7671 if(ref_type->reference == (hRefType & (~0x3)))
7672 break;
7674 if(&ref_type->entry == &This->pTypeLib->ref_list)
7676 FIXME("Can't find pRefType for ref %x\n", hRefType);
7677 goto end;
7680 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7681 UINT Index;
7682 TRACE("internal reference\n");
7683 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7684 } else {
7685 if(ref_type->pImpTLInfo->pImpTypeLib) {
7686 TRACE("typeinfo in imported typelib that is already loaded\n");
7687 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
7688 ITypeLib_AddRef(pTLib);
7689 result = S_OK;
7690 } else {
7691 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
7692 struct search_res_tlb_params params;
7693 BSTR libnam;
7695 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7697 /* Search in resource table */
7698 params.guid = TLB_get_guid_null(ref_type->pImpTLInfo->guid);
7699 params.pTLib = NULL;
7700 EnumResourceNamesW(NULL, TYPELIBW, search_res_tlb, (LONG_PTR)&params);
7701 pTLib = params.pTLib;
7702 result = S_OK;
7704 if (!pTLib)
7706 /* Search on disk */
7707 result = query_typelib_path(TLB_get_guid_null(ref_type->pImpTLInfo->guid),
7708 ref_type->pImpTLInfo->wVersionMajor,
7709 ref_type->pImpTLInfo->wVersionMinor,
7710 This->pTypeLib->syskind,
7711 ref_type->pImpTLInfo->lcid, &libnam, TRUE);
7712 if (FAILED(result))
7713 libnam = SysAllocString(ref_type->pImpTLInfo->name);
7715 result = LoadTypeLib(libnam, &pTLib);
7716 SysFreeString(libnam);
7719 if(SUCCEEDED(result)) {
7720 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
7721 ITypeLib_AddRef(pTLib);
7725 if(SUCCEEDED(result)) {
7726 if(ref_type->index == TLB_REF_USE_GUID)
7727 result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), ppTInfo);
7728 else
7729 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, ppTInfo);
7731 if (pTLib != NULL)
7732 ITypeLib_Release(pTLib);
7735 end:
7736 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
7737 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
7738 return result;
7741 /* ITypeInfo::AddressOfMember
7743 * Retrieves the addresses of static functions or variables, such as those
7744 * defined in a DLL.
7746 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
7747 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
7749 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7750 HRESULT hr;
7751 BSTR dll, entry;
7752 WORD ordinal;
7753 HMODULE module;
7755 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
7757 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
7758 if (FAILED(hr))
7759 return hr;
7761 module = LoadLibraryW(dll);
7762 if (!module)
7764 ERR("couldn't load %s\n", debugstr_w(dll));
7765 SysFreeString(dll);
7766 SysFreeString(entry);
7767 return STG_E_FILENOTFOUND;
7769 /* FIXME: store library somewhere where we can free it */
7771 if (entry)
7773 LPSTR entryA;
7774 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
7775 entryA = heap_alloc(len);
7776 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
7778 *ppv = GetProcAddress(module, entryA);
7779 if (!*ppv)
7780 ERR("function not found %s\n", debugstr_a(entryA));
7782 heap_free(entryA);
7784 else
7786 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7787 if (!*ppv)
7788 ERR("function not found %d\n", ordinal);
7791 SysFreeString(dll);
7792 SysFreeString(entry);
7794 if (!*ppv)
7795 return TYPE_E_DLLFUNCTIONNOTFOUND;
7797 return S_OK;
7800 /* ITypeInfo::CreateInstance
7802 * Creates a new instance of a type that describes a component object class
7803 * (coclass).
7805 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7806 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7808 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7809 HRESULT hr;
7810 TYPEATTR *pTA;
7812 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7814 *ppvObj = NULL;
7816 if(pOuterUnk)
7818 WARN("Not able to aggregate\n");
7819 return CLASS_E_NOAGGREGATION;
7822 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
7823 if(FAILED(hr)) return hr;
7825 if(pTA->typekind != TKIND_COCLASS)
7827 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7828 hr = E_INVALIDARG;
7829 goto end;
7832 hr = S_FALSE;
7833 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7835 IUnknown *pUnk;
7836 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7837 TRACE("GetActiveObject rets %08x\n", hr);
7838 if(hr == S_OK)
7840 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7841 IUnknown_Release(pUnk);
7845 if(hr != S_OK)
7846 hr = CoCreateInstance(&pTA->guid, NULL,
7847 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7848 riid, ppvObj);
7850 end:
7851 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
7852 return hr;
7855 /* ITypeInfo::GetMops
7857 * Retrieves marshalling information.
7859 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7860 BSTR *pBstrMops)
7862 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7863 FIXME("(%p %d) stub!\n", This, memid);
7864 *pBstrMops = NULL;
7865 return S_OK;
7868 /* ITypeInfo::GetContainingTypeLib
7870 * Retrieves the containing type library and the index of the type description
7871 * within that type library.
7873 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7874 ITypeLib * *ppTLib, UINT *pIndex)
7876 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7878 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7879 if (pIndex) {
7880 *pIndex=This->index;
7881 TRACE("returning pIndex=%d\n", *pIndex);
7884 if (ppTLib) {
7885 *ppTLib=(LPTYPELIB )(This->pTypeLib);
7886 ITypeLib_AddRef(*ppTLib);
7887 TRACE("returning ppTLib=%p\n", *ppTLib);
7890 return S_OK;
7893 /* ITypeInfo::ReleaseTypeAttr
7895 * Releases a TYPEATTR previously returned by Get
7898 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7899 TYPEATTR* pTypeAttr)
7901 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7902 TRACE("(%p)->(%p)\n", This, pTypeAttr);
7903 heap_free(pTypeAttr);
7906 /* ITypeInfo::ReleaseFuncDesc
7908 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7910 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7911 ITypeInfo2 *iface,
7912 FUNCDESC *pFuncDesc)
7914 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7915 SHORT i;
7917 TRACE("(%p)->(%p)\n", This, pFuncDesc);
7919 for (i = 0; i < pFuncDesc->cParams; i++)
7920 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7921 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7923 SysFreeString((BSTR)pFuncDesc);
7926 /* ITypeInfo::ReleaseVarDesc
7928 * Releases a VARDESC previously returned by GetVarDesc.
7930 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7931 VARDESC *pVarDesc)
7933 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7934 TRACE("(%p)->(%p)\n", This, pVarDesc);
7936 TLB_FreeVarDesc(pVarDesc);
7939 /* ITypeInfo2::GetTypeKind
7941 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7944 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7945 TYPEKIND *pTypeKind)
7947 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7948 *pTypeKind=This->typekind;
7949 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7950 return S_OK;
7953 /* ITypeInfo2::GetTypeFlags
7955 * Returns the type flags without any allocations. This returns a DWORD type
7956 * flag, which expands the type flags without growing the TYPEATTR (type
7957 * attribute).
7960 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7962 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7963 *pTypeFlags=This->wTypeFlags;
7964 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7965 return S_OK;
7968 /* ITypeInfo2::GetFuncIndexOfMemId
7969 * Binds to a specific member based on a known DISPID, where the member name
7970 * is not known (for example, when binding to a default member).
7973 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7974 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7976 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7977 UINT fdc;
7978 HRESULT result;
7980 for (fdc = 0; fdc < This->cFuncs; ++fdc){
7981 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
7982 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7983 break;
7985 if(fdc < This->cFuncs) {
7986 *pFuncIndex = fdc;
7987 result = S_OK;
7988 } else
7989 result = TYPE_E_ELEMENTNOTFOUND;
7991 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7992 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7993 return result;
7996 /* TypeInfo2::GetVarIndexOfMemId
7998 * Binds to a specific member based on a known DISPID, where the member name
7999 * is not known (for example, when binding to a default member).
8002 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
8003 MEMBERID memid, UINT *pVarIndex)
8005 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8006 TLBVarDesc *pVarInfo;
8008 TRACE("%p %d %p\n", iface, memid, pVarIndex);
8010 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
8011 if(!pVarInfo)
8012 return TYPE_E_ELEMENTNOTFOUND;
8014 *pVarIndex = (pVarInfo - This->vardescs);
8016 return S_OK;
8019 /* ITypeInfo2::GetCustData
8021 * Gets the custom data
8023 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
8024 ITypeInfo2 * iface,
8025 REFGUID guid,
8026 VARIANT *pVarVal)
8028 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8029 TLBCustData *pCData;
8031 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8033 if(!guid || !pVarVal)
8034 return E_INVALIDARG;
8036 pCData = TLB_get_custdata_by_guid(This->pcustdata_list, guid);
8038 VariantInit( pVarVal);
8039 if (pCData)
8040 VariantCopy( pVarVal, &pCData->data);
8041 else
8042 VariantClear( pVarVal );
8043 return S_OK;
8046 /* ITypeInfo2::GetFuncCustData
8048 * Gets the custom data
8050 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
8051 ITypeInfo2 * iface,
8052 UINT index,
8053 REFGUID guid,
8054 VARIANT *pVarVal)
8056 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8057 TLBCustData *pCData;
8058 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8060 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8062 if(index >= This->cFuncs)
8063 return TYPE_E_ELEMENTNOTFOUND;
8065 pCData = TLB_get_custdata_by_guid(&pFDesc->custdata_list, guid);
8066 if(!pCData)
8067 return TYPE_E_ELEMENTNOTFOUND;
8069 VariantInit(pVarVal);
8070 VariantCopy(pVarVal, &pCData->data);
8072 return S_OK;
8075 /* ITypeInfo2::GetParamCustData
8077 * Gets the custom data
8079 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
8080 ITypeInfo2 * iface,
8081 UINT indexFunc,
8082 UINT indexParam,
8083 REFGUID guid,
8084 VARIANT *pVarVal)
8086 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8087 TLBCustData *pCData;
8088 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8090 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
8091 debugstr_guid(guid), pVarVal);
8093 if(indexFunc >= This->cFuncs)
8094 return TYPE_E_ELEMENTNOTFOUND;
8096 if(indexParam >= pFDesc->funcdesc.cParams)
8097 return TYPE_E_ELEMENTNOTFOUND;
8099 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
8100 if(!pCData)
8101 return TYPE_E_ELEMENTNOTFOUND;
8103 VariantInit(pVarVal);
8104 VariantCopy(pVarVal, &pCData->data);
8106 return S_OK;
8109 /* ITypeInfo2::GetVarCustData
8111 * Gets the custom data
8113 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
8114 ITypeInfo2 * iface,
8115 UINT index,
8116 REFGUID guid,
8117 VARIANT *pVarVal)
8119 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8120 TLBCustData *pCData;
8121 TLBVarDesc *pVDesc = &This->vardescs[index];
8123 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8125 if(index >= This->cVars)
8126 return TYPE_E_ELEMENTNOTFOUND;
8128 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
8129 if(!pCData)
8130 return TYPE_E_ELEMENTNOTFOUND;
8132 VariantInit(pVarVal);
8133 VariantCopy(pVarVal, &pCData->data);
8135 return S_OK;
8138 /* ITypeInfo2::GetImplCustData
8140 * Gets the custom data
8142 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
8143 ITypeInfo2 * iface,
8144 UINT index,
8145 REFGUID guid,
8146 VARIANT *pVarVal)
8148 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8149 TLBCustData *pCData;
8150 TLBImplType *pRDesc = &This->impltypes[index];
8152 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8154 if(index >= This->cImplTypes)
8155 return TYPE_E_ELEMENTNOTFOUND;
8157 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
8158 if(!pCData)
8159 return TYPE_E_ELEMENTNOTFOUND;
8161 VariantInit(pVarVal);
8162 VariantCopy(pVarVal, &pCData->data);
8164 return S_OK;
8167 /* ITypeInfo2::GetDocumentation2
8169 * Retrieves the documentation string, the complete Help file name and path,
8170 * the localization context to use, and the context ID for the library Help
8171 * topic in the Help file.
8174 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
8175 ITypeInfo2 * iface,
8176 MEMBERID memid,
8177 LCID lcid,
8178 BSTR *pbstrHelpString,
8179 DWORD *pdwHelpStringContext,
8180 BSTR *pbstrHelpStringDll)
8182 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8183 const TLBFuncDesc *pFDesc;
8184 const TLBVarDesc *pVDesc;
8185 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8186 "HelpStringContext(%p) HelpStringDll(%p)\n",
8187 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
8188 pbstrHelpStringDll );
8189 /* the help string should be obtained from the helpstringdll,
8190 * using the _DLLGetDocumentation function, based on the supplied
8191 * lcid. Nice to do sometime...
8193 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
8194 if(pbstrHelpString)
8195 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->Name));
8196 if(pdwHelpStringContext)
8197 *pdwHelpStringContext=This->dwHelpStringContext;
8198 if(pbstrHelpStringDll)
8199 *pbstrHelpStringDll=
8200 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8201 return S_OK;
8202 }else {/* for a member */
8203 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
8204 if(pFDesc){
8205 if(pbstrHelpString)
8206 *pbstrHelpString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
8207 if(pdwHelpStringContext)
8208 *pdwHelpStringContext=pFDesc->HelpStringContext;
8209 if(pbstrHelpStringDll)
8210 *pbstrHelpStringDll=
8211 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8212 return S_OK;
8214 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
8215 if(pVDesc){
8216 if(pbstrHelpString)
8217 *pbstrHelpString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
8218 if(pdwHelpStringContext)
8219 *pdwHelpStringContext=pVDesc->HelpStringContext;
8220 if(pbstrHelpStringDll)
8221 *pbstrHelpStringDll=
8222 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8223 return S_OK;
8226 return TYPE_E_ELEMENTNOTFOUND;
8229 /* ITypeInfo2::GetAllCustData
8231 * Gets all custom data items for the Type info.
8234 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
8235 ITypeInfo2 * iface,
8236 CUSTDATA *pCustData)
8238 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8240 TRACE("%p %p\n", This, pCustData);
8242 return TLB_copy_all_custdata(This->pcustdata_list, pCustData);
8245 /* ITypeInfo2::GetAllFuncCustData
8247 * Gets all custom data items for the specified Function
8250 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
8251 ITypeInfo2 * iface,
8252 UINT index,
8253 CUSTDATA *pCustData)
8255 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8256 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8258 TRACE("%p %u %p\n", This, index, pCustData);
8260 if(index >= This->cFuncs)
8261 return TYPE_E_ELEMENTNOTFOUND;
8263 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
8266 /* ITypeInfo2::GetAllParamCustData
8268 * Gets all custom data items for the Functions
8271 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
8272 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
8274 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8275 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8277 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
8279 if(indexFunc >= This->cFuncs)
8280 return TYPE_E_ELEMENTNOTFOUND;
8282 if(indexParam >= pFDesc->funcdesc.cParams)
8283 return TYPE_E_ELEMENTNOTFOUND;
8285 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
8288 /* ITypeInfo2::GetAllVarCustData
8290 * Gets all custom data items for the specified Variable
8293 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
8294 UINT index, CUSTDATA *pCustData)
8296 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8297 TLBVarDesc * pVDesc = &This->vardescs[index];
8299 TRACE("%p %u %p\n", This, index, pCustData);
8301 if(index >= This->cVars)
8302 return TYPE_E_ELEMENTNOTFOUND;
8304 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
8307 /* ITypeInfo2::GetAllImplCustData
8309 * Gets all custom data items for the specified implementation type
8312 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
8313 ITypeInfo2 * iface,
8314 UINT index,
8315 CUSTDATA *pCustData)
8317 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8318 TLBImplType *pRDesc = &This->impltypes[index];
8320 TRACE("%p %u %p\n", This, index, pCustData);
8322 if(index >= This->cImplTypes)
8323 return TYPE_E_ELEMENTNOTFOUND;
8325 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
8328 static const ITypeInfo2Vtbl tinfvt =
8331 ITypeInfo_fnQueryInterface,
8332 ITypeInfo_fnAddRef,
8333 ITypeInfo_fnRelease,
8335 ITypeInfo_fnGetTypeAttr,
8336 ITypeInfo_fnGetTypeComp,
8337 ITypeInfo_fnGetFuncDesc,
8338 ITypeInfo_fnGetVarDesc,
8339 ITypeInfo_fnGetNames,
8340 ITypeInfo_fnGetRefTypeOfImplType,
8341 ITypeInfo_fnGetImplTypeFlags,
8342 ITypeInfo_fnGetIDsOfNames,
8343 ITypeInfo_fnInvoke,
8344 ITypeInfo_fnGetDocumentation,
8345 ITypeInfo_fnGetDllEntry,
8346 ITypeInfo_fnGetRefTypeInfo,
8347 ITypeInfo_fnAddressOfMember,
8348 ITypeInfo_fnCreateInstance,
8349 ITypeInfo_fnGetMops,
8350 ITypeInfo_fnGetContainingTypeLib,
8351 ITypeInfo_fnReleaseTypeAttr,
8352 ITypeInfo_fnReleaseFuncDesc,
8353 ITypeInfo_fnReleaseVarDesc,
8355 ITypeInfo2_fnGetTypeKind,
8356 ITypeInfo2_fnGetTypeFlags,
8357 ITypeInfo2_fnGetFuncIndexOfMemId,
8358 ITypeInfo2_fnGetVarIndexOfMemId,
8359 ITypeInfo2_fnGetCustData,
8360 ITypeInfo2_fnGetFuncCustData,
8361 ITypeInfo2_fnGetParamCustData,
8362 ITypeInfo2_fnGetVarCustData,
8363 ITypeInfo2_fnGetImplTypeCustData,
8364 ITypeInfo2_fnGetDocumentation2,
8365 ITypeInfo2_fnGetAllCustData,
8366 ITypeInfo2_fnGetAllFuncCustData,
8367 ITypeInfo2_fnGetAllParamCustData,
8368 ITypeInfo2_fnGetAllVarCustData,
8369 ITypeInfo2_fnGetAllImplTypeCustData,
8372 /******************************************************************************
8373 * CreateDispTypeInfo [OLEAUT32.31]
8375 * Build type information for an object so it can be called through an
8376 * IDispatch interface.
8378 * RETURNS
8379 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8380 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8382 * NOTES
8383 * This call allows an objects methods to be accessed through IDispatch, by
8384 * building an ITypeInfo object that IDispatch can use to call through.
8386 HRESULT WINAPI CreateDispTypeInfo(
8387 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
8388 LCID lcid, /* [I] Locale Id */
8389 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
8391 ITypeInfoImpl *pTIClass, *pTIIface;
8392 ITypeLibImpl *pTypeLibImpl;
8393 unsigned int param, func;
8394 TLBFuncDesc *pFuncDesc;
8395 TLBRefType *ref;
8397 TRACE("\n");
8398 pTypeLibImpl = TypeLibImpl_Constructor();
8399 if (!pTypeLibImpl) return E_FAIL;
8401 pTypeLibImpl->TypeInfoCount = 2;
8402 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
8404 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
8405 pTIIface->pTypeLib = pTypeLibImpl;
8406 pTIIface->index = 0;
8407 pTIIface->Name = NULL;
8408 pTIIface->dwHelpContext = -1;
8409 pTIIface->guid = NULL;
8410 pTIIface->lcid = lcid;
8411 pTIIface->typekind = TKIND_INTERFACE;
8412 pTIIface->wMajorVerNum = 0;
8413 pTIIface->wMinorVerNum = 0;
8414 pTIIface->cbAlignment = 2;
8415 pTIIface->cbSizeInstance = -1;
8416 pTIIface->cbSizeVft = -1;
8417 pTIIface->cFuncs = 0;
8418 pTIIface->cImplTypes = 0;
8419 pTIIface->cVars = 0;
8420 pTIIface->wTypeFlags = 0;
8421 pTIIface->hreftype = 0;
8423 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers);
8424 pFuncDesc = pTIIface->funcdescs;
8425 for(func = 0; func < pidata->cMembers; func++) {
8426 METHODDATA *md = pidata->pmethdata + func;
8427 pFuncDesc->Name = TLB_append_str(&pTypeLibImpl->name_list, md->szName);
8428 pFuncDesc->funcdesc.memid = md->dispid;
8429 pFuncDesc->funcdesc.lprgscode = NULL;
8430 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
8431 pFuncDesc->funcdesc.invkind = md->wFlags;
8432 pFuncDesc->funcdesc.callconv = md->cc;
8433 pFuncDesc->funcdesc.cParams = md->cArgs;
8434 pFuncDesc->funcdesc.cParamsOpt = 0;
8435 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
8436 pFuncDesc->funcdesc.cScodes = 0;
8437 pFuncDesc->funcdesc.wFuncFlags = 0;
8438 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
8439 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
8440 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
8441 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8442 md->cArgs * sizeof(ELEMDESC));
8443 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
8444 for(param = 0; param < md->cArgs; param++) {
8445 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
8446 pFuncDesc->pParamDesc[param].Name = TLB_append_str(&pTypeLibImpl->name_list, md->ppdata[param].szName);
8448 pFuncDesc->helpcontext = 0;
8449 pFuncDesc->HelpStringContext = 0;
8450 pFuncDesc->HelpString = NULL;
8451 pFuncDesc->Entry = NULL;
8452 list_init(&pFuncDesc->custdata_list);
8453 pTIIface->cFuncs++;
8454 ++pFuncDesc;
8457 dump_TypeInfo(pTIIface);
8459 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
8460 pTIClass->pTypeLib = pTypeLibImpl;
8461 pTIClass->index = 1;
8462 pTIClass->Name = NULL;
8463 pTIClass->dwHelpContext = -1;
8464 pTIClass->guid = NULL;
8465 pTIClass->lcid = lcid;
8466 pTIClass->typekind = TKIND_COCLASS;
8467 pTIClass->wMajorVerNum = 0;
8468 pTIClass->wMinorVerNum = 0;
8469 pTIClass->cbAlignment = 2;
8470 pTIClass->cbSizeInstance = -1;
8471 pTIClass->cbSizeVft = -1;
8472 pTIClass->cFuncs = 0;
8473 pTIClass->cImplTypes = 1;
8474 pTIClass->cVars = 0;
8475 pTIClass->wTypeFlags = 0;
8476 pTIClass->hreftype = sizeof(MSFT_TypeInfoBase);
8478 pTIClass->impltypes = TLBImplType_Alloc(1);
8480 ref = heap_alloc_zero(sizeof(*ref));
8481 ref->pImpTLInfo = TLB_REF_INTERNAL;
8482 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
8484 dump_TypeInfo(pTIClass);
8486 *pptinfo = (ITypeInfo *)&pTIClass->ITypeInfo2_iface;
8488 ITypeInfo_AddRef(*pptinfo);
8489 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
8491 return S_OK;
8495 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
8497 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8499 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, ppv);
8502 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
8504 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8506 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
8509 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
8511 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8513 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
8516 static HRESULT WINAPI ITypeComp_fnBind(
8517 ITypeComp * iface,
8518 OLECHAR * szName,
8519 ULONG lHash,
8520 WORD wFlags,
8521 ITypeInfo ** ppTInfo,
8522 DESCKIND * pDescKind,
8523 BINDPTR * pBindPtr)
8525 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8526 const TLBFuncDesc *pFDesc;
8527 const TLBVarDesc *pVDesc;
8528 HRESULT hr = DISP_E_MEMBERNOTFOUND;
8529 UINT fdc;
8531 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8533 *pDescKind = DESCKIND_NONE;
8534 pBindPtr->lpfuncdesc = NULL;
8535 *ppTInfo = NULL;
8537 for(fdc = 0; fdc < This->cFuncs; ++fdc){
8538 pFDesc = &This->funcdescs[fdc];
8539 if (!lstrcmpiW(TLB_get_bstr(pFDesc->Name), szName)) {
8540 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
8541 break;
8542 else
8543 /* name found, but wrong flags */
8544 hr = TYPE_E_TYPEMISMATCH;
8548 if (fdc < This->cFuncs)
8550 HRESULT hr = TLB_AllocAndInitFuncDesc(
8551 &pFDesc->funcdesc,
8552 &pBindPtr->lpfuncdesc,
8553 This->typekind == TKIND_DISPATCH);
8554 if (FAILED(hr))
8555 return hr;
8556 *pDescKind = DESCKIND_FUNCDESC;
8557 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8558 ITypeInfo_AddRef(*ppTInfo);
8559 return S_OK;
8560 } else {
8561 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->cVars, szName);
8562 if(pVDesc){
8563 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
8564 if (FAILED(hr))
8565 return hr;
8566 *pDescKind = DESCKIND_VARDESC;
8567 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8568 ITypeInfo_AddRef(*ppTInfo);
8569 return S_OK;
8573 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
8574 /* recursive search */
8575 ITypeInfo *pTInfo;
8576 ITypeComp *pTComp;
8577 HRESULT hr;
8578 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
8579 if (SUCCEEDED(hr))
8581 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
8582 ITypeInfo_Release(pTInfo);
8584 if (SUCCEEDED(hr))
8586 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8587 ITypeComp_Release(pTComp);
8588 if (SUCCEEDED(hr) && *pDescKind == DESCKIND_FUNCDESC &&
8589 This->typekind == TKIND_DISPATCH)
8591 FUNCDESC *tmp = pBindPtr->lpfuncdesc;
8592 hr = TLB_AllocAndInitFuncDesc(tmp, &pBindPtr->lpfuncdesc, TRUE);
8593 SysFreeString((BSTR)tmp);
8595 return hr;
8597 WARN("Could not search inherited interface!\n");
8599 if (hr == DISP_E_MEMBERNOTFOUND)
8600 hr = S_OK;
8601 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
8602 return hr;
8605 static HRESULT WINAPI ITypeComp_fnBindType(
8606 ITypeComp * iface,
8607 OLECHAR * szName,
8608 ULONG lHash,
8609 ITypeInfo ** ppTInfo,
8610 ITypeComp ** ppTComp)
8612 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
8614 /* strange behaviour (does nothing) but like the
8615 * original */
8617 if (!ppTInfo || !ppTComp)
8618 return E_POINTER;
8620 *ppTInfo = NULL;
8621 *ppTComp = NULL;
8623 return S_OK;
8626 static const ITypeCompVtbl tcompvt =
8629 ITypeComp_fnQueryInterface,
8630 ITypeComp_fnAddRef,
8631 ITypeComp_fnRelease,
8633 ITypeComp_fnBind,
8634 ITypeComp_fnBindType
8637 HRESULT WINAPI CreateTypeLib2(SYSKIND syskind, LPCOLESTR szFile,
8638 ICreateTypeLib2** ppctlib)
8640 ITypeLibImpl *This;
8641 HRESULT hres;
8643 TRACE("(%d,%s,%p)\n", syskind, debugstr_w(szFile), ppctlib);
8645 if (!szFile) return E_INVALIDARG;
8647 This = TypeLibImpl_Constructor();
8648 if (!This)
8649 return E_OUTOFMEMORY;
8651 This->lcid = GetSystemDefaultLCID();
8652 This->syskind = syskind;
8653 This->ptr_size = get_ptr_size(syskind);
8655 This->path = heap_alloc((lstrlenW(szFile) + 1) * sizeof(WCHAR));
8656 if (!This->path) {
8657 ITypeLib2_Release(&This->ITypeLib2_iface);
8658 return E_OUTOFMEMORY;
8660 lstrcpyW(This->path, szFile);
8662 hres = ITypeLib2_QueryInterface(&This->ITypeLib2_iface, &IID_ICreateTypeLib2, (LPVOID*)ppctlib);
8663 ITypeLib2_Release(&This->ITypeLib2_iface);
8664 return hres;
8667 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
8668 REFIID riid, void **object)
8670 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8672 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, object);
8675 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
8677 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8679 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
8682 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
8684 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8686 return ITypeLib2_Release(&This->ITypeLib2_iface);
8689 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
8690 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
8692 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8693 ITypeInfoImpl *info;
8694 HRESULT hres;
8696 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo);
8698 if (!ctinfo || !name)
8699 return E_INVALIDARG;
8701 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, name);
8702 if (info)
8703 return TYPE_E_NAMECONFLICT;
8705 if (This->typeinfos)
8706 This->typeinfos = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->typeinfos,
8707 sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1));
8708 else
8709 This->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*));
8711 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor();
8713 info->pTypeLib = This;
8714 info->Name = TLB_append_str(&This->name_list, name);
8715 info->index = This->TypeInfoCount;
8716 info->typekind = kind;
8717 info->cbAlignment = 4;
8719 switch(info->typekind) {
8720 case TKIND_ENUM:
8721 case TKIND_INTERFACE:
8722 case TKIND_DISPATCH:
8723 case TKIND_COCLASS:
8724 info->cbSizeInstance = This->ptr_size;
8725 break;
8726 case TKIND_RECORD:
8727 case TKIND_UNION:
8728 info->cbSizeInstance = 0;
8729 break;
8730 case TKIND_MODULE:
8731 info->cbSizeInstance = 2;
8732 break;
8733 case TKIND_ALIAS:
8734 info->cbSizeInstance = -0x75;
8735 break;
8736 default:
8737 FIXME("unrecognized typekind %d\n", info->typekind);
8738 info->cbSizeInstance = 0xdeadbeef;
8739 break;
8742 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface,
8743 &IID_ICreateTypeInfo, (void **)ctinfo);
8744 if (FAILED(hres)) {
8745 ITypeInfo2_Release(&info->ITypeInfo2_iface);
8746 return hres;
8749 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase);
8751 ++This->TypeInfoCount;
8753 return S_OK;
8756 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
8757 LPOLESTR name)
8759 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8761 TRACE("%p %s\n", This, wine_dbgstr_w(name));
8763 if (!name)
8764 return E_INVALIDARG;
8766 This->Name = TLB_append_str(&This->name_list, name);
8768 return S_OK;
8771 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
8772 WORD majorVerNum, WORD minorVerNum)
8774 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8776 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
8778 This->ver_major = majorVerNum;
8779 This->ver_minor = minorVerNum;
8781 return S_OK;
8784 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
8785 REFGUID guid)
8787 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8789 TRACE("%p %s\n", This, debugstr_guid(guid));
8791 This->guid = TLB_append_guid(&This->guid_list, guid, -2);
8793 return S_OK;
8796 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
8797 LPOLESTR doc)
8799 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8801 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
8803 if (!doc)
8804 return E_INVALIDARG;
8806 This->DocString = TLB_append_str(&This->string_list, doc);
8808 return S_OK;
8811 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
8812 LPOLESTR helpFileName)
8814 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8816 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
8818 if (!helpFileName)
8819 return E_INVALIDARG;
8821 This->HelpFile = TLB_append_str(&This->string_list, helpFileName);
8823 return S_OK;
8826 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
8827 DWORD helpContext)
8829 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8831 TRACE("%p %d\n", This, helpContext);
8833 This->dwHelpContext = helpContext;
8835 return S_OK;
8838 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
8839 LCID lcid)
8841 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8843 TRACE("%p %x\n", This, lcid);
8845 This->set_lcid = lcid;
8847 return S_OK;
8850 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
8851 UINT libFlags)
8853 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8855 TRACE("%p %x\n", This, libFlags);
8857 This->libflags = libFlags;
8859 return S_OK;
8862 typedef struct tagWMSFT_SegContents {
8863 DWORD len;
8864 void *data;
8865 } WMSFT_SegContents;
8867 typedef struct tagWMSFT_TLBFile {
8868 MSFT_Header header;
8869 WMSFT_SegContents typeinfo_seg;
8870 WMSFT_SegContents impfile_seg;
8871 WMSFT_SegContents impinfo_seg;
8872 WMSFT_SegContents ref_seg;
8873 WMSFT_SegContents guidhash_seg;
8874 WMSFT_SegContents guid_seg;
8875 WMSFT_SegContents namehash_seg;
8876 WMSFT_SegContents name_seg;
8877 WMSFT_SegContents string_seg;
8878 WMSFT_SegContents typdesc_seg;
8879 WMSFT_SegContents arraydesc_seg;
8880 WMSFT_SegContents custdata_seg;
8881 WMSFT_SegContents cdguids_seg;
8882 MSFT_SegDir segdir;
8883 WMSFT_SegContents aux_seg;
8884 } WMSFT_TLBFile;
8886 static HRESULT WMSFT_compile_strings(ITypeLibImpl *This,
8887 WMSFT_TLBFile *file)
8889 TLBString *str;
8890 UINT last_offs;
8891 char *data;
8893 file->string_seg.len = 0;
8894 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8895 int size;
8897 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str), NULL, 0, NULL, NULL);
8898 if (size == 0)
8899 return E_UNEXPECTED;
8901 size += sizeof(INT16);
8902 if (size % 4)
8903 size = (size + 4) & ~0x3;
8904 if (size < 8)
8905 size = 8;
8907 file->string_seg.len += size;
8909 /* temporarily use str->offset to store the length of the aligned,
8910 * converted string */
8911 str->offset = size;
8914 file->string_seg.data = data = heap_alloc(file->string_seg.len);
8916 last_offs = 0;
8917 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8918 int size;
8920 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8921 data + sizeof(INT16), file->string_seg.len - last_offs - sizeof(INT16), NULL, NULL);
8922 if (size == 0) {
8923 heap_free(file->string_seg.data);
8924 return E_UNEXPECTED;
8927 *((INT16*)data) = size;
8929 memset(data + sizeof(INT16) + size, 0x57, str->offset - size - sizeof(INT16));
8931 size = str->offset;
8932 data += size;
8933 str->offset = last_offs;
8934 last_offs += size;
8937 return S_OK;
8940 static HRESULT WMSFT_compile_names(ITypeLibImpl *This,
8941 WMSFT_TLBFile *file)
8943 TLBString *str;
8944 UINT last_offs;
8945 char *data;
8946 MSFT_NameIntro *last_intro = NULL;
8948 file->header.nametablecount = 0;
8949 file->header.nametablechars = 0;
8951 file->name_seg.len = 0;
8952 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8953 int size;
8955 size = strlenW(str->str);
8956 file->header.nametablechars += size;
8957 file->header.nametablecount++;
8959 size = WideCharToMultiByte(CP_ACP, 0, str->str, size, NULL, 0, NULL, NULL);
8960 if (size == 0)
8961 return E_UNEXPECTED;
8963 size += sizeof(MSFT_NameIntro);
8964 if (size % 4)
8965 size = (size + 4) & ~0x3;
8966 if (size < 8)
8967 size = 8;
8969 file->name_seg.len += size;
8971 /* temporarily use str->offset to store the length of the aligned,
8972 * converted string */
8973 str->offset = size;
8976 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
8977 file->name_seg.data = data = heap_alloc(file->name_seg.len+1);
8979 last_offs = 0;
8980 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8981 int size, hash;
8982 MSFT_NameIntro *intro = (MSFT_NameIntro*)data;
8984 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8985 data + sizeof(MSFT_NameIntro),
8986 file->name_seg.len - last_offs - sizeof(MSFT_NameIntro), NULL, NULL);
8987 if (size == 0) {
8988 heap_free(file->name_seg.data);
8989 return E_UNEXPECTED;
8991 data[sizeof(MSFT_NameIntro) + size] = '\0';
8993 intro->hreftype = -1; /* TODO? */
8994 intro->namelen = size & 0xFF;
8995 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
8996 hash = LHashValOfNameSysA(This->syskind, This->lcid, data + sizeof(MSFT_NameIntro));
8997 intro->namelen |= hash << 16;
8998 intro->next_hash = ((DWORD*)file->namehash_seg.data)[hash & 0x7f];
8999 ((DWORD*)file->namehash_seg.data)[hash & 0x7f] = last_offs;
9001 memset(data + sizeof(MSFT_NameIntro) + size, 0x57,
9002 str->offset - size - sizeof(MSFT_NameIntro));
9004 /* update str->offset to actual value to use in other
9005 * compilation functions that require positions within
9006 * the string table */
9007 last_intro = intro;
9008 size = str->offset;
9009 data += size;
9010 str->offset = last_offs;
9011 last_offs += size;
9014 if(last_intro)
9015 last_intro->hreftype = 0; /* last one is 0? */
9017 return S_OK;
9020 static inline int hash_guid(GUID *guid)
9022 int i, hash = 0;
9024 for (i = 0; i < 8; i ++)
9025 hash ^= ((const short *)guid)[i];
9027 return hash & 0x1f;
9030 static HRESULT WMSFT_compile_guids(ITypeLibImpl *This, WMSFT_TLBFile *file)
9032 TLBGuid *guid;
9033 MSFT_GuidEntry *entry;
9034 DWORD offs;
9035 int hash_key, *guidhashtab;
9037 file->guid_seg.len = sizeof(MSFT_GuidEntry) * list_count(&This->guid_list);
9038 file->guid_seg.data = heap_alloc(file->guid_seg.len);
9040 entry = file->guid_seg.data;
9041 offs = 0;
9042 guidhashtab = file->guidhash_seg.data;
9043 LIST_FOR_EACH_ENTRY(guid, &This->guid_list, TLBGuid, entry){
9044 memcpy(&entry->guid, &guid->guid, sizeof(GUID));
9045 entry->hreftype = guid->hreftype;
9047 hash_key = hash_guid(&guid->guid);
9048 entry->next_hash = guidhashtab[hash_key];
9049 guidhashtab[hash_key] = offs;
9051 guid->offset = offs;
9052 offs += sizeof(MSFT_GuidEntry);
9053 ++entry;
9056 return S_OK;
9059 static DWORD WMSFT_encode_variant(VARIANT *value, WMSFT_TLBFile *file)
9061 VARIANT v = *value;
9062 VARTYPE arg_type = V_VT(value);
9063 int mask = 0;
9064 HRESULT hres;
9065 DWORD ret = file->custdata_seg.len;
9067 if(arg_type == VT_INT)
9068 arg_type = VT_I4;
9069 if(arg_type == VT_UINT)
9070 arg_type = VT_UI4;
9072 v = *value;
9073 if(V_VT(value) != arg_type) {
9074 hres = VariantChangeType(&v, value, 0, arg_type);
9075 if(FAILED(hres)){
9076 ERR("VariantChangeType failed: %08x\n", hres);
9077 return -1;
9081 /* Check if default value can be stored in-place */
9082 switch(arg_type){
9083 case VT_I4:
9084 case VT_UI4:
9085 mask = 0x3ffffff;
9086 if(V_UI4(&v) > 0x3ffffff)
9087 break;
9088 /* fall through */
9089 case VT_I1:
9090 case VT_UI1:
9091 case VT_BOOL:
9092 if(!mask)
9093 mask = 0xff;
9094 /* fall through */
9095 case VT_I2:
9096 case VT_UI2:
9097 if(!mask)
9098 mask = 0xffff;
9099 return ((0x80 + 0x4 * V_VT(value)) << 24) | (V_UI4(&v) & mask);
9102 /* have to allocate space in custdata_seg */
9103 switch(arg_type) {
9104 case VT_I4:
9105 case VT_R4:
9106 case VT_UI4:
9107 case VT_INT:
9108 case VT_UINT:
9109 case VT_HRESULT:
9110 case VT_PTR: {
9111 /* Construct the data to be allocated */
9112 int *data;
9114 if(file->custdata_seg.data){
9115 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + sizeof(int) * 2);
9116 data = (int *)(((char *)file->custdata_seg.data) + file->custdata_seg.len);
9117 file->custdata_seg.len += sizeof(int) * 2;
9118 }else{
9119 file->custdata_seg.len = sizeof(int) * 2;
9120 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9123 data[0] = V_VT(value) + (V_UI4(&v) << 16);
9124 data[1] = (V_UI4(&v) >> 16) + 0x57570000;
9126 /* TODO: Check if the encoded data is already present in custdata_seg */
9128 return ret;
9131 case VT_BSTR: {
9132 int i, len = (6+SysStringLen(V_BSTR(&v))+3) & ~0x3;
9133 char *data;
9135 if(file->custdata_seg.data){
9136 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + len);
9137 data = ((char *)file->custdata_seg.data) + file->custdata_seg.len;
9138 file->custdata_seg.len += len;
9139 }else{
9140 file->custdata_seg.len = len;
9141 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9144 *((unsigned short *)data) = V_VT(value);
9145 *((unsigned int *)(data+2)) = SysStringLen(V_BSTR(&v));
9146 for(i=0; i<SysStringLen(V_BSTR(&v)); i++) {
9147 if(V_BSTR(&v)[i] <= 0x7f)
9148 data[i+6] = V_BSTR(&v)[i];
9149 else
9150 data[i+6] = '?';
9152 WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], len-6, NULL, NULL);
9153 for(i=6+SysStringLen(V_BSTR(&v)); i<len; i++)
9154 data[i] = 0x57;
9156 /* TODO: Check if the encoded data is already present in custdata_seg */
9158 return ret;
9160 default:
9161 FIXME("Argument type not yet handled\n");
9162 return -1;
9166 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size);
9168 static DWORD WMSFT_append_arraydesc(ARRAYDESC *desc, WMSFT_TLBFile *file)
9170 DWORD offs = file->arraydesc_seg.len;
9171 DWORD *encoded;
9172 USHORT i;
9174 /* TODO: we should check for duplicates, but that's harder because each
9175 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9176 * at the library-level) */
9178 file->arraydesc_seg.len += (2 + desc->cDims * 2) * sizeof(DWORD);
9179 if(!file->arraydesc_seg.data)
9180 file->arraydesc_seg.data = heap_alloc(file->arraydesc_seg.len);
9181 else
9182 file->arraydesc_seg.data = heap_realloc(file->arraydesc_seg.data, file->arraydesc_seg.len);
9183 encoded = (DWORD*)((char *)file->arraydesc_seg.data + offs);
9185 encoded[0] = WMSFT_append_typedesc(&desc->tdescElem, file, NULL, NULL);
9186 encoded[1] = desc->cDims | ((desc->cDims * 2 * sizeof(DWORD)) << 16);
9187 for(i = 0; i < desc->cDims; ++i){
9188 encoded[2 + i * 2] = desc->rgbounds[i].cElements;
9189 encoded[2 + i * 2 + 1] = desc->rgbounds[i].lLbound;
9192 return offs;
9195 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size)
9197 DWORD junk;
9198 INT16 junk2;
9199 DWORD offs = 0;
9200 DWORD encoded[2];
9201 VARTYPE vt, subtype;
9202 char *data;
9204 if(!desc)
9205 return -1;
9207 if(!out_mix)
9208 out_mix = &junk;
9209 if(!out_size)
9210 out_size = &junk2;
9212 vt = desc->vt & VT_TYPEMASK;
9214 if(vt == VT_PTR || vt == VT_SAFEARRAY){
9215 DWORD mix;
9216 encoded[1] = WMSFT_append_typedesc(desc->u.lptdesc, file, &mix, out_size);
9217 encoded[0] = desc->vt | ((mix | VT_BYREF) << 16);
9218 *out_mix = 0x7FFF;
9219 *out_size += 2 * sizeof(DWORD);
9220 }else if(vt == VT_CARRAY){
9221 encoded[0] = desc->vt | (0x7FFE << 16);
9222 encoded[1] = WMSFT_append_arraydesc(desc->u.lpadesc, file);
9223 *out_mix = 0x7FFE;
9224 }else if(vt == VT_USERDEFINED){
9225 encoded[0] = desc->vt | (0x7FFF << 16);
9226 encoded[1] = desc->u.hreftype;
9227 *out_mix = 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9228 }else{
9229 TRACE("Mixing in-place, VT: 0x%x\n", desc->vt);
9231 switch(vt){
9232 case VT_INT:
9233 subtype = VT_I4;
9234 break;
9235 case VT_UINT:
9236 subtype = VT_UI4;
9237 break;
9238 case VT_VOID:
9239 subtype = VT_EMPTY;
9240 break;
9241 default:
9242 subtype = vt;
9243 break;
9246 *out_mix = subtype;
9247 return 0x80000000 | (subtype << 16) | desc->vt;
9250 data = file->typdesc_seg.data;
9251 while(offs < file->typdesc_seg.len){
9252 if(!memcmp(&data[offs], encoded, sizeof(encoded)))
9253 return offs;
9254 offs += sizeof(encoded);
9257 file->typdesc_seg.len += sizeof(encoded);
9258 if(!file->typdesc_seg.data)
9259 data = file->typdesc_seg.data = heap_alloc(file->typdesc_seg.len);
9260 else
9261 data = file->typdesc_seg.data = heap_realloc(file->typdesc_seg.data, file->typdesc_seg.len);
9263 memcpy(&data[offs], encoded, sizeof(encoded));
9265 return offs;
9268 static DWORD WMSFT_compile_custdata(struct list *custdata_list, WMSFT_TLBFile *file)
9270 WMSFT_SegContents *cdguids_seg = &file->cdguids_seg;
9271 DWORD ret = cdguids_seg->len, offs;
9272 MSFT_CDGuid *cdguid = cdguids_seg->data;
9273 TLBCustData *cd;
9275 if(list_empty(custdata_list))
9276 return -1;
9278 cdguids_seg->len += sizeof(MSFT_CDGuid) * list_count(custdata_list);
9279 if(!cdguids_seg->data){
9280 cdguid = cdguids_seg->data = heap_alloc(cdguids_seg->len);
9281 }else
9282 cdguids_seg->data = heap_realloc(cdguids_seg->data, cdguids_seg->len);
9284 offs = ret + sizeof(MSFT_CDGuid);
9285 LIST_FOR_EACH_ENTRY(cd, custdata_list, TLBCustData, entry){
9286 cdguid->GuidOffset = cd->guid->offset;
9287 cdguid->DataOffset = WMSFT_encode_variant(&cd->data, file);
9288 cdguid->next = offs;
9289 offs += sizeof(MSFT_CDGuid);
9290 ++cdguid;
9293 --cdguid;
9294 cdguid->next = -1;
9296 return ret;
9299 static DWORD WMSFT_compile_typeinfo_aux(ITypeInfoImpl *info,
9300 WMSFT_TLBFile *file)
9302 WMSFT_SegContents *aux_seg = &file->aux_seg;
9303 DWORD ret = aux_seg->len, i, j, recorded_size = 0, extra_size = 0;
9304 MSFT_VarRecord *varrecord;
9305 MSFT_FuncRecord *funcrecord;
9306 MEMBERID *memid;
9307 DWORD *name, *offsets, offs;
9309 for(i = 0; i < info->cFuncs; ++i){
9310 TLBFuncDesc *desc = &info->funcdescs[i];
9312 recorded_size += 6 * sizeof(INT); /* mandatory fields */
9314 /* optional fields */
9315 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9316 if(!list_empty(&desc->custdata_list))
9317 recorded_size += 7 * sizeof(INT);
9318 else if(desc->HelpStringContext != 0)
9319 recorded_size += 6 * sizeof(INT);
9320 /* res9? resA? */
9321 else if(desc->Entry)
9322 recorded_size += 3 * sizeof(INT);
9323 else if(desc->HelpString)
9324 recorded_size += 2 * sizeof(INT);
9325 else if(desc->helpcontext)
9326 recorded_size += sizeof(INT);
9328 recorded_size += desc->funcdesc.cParams * sizeof(MSFT_ParameterInfo);
9330 for(j = 0; j < desc->funcdesc.cParams; ++j){
9331 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9332 recorded_size += desc->funcdesc.cParams * sizeof(INT);
9333 break;
9337 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9340 for(i = 0; i < info->cVars; ++i){
9341 TLBVarDesc *desc = &info->vardescs[i];
9343 recorded_size += 5 * sizeof(INT); /* mandatory fields */
9345 /* optional fields */
9346 if(desc->HelpStringContext != 0)
9347 recorded_size += 5 * sizeof(INT);
9348 else if(!list_empty(&desc->custdata_list))
9349 recorded_size += 4 * sizeof(INT);
9350 /* res9? */
9351 else if(desc->HelpString)
9352 recorded_size += 2 * sizeof(INT);
9353 else if(desc->HelpContext != 0)
9354 recorded_size += sizeof(INT);
9356 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9359 if(!recorded_size && !extra_size)
9360 return ret;
9362 extra_size += sizeof(INT); /* total aux size for this typeinfo */
9364 aux_seg->len += recorded_size + extra_size;
9366 aux_seg->len += sizeof(INT) * (info->cVars + info->cFuncs); /* offsets at the end */
9368 if(aux_seg->data)
9369 aux_seg->data = heap_realloc(aux_seg->data, aux_seg->len);
9370 else
9371 aux_seg->data = heap_alloc(aux_seg->len);
9373 *((DWORD*)((char *)aux_seg->data + ret)) = recorded_size;
9375 offsets = (DWORD*)((char *)aux_seg->data + ret + recorded_size + extra_size);
9376 offs = 0;
9378 funcrecord = (MSFT_FuncRecord*)(((char *)aux_seg->data) + ret + sizeof(INT));
9379 for(i = 0; i < info->cFuncs; ++i){
9380 TLBFuncDesc *desc = &info->funcdescs[i];
9381 DWORD size = 6 * sizeof(INT), paramdefault_size = 0, *paramdefault;
9383 funcrecord->funcdescsize = sizeof(desc->funcdesc) + desc->funcdesc.cParams * sizeof(ELEMDESC);
9384 funcrecord->DataType = WMSFT_append_typedesc(&desc->funcdesc.elemdescFunc.tdesc, file, NULL, &funcrecord->funcdescsize);
9385 funcrecord->Flags = desc->funcdesc.wFuncFlags;
9386 funcrecord->VtableOffset = desc->funcdesc.oVft;
9388 /* FKCCIC:
9389 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9390 * ^^^funckind
9391 * ^^^ ^invkind
9392 * ^has_cust_data
9393 * ^^^^callconv
9394 * ^has_param_defaults
9395 * ^oEntry_is_intresource
9397 funcrecord->FKCCIC =
9398 desc->funcdesc.funckind |
9399 (desc->funcdesc.invkind << 3) |
9400 (list_empty(&desc->custdata_list) ? 0 : 0x80) |
9401 (desc->funcdesc.callconv << 8);
9403 if(desc->Entry && desc->Entry != (TLBString*)-1 && IS_INTRESOURCE(desc->Entry))
9404 funcrecord->FKCCIC |= 0x2000;
9406 for(j = 0; j < desc->funcdesc.cParams; ++j){
9407 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9408 paramdefault_size = sizeof(INT) * desc->funcdesc.cParams;
9409 funcrecord->funcdescsize += sizeof(PARAMDESCEX);
9412 if(paramdefault_size > 0)
9413 funcrecord->FKCCIC |= 0x1000;
9415 funcrecord->nrargs = desc->funcdesc.cParams;
9416 funcrecord->nroargs = desc->funcdesc.cParamsOpt;
9418 /* optional fields */
9419 /* res9? resA? */
9420 if(!list_empty(&desc->custdata_list)){
9421 size += 7 * sizeof(INT);
9422 funcrecord->HelpContext = desc->helpcontext;
9423 if(desc->HelpString)
9424 funcrecord->oHelpString = desc->HelpString->offset;
9425 else
9426 funcrecord->oHelpString = -1;
9427 if(!desc->Entry)
9428 funcrecord->oEntry = -1;
9429 else if(IS_INTRESOURCE(desc->Entry))
9430 funcrecord->oEntry = LOWORD(desc->Entry);
9431 else
9432 funcrecord->oEntry = desc->Entry->offset;
9433 funcrecord->res9 = -1;
9434 funcrecord->resA = -1;
9435 funcrecord->HelpStringContext = desc->HelpStringContext;
9436 funcrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9437 }else if(desc->HelpStringContext != 0){
9438 size += 6 * sizeof(INT);
9439 funcrecord->HelpContext = desc->helpcontext;
9440 if(desc->HelpString)
9441 funcrecord->oHelpString = desc->HelpString->offset;
9442 else
9443 funcrecord->oHelpString = -1;
9444 if(!desc->Entry)
9445 funcrecord->oEntry = -1;
9446 else if(IS_INTRESOURCE(desc->Entry))
9447 funcrecord->oEntry = LOWORD(desc->Entry);
9448 else
9449 funcrecord->oEntry = desc->Entry->offset;
9450 funcrecord->res9 = -1;
9451 funcrecord->resA = -1;
9452 funcrecord->HelpStringContext = desc->HelpStringContext;
9453 }else if(desc->Entry){
9454 size += 3 * sizeof(INT);
9455 funcrecord->HelpContext = desc->helpcontext;
9456 if(desc->HelpString)
9457 funcrecord->oHelpString = desc->HelpString->offset;
9458 else
9459 funcrecord->oHelpString = -1;
9460 if(!desc->Entry)
9461 funcrecord->oEntry = -1;
9462 else if(IS_INTRESOURCE(desc->Entry))
9463 funcrecord->oEntry = LOWORD(desc->Entry);
9464 else
9465 funcrecord->oEntry = desc->Entry->offset;
9466 }else if(desc->HelpString){
9467 size += 2 * sizeof(INT);
9468 funcrecord->HelpContext = desc->helpcontext;
9469 funcrecord->oHelpString = desc->HelpString->offset;
9470 }else if(desc->helpcontext){
9471 size += sizeof(INT);
9472 funcrecord->HelpContext = desc->helpcontext;
9475 paramdefault = (DWORD*)((char *)funcrecord + size);
9476 size += paramdefault_size;
9478 for(j = 0; j < desc->funcdesc.cParams; ++j){
9479 MSFT_ParameterInfo *info = (MSFT_ParameterInfo*)(((char *)funcrecord) + size);
9481 info->DataType = WMSFT_append_typedesc(&desc->funcdesc.lprgelemdescParam[j].tdesc, file, NULL, &funcrecord->funcdescsize);
9482 if(desc->pParamDesc[j].Name)
9483 info->oName = desc->pParamDesc[j].Name->offset;
9484 else
9485 info->oName = -1;
9486 info->Flags = desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags;
9488 if(paramdefault_size){
9489 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
9490 *paramdefault = WMSFT_encode_variant(&desc->funcdesc.lprgelemdescParam[j].u.paramdesc.pparamdescex->varDefaultValue, file);
9491 else if(paramdefault_size)
9492 *paramdefault = -1;
9493 ++paramdefault;
9496 size += sizeof(MSFT_ParameterInfo);
9499 funcrecord->Info = size | (i << 16); /* is it just the index? */
9501 *offsets = offs;
9502 offs += size;
9503 ++offsets;
9505 funcrecord = (MSFT_FuncRecord*)(((char*)funcrecord) + size);
9508 varrecord = (MSFT_VarRecord*)funcrecord;
9509 for(i = 0; i < info->cVars; ++i){
9510 TLBVarDesc *desc = &info->vardescs[i];
9511 DWORD size = 5 * sizeof(INT);
9513 varrecord->vardescsize = sizeof(desc->vardesc);
9514 varrecord->DataType = WMSFT_append_typedesc(&desc->vardesc.elemdescVar.tdesc, file, NULL, &varrecord->vardescsize);
9515 varrecord->Flags = desc->vardesc.wVarFlags;
9516 varrecord->VarKind = desc->vardesc.varkind;
9518 if(desc->vardesc.varkind == VAR_CONST){
9519 varrecord->vardescsize += sizeof(VARIANT);
9520 varrecord->OffsValue = WMSFT_encode_variant(desc->vardesc.u.lpvarValue, file);
9521 }else
9522 varrecord->OffsValue = desc->vardesc.u.oInst;
9524 /* res9? */
9525 if(desc->HelpStringContext != 0){
9526 size += 5 * sizeof(INT);
9527 varrecord->HelpContext = desc->HelpContext;
9528 if(desc->HelpString)
9529 varrecord->HelpString = desc->HelpString->offset;
9530 else
9531 varrecord->HelpString = -1;
9532 varrecord->res9 = -1;
9533 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9534 varrecord->HelpStringContext = desc->HelpStringContext;
9535 }else if(!list_empty(&desc->custdata_list)){
9536 size += 4 * sizeof(INT);
9537 varrecord->HelpContext = desc->HelpContext;
9538 if(desc->HelpString)
9539 varrecord->HelpString = desc->HelpString->offset;
9540 else
9541 varrecord->HelpString = -1;
9542 varrecord->res9 = -1;
9543 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9544 }else if(desc->HelpString){
9545 size += 2 * sizeof(INT);
9546 varrecord->HelpContext = desc->HelpContext;
9547 if(desc->HelpString)
9548 varrecord->HelpString = desc->HelpString->offset;
9549 else
9550 varrecord->HelpString = -1;
9551 }else if(desc->HelpContext != 0){
9552 size += sizeof(INT);
9553 varrecord->HelpContext = desc->HelpContext;
9556 varrecord->Info = size | (i << 16);
9558 *offsets = offs;
9559 offs += size;
9560 ++offsets;
9562 varrecord = (MSFT_VarRecord*)(((char*)varrecord) + size);
9565 memid = (MEMBERID*)varrecord;
9566 for(i = 0; i < info->cFuncs; ++i){
9567 TLBFuncDesc *desc = &info->funcdescs[i];
9568 *memid = desc->funcdesc.memid;
9569 ++memid;
9571 for(i = 0; i < info->cVars; ++i){
9572 TLBVarDesc *desc = &info->vardescs[i];
9573 *memid = desc->vardesc.memid;
9574 ++memid;
9577 name = (UINT*)memid;
9578 for(i = 0; i < info->cFuncs; ++i){
9579 TLBFuncDesc *desc = &info->funcdescs[i];
9580 if(desc->Name)
9581 *name = desc->Name->offset;
9582 else
9583 *name = -1;
9584 ++name;
9586 for(i = 0; i < info->cVars; ++i){
9587 TLBVarDesc *desc = &info->vardescs[i];
9588 if(desc->Name)
9589 *name = desc->Name->offset;
9590 else
9591 *name = -1;
9592 ++name;
9595 return ret;
9598 typedef struct tagWMSFT_RefChunk {
9599 DWORD href;
9600 DWORD res04;
9601 DWORD res08;
9602 DWORD next;
9603 } WMSFT_RefChunk;
9605 static DWORD WMSFT_compile_typeinfo_ref(ITypeInfoImpl *info, WMSFT_TLBFile *file)
9607 DWORD offs = file->ref_seg.len, i;
9608 WMSFT_RefChunk *chunk;
9610 file->ref_seg.len += info->cImplTypes * sizeof(WMSFT_RefChunk);
9611 if(!file->ref_seg.data)
9612 file->ref_seg.data = heap_alloc(file->ref_seg.len);
9613 else
9614 file->ref_seg.data = heap_realloc(file->ref_seg.data, file->ref_seg.len);
9616 chunk = (WMSFT_RefChunk*)((char*)file->ref_seg.data + offs);
9618 for(i = 0; i < info->cImplTypes; ++i){
9619 chunk->href = info->impltypes[i].hRef;
9620 chunk->res04 = info->impltypes[i].implflags;
9621 chunk->res08 = -1;
9622 if(i < info->cImplTypes - 1)
9623 chunk->next = offs + sizeof(WMSFT_RefChunk) * (i + 1);
9624 else
9625 chunk->next = -1;
9626 ++chunk;
9629 return offs;
9632 static DWORD WMSFT_compile_typeinfo(ITypeInfoImpl *info, INT16 index, WMSFT_TLBFile *file, char *data)
9634 DWORD size;
9636 size = sizeof(MSFT_TypeInfoBase);
9638 if(data){
9639 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase*)data;
9640 if(info->wTypeFlags & TYPEFLAG_FDUAL)
9641 base->typekind = TKIND_DISPATCH;
9642 else
9643 base->typekind = info->typekind;
9644 base->typekind |= index << 16; /* TODO: There are some other flags here */
9645 base->typekind |= (info->cbAlignment << 11) | (info->cbAlignment << 6);
9646 base->memoffset = WMSFT_compile_typeinfo_aux(info, file);
9647 base->res2 = 0;
9648 base->res3 = 0;
9649 base->res4 = 3;
9650 base->res5 = 0;
9651 base->cElement = (info->cVars << 16) | info->cFuncs;
9652 base->res7 = 0;
9653 base->res8 = 0;
9654 base->res9 = 0;
9655 base->resA = 0;
9656 if(info->guid)
9657 base->posguid = info->guid->offset;
9658 else
9659 base->posguid = -1;
9660 base->flags = info->wTypeFlags;
9661 if(info->Name) {
9662 base->NameOffset = info->Name->offset;
9664 ((unsigned char*)file->name_seg.data)[info->Name->offset+9] = 0x38;
9665 *(HREFTYPE*)((unsigned char*)file->name_seg.data+info->Name->offset) = info->hreftype;
9666 }else {
9667 base->NameOffset = -1;
9669 base->version = (info->wMinorVerNum << 16) | info->wMajorVerNum;
9670 if(info->DocString)
9671 base->docstringoffs = info->DocString->offset;
9672 else
9673 base->docstringoffs = -1;
9674 base->helpstringcontext = info->dwHelpStringContext;
9675 base->helpcontext = info->dwHelpContext;
9676 base->oCustData = WMSFT_compile_custdata(info->pcustdata_list, file);
9677 base->cImplTypes = info->cImplTypes;
9678 base->cbSizeVft = info->cbSizeVft;
9679 base->size = info->cbSizeInstance;
9680 if(info->typekind == TKIND_COCLASS){
9681 base->datatype1 = WMSFT_compile_typeinfo_ref(info, file);
9682 }else if(info->typekind == TKIND_ALIAS){
9683 base->datatype1 = WMSFT_append_typedesc(info->tdescAlias, file, NULL, NULL);
9684 }else if(info->typekind == TKIND_MODULE){
9685 if(info->DllName)
9686 base->datatype1 = info->DllName->offset;
9687 else
9688 base->datatype1 = -1;
9689 }else{
9690 if(info->cImplTypes > 0)
9691 base->datatype1 = info->impltypes[0].hRef;
9692 else
9693 base->datatype1 = -1;
9695 base->datatype2 = index; /* FIXME: i think there's more here */
9696 base->res18 = 0;
9697 base->res19 = -1;
9700 return size;
9703 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl *This, WMSFT_TLBFile *file, DWORD *junk)
9705 UINT i;
9707 file->typeinfo_seg.len = 0;
9708 for(i = 0; i < This->TypeInfoCount; ++i){
9709 ITypeInfoImpl *info = This->typeinfos[i];
9710 *junk = file->typeinfo_seg.len;
9711 ++junk;
9712 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, NULL, NULL);
9715 file->typeinfo_seg.data = heap_alloc(file->typeinfo_seg.len);
9716 memset(file->typeinfo_seg.data, 0x96, file->typeinfo_seg.len);
9718 file->aux_seg.len = 0;
9719 file->aux_seg.data = NULL;
9721 file->typeinfo_seg.len = 0;
9722 for(i = 0; i < This->TypeInfoCount; ++i){
9723 ITypeInfoImpl *info = This->typeinfos[i];
9724 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, file,
9725 ((char *)file->typeinfo_seg.data) + file->typeinfo_seg.len);
9729 typedef struct tagWMSFT_ImpFile {
9730 INT guid_offs;
9731 LCID lcid;
9732 DWORD version;
9733 } WMSFT_ImpFile;
9735 static void WMSFT_compile_impfile(ITypeLibImpl *This, WMSFT_TLBFile *file)
9737 TLBImpLib *implib;
9738 WMSFT_ImpFile *impfile;
9739 char *data;
9740 DWORD last_offs = 0;
9742 file->impfile_seg.len = 0;
9743 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9744 int size = 0;
9746 if(implib->name){
9747 WCHAR *path = strrchrW(implib->name, '\\');
9748 if(path)
9749 ++path;
9750 else
9751 path = implib->name;
9752 size = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path), NULL, 0, NULL, NULL);
9753 if (size == 0)
9754 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9757 size += sizeof(INT16);
9758 if (size % 4)
9759 size = (size + 4) & ~0x3;
9760 if (size < 8)
9761 size = 8;
9763 file->impfile_seg.len += sizeof(WMSFT_ImpFile) + size;
9766 data = file->impfile_seg.data = heap_alloc(file->impfile_seg.len);
9768 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9769 int strlen = 0, size;
9771 impfile = (WMSFT_ImpFile*)data;
9772 impfile->guid_offs = implib->guid->offset;
9773 impfile->lcid = implib->lcid;
9774 impfile->version = (implib->wVersionMinor << 16) | implib->wVersionMajor;
9776 data += sizeof(WMSFT_ImpFile);
9778 if(implib->name){
9779 WCHAR *path= strrchrW(implib->name, '\\');
9780 if(path)
9781 ++path;
9782 else
9783 path = implib->name;
9784 strlen = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path),
9785 data + sizeof(INT16), file->impfile_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9786 if (strlen == 0)
9787 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9790 *((INT16*)data) = (strlen << 2) | 1; /* FIXME: is that a flag, or what? */
9792 size = strlen + sizeof(INT16);
9793 if (size % 4)
9794 size = (size + 4) & ~0x3;
9795 if (size < 8)
9796 size = 8;
9797 memset(data + sizeof(INT16) + strlen, 0x57, size - strlen - sizeof(INT16));
9799 data += size;
9800 implib->offset = last_offs;
9801 last_offs += size + sizeof(WMSFT_ImpFile);
9805 static void WMSFT_compile_impinfo(ITypeLibImpl *This, WMSFT_TLBFile *file)
9807 MSFT_ImpInfo *info;
9808 TLBRefType *ref_type;
9809 UINT i = 0;
9811 WMSFT_compile_impfile(This, file);
9813 file->impinfo_seg.len = sizeof(MSFT_ImpInfo) * list_count(&This->ref_list);
9814 info = file->impinfo_seg.data = heap_alloc(file->impinfo_seg.len);
9816 LIST_FOR_EACH_ENTRY(ref_type, &This->ref_list, TLBRefType, entry){
9817 info->flags = i | ((ref_type->tkind & 0xFF) << 24);
9818 if(ref_type->index == TLB_REF_USE_GUID){
9819 info->flags |= MSFT_IMPINFO_OFFSET_IS_GUID;
9820 info->oGuid = ref_type->guid->offset;
9821 }else
9822 info->oGuid = ref_type->index;
9823 info->oImpFile = ref_type->pImpTLInfo->offset;
9824 ++i;
9825 ++info;
9829 static void WMSFT_compile_guidhash(ITypeLibImpl *This, WMSFT_TLBFile *file)
9831 file->guidhash_seg.len = 0x80;
9832 file->guidhash_seg.data = heap_alloc(file->guidhash_seg.len);
9833 memset(file->guidhash_seg.data, 0xFF, file->guidhash_seg.len);
9836 static void WMSFT_compile_namehash(ITypeLibImpl *This, WMSFT_TLBFile *file)
9838 file->namehash_seg.len = 0x200;
9839 file->namehash_seg.data = heap_alloc(file->namehash_seg.len);
9840 memset(file->namehash_seg.data, 0xFF, file->namehash_seg.len);
9843 static void tmp_fill_segdir_seg(MSFT_pSeg *segdir, WMSFT_SegContents *contents, DWORD *running_offset)
9845 if(contents && contents->len){
9846 segdir->offset = *running_offset;
9847 segdir->length = contents->len;
9848 *running_offset += segdir->length;
9849 }else{
9850 segdir->offset = -1;
9851 segdir->length = 0;
9854 /* TODO: do these ever change? */
9855 segdir->res08 = -1;
9856 segdir->res0c = 0xf;
9859 static void WMSFT_write_segment(HANDLE outfile, WMSFT_SegContents *segment)
9861 DWORD written;
9862 if(segment)
9863 WriteFile(outfile, segment->data, segment->len, &written, NULL);
9866 static HRESULT WMSFT_fixup_typeinfos(ITypeLibImpl *This, WMSFT_TLBFile *file,
9867 DWORD file_len)
9869 DWORD i;
9870 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase *)file->typeinfo_seg.data;
9872 for(i = 0; i < This->TypeInfoCount; ++i){
9873 base->memoffset += file_len;
9874 ++base;
9877 return S_OK;
9880 static void WMSFT_free_file(WMSFT_TLBFile *file)
9882 HeapFree(GetProcessHeap(), 0, file->typeinfo_seg.data);
9883 HeapFree(GetProcessHeap(), 0, file->guidhash_seg.data);
9884 HeapFree(GetProcessHeap(), 0, file->guid_seg.data);
9885 HeapFree(GetProcessHeap(), 0, file->ref_seg.data);
9886 HeapFree(GetProcessHeap(), 0, file->impinfo_seg.data);
9887 HeapFree(GetProcessHeap(), 0, file->impfile_seg.data);
9888 HeapFree(GetProcessHeap(), 0, file->namehash_seg.data);
9889 HeapFree(GetProcessHeap(), 0, file->name_seg.data);
9890 HeapFree(GetProcessHeap(), 0, file->string_seg.data);
9891 HeapFree(GetProcessHeap(), 0, file->typdesc_seg.data);
9892 HeapFree(GetProcessHeap(), 0, file->arraydesc_seg.data);
9893 HeapFree(GetProcessHeap(), 0, file->custdata_seg.data);
9894 HeapFree(GetProcessHeap(), 0, file->cdguids_seg.data);
9895 HeapFree(GetProcessHeap(), 0, file->aux_seg.data);
9898 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
9900 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9901 WMSFT_TLBFile file;
9902 DWORD written, junk_size, junk_offs, running_offset;
9903 BOOL br;
9904 HANDLE outfile;
9905 HRESULT hres;
9906 DWORD *junk;
9907 UINT i;
9909 TRACE("%p\n", This);
9911 for(i = 0; i < This->TypeInfoCount; ++i)
9912 if(This->typeinfos[i]->needs_layout)
9913 ICreateTypeInfo2_LayOut(&This->typeinfos[i]->ICreateTypeInfo2_iface);
9915 memset(&file, 0, sizeof(file));
9917 file.header.magic1 = 0x5446534D;
9918 file.header.magic2 = 0x00010002;
9919 file.header.lcid = This->set_lcid ? This->set_lcid : MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
9920 file.header.lcid2 = This->set_lcid;
9921 file.header.varflags = 0x40 | This->syskind;
9922 if (This->HelpFile)
9923 file.header.varflags |= 0x10;
9924 if (This->HelpStringDll)
9925 file.header.varflags |= HELPDLLFLAG;
9926 file.header.version = (This->ver_minor << 16) | This->ver_major;
9927 file.header.flags = This->libflags;
9928 file.header.helpstringcontext = 0; /* TODO - SetHelpStringContext not implemented yet */
9929 file.header.helpcontext = This->dwHelpContext;
9930 file.header.res44 = 0x20;
9931 file.header.res48 = 0x80;
9932 file.header.dispatchpos = This->dispatch_href;
9934 WMSFT_compile_namehash(This, &file);
9935 /* do name and string compilation to get offsets for other compilations */
9936 hres = WMSFT_compile_names(This, &file);
9937 if (FAILED(hres)){
9938 WMSFT_free_file(&file);
9939 return hres;
9942 hres = WMSFT_compile_strings(This, &file);
9943 if (FAILED(hres)){
9944 WMSFT_free_file(&file);
9945 return hres;
9948 WMSFT_compile_guidhash(This, &file);
9949 hres = WMSFT_compile_guids(This, &file);
9950 if (FAILED(hres)){
9951 WMSFT_free_file(&file);
9952 return hres;
9955 if(This->HelpFile)
9956 file.header.helpfile = This->HelpFile->offset;
9957 else
9958 file.header.helpfile = -1;
9960 if(This->DocString)
9961 file.header.helpstring = This->DocString->offset;
9962 else
9963 file.header.helpstring = -1;
9965 /* do some more segment compilation */
9966 file.header.nimpinfos = list_count(&This->ref_list);
9967 file.header.nrtypeinfos = This->TypeInfoCount;
9969 if(This->Name)
9970 file.header.NameOffset = This->Name->offset;
9971 else
9972 file.header.NameOffset = -1;
9974 file.header.CustomDataOffset = -1; /* TODO SetCustData not impl yet */
9976 if(This->guid)
9977 file.header.posguid = This->guid->offset;
9978 else
9979 file.header.posguid = -1;
9981 junk_size = file.header.nrtypeinfos * sizeof(DWORD);
9982 if(file.header.varflags & HELPDLLFLAG)
9983 junk_size += sizeof(DWORD);
9984 if(junk_size){
9985 junk = heap_alloc_zero(junk_size);
9986 if(file.header.varflags & HELPDLLFLAG){
9987 *junk = This->HelpStringDll->offset;
9988 junk_offs = 1;
9989 }else
9990 junk_offs = 0;
9991 }else{
9992 junk = NULL;
9993 junk_offs = 0;
9996 WMSFT_compile_typeinfo_seg(This, &file, junk + junk_offs);
9997 WMSFT_compile_impinfo(This, &file);
9999 running_offset = 0;
10001 TRACE("header at: 0x%x\n", running_offset);
10002 running_offset += sizeof(file.header);
10004 TRACE("junk at: 0x%x\n", running_offset);
10005 running_offset += junk_size;
10007 TRACE("segdir at: 0x%x\n", running_offset);
10008 running_offset += sizeof(file.segdir);
10010 TRACE("typeinfo at: 0x%x\n", running_offset);
10011 tmp_fill_segdir_seg(&file.segdir.pTypeInfoTab, &file.typeinfo_seg, &running_offset);
10013 TRACE("guidhashtab at: 0x%x\n", running_offset);
10014 tmp_fill_segdir_seg(&file.segdir.pGuidHashTab, &file.guidhash_seg, &running_offset);
10016 TRACE("guidtab at: 0x%x\n", running_offset);
10017 tmp_fill_segdir_seg(&file.segdir.pGuidTab, &file.guid_seg, &running_offset);
10019 TRACE("reftab at: 0x%x\n", running_offset);
10020 tmp_fill_segdir_seg(&file.segdir.pRefTab, &file.ref_seg, &running_offset);
10022 TRACE("impinfo at: 0x%x\n", running_offset);
10023 tmp_fill_segdir_seg(&file.segdir.pImpInfo, &file.impinfo_seg, &running_offset);
10025 TRACE("impfiles at: 0x%x\n", running_offset);
10026 tmp_fill_segdir_seg(&file.segdir.pImpFiles, &file.impfile_seg, &running_offset);
10028 TRACE("namehashtab at: 0x%x\n", running_offset);
10029 tmp_fill_segdir_seg(&file.segdir.pNameHashTab, &file.namehash_seg, &running_offset);
10031 TRACE("nametab at: 0x%x\n", running_offset);
10032 tmp_fill_segdir_seg(&file.segdir.pNametab, &file.name_seg, &running_offset);
10034 TRACE("stringtab at: 0x%x\n", running_offset);
10035 tmp_fill_segdir_seg(&file.segdir.pStringtab, &file.string_seg, &running_offset);
10037 TRACE("typdesc at: 0x%x\n", running_offset);
10038 tmp_fill_segdir_seg(&file.segdir.pTypdescTab, &file.typdesc_seg, &running_offset);
10040 TRACE("arraydescriptions at: 0x%x\n", running_offset);
10041 tmp_fill_segdir_seg(&file.segdir.pArrayDescriptions, &file.arraydesc_seg, &running_offset);
10043 TRACE("custdata at: 0x%x\n", running_offset);
10044 tmp_fill_segdir_seg(&file.segdir.pCustData, &file.custdata_seg, &running_offset);
10046 TRACE("cdguids at: 0x%x\n", running_offset);
10047 tmp_fill_segdir_seg(&file.segdir.pCDGuids, &file.cdguids_seg, &running_offset);
10049 TRACE("res0e at: 0x%x\n", running_offset);
10050 tmp_fill_segdir_seg(&file.segdir.res0e, NULL, &running_offset);
10052 TRACE("res0f at: 0x%x\n", running_offset);
10053 tmp_fill_segdir_seg(&file.segdir.res0f, NULL, &running_offset);
10055 TRACE("aux_seg at: 0x%x\n", running_offset);
10057 WMSFT_fixup_typeinfos(This, &file, running_offset);
10059 outfile = CreateFileW(This->path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
10060 FILE_ATTRIBUTE_NORMAL, 0);
10061 if (outfile == INVALID_HANDLE_VALUE){
10062 WMSFT_free_file(&file);
10063 heap_free(junk);
10064 return TYPE_E_IOERROR;
10067 br = WriteFile(outfile, &file.header, sizeof(file.header), &written, NULL);
10068 if (!br) {
10069 WMSFT_free_file(&file);
10070 CloseHandle(outfile);
10071 heap_free(junk);
10072 return TYPE_E_IOERROR;
10075 br = WriteFile(outfile, junk, junk_size, &written, NULL);
10076 heap_free(junk);
10077 if (!br) {
10078 WMSFT_free_file(&file);
10079 CloseHandle(outfile);
10080 return TYPE_E_IOERROR;
10083 br = WriteFile(outfile, &file.segdir, sizeof(file.segdir), &written, NULL);
10084 if (!br) {
10085 WMSFT_free_file(&file);
10086 CloseHandle(outfile);
10087 return TYPE_E_IOERROR;
10090 WMSFT_write_segment(outfile, &file.typeinfo_seg);
10091 WMSFT_write_segment(outfile, &file.guidhash_seg);
10092 WMSFT_write_segment(outfile, &file.guid_seg);
10093 WMSFT_write_segment(outfile, &file.ref_seg);
10094 WMSFT_write_segment(outfile, &file.impinfo_seg);
10095 WMSFT_write_segment(outfile, &file.impfile_seg);
10096 WMSFT_write_segment(outfile, &file.namehash_seg);
10097 WMSFT_write_segment(outfile, &file.name_seg);
10098 WMSFT_write_segment(outfile, &file.string_seg);
10099 WMSFT_write_segment(outfile, &file.typdesc_seg);
10100 WMSFT_write_segment(outfile, &file.arraydesc_seg);
10101 WMSFT_write_segment(outfile, &file.custdata_seg);
10102 WMSFT_write_segment(outfile, &file.cdguids_seg);
10103 WMSFT_write_segment(outfile, &file.aux_seg);
10105 WMSFT_free_file(&file);
10107 CloseHandle(outfile);
10109 return S_OK;
10112 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
10113 LPOLESTR name)
10115 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10116 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
10117 return E_NOTIMPL;
10120 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
10121 REFGUID guid, VARIANT *varVal)
10123 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10124 FIXME("%p %s %p - stub\n", This, debugstr_guid(guid), varVal);
10125 return E_NOTIMPL;
10128 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
10129 ULONG helpStringContext)
10131 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10132 FIXME("%p %u - stub\n", This, helpStringContext);
10133 return E_NOTIMPL;
10136 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
10137 LPOLESTR filename)
10139 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10140 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
10142 if (!filename)
10143 return E_INVALIDARG;
10145 This->HelpStringDll = TLB_append_str(&This->string_list, filename);
10147 return S_OK;
10150 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
10151 ICreateTypeLib2_fnQueryInterface,
10152 ICreateTypeLib2_fnAddRef,
10153 ICreateTypeLib2_fnRelease,
10154 ICreateTypeLib2_fnCreateTypeInfo,
10155 ICreateTypeLib2_fnSetName,
10156 ICreateTypeLib2_fnSetVersion,
10157 ICreateTypeLib2_fnSetGuid,
10158 ICreateTypeLib2_fnSetDocString,
10159 ICreateTypeLib2_fnSetHelpFileName,
10160 ICreateTypeLib2_fnSetHelpContext,
10161 ICreateTypeLib2_fnSetLcid,
10162 ICreateTypeLib2_fnSetLibFlags,
10163 ICreateTypeLib2_fnSaveAllChanges,
10164 ICreateTypeLib2_fnDeleteTypeInfo,
10165 ICreateTypeLib2_fnSetCustData,
10166 ICreateTypeLib2_fnSetHelpStringContext,
10167 ICreateTypeLib2_fnSetHelpStringDll
10170 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
10171 REFIID riid, void **object)
10173 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10175 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, object);
10178 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
10180 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10182 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
10185 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
10187 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10189 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
10192 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
10193 REFGUID guid)
10195 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10197 TRACE("%p %s\n", This, debugstr_guid(guid));
10199 This->guid = TLB_append_guid(&This->pTypeLib->guid_list, guid, This->hreftype);
10201 return S_OK;
10204 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
10205 UINT typeFlags)
10207 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10208 WORD old_flags;
10209 HRESULT hres;
10211 TRACE("%p %x\n", This, typeFlags);
10213 if (typeFlags & TYPEFLAG_FDUAL) {
10214 static const WCHAR stdole2tlb[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10215 ITypeLib *stdole;
10216 ITypeInfo *dispatch;
10217 HREFTYPE hreftype;
10218 HRESULT hres;
10220 hres = LoadTypeLib(stdole2tlb, &stdole);
10221 if(FAILED(hres))
10222 return hres;
10224 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
10225 ITypeLib_Release(stdole);
10226 if(FAILED(hres))
10227 return hres;
10229 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
10230 ITypeInfo_Release(dispatch);
10231 if(FAILED(hres))
10232 return hres;
10235 old_flags = This->wTypeFlags;
10236 This->wTypeFlags = typeFlags;
10238 hres = ICreateTypeInfo2_LayOut(iface);
10239 if (FAILED(hres)) {
10240 This->wTypeFlags = old_flags;
10241 return hres;
10244 return S_OK;
10247 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
10248 LPOLESTR doc)
10250 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10252 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
10254 if (!doc)
10255 return E_INVALIDARG;
10257 This->DocString = TLB_append_str(&This->pTypeLib->string_list, doc);
10259 return S_OK;
10262 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
10263 DWORD helpContext)
10265 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10267 TRACE("%p %d\n", This, helpContext);
10269 This->dwHelpContext = helpContext;
10271 return S_OK;
10274 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
10275 WORD majorVerNum, WORD minorVerNum)
10277 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10279 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
10281 This->wMajorVerNum = majorVerNum;
10282 This->wMinorVerNum = minorVerNum;
10284 return S_OK;
10287 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
10288 ITypeInfo *typeInfo, HREFTYPE *refType)
10290 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10291 UINT index;
10292 ITypeLib *container;
10293 TLBRefType *ref_type;
10294 TLBImpLib *implib;
10295 TYPEATTR *typeattr;
10296 TLIBATTR *libattr;
10297 HRESULT hres;
10299 TRACE("%p %p %p\n", This, typeInfo, refType);
10301 if (!typeInfo || !refType)
10302 return E_INVALIDARG;
10304 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
10305 if (FAILED(hres))
10306 return hres;
10308 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
10309 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
10311 ITypeLib_Release(container);
10313 *refType = target->hreftype;
10315 return S_OK;
10318 hres = ITypeLib_GetLibAttr(container, &libattr);
10319 if (FAILED(hres)) {
10320 ITypeLib_Release(container);
10321 return hres;
10324 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
10325 if(IsEqualGUID(&implib->guid->guid, &libattr->guid) &&
10326 implib->lcid == libattr->lcid &&
10327 implib->wVersionMajor == libattr->wMajorVerNum &&
10328 implib->wVersionMinor == libattr->wMinorVerNum)
10329 break;
10332 if(&implib->entry == &This->pTypeLib->implib_list){
10333 implib = heap_alloc_zero(sizeof(TLBImpLib));
10335 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
10336 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
10337 implib->name = SysAllocString(our_container->path);
10338 }else{
10339 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
10340 libattr->wMinorVerNum, libattr->lcid, &implib->name);
10341 if(FAILED(hres)){
10342 implib->name = NULL;
10343 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres);
10347 implib->guid = TLB_append_guid(&This->pTypeLib->guid_list, &libattr->guid, 2);
10348 implib->lcid = libattr->lcid;
10349 implib->wVersionMajor = libattr->wMajorVerNum;
10350 implib->wVersionMinor = libattr->wMinorVerNum;
10352 list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
10355 ITypeLib_ReleaseTLibAttr(container, libattr);
10356 ITypeLib_Release(container);
10358 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
10359 if (FAILED(hres))
10360 return hres;
10362 index = 0;
10363 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
10364 if(ref_type->index == TLB_REF_USE_GUID &&
10365 IsEqualGUID(&ref_type->guid->guid, &typeattr->guid) &&
10366 ref_type->tkind == typeattr->typekind)
10367 break;
10368 ++index;
10371 if(&ref_type->entry == &This->pTypeLib->ref_list){
10372 ref_type = heap_alloc_zero(sizeof(TLBRefType));
10374 ref_type->tkind = typeattr->typekind;
10375 ref_type->pImpTLInfo = implib;
10376 ref_type->reference = index * sizeof(MSFT_ImpInfo);
10378 ref_type->index = TLB_REF_USE_GUID;
10380 ref_type->guid = TLB_append_guid(&This->pTypeLib->guid_list, &typeattr->guid, ref_type->reference+1);
10382 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
10385 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
10387 *refType = ref_type->reference | 0x1;
10389 if(IsEqualGUID(&ref_type->guid->guid, &IID_IDispatch))
10390 This->pTypeLib->dispatch_href = *refType;
10392 return S_OK;
10395 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
10396 UINT index, FUNCDESC *funcDesc)
10398 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10399 TLBFuncDesc tmp_func_desc, *func_desc;
10400 int buf_size, i;
10401 char *buffer;
10402 HRESULT hres;
10404 TRACE("%p %u %p\n", This, index, funcDesc);
10406 if (!funcDesc || funcDesc->oVft & 3)
10407 return E_INVALIDARG;
10409 switch (This->typekind) {
10410 case TKIND_MODULE:
10411 if (funcDesc->funckind != FUNC_STATIC)
10412 return TYPE_E_BADMODULEKIND;
10413 break;
10414 case TKIND_DISPATCH:
10415 if (funcDesc->funckind != FUNC_DISPATCH)
10416 return TYPE_E_BADMODULEKIND;
10417 break;
10418 default:
10419 if (funcDesc->funckind != FUNC_PUREVIRTUAL)
10420 return TYPE_E_BADMODULEKIND;
10423 if (index > This->cFuncs)
10424 return TYPE_E_ELEMENTNOTFOUND;
10426 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) &&
10427 !funcDesc->cParams)
10428 return TYPE_E_INCONSISTENTPROPFUNCS;
10430 #ifdef _WIN64
10431 if(This->pTypeLib->syskind == SYS_WIN64 &&
10432 funcDesc->oVft % 8 != 0)
10433 return E_INVALIDARG;
10434 #endif
10436 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc));
10437 TLBFuncDesc_Constructor(&tmp_func_desc);
10439 tmp_func_desc.funcdesc = *funcDesc;
10441 if (tmp_func_desc.funcdesc.oVft != 0)
10442 tmp_func_desc.funcdesc.oVft |= 1;
10444 if (funcDesc->cScodes) {
10445 tmp_func_desc.funcdesc.lprgscode = heap_alloc(sizeof(SCODE) * funcDesc->cScodes);
10446 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes);
10447 } else
10448 tmp_func_desc.funcdesc.lprgscode = NULL;
10450 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc);
10451 for (i = 0; i < funcDesc->cParams; ++i) {
10452 buf_size += sizeof(ELEMDESC);
10453 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i);
10455 tmp_func_desc.funcdesc.lprgelemdescParam = heap_alloc(buf_size);
10456 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams);
10458 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer);
10459 if (FAILED(hres)) {
10460 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10461 heap_free(tmp_func_desc.funcdesc.lprgscode);
10462 return hres;
10465 for (i = 0; i < funcDesc->cParams; ++i) {
10466 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i,
10467 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer);
10468 if (FAILED(hres)) {
10469 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10470 heap_free(tmp_func_desc.funcdesc.lprgscode);
10471 return hres;
10473 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT &&
10474 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT &&
10475 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){
10476 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
10477 if (FAILED(hres)) {
10478 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10479 heap_free(tmp_func_desc.funcdesc.lprgscode);
10480 return hres;
10485 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams);
10487 if (This->funcdescs) {
10488 This->funcdescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->funcdescs,
10489 sizeof(TLBFuncDesc) * (This->cFuncs + 1));
10491 if (index < This->cFuncs) {
10492 memmove(This->funcdescs + index + 1, This->funcdescs + index,
10493 (This->cFuncs - index) * sizeof(TLBFuncDesc));
10494 func_desc = This->funcdescs + index;
10495 } else
10496 func_desc = This->funcdescs + This->cFuncs;
10498 /* move custdata lists to the new memory location */
10499 for(i = 0; i < This->cFuncs + 1; ++i){
10500 if(index != i){
10501 TLBFuncDesc *fd = &This->funcdescs[i];
10502 if(fd->custdata_list.prev == fd->custdata_list.next)
10503 list_init(&fd->custdata_list);
10504 else{
10505 fd->custdata_list.prev->next = &fd->custdata_list;
10506 fd->custdata_list.next->prev = &fd->custdata_list;
10510 } else
10511 func_desc = This->funcdescs = heap_alloc(sizeof(TLBFuncDesc));
10513 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc));
10514 list_init(&func_desc->custdata_list);
10516 ++This->cFuncs;
10518 This->needs_layout = TRUE;
10520 return S_OK;
10523 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
10524 UINT index, HREFTYPE refType)
10526 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10527 TLBImplType *impl_type;
10528 HRESULT hres;
10530 TRACE("%p %u %d\n", This, index, refType);
10532 switch(This->typekind){
10533 case TKIND_COCLASS: {
10534 if (index == -1) {
10535 FIXME("Unhandled index: -1\n");
10536 return E_NOTIMPL;
10539 if(index != This->cImplTypes)
10540 return TYPE_E_ELEMENTNOTFOUND;
10542 break;
10544 case TKIND_INTERFACE:
10545 case TKIND_DISPATCH:
10546 if (index != 0 || This->cImplTypes)
10547 return TYPE_E_ELEMENTNOTFOUND;
10548 break;
10549 default:
10550 FIXME("Unimplemented typekind: %d\n", This->typekind);
10551 return E_NOTIMPL;
10554 if (This->impltypes){
10555 UINT i;
10557 This->impltypes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->impltypes,
10558 sizeof(TLBImplType) * (This->cImplTypes + 1));
10560 if (index < This->cImplTypes) {
10561 memmove(This->impltypes + index + 1, This->impltypes + index,
10562 (This->cImplTypes - index) * sizeof(TLBImplType));
10563 impl_type = This->impltypes + index;
10564 } else
10565 impl_type = This->impltypes + This->cImplTypes;
10567 /* move custdata lists to the new memory location */
10568 for(i = 0; i < This->cImplTypes + 1; ++i){
10569 if(index != i){
10570 TLBImplType *it = &This->impltypes[i];
10571 if(it->custdata_list.prev == it->custdata_list.next)
10572 list_init(&it->custdata_list);
10573 else{
10574 it->custdata_list.prev->next = &it->custdata_list;
10575 it->custdata_list.next->prev = &it->custdata_list;
10579 } else
10580 impl_type = This->impltypes = heap_alloc(sizeof(TLBImplType));
10582 memset(impl_type, 0, sizeof(TLBImplType));
10583 TLBImplType_Constructor(impl_type);
10584 impl_type->hRef = refType;
10586 ++This->cImplTypes;
10588 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
10589 This->wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
10591 hres = ICreateTypeInfo2_LayOut(iface);
10592 if (FAILED(hres))
10593 return hres;
10595 return S_OK;
10598 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
10599 UINT index, INT implTypeFlags)
10601 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10602 TLBImplType *impl_type = &This->impltypes[index];
10604 TRACE("%p %u %x\n", This, index, implTypeFlags);
10606 if (This->typekind != TKIND_COCLASS)
10607 return TYPE_E_BADMODULEKIND;
10609 if (index >= This->cImplTypes)
10610 return TYPE_E_ELEMENTNOTFOUND;
10612 impl_type->implflags = implTypeFlags;
10614 return S_OK;
10617 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
10618 WORD alignment)
10620 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10622 TRACE("%p %d\n", This, alignment);
10624 This->cbAlignment = alignment;
10626 return S_OK;
10629 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
10630 LPOLESTR schema)
10632 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10634 TRACE("%p %s\n", This, wine_dbgstr_w(schema));
10636 if (!schema)
10637 return E_INVALIDARG;
10639 This->Schema = TLB_append_str(&This->pTypeLib->string_list, schema);
10641 This->lpstrSchema = This->Schema->str;
10643 return S_OK;
10646 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
10647 UINT index, VARDESC *varDesc)
10649 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10650 TLBVarDesc *var_desc;
10652 TRACE("%p %u %p\n", This, index, varDesc);
10654 if (This->vardescs){
10655 UINT i;
10657 This->vardescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->vardescs,
10658 sizeof(TLBVarDesc) * (This->cVars + 1));
10660 if (index < This->cVars) {
10661 memmove(This->vardescs + index + 1, This->vardescs + index,
10662 (This->cVars - index) * sizeof(TLBVarDesc));
10663 var_desc = This->vardescs + index;
10664 } else
10665 var_desc = This->vardescs + This->cVars;
10667 /* move custdata lists to the new memory location */
10668 for(i = 0; i < This->cVars + 1; ++i){
10669 if(index != i){
10670 TLBVarDesc *var = &This->vardescs[i];
10671 if(var->custdata_list.prev == var->custdata_list.next)
10672 list_init(&var->custdata_list);
10673 else{
10674 var->custdata_list.prev->next = &var->custdata_list;
10675 var->custdata_list.next->prev = &var->custdata_list;
10679 } else
10680 var_desc = This->vardescs = heap_alloc_zero(sizeof(TLBVarDesc));
10682 TLBVarDesc_Constructor(var_desc);
10683 TLB_AllocAndInitVarDesc(varDesc, &var_desc->vardesc_create);
10684 var_desc->vardesc = *var_desc->vardesc_create;
10686 ++This->cVars;
10688 This->needs_layout = TRUE;
10690 return S_OK;
10693 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
10694 UINT index, LPOLESTR *names, UINT numNames)
10696 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10697 TLBFuncDesc *func_desc = &This->funcdescs[index];
10698 int i;
10700 TRACE("%p %u %p %u\n", This, index, names, numNames);
10702 if (!names)
10703 return E_INVALIDARG;
10705 if (index >= This->cFuncs || numNames == 0)
10706 return TYPE_E_ELEMENTNOTFOUND;
10708 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){
10709 if(numNames > func_desc->funcdesc.cParams)
10710 return TYPE_E_ELEMENTNOTFOUND;
10711 } else
10712 if(numNames > func_desc->funcdesc.cParams + 1)
10713 return TYPE_E_ELEMENTNOTFOUND;
10715 for(i = 0; i < This->cFuncs; ++i) {
10716 TLBFuncDesc *iter = &This->funcdescs[i];
10717 if (iter->Name && !strcmpW(TLB_get_bstr(iter->Name), *names)) {
10718 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10719 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10720 func_desc->funcdesc.invkind != iter->funcdesc.invkind)
10721 continue;
10722 return TYPE_E_AMBIGUOUSNAME;
10726 func_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *names);
10728 for (i = 1; i < numNames; ++i) {
10729 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1;
10730 par_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *(names + i));
10733 return S_OK;
10736 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
10737 UINT index, LPOLESTR name)
10739 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10741 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(name));
10743 if(!name)
10744 return E_INVALIDARG;
10746 if(index >= This->cVars)
10747 return TYPE_E_ELEMENTNOTFOUND;
10749 This->vardescs[index].Name = TLB_append_str(&This->pTypeLib->name_list, name);
10750 return S_OK;
10753 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
10754 TYPEDESC *tdescAlias)
10756 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10757 HRESULT hr;
10759 TRACE("%p %p\n", This, tdescAlias);
10761 if(!tdescAlias)
10762 return E_INVALIDARG;
10764 if(This->typekind != TKIND_ALIAS)
10765 return TYPE_E_BADMODULEKIND;
10767 hr = TLB_size_instance(This, This->pTypeLib->syskind, tdescAlias, &This->cbSizeInstance, &This->cbAlignment);
10768 if(FAILED(hr))
10769 return hr;
10771 heap_free(This->tdescAlias);
10772 This->tdescAlias = heap_alloc(TLB_SizeTypeDesc(tdescAlias, TRUE));
10773 TLB_CopyTypeDesc(NULL, tdescAlias, This->tdescAlias);
10775 return S_OK;
10778 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
10779 UINT index, LPOLESTR dllName, LPOLESTR procName)
10781 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10782 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
10783 return E_NOTIMPL;
10786 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
10787 UINT index, LPOLESTR docString)
10789 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10790 TLBFuncDesc *func_desc = &This->funcdescs[index];
10792 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10794 if(!docString)
10795 return E_INVALIDARG;
10797 if(index >= This->cFuncs)
10798 return TYPE_E_ELEMENTNOTFOUND;
10800 func_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10802 return S_OK;
10805 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
10806 UINT index, LPOLESTR docString)
10808 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10809 TLBVarDesc *var_desc = &This->vardescs[index];
10811 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10813 if(!docString)
10814 return E_INVALIDARG;
10816 if(index >= This->cVars)
10817 return TYPE_E_ELEMENTNOTFOUND;
10819 var_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10821 return S_OK;
10824 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
10825 UINT index, DWORD helpContext)
10827 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10828 TLBFuncDesc *func_desc = &This->funcdescs[index];
10830 TRACE("%p %u %d\n", This, index, helpContext);
10832 if(index >= This->cFuncs)
10833 return TYPE_E_ELEMENTNOTFOUND;
10835 func_desc->helpcontext = helpContext;
10837 return S_OK;
10840 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
10841 UINT index, DWORD helpContext)
10843 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10844 TLBVarDesc *var_desc = &This->vardescs[index];
10846 TRACE("%p %u %d\n", This, index, helpContext);
10848 if(index >= This->cVars)
10849 return TYPE_E_ELEMENTNOTFOUND;
10851 var_desc->HelpContext = helpContext;
10853 return S_OK;
10856 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
10857 UINT index, BSTR bstrMops)
10859 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10860 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
10861 return E_NOTIMPL;
10864 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
10865 IDLDESC *idlDesc)
10867 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10869 TRACE("%p %p\n", This, idlDesc);
10871 if (!idlDesc)
10872 return E_INVALIDARG;
10874 This->idldescType.dwReserved = idlDesc->dwReserved;
10875 This->idldescType.wIDLFlags = idlDesc->wIDLFlags;
10877 return S_OK;
10880 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
10882 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10883 ITypeInfo *tinfo;
10884 TLBFuncDesc *func_desc;
10885 UINT user_vft = 0, i, depth = 0;
10886 HRESULT hres = S_OK;
10888 TRACE("%p\n", This);
10890 This->needs_layout = FALSE;
10892 hres = ICreateTypeInfo2_QueryInterface(iface, &IID_ITypeInfo, (LPVOID*)&tinfo);
10893 if (FAILED(hres))
10894 return hres;
10896 if (This->typekind == TKIND_INTERFACE) {
10897 ITypeInfo *inh;
10898 TYPEATTR *attr;
10899 HREFTYPE inh_href;
10901 hres = ITypeInfo_GetRefTypeOfImplType(tinfo, 0, &inh_href);
10903 if (SUCCEEDED(hres)) {
10904 hres = ITypeInfo_GetRefTypeInfo(tinfo, inh_href, &inh);
10906 if (SUCCEEDED(hres)) {
10907 hres = ITypeInfo_GetTypeAttr(inh, &attr);
10908 if (FAILED(hres)) {
10909 ITypeInfo_Release(inh);
10910 ITypeInfo_Release(tinfo);
10911 return hres;
10913 This->cbSizeVft = attr->cbSizeVft;
10914 ITypeInfo_ReleaseTypeAttr(inh, attr);
10917 ++depth;
10918 hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href);
10919 if(SUCCEEDED(hres)){
10920 ITypeInfo *next;
10921 hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next);
10922 if(SUCCEEDED(hres)){
10923 ITypeInfo_Release(inh);
10924 inh = next;
10927 }while(SUCCEEDED(hres));
10928 hres = S_OK;
10930 ITypeInfo_Release(inh);
10931 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10932 This->cbSizeVft = 0;
10933 hres = S_OK;
10934 } else {
10935 ITypeInfo_Release(tinfo);
10936 return hres;
10938 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10939 This->cbSizeVft = 0;
10940 hres = S_OK;
10941 } else {
10942 ITypeInfo_Release(tinfo);
10943 return hres;
10945 } else if (This->typekind == TKIND_DISPATCH)
10946 This->cbSizeVft = 7 * This->pTypeLib->ptr_size;
10947 else
10948 This->cbSizeVft = 0;
10950 func_desc = This->funcdescs;
10951 i = 0;
10952 while (i < This->cFuncs) {
10953 if (!(func_desc->funcdesc.oVft & 0x1))
10954 func_desc->funcdesc.oVft = This->cbSizeVft;
10956 if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft)
10957 user_vft = func_desc->funcdesc.oVft & 0xFFFC;
10959 This->cbSizeVft += This->pTypeLib->ptr_size;
10961 if (func_desc->funcdesc.memid == MEMBERID_NIL) {
10962 TLBFuncDesc *iter;
10963 UINT j = 0;
10964 BOOL reset = FALSE;
10966 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i;
10968 iter = This->funcdescs;
10969 while (j < This->cFuncs) {
10970 if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) {
10971 if (!reset) {
10972 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->cFuncs;
10973 reset = TRUE;
10974 } else
10975 ++func_desc->funcdesc.memid;
10976 iter = This->funcdescs;
10977 j = 0;
10978 } else {
10979 ++iter;
10980 ++j;
10985 ++func_desc;
10986 ++i;
10989 if (user_vft > This->cbSizeVft)
10990 This->cbSizeVft = user_vft + This->pTypeLib->ptr_size;
10992 for(i = 0; i < This->cVars; ++i){
10993 TLBVarDesc *var_desc = &This->vardescs[i];
10994 if(var_desc->vardesc.memid == MEMBERID_NIL){
10995 UINT j = 0;
10996 BOOL reset = FALSE;
10997 TLBVarDesc *iter;
10999 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + i;
11001 iter = This->vardescs;
11002 while (j < This->cVars) {
11003 if (iter != var_desc && iter->vardesc.memid == var_desc->vardesc.memid) {
11004 if (!reset) {
11005 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + This->cVars;
11006 reset = TRUE;
11007 } else
11008 ++var_desc->vardesc.memid;
11009 iter = This->vardescs;
11010 j = 0;
11011 } else {
11012 ++iter;
11013 ++j;
11019 ITypeInfo_Release(tinfo);
11020 return hres;
11023 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
11024 UINT index)
11026 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11027 FIXME("%p %u - stub\n", This, index);
11028 return E_NOTIMPL;
11031 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
11032 MEMBERID memid, INVOKEKIND invKind)
11034 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11035 FIXME("%p %x %d - stub\n", This, memid, invKind);
11036 return E_NOTIMPL;
11039 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
11040 UINT index)
11042 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11043 FIXME("%p %u - stub\n", This, index);
11044 return E_NOTIMPL;
11047 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
11048 MEMBERID memid)
11050 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11051 FIXME("%p %x - stub\n", This, memid);
11052 return E_NOTIMPL;
11055 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
11056 UINT index)
11058 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11059 FIXME("%p %u - stub\n", This, index);
11060 return E_NOTIMPL;
11063 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
11064 REFGUID guid, VARIANT *varVal)
11066 TLBGuid *tlbguid;
11068 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11070 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
11072 if (!guid || !varVal)
11073 return E_INVALIDARG;
11075 tlbguid = TLB_append_guid(&This->pTypeLib->guid_list, guid, -1);
11077 return TLB_set_custdata(This->pcustdata_list, tlbguid, varVal);
11080 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
11081 UINT index, REFGUID guid, VARIANT *varVal)
11083 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11084 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11085 return E_NOTIMPL;
11088 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
11089 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
11091 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11092 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
11093 return E_NOTIMPL;
11096 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
11097 UINT index, REFGUID guid, VARIANT *varVal)
11099 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11100 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11101 return E_NOTIMPL;
11104 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
11105 UINT index, REFGUID guid, VARIANT *varVal)
11107 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11108 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11109 return E_NOTIMPL;
11112 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
11113 ULONG helpStringContext)
11115 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11117 TRACE("%p %u\n", This, helpStringContext);
11119 This->dwHelpStringContext = helpStringContext;
11121 return S_OK;
11124 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
11125 UINT index, ULONG helpStringContext)
11127 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11128 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11129 return E_NOTIMPL;
11132 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
11133 UINT index, ULONG helpStringContext)
11135 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11136 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11137 return E_NOTIMPL;
11140 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
11142 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11143 FIXME("%p - stub\n", This);
11144 return E_NOTIMPL;
11147 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
11148 LPOLESTR name)
11150 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11152 TRACE("%p %s\n", This, wine_dbgstr_w(name));
11154 if (!name)
11155 return E_INVALIDARG;
11157 This->Name = TLB_append_str(&This->pTypeLib->name_list, name);
11159 return S_OK;
11162 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
11163 ICreateTypeInfo2_fnQueryInterface,
11164 ICreateTypeInfo2_fnAddRef,
11165 ICreateTypeInfo2_fnRelease,
11166 ICreateTypeInfo2_fnSetGuid,
11167 ICreateTypeInfo2_fnSetTypeFlags,
11168 ICreateTypeInfo2_fnSetDocString,
11169 ICreateTypeInfo2_fnSetHelpContext,
11170 ICreateTypeInfo2_fnSetVersion,
11171 ICreateTypeInfo2_fnAddRefTypeInfo,
11172 ICreateTypeInfo2_fnAddFuncDesc,
11173 ICreateTypeInfo2_fnAddImplType,
11174 ICreateTypeInfo2_fnSetImplTypeFlags,
11175 ICreateTypeInfo2_fnSetAlignment,
11176 ICreateTypeInfo2_fnSetSchema,
11177 ICreateTypeInfo2_fnAddVarDesc,
11178 ICreateTypeInfo2_fnSetFuncAndParamNames,
11179 ICreateTypeInfo2_fnSetVarName,
11180 ICreateTypeInfo2_fnSetTypeDescAlias,
11181 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
11182 ICreateTypeInfo2_fnSetFuncDocString,
11183 ICreateTypeInfo2_fnSetVarDocString,
11184 ICreateTypeInfo2_fnSetFuncHelpContext,
11185 ICreateTypeInfo2_fnSetVarHelpContext,
11186 ICreateTypeInfo2_fnSetMops,
11187 ICreateTypeInfo2_fnSetTypeIdldesc,
11188 ICreateTypeInfo2_fnLayOut,
11189 ICreateTypeInfo2_fnDeleteFuncDesc,
11190 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
11191 ICreateTypeInfo2_fnDeleteVarDesc,
11192 ICreateTypeInfo2_fnDeleteVarDescByMemId,
11193 ICreateTypeInfo2_fnDeleteImplType,
11194 ICreateTypeInfo2_fnSetCustData,
11195 ICreateTypeInfo2_fnSetFuncCustData,
11196 ICreateTypeInfo2_fnSetParamCustData,
11197 ICreateTypeInfo2_fnSetVarCustData,
11198 ICreateTypeInfo2_fnSetImplTypeCustData,
11199 ICreateTypeInfo2_fnSetHelpStringContext,
11200 ICreateTypeInfo2_fnSetFuncHelpStringContext,
11201 ICreateTypeInfo2_fnSetVarHelpStringContext,
11202 ICreateTypeInfo2_fnInvalidate,
11203 ICreateTypeInfo2_fnSetName
11206 /******************************************************************************
11207 * ClearCustData (OLEAUT32.171)
11209 * Clear a custom data type's data.
11211 * PARAMS
11212 * lpCust [I] The custom data type instance
11214 * RETURNS
11215 * Nothing.
11217 void WINAPI ClearCustData(CUSTDATA *lpCust)
11219 if (lpCust && lpCust->cCustData)
11221 if (lpCust->prgCustData)
11223 DWORD i;
11225 for (i = 0; i < lpCust->cCustData; i++)
11226 VariantClear(&lpCust->prgCustData[i].varValue);
11228 CoTaskMemFree(lpCust->prgCustData);
11229 lpCust->prgCustData = NULL;
11231 lpCust->cCustData = 0;