d3d10core: Remove unnecessary DllMain implementation.
[wine.git] / dlls / oleaut32 / typelib.c
blob4a16fca44ee4ad3c03180e950ad15fd8e4bdb8d1
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;
842 /******************************************************************************
843 * UnRegisterTypeLib [OLEAUT32.186]
844 * Removes information about a type library from the System Registry
845 * NOTES
847 * RETURNS
848 * Success: S_OK
849 * Failure: Status
851 HRESULT WINAPI UnRegisterTypeLib(
852 REFGUID libid, /* [in] Guid of the library */
853 WORD wVerMajor, /* [in] major version */
854 WORD wVerMinor, /* [in] minor version */
855 LCID lcid, /* [in] locale id */
856 SYSKIND syskind)
858 BSTR tlibPath = NULL;
859 DWORD tmpLength;
860 WCHAR keyName[60];
861 WCHAR subKeyName[50];
862 int result = S_OK;
863 DWORD i = 0;
864 BOOL deleteOtherStuff;
865 HKEY key = NULL;
866 HKEY subKey = NULL;
867 TYPEATTR* typeAttr = NULL;
868 TYPEKIND kind;
869 ITypeInfo* typeInfo = NULL;
870 ITypeLib* typeLib = NULL;
871 int numTypes;
873 TRACE("(IID: %s)\n",debugstr_guid(libid));
875 /* Create the path to the key */
876 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
878 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
880 TRACE("Unsupported syskind %i\n", syskind);
881 result = E_INVALIDARG;
882 goto end;
885 /* get the path to the typelib on disk */
886 if (query_typelib_path(libid, wVerMajor, wVerMinor, syskind, lcid, &tlibPath, FALSE) != S_OK) {
887 result = E_INVALIDARG;
888 goto end;
891 /* Try and open the key to the type library. */
892 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
893 result = E_INVALIDARG;
894 goto end;
897 /* Try and load the type library */
898 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib) != S_OK) {
899 result = TYPE_E_INVALIDSTATE;
900 goto end;
903 /* remove any types registered with this typelib */
904 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
905 for (i=0; i<numTypes; i++) {
906 /* get the kind of type */
907 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
908 goto enddeleteloop;
911 /* skip non-interfaces, and get type info for the type */
912 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
913 goto enddeleteloop;
915 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
916 goto enddeleteloop;
918 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
919 goto enddeleteloop;
922 if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
923 kind == TKIND_DISPATCH)
925 /* the path to the type */
926 get_interface_key( &typeAttr->guid, subKeyName );
928 /* Delete its bits */
929 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS)
930 goto enddeleteloop;
932 RegDeleteKeyW(subKey, ProxyStubClsidW);
933 RegDeleteKeyW(subKey, ProxyStubClsid32W);
934 RegDeleteKeyW(subKey, TypeLibW);
935 RegCloseKey(subKey);
936 subKey = NULL;
937 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
940 enddeleteloop:
941 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
942 typeAttr = NULL;
943 if (typeInfo) ITypeInfo_Release(typeInfo);
944 typeInfo = NULL;
947 /* Now, delete the type library path subkey */
948 get_lcid_subkey( lcid, syskind, subKeyName );
949 RegDeleteKeyW(key, subKeyName);
950 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
951 RegDeleteKeyW(key, subKeyName);
953 /* check if there is anything besides the FLAGS/HELPDIR keys.
954 If there is, we don't delete them */
955 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
956 deleteOtherStuff = TRUE;
957 i = 0;
958 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
959 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
961 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
962 if (!strcmpW(subKeyName, FLAGSW)) continue;
963 if (!strcmpW(subKeyName, HELPDIRW)) continue;
964 deleteOtherStuff = FALSE;
965 break;
968 /* only delete the other parts of the key if we're absolutely sure */
969 if (deleteOtherStuff) {
970 RegDeleteKeyW(key, FLAGSW);
971 RegDeleteKeyW(key, HELPDIRW);
972 RegCloseKey(key);
973 key = NULL;
975 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
976 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
977 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
980 end:
981 SysFreeString(tlibPath);
982 if (typeLib) ITypeLib_Release(typeLib);
983 if (subKey) RegCloseKey(subKey);
984 if (key) RegCloseKey(key);
985 return result;
988 /******************************************************************************
989 * RegisterTypeLibForUser [OLEAUT32.442]
990 * Adds information about a type library to the user registry
991 * NOTES
992 * Docs: ITypeLib FAR * ptlib
993 * Docs: OLECHAR FAR* szFullPath
994 * Docs: OLECHAR FAR* szHelpDir
996 * RETURNS
997 * Success: S_OK
998 * Failure: Status
1000 HRESULT WINAPI RegisterTypeLibForUser(
1001 ITypeLib * ptlib, /* [in] Pointer to the library*/
1002 OLECHAR * szFullPath, /* [in] full Path of the library*/
1003 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
1004 may be NULL*/
1006 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib,
1007 debugstr_w(szFullPath), debugstr_w(szHelpDir));
1008 return RegisterTypeLib(ptlib, szFullPath, szHelpDir);
1011 /******************************************************************************
1012 * UnRegisterTypeLibForUser [OLEAUT32.443]
1013 * Removes information about a type library from the user registry
1015 * RETURNS
1016 * Success: S_OK
1017 * Failure: Status
1019 HRESULT WINAPI UnRegisterTypeLibForUser(
1020 REFGUID libid, /* [in] GUID of the library */
1021 WORD wVerMajor, /* [in] major version */
1022 WORD wVerMinor, /* [in] minor version */
1023 LCID lcid, /* [in] locale id */
1024 SYSKIND syskind)
1026 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
1027 debugstr_guid(libid), wVerMajor, wVerMinor, lcid, syskind);
1028 return UnRegisterTypeLib(libid, wVerMajor, wVerMinor, lcid, syskind);
1031 /*======================= ITypeLib implementation =======================*/
1033 typedef struct tagTLBGuid {
1034 GUID guid;
1035 INT hreftype;
1036 UINT offset;
1037 struct list entry;
1038 } TLBGuid;
1040 typedef struct tagTLBCustData
1042 TLBGuid *guid;
1043 VARIANT data;
1044 struct list entry;
1045 } TLBCustData;
1047 /* data structure for import typelibs */
1048 typedef struct tagTLBImpLib
1050 int offset; /* offset in the file (MSFT)
1051 offset in nametable (SLTG)
1052 just used to identify library while reading
1053 data from file */
1054 TLBGuid *guid; /* libid */
1055 BSTR name; /* name */
1057 LCID lcid; /* lcid of imported typelib */
1059 WORD wVersionMajor; /* major version number */
1060 WORD wVersionMinor; /* minor version number */
1062 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
1063 NULL if not yet loaded */
1064 struct list entry;
1065 } TLBImpLib;
1067 typedef struct tagTLBString {
1068 BSTR str;
1069 UINT offset;
1070 struct list entry;
1071 } TLBString;
1073 /* internal ITypeLib data */
1074 typedef struct tagITypeLibImpl
1076 ITypeLib2 ITypeLib2_iface;
1077 ITypeComp ITypeComp_iface;
1078 ICreateTypeLib2 ICreateTypeLib2_iface;
1079 LONG ref;
1080 TLBGuid *guid;
1081 LCID lcid;
1082 SYSKIND syskind;
1083 int ptr_size;
1084 WORD ver_major;
1085 WORD ver_minor;
1086 WORD libflags;
1087 LCID set_lcid;
1089 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1090 * exported to the application as a UNICODE string.
1092 struct list string_list;
1093 struct list name_list;
1094 struct list guid_list;
1096 const TLBString *Name;
1097 const TLBString *DocString;
1098 const TLBString *HelpFile;
1099 const TLBString *HelpStringDll;
1100 DWORD dwHelpContext;
1101 int TypeInfoCount; /* nr of typeinfo's in librarry */
1102 struct tagITypeInfoImpl **typeinfos;
1103 struct list custdata_list;
1104 struct list implib_list;
1105 int ctTypeDesc; /* number of items in type desc array */
1106 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1107 library. Only used while reading MSFT
1108 typelibs */
1109 struct list ref_list; /* list of ref types in this typelib */
1110 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1113 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1114 struct list entry;
1115 WCHAR *path;
1116 INT index;
1117 } ITypeLibImpl;
1119 static const ITypeLib2Vtbl tlbvt;
1120 static const ITypeCompVtbl tlbtcvt;
1121 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl;
1123 static inline ITypeLibImpl *impl_from_ITypeLib2(ITypeLib2 *iface)
1125 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeLib2_iface);
1128 static inline ITypeLibImpl *impl_from_ITypeLib(ITypeLib *iface)
1130 return impl_from_ITypeLib2((ITypeLib2*)iface);
1133 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1135 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeComp_iface);
1138 static inline ITypeLibImpl *impl_from_ICreateTypeLib2( ICreateTypeLib2 *iface )
1140 return CONTAINING_RECORD(iface, ITypeLibImpl, ICreateTypeLib2_iface);
1143 /* ITypeLib methods */
1144 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1145 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1147 /*======================= ITypeInfo implementation =======================*/
1149 /* data for referenced types */
1150 typedef struct tagTLBRefType
1152 INT index; /* Type index for internal ref or for external ref
1153 it the format is SLTG. -2 indicates to
1154 use guid */
1156 TYPEKIND tkind;
1157 TLBGuid *guid; /* guid of the referenced type */
1158 /* if index == TLB_REF_USE_GUID */
1160 HREFTYPE reference; /* The href of this ref */
1161 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1162 TLB_REF_INTERNAL for internal refs
1163 TLB_REF_NOT_FOUND for broken refs */
1165 struct list entry;
1166 } TLBRefType;
1168 #define TLB_REF_USE_GUID -2
1170 #define TLB_REF_INTERNAL (void*)-2
1171 #define TLB_REF_NOT_FOUND (void*)-1
1173 /* internal Parameter data */
1174 typedef struct tagTLBParDesc
1176 const TLBString *Name;
1177 struct list custdata_list;
1178 } TLBParDesc;
1180 /* internal Function data */
1181 typedef struct tagTLBFuncDesc
1183 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1184 const TLBString *Name; /* the name of this function */
1185 TLBParDesc *pParamDesc; /* array with param names and custom data */
1186 int helpcontext;
1187 int HelpStringContext;
1188 const TLBString *HelpString;
1189 const TLBString *Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1190 struct list custdata_list;
1191 } TLBFuncDesc;
1193 /* internal Variable data */
1194 typedef struct tagTLBVarDesc
1196 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1197 VARDESC *vardesc_create; /* additional data needed for storing VARDESC */
1198 const TLBString *Name; /* the name of this variable */
1199 int HelpContext;
1200 int HelpStringContext;
1201 const TLBString *HelpString;
1202 struct list custdata_list;
1203 } TLBVarDesc;
1205 /* internal implemented interface data */
1206 typedef struct tagTLBImplType
1208 HREFTYPE hRef; /* hRef of interface */
1209 int implflags; /* IMPLFLAG_*s */
1210 struct list custdata_list;
1211 } TLBImplType;
1213 /* internal TypeInfo data */
1214 typedef struct tagITypeInfoImpl
1216 ITypeInfo2 ITypeInfo2_iface;
1217 ITypeComp ITypeComp_iface;
1218 ICreateTypeInfo2 ICreateTypeInfo2_iface;
1219 LONG ref;
1220 BOOL not_attached_to_typelib;
1221 BOOL needs_layout;
1223 TLBGuid *guid;
1224 LCID lcid;
1225 MEMBERID memidConstructor;
1226 MEMBERID memidDestructor;
1227 LPOLESTR lpstrSchema;
1228 ULONG cbSizeInstance;
1229 TYPEKIND typekind;
1230 WORD cFuncs;
1231 WORD cVars;
1232 WORD cImplTypes;
1233 WORD cbSizeVft;
1234 WORD cbAlignment;
1235 WORD wTypeFlags;
1236 WORD wMajorVerNum;
1237 WORD wMinorVerNum;
1238 TYPEDESC *tdescAlias;
1239 IDLDESC idldescType;
1241 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1242 int index; /* index in this typelib; */
1243 HREFTYPE hreftype; /* hreftype for app object binding */
1244 /* type libs seem to store the doc strings in ascii
1245 * so why should we do it in unicode?
1247 const TLBString *Name;
1248 const TLBString *DocString;
1249 const TLBString *DllName;
1250 const TLBString *Schema;
1251 DWORD dwHelpContext;
1252 DWORD dwHelpStringContext;
1254 /* functions */
1255 TLBFuncDesc *funcdescs;
1257 /* variables */
1258 TLBVarDesc *vardescs;
1260 /* Implemented Interfaces */
1261 TLBImplType *impltypes;
1263 struct list *pcustdata_list;
1264 struct list custdata_list;
1265 } ITypeInfoImpl;
1267 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1269 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeComp_iface);
1272 static inline ITypeInfoImpl *impl_from_ITypeInfo2( ITypeInfo2 *iface )
1274 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeInfo2_iface);
1277 static inline ITypeInfoImpl *impl_from_ITypeInfo( ITypeInfo *iface )
1279 return impl_from_ITypeInfo2((ITypeInfo2*)iface);
1282 static inline ITypeInfoImpl *info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2 *iface )
1284 return CONTAINING_RECORD(iface, ITypeInfoImpl, ICreateTypeInfo2_iface);
1287 static const ITypeInfo2Vtbl tinfvt;
1288 static const ITypeCompVtbl tcompvt;
1289 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl;
1291 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1292 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1294 typedef struct tagTLBContext
1296 unsigned int oStart; /* start of TLB in file */
1297 unsigned int pos; /* current pos */
1298 unsigned int length; /* total length */
1299 void *mapping; /* memory mapping */
1300 MSFT_SegDir * pTblDir;
1301 ITypeLibImpl* pLibInfo;
1302 } TLBContext;
1305 static inline BSTR TLB_get_bstr(const TLBString *str)
1307 return str != NULL ? str->str : NULL;
1310 static inline int TLB_str_memcmp(void *left, const TLBString *str, DWORD len)
1312 if(!str)
1313 return 1;
1314 return memcmp(left, str->str, len);
1317 static inline const GUID *TLB_get_guidref(const TLBGuid *guid)
1319 return guid != NULL ? &guid->guid : NULL;
1322 static inline const GUID *TLB_get_guid_null(const TLBGuid *guid)
1324 return guid != NULL ? &guid->guid : &GUID_NULL;
1327 static int get_ptr_size(SYSKIND syskind)
1329 switch(syskind){
1330 case SYS_WIN64:
1331 return 8;
1332 case SYS_WIN32:
1333 case SYS_MAC:
1334 case SYS_WIN16:
1335 return 4;
1337 WARN("Unhandled syskind: 0x%x\n", syskind);
1338 return 4;
1342 debug
1344 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1345 if (pTD->vt & VT_RESERVED)
1346 szVarType += strlen(strcpy(szVarType, "reserved | "));
1347 if (pTD->vt & VT_BYREF)
1348 szVarType += strlen(strcpy(szVarType, "ref to "));
1349 if (pTD->vt & VT_ARRAY)
1350 szVarType += strlen(strcpy(szVarType, "array of "));
1351 if (pTD->vt & VT_VECTOR)
1352 szVarType += strlen(strcpy(szVarType, "vector of "));
1353 switch(pTD->vt & VT_TYPEMASK) {
1354 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1355 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1356 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1357 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1358 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1359 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1360 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1361 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1362 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1363 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1364 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1365 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1366 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1367 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1368 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1369 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1370 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1371 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1372 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1373 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1374 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1375 pTD->u.hreftype); break;
1376 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1377 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1378 case VT_PTR: sprintf(szVarType, "ptr to ");
1379 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1380 break;
1381 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1382 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1383 break;
1384 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1385 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1386 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1387 break;
1389 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1393 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1394 char buf[200];
1395 USHORT flags = edesc->u.paramdesc.wParamFlags;
1396 dump_TypeDesc(&edesc->tdesc,buf);
1397 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1398 MESSAGE("\t\tu.paramdesc.wParamFlags");
1399 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1400 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1401 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1402 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1403 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1404 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1405 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1406 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1407 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1409 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1410 int i;
1411 MESSAGE("memid is %08x\n",funcdesc->memid);
1412 for (i=0;i<funcdesc->cParams;i++) {
1413 MESSAGE("Param %d:\n",i);
1414 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1416 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1417 switch (funcdesc->funckind) {
1418 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1419 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1420 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1421 case FUNC_STATIC: MESSAGE("static");break;
1422 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1423 default: MESSAGE("unknown");break;
1425 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1426 switch (funcdesc->invkind) {
1427 case INVOKE_FUNC: MESSAGE("func");break;
1428 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1429 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1430 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1432 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1433 switch (funcdesc->callconv) {
1434 case CC_CDECL: MESSAGE("cdecl");break;
1435 case CC_PASCAL: MESSAGE("pascal");break;
1436 case CC_STDCALL: MESSAGE("stdcall");break;
1437 case CC_SYSCALL: MESSAGE("syscall");break;
1438 default:break;
1440 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1441 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1442 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1444 MESSAGE("\telemdescFunc (return value type):\n");
1445 dump_ELEMDESC(&funcdesc->elemdescFunc);
1448 static const char * const typekind_desc[] =
1450 "TKIND_ENUM",
1451 "TKIND_RECORD",
1452 "TKIND_MODULE",
1453 "TKIND_INTERFACE",
1454 "TKIND_DISPATCH",
1455 "TKIND_COCLASS",
1456 "TKIND_ALIAS",
1457 "TKIND_UNION",
1458 "TKIND_MAX"
1461 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1463 int i;
1464 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd->Name)), pfd->funcdesc.cParams);
1465 for (i=0;i<pfd->funcdesc.cParams;i++)
1466 MESSAGE("\tparm%d: %s\n",i,debugstr_w(TLB_get_bstr(pfd->pParamDesc[i].Name)));
1469 dump_FUNCDESC(&(pfd->funcdesc));
1471 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd->HelpString)));
1472 if(pfd->Entry == NULL)
1473 MESSAGE("\tentry: (null)\n");
1474 else if(pfd->Entry == (void*)-1)
1475 MESSAGE("\tentry: invalid\n");
1476 else if(IS_INTRESOURCE(pfd->Entry))
1477 MESSAGE("\tentry: %p\n", pfd->Entry);
1478 else
1479 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd->Entry)));
1481 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1483 while (n)
1485 dump_TLBFuncDescOne(pfd);
1486 ++pfd;
1487 --n;
1490 static void dump_TLBVarDesc(const TLBVarDesc * pvd, UINT n)
1492 while (n)
1494 TRACE_(typelib)("%s\n", debugstr_w(TLB_get_bstr(pvd->Name)));
1495 ++pvd;
1496 --n;
1500 static void dump_TLBImpLib(const TLBImpLib *import)
1502 TRACE_(typelib)("%s %s\n", debugstr_guid(TLB_get_guidref(import->guid)),
1503 debugstr_w(import->name));
1504 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1505 import->wVersionMinor, import->lcid, import->offset);
1508 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1510 TLBRefType *ref;
1512 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1514 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1515 if(ref->index == -1)
1516 TRACE_(typelib)("%s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
1517 else
1518 TRACE_(typelib)("type no: %d\n", ref->index);
1520 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1522 TRACE_(typelib)("in lib\n");
1523 dump_TLBImpLib(ref->pImpTLInfo);
1528 static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1530 if(!impl)
1531 return;
1532 while (n) {
1533 TRACE_(typelib)("implementing/inheriting interface hRef = %x implflags %x\n",
1534 impl->hRef, impl->implflags);
1535 ++impl;
1536 --n;
1540 static void dump_Variant(const VARIANT * pvar)
1542 SYSTEMTIME st;
1544 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1546 if (pvar)
1548 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1549 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1551 TRACE(",%p", V_BYREF(pvar));
1553 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1555 TRACE(",%p", V_ARRAY(pvar));
1557 else switch (V_TYPE(pvar))
1559 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1560 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1561 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1562 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1563 case VT_INT:
1564 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1565 case VT_UINT:
1566 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1567 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1568 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1569 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1570 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1571 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1572 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1573 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1574 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1575 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1576 V_CY(pvar).s.Lo); break;
1577 case VT_DATE:
1578 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1579 TRACE(",<invalid>");
1580 else
1581 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1582 st.wHour, st.wMinute, st.wSecond);
1583 break;
1584 case VT_ERROR:
1585 case VT_VOID:
1586 case VT_USERDEFINED:
1587 case VT_EMPTY:
1588 case VT_NULL: break;
1589 default: TRACE(",?"); break;
1592 TRACE("}\n");
1595 static void dump_DispParms(const DISPPARAMS * pdp)
1597 unsigned int index;
1599 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1601 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1603 TRACE("named args:\n");
1604 for (index = 0; index < pdp->cNamedArgs; index++)
1605 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1608 if (pdp->cArgs && pdp->rgvarg)
1610 TRACE("args:\n");
1611 for (index = 0; index < pdp->cArgs; index++)
1612 dump_Variant( &pdp->rgvarg[index] );
1616 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1618 TRACE("%p ref=%u\n", pty, pty->ref);
1619 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty->Name)), debugstr_w(TLB_get_bstr(pty->DocString)));
1620 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty->guid)));
1621 TRACE("kind:%s\n", typekind_desc[pty->typekind]);
1622 TRACE("fct:%u var:%u impl:%u\n", pty->cFuncs, pty->cVars, pty->cImplTypes);
1623 TRACE("wTypeFlags: 0x%04x\n", pty->wTypeFlags);
1624 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1625 if (pty->typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty->DllName)));
1626 if (TRACE_ON(ole))
1627 dump_TLBFuncDesc(pty->funcdescs, pty->cFuncs);
1628 dump_TLBVarDesc(pty->vardescs, pty->cVars);
1629 dump_TLBImplType(pty->impltypes, pty->cImplTypes);
1632 static void dump_VARDESC(const VARDESC *v)
1634 MESSAGE("memid %d\n",v->memid);
1635 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1636 MESSAGE("oInst %d\n",v->u.oInst);
1637 dump_ELEMDESC(&(v->elemdescVar));
1638 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1639 MESSAGE("varkind %d\n",v->varkind);
1642 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1644 /* VT_LPWSTR is largest type that, may appear in type description */
1645 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1646 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1647 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1648 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1649 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1650 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1651 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1652 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1655 static void TLB_abort(void)
1657 DebugBreak();
1660 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size)
1662 void *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
1663 if (!ret) ERR("cannot allocate memory\n");
1664 return ret;
1667 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size)
1669 void *ret = HeapAlloc(GetProcessHeap(), 0, size);
1670 if (!ret) ERR("cannot allocate memory\n");
1671 return ret;
1674 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr, unsigned size)
1676 return HeapReAlloc(GetProcessHeap(), 0, ptr, size);
1679 void heap_free(void *ptr)
1681 HeapFree(GetProcessHeap(), 0, ptr);
1684 /* returns the size required for a deep copy of a typedesc into a
1685 * flat buffer */
1686 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1688 SIZE_T size = 0;
1690 if (alloc_initial_space)
1691 size += sizeof(TYPEDESC);
1693 switch (tdesc->vt)
1695 case VT_PTR:
1696 case VT_SAFEARRAY:
1697 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1698 break;
1699 case VT_CARRAY:
1700 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1701 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1702 break;
1704 return size;
1707 /* deep copy a typedesc into a flat buffer */
1708 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1710 if (!dest)
1712 dest = buffer;
1713 buffer = (char *)buffer + sizeof(TYPEDESC);
1716 *dest = *src;
1718 switch (src->vt)
1720 case VT_PTR:
1721 case VT_SAFEARRAY:
1722 dest->u.lptdesc = buffer;
1723 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1724 break;
1725 case VT_CARRAY:
1726 dest->u.lpadesc = buffer;
1727 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1728 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1729 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1730 break;
1732 return buffer;
1735 /* free custom data allocated by MSFT_CustData */
1736 static inline void TLB_FreeCustData(struct list *custdata_list)
1738 TLBCustData *cd, *cdn;
1739 LIST_FOR_EACH_ENTRY_SAFE(cd, cdn, custdata_list, TLBCustData, entry)
1741 list_remove(&cd->entry);
1742 VariantClear(&cd->data);
1743 heap_free(cd);
1747 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1749 DWORD len;
1750 BSTR ret;
1752 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1753 ret = SysAllocStringLen(NULL, len - 1);
1754 if (!ret) return ret;
1755 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1756 return ret;
1759 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(TLBFuncDesc *funcdescs,
1760 UINT n, MEMBERID memid)
1762 while(n){
1763 if(funcdescs->funcdesc.memid == memid)
1764 return funcdescs;
1765 ++funcdescs;
1766 --n;
1768 return NULL;
1771 static inline TLBFuncDesc *TLB_get_funcdesc_by_name(TLBFuncDesc *funcdescs,
1772 UINT n, const OLECHAR *name)
1774 while(n){
1775 if(!lstrcmpiW(TLB_get_bstr(funcdescs->Name), name))
1776 return funcdescs;
1777 ++funcdescs;
1778 --n;
1780 return NULL;
1783 static inline TLBVarDesc *TLB_get_vardesc_by_memberid(TLBVarDesc *vardescs,
1784 UINT n, MEMBERID memid)
1786 while(n){
1787 if(vardescs->vardesc.memid == memid)
1788 return vardescs;
1789 ++vardescs;
1790 --n;
1792 return NULL;
1795 static inline TLBVarDesc *TLB_get_vardesc_by_name(TLBVarDesc *vardescs,
1796 UINT n, const OLECHAR *name)
1798 while(n){
1799 if(!lstrcmpiW(TLB_get_bstr(vardescs->Name), name))
1800 return vardescs;
1801 ++vardescs;
1802 --n;
1804 return NULL;
1807 static inline TLBCustData *TLB_get_custdata_by_guid(struct list *custdata_list, REFGUID guid)
1809 TLBCustData *cust_data;
1810 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1811 if(IsEqualIID(TLB_get_guid_null(cust_data->guid), guid))
1812 return cust_data;
1813 return NULL;
1816 static inline ITypeInfoImpl *TLB_get_typeinfo_by_name(ITypeInfoImpl **typeinfos,
1817 UINT n, const OLECHAR *name)
1819 while(n){
1820 if(!lstrcmpiW(TLB_get_bstr((*typeinfos)->Name), name))
1821 return *typeinfos;
1822 ++typeinfos;
1823 --n;
1825 return NULL;
1828 static void TLBVarDesc_Constructor(TLBVarDesc *var_desc)
1830 list_init(&var_desc->custdata_list);
1833 static TLBVarDesc *TLBVarDesc_Alloc(UINT n)
1835 TLBVarDesc *ret;
1837 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1838 if(!ret)
1839 return NULL;
1841 while(n){
1842 TLBVarDesc_Constructor(&ret[n-1]);
1843 --n;
1846 return ret;
1849 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1851 TLBParDesc *ret;
1853 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1854 if(!ret)
1855 return NULL;
1857 while(n){
1858 list_init(&ret[n-1].custdata_list);
1859 --n;
1862 return ret;
1865 static void TLBFuncDesc_Constructor(TLBFuncDesc *func_desc)
1867 list_init(&func_desc->custdata_list);
1870 static TLBFuncDesc *TLBFuncDesc_Alloc(UINT n)
1872 TLBFuncDesc *ret;
1874 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1875 if(!ret)
1876 return NULL;
1878 while(n){
1879 TLBFuncDesc_Constructor(&ret[n-1]);
1880 --n;
1883 return ret;
1886 static void TLBImplType_Constructor(TLBImplType *impl)
1888 list_init(&impl->custdata_list);
1891 static TLBImplType *TLBImplType_Alloc(UINT n)
1893 TLBImplType *ret;
1895 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1896 if(!ret)
1897 return NULL;
1899 while(n){
1900 TLBImplType_Constructor(&ret[n-1]);
1901 --n;
1904 return ret;
1907 static TLBGuid *TLB_append_guid(struct list *guid_list,
1908 const GUID *new_guid, HREFTYPE hreftype)
1910 TLBGuid *guid;
1912 LIST_FOR_EACH_ENTRY(guid, guid_list, TLBGuid, entry) {
1913 if (IsEqualGUID(&guid->guid, new_guid))
1914 return guid;
1917 guid = heap_alloc(sizeof(TLBGuid));
1918 if (!guid)
1919 return NULL;
1921 memcpy(&guid->guid, new_guid, sizeof(GUID));
1922 guid->hreftype = hreftype;
1924 list_add_tail(guid_list, &guid->entry);
1926 return guid;
1929 static HRESULT TLB_set_custdata(struct list *custdata_list, TLBGuid *tlbguid, VARIANT *var)
1931 TLBCustData *cust_data;
1933 switch(V_VT(var)){
1934 case VT_I4:
1935 case VT_R4:
1936 case VT_UI4:
1937 case VT_INT:
1938 case VT_UINT:
1939 case VT_HRESULT:
1940 case VT_BSTR:
1941 break;
1942 default:
1943 return DISP_E_BADVARTYPE;
1946 cust_data = TLB_get_custdata_by_guid(custdata_list, TLB_get_guid_null(tlbguid));
1948 if (!cust_data) {
1949 cust_data = heap_alloc(sizeof(TLBCustData));
1950 if (!cust_data)
1951 return E_OUTOFMEMORY;
1953 cust_data->guid = tlbguid;
1954 VariantInit(&cust_data->data);
1956 list_add_tail(custdata_list, &cust_data->entry);
1957 }else
1958 VariantClear(&cust_data->data);
1960 return VariantCopy(&cust_data->data, var);
1963 static TLBString *TLB_append_str(struct list *string_list, BSTR new_str)
1965 TLBString *str;
1967 if(!new_str)
1968 return NULL;
1970 LIST_FOR_EACH_ENTRY(str, string_list, TLBString, entry) {
1971 if (strcmpW(str->str, new_str) == 0)
1972 return str;
1975 str = heap_alloc(sizeof(TLBString));
1976 if (!str)
1977 return NULL;
1979 str->str = SysAllocString(new_str);
1980 if (!str->str) {
1981 heap_free(str);
1982 return NULL;
1985 list_add_tail(string_list, &str->entry);
1987 return str;
1990 static HRESULT TLB_get_size_from_hreftype(ITypeInfoImpl *info, HREFTYPE href,
1991 ULONG *size, WORD *align)
1993 ITypeInfo *other;
1994 TYPEATTR *attr;
1995 HRESULT hr;
1997 hr = ITypeInfo2_GetRefTypeInfo(&info->ITypeInfo2_iface, href, &other);
1998 if(FAILED(hr))
1999 return hr;
2001 hr = ITypeInfo_GetTypeAttr(other, &attr);
2002 if(FAILED(hr)){
2003 ITypeInfo_Release(other);
2004 return hr;
2007 if(size)
2008 *size = attr->cbSizeInstance;
2009 if(align)
2010 *align = attr->cbAlignment;
2012 ITypeInfo_ReleaseTypeAttr(other, attr);
2013 ITypeInfo_Release(other);
2015 return S_OK;
2018 static HRESULT TLB_size_instance(ITypeInfoImpl *info, SYSKIND sys,
2019 TYPEDESC *tdesc, ULONG *size, WORD *align)
2021 ULONG i, sub, ptr_size;
2022 HRESULT hr;
2024 ptr_size = get_ptr_size(sys);
2026 switch(tdesc->vt){
2027 case VT_VOID:
2028 *size = 0;
2029 break;
2030 case VT_I1:
2031 case VT_UI1:
2032 *size = 1;
2033 break;
2034 case VT_I2:
2035 case VT_BOOL:
2036 case VT_UI2:
2037 *size = 2;
2038 break;
2039 case VT_I4:
2040 case VT_R4:
2041 case VT_ERROR:
2042 case VT_UI4:
2043 case VT_INT:
2044 case VT_UINT:
2045 case VT_HRESULT:
2046 *size = 4;
2047 break;
2048 case VT_R8:
2049 case VT_I8:
2050 case VT_UI8:
2051 *size = 8;
2052 break;
2053 case VT_BSTR:
2054 case VT_DISPATCH:
2055 case VT_UNKNOWN:
2056 case VT_PTR:
2057 case VT_SAFEARRAY:
2058 case VT_LPSTR:
2059 case VT_LPWSTR:
2060 *size = ptr_size;
2061 break;
2062 case VT_DATE:
2063 *size = sizeof(DATE);
2064 break;
2065 case VT_VARIANT:
2066 *size = sizeof(VARIANT);
2067 #ifdef _WIN64
2068 if(sys == SYS_WIN32)
2069 *size -= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
2070 #endif
2071 break;
2072 case VT_DECIMAL:
2073 *size = sizeof(DECIMAL);
2074 break;
2075 case VT_CY:
2076 *size = sizeof(CY);
2077 break;
2078 case VT_CARRAY:
2079 *size = 0;
2080 for(i = 0; i < tdesc->u.lpadesc->cDims; ++i)
2081 *size += tdesc->u.lpadesc->rgbounds[i].cElements;
2082 hr = TLB_size_instance(info, sys, &tdesc->u.lpadesc->tdescElem, &sub, align);
2083 if(FAILED(hr))
2084 return hr;
2085 *size *= sub;
2086 return S_OK;
2087 case VT_USERDEFINED:
2088 return TLB_get_size_from_hreftype(info, tdesc->u.hreftype, size, align);
2089 default:
2090 FIXME("Unsized VT: 0x%x\n", tdesc->vt);
2091 return E_FAIL;
2094 if(align){
2095 if(*size < 4)
2096 *align = *size;
2097 else
2098 *align = 4;
2101 return S_OK;
2104 /**********************************************************************
2106 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2108 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
2110 return pcx->pos;
2113 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
2115 if (where != DO_NOT_SEEK)
2117 where += pcx->oStart;
2118 if (where > pcx->length)
2120 /* FIXME */
2121 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
2122 TLB_abort();
2124 pcx->pos = where;
2128 /* read function */
2129 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
2131 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2132 pcx->pos, count, pcx->oStart, pcx->length, where);
2134 MSFT_Seek(pcx, where);
2135 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
2136 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
2137 pcx->pos += count;
2138 return count;
2141 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
2142 LONG where )
2144 DWORD ret;
2146 ret = MSFT_Read(buffer, count, pcx, where);
2147 FromLEDWords(buffer, ret);
2149 return ret;
2152 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
2153 LONG where )
2155 DWORD ret;
2157 ret = MSFT_Read(buffer, count, pcx, where);
2158 FromLEWords(buffer, ret);
2160 return ret;
2163 static HRESULT MSFT_ReadAllGuids(TLBContext *pcx)
2165 TLBGuid *guid;
2166 MSFT_GuidEntry entry;
2167 int offs = 0;
2169 MSFT_Seek(pcx, pcx->pTblDir->pGuidTab.offset);
2170 while (1) {
2171 if (offs >= pcx->pTblDir->pGuidTab.length)
2172 return S_OK;
2174 MSFT_ReadLEWords(&entry, sizeof(MSFT_GuidEntry), pcx, DO_NOT_SEEK);
2176 guid = heap_alloc(sizeof(TLBGuid));
2178 guid->offset = offs;
2179 guid->guid = entry.guid;
2180 guid->hreftype = entry.hreftype;
2182 list_add_tail(&pcx->pLibInfo->guid_list, &guid->entry);
2184 offs += sizeof(MSFT_GuidEntry);
2188 static TLBGuid *MSFT_ReadGuid( int offset, TLBContext *pcx)
2190 TLBGuid *ret;
2192 LIST_FOR_EACH_ENTRY(ret, &pcx->pLibInfo->guid_list, TLBGuid, entry){
2193 if(ret->offset == offset){
2194 TRACE_(typelib)("%s\n", debugstr_guid(&ret->guid));
2195 return ret;
2199 return NULL;
2202 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
2204 MSFT_NameIntro niName;
2206 if (offset < 0)
2208 ERR_(typelib)("bad offset %d\n", offset);
2209 return -1;
2212 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
2213 pcx->pTblDir->pNametab.offset+offset);
2215 return niName.hreftype;
2218 static HRESULT MSFT_ReadAllNames(TLBContext *pcx)
2220 char *string;
2221 MSFT_NameIntro intro;
2222 INT16 len_piece;
2223 int offs = 0, lengthInChars;
2225 MSFT_Seek(pcx, pcx->pTblDir->pNametab.offset);
2226 while (1) {
2227 TLBString *tlbstr;
2229 if (offs >= pcx->pTblDir->pNametab.length)
2230 return S_OK;
2232 MSFT_ReadLEWords(&intro, sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2233 intro.namelen &= 0xFF;
2234 len_piece = intro.namelen + sizeof(MSFT_NameIntro);
2235 if(len_piece % 4)
2236 len_piece = (len_piece + 4) & ~0x3;
2237 if(len_piece < 8)
2238 len_piece = 8;
2240 string = heap_alloc(len_piece + 1);
2241 MSFT_Read(string, len_piece - sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2242 string[intro.namelen] = '\0';
2244 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2245 string, -1, NULL, 0);
2246 if (!lengthInChars) {
2247 heap_free(string);
2248 return E_UNEXPECTED;
2251 tlbstr = heap_alloc(sizeof(TLBString));
2253 tlbstr->offset = offs;
2254 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2255 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2257 heap_free(string);
2259 list_add_tail(&pcx->pLibInfo->name_list, &tlbstr->entry);
2261 offs += len_piece;
2265 static TLBString *MSFT_ReadName( TLBContext *pcx, int offset)
2267 TLBString *tlbstr;
2269 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->name_list, TLBString, entry) {
2270 if (tlbstr->offset == offset) {
2271 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2272 return tlbstr;
2276 return NULL;
2279 static TLBString *MSFT_ReadString( TLBContext *pcx, int offset)
2281 TLBString *tlbstr;
2283 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->string_list, TLBString, entry) {
2284 if (tlbstr->offset == offset) {
2285 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2286 return tlbstr;
2290 return NULL;
2294 * read a value and fill a VARIANT structure
2296 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
2298 int size;
2300 TRACE_(typelib)("\n");
2302 if(offset <0) { /* data are packed in here */
2303 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
2304 V_I4(pVar) = offset & 0x3ffffff;
2305 return;
2307 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
2308 pcx->pTblDir->pCustData.offset + offset );
2309 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
2310 switch (V_VT(pVar)){
2311 case VT_EMPTY: /* FIXME: is this right? */
2312 case VT_NULL: /* FIXME: is this right? */
2313 case VT_I2 : /* this should not happen */
2314 case VT_I4 :
2315 case VT_R4 :
2316 case VT_ERROR :
2317 case VT_BOOL :
2318 case VT_I1 :
2319 case VT_UI1 :
2320 case VT_UI2 :
2321 case VT_UI4 :
2322 case VT_INT :
2323 case VT_UINT :
2324 case VT_VOID : /* FIXME: is this right? */
2325 case VT_HRESULT :
2326 size=4; break;
2327 case VT_R8 :
2328 case VT_CY :
2329 case VT_DATE :
2330 case VT_I8 :
2331 case VT_UI8 :
2332 case VT_DECIMAL : /* FIXME: is this right? */
2333 case VT_FILETIME :
2334 size=8;break;
2335 /* pointer types with known behaviour */
2336 case VT_BSTR :{
2337 char * ptr;
2338 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
2339 if(size == -1){
2340 V_BSTR(pVar) = NULL;
2341 }else{
2342 ptr = heap_alloc_zero(size);
2343 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);
2344 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
2345 /* FIXME: do we need a AtoW conversion here? */
2346 V_UNION(pVar, bstrVal[size])='\0';
2347 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
2348 heap_free(ptr);
2351 size=-4; break;
2352 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2353 case VT_DISPATCH :
2354 case VT_VARIANT :
2355 case VT_UNKNOWN :
2356 case VT_PTR :
2357 case VT_SAFEARRAY :
2358 case VT_CARRAY :
2359 case VT_USERDEFINED :
2360 case VT_LPSTR :
2361 case VT_LPWSTR :
2362 case VT_BLOB :
2363 case VT_STREAM :
2364 case VT_STORAGE :
2365 case VT_STREAMED_OBJECT :
2366 case VT_STORED_OBJECT :
2367 case VT_BLOB_OBJECT :
2368 case VT_CF :
2369 case VT_CLSID :
2370 default:
2371 size=0;
2372 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2373 V_VT(pVar));
2376 if(size>0) /* (big|small) endian correct? */
2377 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
2378 return;
2381 * create a linked list with custom data
2383 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
2385 MSFT_CDGuid entry;
2386 TLBCustData* pNew;
2387 int count=0;
2389 TRACE_(typelib)("\n");
2391 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
2393 while(offset >=0){
2394 count++;
2395 pNew=heap_alloc_zero(sizeof(TLBCustData));
2396 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
2397 pNew->guid = MSFT_ReadGuid(entry.GuidOffset, pcx);
2398 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
2399 list_add_head(custdata_list, &pNew->entry);
2400 offset = entry.next;
2402 return count;
2405 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd)
2407 if(type <0)
2408 pTd->vt=type & VT_TYPEMASK;
2409 else
2410 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
2412 TRACE_(typelib)("vt type = %X\n", pTd->vt);
2415 static BOOL TLB_is_propgetput(INVOKEKIND invkind)
2417 return (invkind == INVOKE_PROPERTYGET ||
2418 invkind == INVOKE_PROPERTYPUT ||
2419 invkind == INVOKE_PROPERTYPUTREF);
2422 static void
2423 MSFT_DoFuncs(TLBContext* pcx,
2424 ITypeInfoImpl* pTI,
2425 int cFuncs,
2426 int cVars,
2427 int offset,
2428 TLBFuncDesc** pptfd)
2431 * member information is stored in a data structure at offset
2432 * indicated by the memoffset field of the typeinfo structure
2433 * There are several distinctive parts.
2434 * The first part starts with a field that holds the total length
2435 * of this (first) part excluding this field. Then follow the records,
2436 * for each member there is one record.
2438 * The first entry is always the length of the record (including this
2439 * length word).
2440 * The rest of the record depends on the type of the member. If there is
2441 * a field indicating the member type (function, variable, interface, etc)
2442 * I have not found it yet. At this time we depend on the information
2443 * in the type info and the usual order how things are stored.
2445 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2446 * for each member;
2448 * Third is an equal sized array with file offsets to the name entry
2449 * of each member.
2451 * The fourth and last (?) part is an array with offsets to the records
2452 * in the first part of this file segment.
2455 int infolen, nameoffset, reclength, i;
2456 int recoffset = offset + sizeof(INT);
2458 char *recbuf = heap_alloc(0xffff);
2459 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2460 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2462 TRACE_(typelib)("\n");
2464 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2466 *pptfd = TLBFuncDesc_Alloc(cFuncs);
2467 ptfd = *pptfd;
2468 for ( i = 0; i < cFuncs ; i++ )
2470 int optional;
2472 /* name, eventually add to a hash table */
2473 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2474 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2476 /* read the function information record */
2477 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2479 reclength &= 0xffff;
2481 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2483 /* size without argument data */
2484 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2485 if (pFuncRec->FKCCIC & 0x1000)
2486 optional -= pFuncRec->nrargs * sizeof(INT);
2488 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2489 ptfd->helpcontext = pFuncRec->HelpContext;
2491 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2492 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2494 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2496 if (pFuncRec->FKCCIC & 0x2000 )
2498 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2499 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2500 ptfd->Entry = (TLBString*)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2502 else
2503 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2505 else
2506 ptfd->Entry = (TLBString*)-1;
2508 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2509 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2511 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2512 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2514 /* fill the FuncDesc Structure */
2515 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2516 offset + infolen + ( i + 1) * sizeof(INT));
2518 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2519 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2520 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2521 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2522 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2523 ptfd->funcdesc.oVft = pFuncRec->VtableOffset & ~1;
2524 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2526 /* nameoffset is sometimes -1 on the second half of a propget/propput
2527 * pair of functions */
2528 if ((nameoffset == -1) && (i > 0) &&
2529 TLB_is_propgetput(ptfd_prev->funcdesc.invkind) &&
2530 TLB_is_propgetput(ptfd->funcdesc.invkind))
2531 ptfd->Name = ptfd_prev->Name;
2532 else
2533 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2535 MSFT_GetTdesc(pcx,
2536 pFuncRec->DataType,
2537 &ptfd->funcdesc.elemdescFunc.tdesc);
2539 /* do the parameters/arguments */
2540 if(pFuncRec->nrargs)
2542 int j = 0;
2543 MSFT_ParameterInfo paraminfo;
2545 ptfd->funcdesc.lprgelemdescParam =
2546 heap_alloc_zero(pFuncRec->nrargs * (sizeof(ELEMDESC) + sizeof(PARAMDESCEX)));
2548 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2550 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2551 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2553 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2555 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2557 MSFT_GetTdesc(pcx,
2558 paraminfo.DataType,
2559 &elemdesc->tdesc);
2561 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2563 /* name */
2564 if (paraminfo.oName != -1)
2565 ptfd->pParamDesc[j].Name =
2566 MSFT_ReadName( pcx, paraminfo.oName );
2567 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(TLB_get_bstr(ptfd->pParamDesc[j].Name)));
2569 /* default value */
2570 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2571 (pFuncRec->FKCCIC & 0x1000) )
2573 INT* pInt = (INT *)((char *)pFuncRec +
2574 reclength -
2575 (pFuncRec->nrargs * 4) * sizeof(INT) );
2577 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2579 pParamDesc->pparamdescex = (PARAMDESCEX*)(ptfd->funcdesc.lprgelemdescParam+pFuncRec->nrargs)+j;
2580 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2582 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2583 pInt[j], pcx);
2585 else
2586 elemdesc->u.paramdesc.pparamdescex = NULL;
2588 /* custom info */
2589 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2590 j*sizeof(pFuncRec->oArgCustData[0])) &&
2591 pFuncRec->FKCCIC & 0x80 )
2593 MSFT_CustData(pcx,
2594 pFuncRec->oArgCustData[j],
2595 &ptfd->pParamDesc[j].custdata_list);
2598 /* SEEK value = jump to offset,
2599 * from there jump to the end of record,
2600 * go back by (j-1) arguments
2602 MSFT_ReadLEDWords( &paraminfo ,
2603 sizeof(MSFT_ParameterInfo), pcx,
2604 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2605 * sizeof(MSFT_ParameterInfo)));
2609 /* scode is not used: archaic win16 stuff FIXME: right? */
2610 ptfd->funcdesc.cScodes = 0 ;
2611 ptfd->funcdesc.lprgscode = NULL ;
2613 ptfd_prev = ptfd;
2614 ++ptfd;
2615 recoffset += reclength;
2617 heap_free(recbuf);
2620 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2621 int cVars, int offset, TLBVarDesc ** pptvd)
2623 int infolen, nameoffset, reclength;
2624 char recbuf[256];
2625 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2626 TLBVarDesc *ptvd;
2627 int i;
2628 int recoffset;
2630 TRACE_(typelib)("\n");
2632 ptvd = *pptvd = TLBVarDesc_Alloc(cVars);
2633 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2634 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2635 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2636 recoffset += offset+sizeof(INT);
2637 for(i=0;i<cVars;i++, ++ptvd){
2638 /* name, eventually add to a hash table */
2639 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2640 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2641 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2642 /* read the variable information record */
2643 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2644 reclength &= 0xff;
2645 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2647 /* optional data */
2648 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2649 ptvd->HelpContext = pVarRec->HelpContext;
2651 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2652 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2654 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2655 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2657 /* fill the VarDesc Structure */
2658 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2659 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2660 ptvd->vardesc.varkind = pVarRec->VarKind;
2661 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2662 MSFT_GetTdesc(pcx, pVarRec->DataType,
2663 &ptvd->vardesc.elemdescVar.tdesc);
2664 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2665 if(pVarRec->VarKind == VAR_CONST ){
2666 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2667 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2668 pVarRec->OffsValue, pcx);
2669 } else
2670 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2671 recoffset += reclength;
2675 /* process Implemented Interfaces of a com class */
2676 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2677 int offset)
2679 int i;
2680 MSFT_RefRecord refrec;
2681 TLBImplType *pImpl;
2683 TRACE_(typelib)("\n");
2685 pTI->impltypes = TLBImplType_Alloc(count);
2686 pImpl = pTI->impltypes;
2687 for(i=0;i<count;i++){
2688 if(offset<0) break; /* paranoia */
2689 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2690 pImpl->hRef = refrec.reftype;
2691 pImpl->implflags=refrec.flags;
2692 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2693 offset=refrec.onext;
2694 ++pImpl;
2698 #ifdef _WIN64
2699 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2700 * and some structures, and fix the alignment */
2701 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl *info)
2703 if(info->typekind == TKIND_ALIAS){
2704 switch(info->tdescAlias->vt){
2705 case VT_BSTR:
2706 case VT_DISPATCH:
2707 case VT_UNKNOWN:
2708 case VT_PTR:
2709 case VT_SAFEARRAY:
2710 case VT_LPSTR:
2711 case VT_LPWSTR:
2712 info->cbSizeInstance = sizeof(void*);
2713 info->cbAlignment = sizeof(void*);
2714 break;
2715 case VT_CARRAY:
2716 case VT_USERDEFINED:
2717 TLB_size_instance(info, SYS_WIN64, info->tdescAlias, &info->cbSizeInstance, &info->cbAlignment);
2718 break;
2719 case VT_VARIANT:
2720 info->cbSizeInstance = sizeof(VARIANT);
2721 info->cbAlignment = 8;
2722 default:
2723 if(info->cbSizeInstance < sizeof(void*))
2724 info->cbAlignment = info->cbSizeInstance;
2725 else
2726 info->cbAlignment = sizeof(void*);
2727 break;
2729 }else if(info->typekind == TKIND_INTERFACE ||
2730 info->typekind == TKIND_DISPATCH ||
2731 info->typekind == TKIND_COCLASS){
2732 info->cbSizeInstance = sizeof(void*);
2733 info->cbAlignment = sizeof(void*);
2736 #endif
2739 * process a typeinfo record
2741 static ITypeInfoImpl * MSFT_DoTypeInfo(
2742 TLBContext *pcx,
2743 int count,
2744 ITypeLibImpl * pLibInfo)
2746 MSFT_TypeInfoBase tiBase;
2747 ITypeInfoImpl *ptiRet;
2749 TRACE_(typelib)("count=%u\n", count);
2751 ptiRet = ITypeInfoImpl_Constructor();
2752 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2753 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2755 /* this is where we are coming from */
2756 ptiRet->pTypeLib = pLibInfo;
2757 ptiRet->index=count;
2759 ptiRet->guid = MSFT_ReadGuid(tiBase.posguid, pcx);
2760 ptiRet->lcid=pLibInfo->set_lcid; /* FIXME: correct? */
2761 ptiRet->lpstrSchema=NULL; /* reserved */
2762 ptiRet->cbSizeInstance=tiBase.size;
2763 ptiRet->typekind=tiBase.typekind & 0xF;
2764 ptiRet->cFuncs=LOWORD(tiBase.cElement);
2765 ptiRet->cVars=HIWORD(tiBase.cElement);
2766 ptiRet->cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2767 ptiRet->wTypeFlags=tiBase.flags;
2768 ptiRet->wMajorVerNum=LOWORD(tiBase.version);
2769 ptiRet->wMinorVerNum=HIWORD(tiBase.version);
2770 ptiRet->cImplTypes=tiBase.cImplTypes;
2771 ptiRet->cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2772 if(ptiRet->typekind == TKIND_ALIAS){
2773 TYPEDESC tmp;
2774 MSFT_GetTdesc(pcx, tiBase.datatype1, &tmp);
2775 ptiRet->tdescAlias = heap_alloc(TLB_SizeTypeDesc(&tmp, TRUE));
2776 TLB_CopyTypeDesc(NULL, &tmp, ptiRet->tdescAlias);
2779 /* FIXME: */
2780 /* IDLDESC idldescType; *//* never saw this one != zero */
2782 /* name, eventually add to a hash table */
2783 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2784 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2785 TRACE_(typelib)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet->Name)));
2786 /* help info */
2787 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2788 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2789 ptiRet->dwHelpContext=tiBase.helpcontext;
2791 if (ptiRet->typekind == TKIND_MODULE)
2792 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2794 /* note: InfoType's Help file and HelpStringDll come from the containing
2795 * library. Further HelpString and Docstring appear to be the same thing :(
2797 /* functions */
2798 if(ptiRet->cFuncs >0 )
2799 MSFT_DoFuncs(pcx, ptiRet, ptiRet->cFuncs,
2800 ptiRet->cVars,
2801 tiBase.memoffset, &ptiRet->funcdescs);
2802 /* variables */
2803 if(ptiRet->cVars >0 )
2804 MSFT_DoVars(pcx, ptiRet, ptiRet->cFuncs,
2805 ptiRet->cVars,
2806 tiBase.memoffset, &ptiRet->vardescs);
2807 if(ptiRet->cImplTypes >0 ) {
2808 switch(ptiRet->typekind)
2810 case TKIND_COCLASS:
2811 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->cImplTypes,
2812 tiBase.datatype1);
2813 break;
2814 case TKIND_DISPATCH:
2815 /* This is not -1 when the interface is a non-base dual interface or
2816 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2817 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2818 not this interface.
2821 if (tiBase.datatype1 != -1)
2823 ptiRet->impltypes = TLBImplType_Alloc(1);
2824 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2826 break;
2827 default:
2828 ptiRet->impltypes = TLBImplType_Alloc(1);
2829 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2830 break;
2833 MSFT_CustData(pcx, tiBase.oCustData, ptiRet->pcustdata_list);
2835 TRACE_(typelib)("%s guid: %s kind:%s\n",
2836 debugstr_w(TLB_get_bstr(ptiRet->Name)),
2837 debugstr_guid(TLB_get_guidref(ptiRet->guid)),
2838 typekind_desc[ptiRet->typekind]);
2839 if (TRACE_ON(typelib))
2840 dump_TypeInfo(ptiRet);
2842 return ptiRet;
2845 static HRESULT MSFT_ReadAllStrings(TLBContext *pcx)
2847 char *string;
2848 INT16 len_str, len_piece;
2849 int offs = 0, lengthInChars;
2851 MSFT_Seek(pcx, pcx->pTblDir->pStringtab.offset);
2852 while (1) {
2853 TLBString *tlbstr;
2855 if (offs >= pcx->pTblDir->pStringtab.length)
2856 return S_OK;
2858 MSFT_ReadLEWords(&len_str, sizeof(INT16), pcx, DO_NOT_SEEK);
2859 len_piece = len_str + sizeof(INT16);
2860 if(len_piece % 4)
2861 len_piece = (len_piece + 4) & ~0x3;
2862 if(len_piece < 8)
2863 len_piece = 8;
2865 string = heap_alloc(len_piece + 1);
2866 MSFT_Read(string, len_piece - sizeof(INT16), pcx, DO_NOT_SEEK);
2867 string[len_str] = '\0';
2869 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2870 string, -1, NULL, 0);
2871 if (!lengthInChars) {
2872 heap_free(string);
2873 return E_UNEXPECTED;
2876 tlbstr = heap_alloc(sizeof(TLBString));
2878 tlbstr->offset = offs;
2879 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2880 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2882 heap_free(string);
2884 list_add_tail(&pcx->pLibInfo->string_list, &tlbstr->entry);
2886 offs += len_piece;
2890 static HRESULT MSFT_ReadAllRefs(TLBContext *pcx)
2892 TLBRefType *ref;
2893 int offs = 0;
2895 MSFT_Seek(pcx, pcx->pTblDir->pImpInfo.offset);
2896 while (offs < pcx->pTblDir->pImpInfo.length) {
2897 MSFT_ImpInfo impinfo;
2898 TLBImpLib *pImpLib;
2900 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx, DO_NOT_SEEK);
2902 ref = heap_alloc_zero(sizeof(TLBRefType));
2903 list_add_tail(&pcx->pLibInfo->ref_list, &ref->entry);
2905 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2906 if(pImpLib->offset==impinfo.oImpFile)
2907 break;
2909 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2910 ref->reference = offs;
2911 ref->pImpTLInfo = pImpLib;
2912 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2913 ref->guid = MSFT_ReadGuid(impinfo.oGuid, pcx);
2914 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
2915 ref->index = TLB_REF_USE_GUID;
2916 } else
2917 ref->index = impinfo.oGuid;
2918 }else{
2919 ERR("Cannot find a reference\n");
2920 ref->reference = -1;
2921 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2924 offs += sizeof(impinfo);
2927 return S_OK;
2930 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2931 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2932 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2933 * tradeoff here.
2935 static struct list tlb_cache = LIST_INIT(tlb_cache);
2936 static CRITICAL_SECTION cache_section;
2937 static CRITICAL_SECTION_DEBUG cache_section_debug =
2939 0, 0, &cache_section,
2940 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2941 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2943 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2946 typedef struct TLB_PEFile
2948 IUnknown IUnknown_iface;
2949 LONG refs;
2950 HMODULE dll;
2951 HRSRC typelib_resource;
2952 HGLOBAL typelib_global;
2953 LPVOID typelib_base;
2954 } TLB_PEFile;
2956 static inline TLB_PEFile *pefile_impl_from_IUnknown(IUnknown *iface)
2958 return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2961 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2963 if (IsEqualIID(riid, &IID_IUnknown))
2965 *ppv = iface;
2966 IUnknown_AddRef(iface);
2967 return S_OK;
2969 *ppv = NULL;
2970 return E_NOINTERFACE;
2973 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2975 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2976 return InterlockedIncrement(&This->refs);
2979 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2981 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2982 ULONG refs = InterlockedDecrement(&This->refs);
2983 if (!refs)
2985 if (This->typelib_global)
2986 FreeResource(This->typelib_global);
2987 if (This->dll)
2988 FreeLibrary(This->dll);
2989 heap_free(This);
2991 return refs;
2994 static const IUnknownVtbl TLB_PEFile_Vtable =
2996 TLB_PEFile_QueryInterface,
2997 TLB_PEFile_AddRef,
2998 TLB_PEFile_Release
3001 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
3003 TLB_PEFile *This;
3004 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
3006 This = heap_alloc(sizeof(TLB_PEFile));
3007 if (!This)
3008 return E_OUTOFMEMORY;
3010 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
3011 This->refs = 1;
3012 This->dll = NULL;
3013 This->typelib_resource = NULL;
3014 This->typelib_global = NULL;
3015 This->typelib_base = NULL;
3017 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
3018 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
3020 if (This->dll)
3022 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
3023 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
3024 if (This->typelib_resource)
3026 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
3027 if (This->typelib_global)
3029 This->typelib_base = LockResource(This->typelib_global);
3031 if (This->typelib_base)
3033 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
3034 *ppBase = This->typelib_base;
3035 *ppFile = &This->IUnknown_iface;
3036 return S_OK;
3041 TRACE("No TYPELIB resource found\n");
3042 hr = E_FAIL;
3045 TLB_PEFile_Release(&This->IUnknown_iface);
3046 return hr;
3049 typedef struct TLB_NEFile
3051 IUnknown IUnknown_iface;
3052 LONG refs;
3053 LPVOID typelib_base;
3054 } TLB_NEFile;
3056 static inline TLB_NEFile *nefile_impl_from_IUnknown(IUnknown *iface)
3058 return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
3061 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3063 if (IsEqualIID(riid, &IID_IUnknown))
3065 *ppv = iface;
3066 IUnknown_AddRef(iface);
3067 return S_OK;
3069 *ppv = NULL;
3070 return E_NOINTERFACE;
3073 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
3075 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
3076 return InterlockedIncrement(&This->refs);
3079 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
3081 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
3082 ULONG refs = InterlockedDecrement(&This->refs);
3083 if (!refs)
3085 heap_free(This->typelib_base);
3086 heap_free(This);
3088 return refs;
3091 static const IUnknownVtbl TLB_NEFile_Vtable =
3093 TLB_NEFile_QueryInterface,
3094 TLB_NEFile_AddRef,
3095 TLB_NEFile_Release
3098 /***********************************************************************
3099 * read_xx_header [internal]
3101 static int read_xx_header( HFILE lzfd )
3103 IMAGE_DOS_HEADER mzh;
3104 char magic[3];
3106 LZSeek( lzfd, 0, SEEK_SET );
3107 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
3108 return 0;
3109 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
3110 return 0;
3112 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3113 if ( 2 != LZRead( lzfd, magic, 2 ) )
3114 return 0;
3116 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3118 if ( magic[0] == 'N' && magic[1] == 'E' )
3119 return IMAGE_OS2_SIGNATURE;
3120 if ( magic[0] == 'P' && magic[1] == 'E' )
3121 return IMAGE_NT_SIGNATURE;
3123 magic[2] = '\0';
3124 WARN("Can't handle %s files.\n", magic );
3125 return 0;
3129 /***********************************************************************
3130 * find_ne_resource [internal]
3132 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
3133 DWORD *resLen, DWORD *resOff )
3135 IMAGE_OS2_HEADER nehd;
3136 NE_TYPEINFO *typeInfo;
3137 NE_NAMEINFO *nameInfo;
3138 DWORD nehdoffset;
3139 LPBYTE resTab;
3140 DWORD resTabSize;
3141 int count;
3143 /* Read in NE header */
3144 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
3145 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return FALSE;
3147 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
3148 if ( !resTabSize )
3150 TRACE("No resources in NE dll\n" );
3151 return FALSE;
3154 /* Read in resource table */
3155 resTab = heap_alloc( resTabSize );
3156 if ( !resTab ) return FALSE;
3158 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
3159 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
3161 heap_free( resTab );
3162 return FALSE;
3165 /* Find resource */
3166 typeInfo = (NE_TYPEINFO *)(resTab + 2);
3168 if (!IS_INTRESOURCE(typeid)) /* named type */
3170 BYTE len = strlen( typeid );
3171 while (typeInfo->type_id)
3173 if (!(typeInfo->type_id & 0x8000))
3175 BYTE *p = resTab + typeInfo->type_id;
3176 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
3178 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3179 typeInfo->count * sizeof(NE_NAMEINFO));
3182 else /* numeric type id */
3184 WORD id = LOWORD(typeid) | 0x8000;
3185 while (typeInfo->type_id)
3187 if (typeInfo->type_id == id) goto found_type;
3188 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3189 typeInfo->count * sizeof(NE_NAMEINFO));
3192 TRACE("No typeid entry found for %p\n", typeid );
3193 heap_free( resTab );
3194 return FALSE;
3196 found_type:
3197 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
3199 if (!IS_INTRESOURCE(resid)) /* named resource */
3201 BYTE len = strlen( resid );
3202 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3204 BYTE *p = resTab + nameInfo->id;
3205 if (nameInfo->id & 0x8000) continue;
3206 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
3209 else /* numeric resource id */
3211 WORD id = LOWORD(resid) | 0x8000;
3212 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3213 if (nameInfo->id == id) goto found_name;
3215 TRACE("No resid entry found for %p\n", typeid );
3216 heap_free( resTab );
3217 return FALSE;
3219 found_name:
3220 /* Return resource data */
3221 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
3222 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
3224 heap_free( resTab );
3225 return TRUE;
3228 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
3230 HFILE lzfd = -1;
3231 OFSTRUCT ofs;
3232 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
3233 TLB_NEFile *This;
3235 This = heap_alloc(sizeof(TLB_NEFile));
3236 if (!This) return E_OUTOFMEMORY;
3238 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
3239 This->refs = 1;
3240 This->typelib_base = NULL;
3242 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
3243 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
3245 DWORD reslen, offset;
3246 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
3248 This->typelib_base = heap_alloc(reslen);
3249 if( !This->typelib_base )
3250 hr = E_OUTOFMEMORY;
3251 else
3253 LZSeek( lzfd, offset, SEEK_SET );
3254 reslen = LZRead( lzfd, This->typelib_base, reslen );
3255 LZClose( lzfd );
3256 *ppBase = This->typelib_base;
3257 *pdwTLBLength = reslen;
3258 *ppFile = &This->IUnknown_iface;
3259 return S_OK;
3264 if( lzfd >= 0) LZClose( lzfd );
3265 TLB_NEFile_Release(&This->IUnknown_iface);
3266 return hr;
3269 typedef struct TLB_Mapping
3271 IUnknown IUnknown_iface;
3272 LONG refs;
3273 HANDLE file;
3274 HANDLE mapping;
3275 LPVOID typelib_base;
3276 } TLB_Mapping;
3278 static inline TLB_Mapping *mapping_impl_from_IUnknown(IUnknown *iface)
3280 return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
3283 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3285 if (IsEqualIID(riid, &IID_IUnknown))
3287 *ppv = iface;
3288 IUnknown_AddRef(iface);
3289 return S_OK;
3291 *ppv = NULL;
3292 return E_NOINTERFACE;
3295 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
3297 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3298 return InterlockedIncrement(&This->refs);
3301 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
3303 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3304 ULONG refs = InterlockedDecrement(&This->refs);
3305 if (!refs)
3307 if (This->typelib_base)
3308 UnmapViewOfFile(This->typelib_base);
3309 if (This->mapping)
3310 CloseHandle(This->mapping);
3311 if (This->file != INVALID_HANDLE_VALUE)
3312 CloseHandle(This->file);
3313 heap_free(This);
3315 return refs;
3318 static const IUnknownVtbl TLB_Mapping_Vtable =
3320 TLB_Mapping_QueryInterface,
3321 TLB_Mapping_AddRef,
3322 TLB_Mapping_Release
3325 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
3327 TLB_Mapping *This;
3329 This = heap_alloc(sizeof(TLB_Mapping));
3330 if (!This)
3331 return E_OUTOFMEMORY;
3333 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
3334 This->refs = 1;
3335 This->file = INVALID_HANDLE_VALUE;
3336 This->mapping = NULL;
3337 This->typelib_base = NULL;
3339 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3340 if (INVALID_HANDLE_VALUE != This->file)
3342 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
3343 if (This->mapping)
3345 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
3346 if(This->typelib_base)
3348 /* retrieve file size */
3349 *pdwTLBLength = GetFileSize(This->file, NULL);
3350 *ppBase = This->typelib_base;
3351 *ppFile = &This->IUnknown_iface;
3352 return S_OK;
3357 IUnknown_Release(&This->IUnknown_iface);
3358 return TYPE_E_CANTLOADLIBRARY;
3361 /****************************************************************************
3362 * TLB_ReadTypeLib
3364 * find the type of the typelib file and map the typelib resource into
3365 * the memory
3368 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3369 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
3371 ITypeLibImpl *entry;
3372 HRESULT ret;
3373 INT index = 1;
3374 LPWSTR index_str, file = (LPWSTR)pszFileName;
3375 LPVOID pBase = NULL;
3376 DWORD dwTLBLength = 0;
3377 IUnknown *pFile = NULL;
3378 HANDLE h;
3380 *ppTypeLib = NULL;
3382 index_str = strrchrW(pszFileName, '\\');
3383 if(index_str && *++index_str != '\0')
3385 LPWSTR end_ptr;
3386 LONG idx = strtolW(index_str, &end_ptr, 10);
3387 if(*end_ptr == '\0')
3389 int str_len = index_str - pszFileName - 1;
3390 index = idx;
3391 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
3392 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
3393 file[str_len] = 0;
3397 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
3399 if(strchrW(file, '\\'))
3401 lstrcpyW(pszPath, file);
3403 else
3405 int len = GetSystemDirectoryW(pszPath, cchPath);
3406 pszPath[len] = '\\';
3407 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
3411 if(file != pszFileName) heap_free(file);
3413 h = CreateFileW(pszPath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
3414 if(h != INVALID_HANDLE_VALUE){
3415 FILE_NAME_INFORMATION *info;
3416 char data[MAX_PATH * sizeof(WCHAR) + sizeof(info->FileNameLength)];
3417 BOOL br;
3419 info = (FILE_NAME_INFORMATION*)data;
3420 /* GetFileInformationByHandleEx returns the path of the file without
3421 * WOW64 redirection */
3422 br = GetFileInformationByHandleEx(h, FileNameInfo, data, sizeof(data));
3423 if(br){
3424 info->FileName[info->FileNameLength / sizeof(WCHAR)] = 0;
3425 lstrcpynW(pszPath + 2, info->FileName, cchPath - 2);
3427 CloseHandle(h);
3430 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
3432 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3433 EnterCriticalSection(&cache_section);
3434 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
3436 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
3438 TRACE("cache hit\n");
3439 *ppTypeLib = &entry->ITypeLib2_iface;
3440 ITypeLib2_AddRef(*ppTypeLib);
3441 LeaveCriticalSection(&cache_section);
3442 return S_OK;
3445 LeaveCriticalSection(&cache_section);
3447 /* now actually load and parse the typelib */
3449 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3450 if (ret == TYPE_E_CANTLOADLIBRARY)
3451 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3452 if (ret == TYPE_E_CANTLOADLIBRARY)
3453 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
3454 if (SUCCEEDED(ret))
3456 if (dwTLBLength >= 4)
3458 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
3459 if (dwSignature == MSFT_SIGNATURE)
3460 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
3461 else if (dwSignature == SLTG_SIGNATURE)
3462 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
3463 else
3465 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
3466 ret = TYPE_E_CANTLOADLIBRARY;
3469 else
3470 ret = TYPE_E_CANTLOADLIBRARY;
3471 IUnknown_Release(pFile);
3474 if(*ppTypeLib) {
3475 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
3477 TRACE("adding to cache\n");
3478 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
3479 lstrcpyW(impl->path, pszPath);
3480 /* We should really canonicalise the path here. */
3481 impl->index = index;
3483 /* FIXME: check if it has added already in the meantime */
3484 EnterCriticalSection(&cache_section);
3485 list_add_head(&tlb_cache, &impl->entry);
3486 LeaveCriticalSection(&cache_section);
3487 ret = S_OK;
3489 else
3491 if(ret != E_FAIL)
3492 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
3494 ret = TYPE_E_CANTLOADLIBRARY;
3498 return ret;
3501 /*================== ITypeLib(2) Methods ===================================*/
3503 static ITypeLibImpl* TypeLibImpl_Constructor(void)
3505 ITypeLibImpl* pTypeLibImpl;
3507 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
3508 if (!pTypeLibImpl) return NULL;
3510 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3511 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3512 pTypeLibImpl->ICreateTypeLib2_iface.lpVtbl = &CreateTypeLib2Vtbl;
3513 pTypeLibImpl->ref = 1;
3515 list_init(&pTypeLibImpl->implib_list);
3516 list_init(&pTypeLibImpl->custdata_list);
3517 list_init(&pTypeLibImpl->name_list);
3518 list_init(&pTypeLibImpl->string_list);
3519 list_init(&pTypeLibImpl->guid_list);
3520 list_init(&pTypeLibImpl->ref_list);
3521 pTypeLibImpl->dispatch_href = -1;
3523 return pTypeLibImpl;
3526 /****************************************************************************
3527 * ITypeLib2_Constructor_MSFT
3529 * loading an MSFT typelib from an in-memory image
3531 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3533 TLBContext cx;
3534 LONG lPSegDir;
3535 MSFT_Header tlbHeader;
3536 MSFT_SegDir tlbSegDir;
3537 ITypeLibImpl * pTypeLibImpl;
3538 int i;
3540 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3542 pTypeLibImpl = TypeLibImpl_Constructor();
3543 if (!pTypeLibImpl) return NULL;
3545 /* get pointer to beginning of typelib data */
3546 cx.pos = 0;
3547 cx.oStart=0;
3548 cx.mapping = pLib;
3549 cx.pLibInfo = pTypeLibImpl;
3550 cx.length = dwTLBLength;
3552 /* read header */
3553 MSFT_ReadLEDWords(&tlbHeader, sizeof(tlbHeader), &cx, 0);
3554 TRACE_(typelib)("header:\n");
3555 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3556 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3557 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3558 return NULL;
3560 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3562 /* there is a small amount of information here until the next important
3563 * part:
3564 * the segment directory . Try to calculate the amount of data */
3565 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3567 /* now read the segment directory */
3568 TRACE("read segment directory (at %d)\n",lPSegDir);
3569 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3570 cx.pTblDir = &tlbSegDir;
3572 /* just check two entries */
3573 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3575 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3576 heap_free(pTypeLibImpl);
3577 return NULL;
3580 MSFT_ReadAllNames(&cx);
3581 MSFT_ReadAllStrings(&cx);
3582 MSFT_ReadAllGuids(&cx);
3584 /* now fill our internal data */
3585 /* TLIBATTR fields */
3586 pTypeLibImpl->guid = MSFT_ReadGuid(tlbHeader.posguid, &cx);
3588 pTypeLibImpl->syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3589 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3590 pTypeLibImpl->ver_major = LOWORD(tlbHeader.version);
3591 pTypeLibImpl->ver_minor = HIWORD(tlbHeader.version);
3592 pTypeLibImpl->libflags = ((WORD) tlbHeader.flags & 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE;
3594 pTypeLibImpl->set_lcid = tlbHeader.lcid2;
3595 pTypeLibImpl->lcid = tlbHeader.lcid;
3597 /* name, eventually add to a hash table */
3598 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3600 /* help info */
3601 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3602 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3604 if( tlbHeader.varflags & HELPDLLFLAG)
3606 int offset;
3607 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3608 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3611 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3613 /* custom data */
3614 if(tlbHeader.CustomDataOffset >= 0)
3616 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3619 /* fill in type descriptions */
3620 if(tlbSegDir.pTypdescTab.length > 0)
3622 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3623 INT16 td[4];
3624 pTypeLibImpl->ctTypeDesc = cTD;
3625 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3626 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3627 for(i=0; i<cTD; )
3629 /* FIXME: add several sanity checks here */
3630 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3631 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3633 /* FIXME: check safearray */
3634 if(td[3] < 0)
3635 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3636 else
3637 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3639 else if(td[0] == VT_CARRAY)
3641 /* array descr table here */
3642 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3644 else if(td[0] == VT_USERDEFINED)
3646 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3648 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3651 /* second time around to fill the array subscript info */
3652 for(i=0;i<cTD;i++)
3654 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3655 if(tlbSegDir.pArrayDescriptions.offset>0)
3657 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3658 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3660 if(td[1]<0)
3661 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3662 else
3663 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3665 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3667 for(j = 0; j<td[2]; j++)
3669 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3670 sizeof(INT), &cx, DO_NOT_SEEK);
3671 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3672 sizeof(INT), &cx, DO_NOT_SEEK);
3675 else
3677 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3678 ERR("didn't find array description data\n");
3683 /* imported type libs */
3684 if(tlbSegDir.pImpFiles.offset>0)
3686 TLBImpLib *pImpLib;
3687 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3688 UINT16 size;
3690 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3692 char *name;
3694 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3695 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3696 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3698 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3699 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3700 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3701 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3703 size >>= 2;
3704 name = heap_alloc_zero(size+1);
3705 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3706 pImpLib->name = TLB_MultiByteToBSTR(name);
3707 heap_free(name);
3709 pImpLib->guid = MSFT_ReadGuid(oGuid, &cx);
3710 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3712 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3716 MSFT_ReadAllRefs(&cx);
3718 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3720 /* type infos */
3721 if(tlbHeader.nrtypeinfos >= 0 )
3723 ITypeInfoImpl **ppTI;
3725 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3727 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3729 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3731 ++ppTI;
3732 (pTypeLibImpl->TypeInfoCount)++;
3736 #ifdef _WIN64
3737 if(pTypeLibImpl->syskind == SYS_WIN32){
3738 for(i = 0; i < pTypeLibImpl->TypeInfoCount; ++i)
3739 TLB_fix_32on64_typeinfo(pTypeLibImpl->typeinfos[i]);
3741 #endif
3743 TRACE("(%p)\n", pTypeLibImpl);
3744 return &pTypeLibImpl->ITypeLib2_iface;
3748 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3750 char b[3];
3751 int i;
3752 short s;
3754 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3755 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3756 return FALSE;
3759 guid->Data4[0] = s >> 8;
3760 guid->Data4[1] = s & 0xff;
3762 b[2] = '\0';
3763 for(i = 0; i < 6; i++) {
3764 memcpy(b, str + 24 + 2 * i, 2);
3765 guid->Data4[i + 2] = strtol(b, NULL, 16);
3767 return TRUE;
3770 static WORD SLTG_ReadString(const char *ptr, const TLBString **pStr, ITypeLibImpl *lib)
3772 WORD bytelen;
3773 DWORD len;
3774 BSTR tmp_str;
3776 *pStr = NULL;
3777 bytelen = *(const WORD*)ptr;
3778 if(bytelen == 0xffff) return 2;
3780 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3781 tmp_str = SysAllocStringLen(NULL, len);
3782 if (tmp_str) {
3783 MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, tmp_str, len);
3784 *pStr = TLB_append_str(&lib->string_list, tmp_str);
3785 SysFreeString(tmp_str);
3787 return bytelen + 2;
3790 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3792 WORD bytelen;
3794 *str = NULL;
3795 bytelen = *(const WORD*)ptr;
3796 if(bytelen == 0xffff) return 2;
3797 *str = heap_alloc(bytelen + 1);
3798 memcpy(*str, ptr + 2, bytelen);
3799 (*str)[bytelen] = '\0';
3800 return bytelen + 2;
3803 static TLBString *SLTG_ReadName(const char *pNameTable, int offset, ITypeLibImpl *lib)
3805 BSTR tmp_str;
3806 TLBString *tlbstr;
3808 LIST_FOR_EACH_ENTRY(tlbstr, &lib->name_list, TLBString, entry) {
3809 if (tlbstr->offset == offset)
3810 return tlbstr;
3813 tmp_str = TLB_MultiByteToBSTR(pNameTable + offset);
3814 tlbstr = TLB_append_str(&lib->name_list, tmp_str);
3815 SysFreeString(tmp_str);
3817 return tlbstr;
3820 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3822 char *ptr = pLibBlk;
3823 WORD w;
3825 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3826 FIXME("libblk magic = %04x\n", w);
3827 return 0;
3830 ptr += 6;
3831 if((w = *(WORD*)ptr) != 0xffff) {
3832 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3833 ptr += w;
3835 ptr += 2;
3837 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString, pTypeLibImpl);
3839 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile, pTypeLibImpl);
3841 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3842 ptr += 4;
3844 pTypeLibImpl->syskind = *(WORD*)ptr;
3845 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3846 ptr += 2;
3848 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3849 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3850 else
3851 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = 0;
3852 ptr += 2;
3854 ptr += 4; /* skip res12 */
3856 pTypeLibImpl->libflags = *(WORD*)ptr;
3857 ptr += 2;
3859 pTypeLibImpl->ver_major = *(WORD*)ptr;
3860 ptr += 2;
3862 pTypeLibImpl->ver_minor = *(WORD*)ptr;
3863 ptr += 2;
3865 pTypeLibImpl->guid = TLB_append_guid(&pTypeLibImpl->guid_list, (GUID*)ptr, -2);
3866 ptr += sizeof(GUID);
3868 return ptr - (char*)pLibBlk;
3871 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3872 typedef struct
3874 unsigned int num;
3875 HREFTYPE refs[1];
3876 } sltg_ref_lookup_t;
3878 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3879 HREFTYPE *typelib_ref)
3881 if(table && typeinfo_ref < table->num)
3883 *typelib_ref = table->refs[typeinfo_ref];
3884 return S_OK;
3887 ERR_(typelib)("Unable to find reference\n");
3888 *typelib_ref = -1;
3889 return E_FAIL;
3892 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3894 BOOL done = FALSE;
3896 while(!done) {
3897 if((*pType & 0xe00) == 0xe00) {
3898 pTD->vt = VT_PTR;
3899 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3900 pTD = pTD->u.lptdesc;
3902 switch(*pType & 0x3f) {
3903 case VT_PTR:
3904 pTD->vt = VT_PTR;
3905 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3906 pTD = pTD->u.lptdesc;
3907 break;
3909 case VT_USERDEFINED:
3910 pTD->vt = VT_USERDEFINED;
3911 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3912 done = TRUE;
3913 break;
3915 case VT_CARRAY:
3917 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3918 array */
3920 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3922 pTD->vt = VT_CARRAY;
3923 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3924 pTD->u.lpadesc->cDims = pSA->cDims;
3925 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3926 pSA->cDims * sizeof(SAFEARRAYBOUND));
3928 pTD = &pTD->u.lpadesc->tdescElem;
3929 break;
3932 case VT_SAFEARRAY:
3934 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3935 useful? */
3937 pType++;
3938 pTD->vt = VT_SAFEARRAY;
3939 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3940 pTD = pTD->u.lptdesc;
3941 break;
3943 default:
3944 pTD->vt = *pType & 0x3f;
3945 done = TRUE;
3946 break;
3948 pType++;
3950 return pType;
3953 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3954 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3956 /* Handle [in/out] first */
3957 if((*pType & 0xc000) == 0xc000)
3958 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3959 else if(*pType & 0x8000)
3960 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3961 else if(*pType & 0x4000)
3962 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3963 else
3964 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3966 if(*pType & 0x2000)
3967 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3969 if(*pType & 0x80)
3970 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3972 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3976 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3977 char *pNameTable)
3979 unsigned int ref;
3980 char *name;
3981 TLBRefType *ref_type;
3982 sltg_ref_lookup_t *table;
3983 HREFTYPE typelib_ref;
3985 if(pRef->magic != SLTG_REF_MAGIC) {
3986 FIXME("Ref magic = %x\n", pRef->magic);
3987 return NULL;
3989 name = ( (char*)pRef->names + pRef->number);
3991 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3992 table->num = pRef->number >> 3;
3994 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3996 /* We don't want the first href to be 0 */
3997 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3999 for(ref = 0; ref < pRef->number >> 3; ref++) {
4000 char *refname;
4001 unsigned int lib_offs, type_num;
4003 ref_type = heap_alloc_zero(sizeof(TLBRefType));
4005 name += SLTG_ReadStringA(name, &refname);
4006 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
4007 FIXME_(typelib)("Can't sscanf ref\n");
4008 if(lib_offs != 0xffff) {
4009 TLBImpLib *import;
4011 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
4012 if(import->offset == lib_offs)
4013 break;
4015 if(&import->entry == &pTL->implib_list) {
4016 char fname[MAX_PATH+1];
4017 int len;
4018 GUID tmpguid;
4020 import = heap_alloc_zero(sizeof(*import));
4021 import->offset = lib_offs;
4022 TLB_GUIDFromString( pNameTable + lib_offs + 4, &tmpguid);
4023 import->guid = TLB_append_guid(&pTL->guid_list, &tmpguid, 2);
4024 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
4025 &import->wVersionMajor,
4026 &import->wVersionMinor,
4027 &import->lcid, fname) != 4) {
4028 FIXME_(typelib)("can't sscanf ref %s\n",
4029 pNameTable + lib_offs + 40);
4031 len = strlen(fname);
4032 if(fname[len-1] != '#')
4033 FIXME("fname = %s\n", fname);
4034 fname[len-1] = '\0';
4035 import->name = TLB_MultiByteToBSTR(fname);
4036 list_add_tail(&pTL->implib_list, &import->entry);
4038 ref_type->pImpTLInfo = import;
4040 /* Store a reference to IDispatch */
4041 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid->guid, &IID_StdOle) && type_num == 4)
4042 pTL->dispatch_href = typelib_ref;
4044 } else { /* internal ref */
4045 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
4047 ref_type->reference = typelib_ref;
4048 ref_type->index = type_num;
4050 heap_free(refname);
4051 list_add_tail(&pTL->ref_list, &ref_type->entry);
4053 table->refs[ref] = typelib_ref;
4054 typelib_ref += 4;
4056 if((BYTE)*name != SLTG_REF_MAGIC)
4057 FIXME_(typelib)("End of ref block magic = %x\n", *name);
4058 dump_TLBRefType(pTL);
4059 return table;
4062 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
4063 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
4065 SLTG_ImplInfo *info;
4066 TLBImplType *pImplType;
4067 /* I don't really get this structure, usually it's 0x16 bytes
4068 long, but iuser.tlb contains some that are 0x18 bytes long.
4069 That's ok because we can use the next ptr to jump to the next
4070 one. But how do we know the length of the last one? The WORD
4071 at offs 0x8 might be the clue. For now I'm just assuming that
4072 the last one is the regular 0x16 bytes. */
4074 info = (SLTG_ImplInfo*)pBlk;
4075 while(1){
4076 pTI->cImplTypes++;
4077 if(info->next == 0xffff)
4078 break;
4079 info = (SLTG_ImplInfo*)(pBlk + info->next);
4082 info = (SLTG_ImplInfo*)pBlk;
4083 pTI->impltypes = TLBImplType_Alloc(pTI->cImplTypes);
4084 pImplType = pTI->impltypes;
4085 while(1) {
4086 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
4087 pImplType->implflags = info->impltypeflags;
4088 ++pImplType;
4090 if(info->next == 0xffff)
4091 break;
4092 if(OneOnly)
4093 FIXME_(typelib)("Interface inheriting more than one interface\n");
4094 info = (SLTG_ImplInfo*)(pBlk + info->next);
4096 info++; /* see comment at top of function */
4097 return (char*)info;
4100 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
4101 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4103 TLBVarDesc *pVarDesc;
4104 const TLBString *prevName = NULL;
4105 SLTG_Variable *pItem;
4106 unsigned short i;
4107 WORD *pType;
4109 pVarDesc = pTI->vardescs = TLBVarDesc_Alloc(cVars);
4111 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
4112 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
4114 pVarDesc->vardesc.memid = pItem->memid;
4116 if (pItem->magic != SLTG_VAR_MAGIC &&
4117 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
4118 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
4119 return;
4122 if (pItem->name == 0xfffe)
4123 pVarDesc->Name = prevName;
4124 else
4125 pVarDesc->Name = SLTG_ReadName(pNameTable, pItem->name, pTI->pTypeLib);
4127 TRACE_(typelib)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc->Name)));
4128 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
4129 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
4131 if(pItem->flags & 0x02)
4132 pType = &pItem->type;
4133 else
4134 pType = (WORD*)(pBlk + pItem->type);
4136 if (pItem->flags & ~0xda)
4137 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
4139 SLTG_DoElem(pType, pBlk,
4140 &pVarDesc->vardesc.elemdescVar, ref_lookup);
4142 if (TRACE_ON(typelib)) {
4143 char buf[300];
4144 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
4145 TRACE_(typelib)("elemdescVar: %s\n", buf);
4148 if (pItem->flags & 0x40) {
4149 TRACE_(typelib)("VAR_DISPATCH\n");
4150 pVarDesc->vardesc.varkind = VAR_DISPATCH;
4152 else if (pItem->flags & 0x10) {
4153 TRACE_(typelib)("VAR_CONST\n");
4154 pVarDesc->vardesc.varkind = VAR_CONST;
4155 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
4156 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
4157 if (pItem->flags & 0x08)
4158 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
4159 else {
4160 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
4162 case VT_LPSTR:
4163 case VT_LPWSTR:
4164 case VT_BSTR:
4166 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
4167 BSTR str;
4168 TRACE_(typelib)("len = %u\n", len);
4169 if (len == 0xffff) {
4170 str = NULL;
4171 } else {
4172 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
4173 str = SysAllocStringLen(NULL, alloc_len);
4174 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
4176 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
4177 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
4178 break;
4180 case VT_I2:
4181 case VT_UI2:
4182 case VT_I4:
4183 case VT_UI4:
4184 case VT_INT:
4185 case VT_UINT:
4186 V_INT(pVarDesc->vardesc.u.lpvarValue) =
4187 *(INT*)(pBlk + pItem->byte_offs);
4188 break;
4189 default:
4190 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
4194 else {
4195 TRACE_(typelib)("VAR_PERINSTANCE\n");
4196 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
4197 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
4200 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
4201 pVarDesc->vardesc.wVarFlags = pItem->varflags;
4203 if (pItem->flags & 0x80)
4204 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
4206 prevName = pVarDesc->Name;
4208 pTI->cVars = cVars;
4211 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
4212 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4214 SLTG_Function *pFunc;
4215 unsigned short i;
4216 TLBFuncDesc *pFuncDesc;
4218 pTI->funcdescs = TLBFuncDesc_Alloc(cFuncs);
4220 pFuncDesc = pTI->funcdescs;
4221 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
4222 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
4224 int param;
4225 WORD *pType, *pArg;
4227 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
4228 case SLTG_FUNCTION_MAGIC:
4229 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
4230 break;
4231 case SLTG_DISPATCH_FUNCTION_MAGIC:
4232 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
4233 break;
4234 case SLTG_STATIC_FUNCTION_MAGIC:
4235 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
4236 break;
4237 default:
4238 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
4239 continue;
4241 pFuncDesc->Name = SLTG_ReadName(pNameTable, pFunc->name, pTI->pTypeLib);
4243 pFuncDesc->funcdesc.memid = pFunc->dispid;
4244 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
4245 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
4246 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
4247 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
4248 pFuncDesc->funcdesc.oVft = pFunc->vtblpos & ~1;
4250 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
4251 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
4253 if(pFunc->retnextopt & 0x80)
4254 pType = &pFunc->rettype;
4255 else
4256 pType = (WORD*)(pBlk + pFunc->rettype);
4258 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
4260 pFuncDesc->funcdesc.lprgelemdescParam =
4261 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
4262 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
4264 pArg = (WORD*)(pBlk + pFunc->arg_off);
4266 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
4267 char *paramName = pNameTable + *pArg;
4268 BOOL HaveOffs;
4269 /* If arg type follows then paramName points to the 2nd
4270 letter of the name, else the next WORD is an offset to
4271 the arg type and paramName points to the first letter.
4272 So let's take one char off paramName and see if we're
4273 pointing at an alpha-numeric char. However if *pArg is
4274 0xffff or 0xfffe then the param has no name, the former
4275 meaning that the next WORD is the type, the latter
4276 meaning that the next WORD is an offset to the type. */
4278 HaveOffs = FALSE;
4279 if(*pArg == 0xffff)
4280 paramName = NULL;
4281 else if(*pArg == 0xfffe) {
4282 paramName = NULL;
4283 HaveOffs = TRUE;
4285 else if(paramName[-1] && !isalnum(paramName[-1]))
4286 HaveOffs = TRUE;
4288 pArg++;
4290 if(HaveOffs) { /* the next word is an offset to type */
4291 pType = (WORD*)(pBlk + *pArg);
4292 SLTG_DoElem(pType, pBlk,
4293 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4294 pArg++;
4295 } else {
4296 if(paramName)
4297 paramName--;
4298 pArg = SLTG_DoElem(pArg, pBlk,
4299 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4302 /* Are we an optional param ? */
4303 if(pFuncDesc->funcdesc.cParams - param <=
4304 pFuncDesc->funcdesc.cParamsOpt)
4305 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
4307 if(paramName) {
4308 pFuncDesc->pParamDesc[param].Name = SLTG_ReadName(pNameTable,
4309 paramName - pNameTable, pTI->pTypeLib);
4310 } else {
4311 pFuncDesc->pParamDesc[param].Name = pFuncDesc->Name;
4315 pTI->cFuncs = cFuncs;
4318 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
4319 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4320 SLTG_TypeInfoTail *pTITail)
4322 char *pFirstItem;
4323 sltg_ref_lookup_t *ref_lookup = NULL;
4325 if(pTIHeader->href_table != 0xffffffff) {
4326 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4327 pNameTable);
4330 pFirstItem = pBlk;
4332 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4333 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
4335 heap_free(ref_lookup);
4339 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
4340 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4341 const SLTG_TypeInfoTail *pTITail)
4343 char *pFirstItem;
4344 sltg_ref_lookup_t *ref_lookup = NULL;
4346 if(pTIHeader->href_table != 0xffffffff) {
4347 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4348 pNameTable);
4351 pFirstItem = pBlk;
4353 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4354 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
4357 if (pTITail->funcs_off != 0xffff)
4358 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4360 heap_free(ref_lookup);
4362 if (TRACE_ON(typelib))
4363 dump_TLBFuncDesc(pTI->funcdescs, pTI->cFuncs);
4366 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
4367 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4368 const SLTG_TypeInfoTail *pTITail)
4370 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4373 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
4374 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4375 const SLTG_TypeInfoTail *pTITail)
4377 WORD *pType;
4378 sltg_ref_lookup_t *ref_lookup = NULL;
4380 if (pTITail->simple_alias) {
4381 /* if simple alias, no more processing required */
4382 pTI->tdescAlias = heap_alloc_zero(sizeof(TYPEDESC));
4383 pTI->tdescAlias->vt = pTITail->tdescalias_vt;
4384 return;
4387 if(pTIHeader->href_table != 0xffffffff) {
4388 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4389 pNameTable);
4392 /* otherwise it is an offset to a type */
4393 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
4395 pTI->tdescAlias = heap_alloc(sizeof(TYPEDESC));
4396 SLTG_DoType(pType, pBlk, pTI->tdescAlias, ref_lookup);
4398 heap_free(ref_lookup);
4401 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
4402 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4403 const SLTG_TypeInfoTail *pTITail)
4405 sltg_ref_lookup_t *ref_lookup = NULL;
4406 if (pTIHeader->href_table != 0xffffffff)
4407 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4408 pNameTable);
4410 if (pTITail->vars_off != 0xffff)
4411 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4413 if (pTITail->funcs_off != 0xffff)
4414 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4416 if (pTITail->impls_off != 0xffff)
4417 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
4419 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4420 * of dispinterface functions including the IDispatch ones, so
4421 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4422 pTI->cbSizeVft = pTI->cFuncs * pTI->pTypeLib->ptr_size;
4424 heap_free(ref_lookup);
4425 if (TRACE_ON(typelib))
4426 dump_TLBFuncDesc(pTI->funcdescs, pTI->cFuncs);
4429 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
4430 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4431 const SLTG_TypeInfoTail *pTITail)
4433 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4436 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
4437 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4438 const SLTG_TypeInfoTail *pTITail)
4440 sltg_ref_lookup_t *ref_lookup = NULL;
4441 if (pTIHeader->href_table != 0xffffffff)
4442 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4443 pNameTable);
4445 if (pTITail->vars_off != 0xffff)
4446 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4448 if (pTITail->funcs_off != 0xffff)
4449 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4450 heap_free(ref_lookup);
4451 if (TRACE_ON(typelib))
4452 dump_TypeInfo(pTI);
4455 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4456 manageable copy of it into this */
4457 typedef struct {
4458 WORD small_no;
4459 char *index_name;
4460 char *other_name;
4461 WORD res1a;
4462 WORD name_offs;
4463 WORD more_bytes;
4464 char *extra;
4465 WORD res20;
4466 DWORD helpcontext;
4467 WORD res26;
4468 GUID uuid;
4469 } SLTG_InternalOtherTypeInfo;
4471 /****************************************************************************
4472 * ITypeLib2_Constructor_SLTG
4474 * loading a SLTG typelib from an in-memory image
4476 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
4478 ITypeLibImpl *pTypeLibImpl;
4479 SLTG_Header *pHeader;
4480 SLTG_BlkEntry *pBlkEntry;
4481 SLTG_Magic *pMagic;
4482 SLTG_Index *pIndex;
4483 SLTG_Pad9 *pPad9;
4484 LPVOID pBlk, pFirstBlk;
4485 SLTG_LibBlk *pLibBlk;
4486 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
4487 char *pAfterOTIBlks = NULL;
4488 char *pNameTable, *ptr;
4489 int i;
4490 DWORD len, order;
4491 ITypeInfoImpl **ppTypeInfoImpl;
4493 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
4496 pTypeLibImpl = TypeLibImpl_Constructor();
4497 if (!pTypeLibImpl) return NULL;
4499 pHeader = pLib;
4501 TRACE_(typelib)("header:\n");
4502 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
4503 pHeader->nrOfFileBlks );
4504 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
4505 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
4506 pHeader->SLTG_magic);
4507 return NULL;
4510 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4511 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
4513 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4514 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
4516 /* Next we have a magic block */
4517 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
4519 /* Let's see if we're still in sync */
4520 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
4521 sizeof(SLTG_COMPOBJ_MAGIC))) {
4522 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
4523 return NULL;
4525 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
4526 sizeof(SLTG_DIR_MAGIC))) {
4527 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
4528 return NULL;
4531 pIndex = (SLTG_Index*)(pMagic+1);
4533 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
4535 pFirstBlk = pPad9 + 1;
4537 /* We'll set up a ptr to the main library block, which is the last one. */
4539 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4540 pBlkEntry[order].next != 0;
4541 order = pBlkEntry[order].next - 1, i++) {
4542 pBlk = (char*)pBlk + pBlkEntry[order].len;
4544 pLibBlk = pBlk;
4546 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
4548 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4549 interspersed */
4551 len += 0x40;
4553 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4555 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
4558 ptr = (char*)pLibBlk + len;
4560 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4561 WORD w, extra;
4562 len = 0;
4564 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
4566 w = *(WORD*)(ptr + 2);
4567 if(w != 0xffff) {
4568 len += w;
4569 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
4570 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4571 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4573 w = *(WORD*)(ptr + 4 + len);
4574 if(w != 0xffff) {
4575 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4576 len += w;
4577 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4578 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4579 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4581 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4582 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4583 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4584 if(extra) {
4585 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4586 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4587 len += extra;
4589 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4590 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4591 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4592 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4593 len += sizeof(SLTG_OtherTypeInfo);
4594 ptr += len;
4597 pAfterOTIBlks = ptr;
4599 /* Skip this WORD and get the next DWORD */
4600 len = *(DWORD*)(pAfterOTIBlks + 2);
4602 /* Now add this to pLibBLk look at what we're pointing at and
4603 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4604 dust and we should be pointing at the beginning of the name
4605 table */
4607 pNameTable = (char*)pLibBlk + len;
4609 switch(*(WORD*)pNameTable) {
4610 case 0xffff:
4611 break;
4612 case 0x0200:
4613 pNameTable += 0x20;
4614 break;
4615 default:
4616 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4617 break;
4620 pNameTable += 0x216;
4622 pNameTable += 2;
4624 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4626 pTypeLibImpl->Name = SLTG_ReadName(pNameTable, pLibBlk->name, pTypeLibImpl);
4629 /* Hopefully we now have enough ptrs set up to actually read in
4630 some TypeInfos. It's not clear which order to do them in, so
4631 I'll just follow the links along the BlkEntry chain and read
4632 them in the order in which they are in the file */
4634 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4635 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4637 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4638 pBlkEntry[order].next != 0;
4639 order = pBlkEntry[order].next - 1, i++) {
4641 SLTG_TypeInfoHeader *pTIHeader;
4642 SLTG_TypeInfoTail *pTITail;
4643 SLTG_MemberHeader *pMemHeader;
4645 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4646 FIXME_(typelib)("Index strings don't match\n");
4647 heap_free(pOtherTypeInfoBlks);
4648 return NULL;
4651 pTIHeader = pBlk;
4652 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4653 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4654 heap_free(pOtherTypeInfoBlks);
4655 return NULL;
4657 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4658 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4659 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4661 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4662 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4663 (*ppTypeInfoImpl)->index = i;
4664 (*ppTypeInfoImpl)->Name = SLTG_ReadName(pNameTable, pOtherTypeInfoBlks[i].name_offs, pTypeLibImpl);
4665 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4666 (*ppTypeInfoImpl)->guid = TLB_append_guid(&pTypeLibImpl->guid_list, &pOtherTypeInfoBlks[i].uuid, 2);
4667 (*ppTypeInfoImpl)->typekind = pTIHeader->typekind;
4668 (*ppTypeInfoImpl)->wMajorVerNum = pTIHeader->major_version;
4669 (*ppTypeInfoImpl)->wMinorVerNum = pTIHeader->minor_version;
4670 (*ppTypeInfoImpl)->wTypeFlags =
4671 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4673 if((*ppTypeInfoImpl)->wTypeFlags & TYPEFLAG_FDUAL)
4674 (*ppTypeInfoImpl)->typekind = TKIND_DISPATCH;
4676 if((pTIHeader->typeflags1 & 7) != 2)
4677 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4678 if(pTIHeader->typeflags3 != 2)
4679 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4681 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4682 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl)->Name)),
4683 typekind_desc[pTIHeader->typekind],
4684 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl)->guid)),
4685 (*ppTypeInfoImpl)->wTypeFlags);
4687 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4689 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4691 (*ppTypeInfoImpl)->cbAlignment = pTITail->cbAlignment;
4692 (*ppTypeInfoImpl)->cbSizeInstance = pTITail->cbSizeInstance;
4693 (*ppTypeInfoImpl)->cbSizeVft = pTITail->cbSizeVft;
4695 switch(pTIHeader->typekind) {
4696 case TKIND_ENUM:
4697 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4698 pTIHeader, pTITail);
4699 break;
4701 case TKIND_RECORD:
4702 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4703 pTIHeader, pTITail);
4704 break;
4706 case TKIND_INTERFACE:
4707 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4708 pTIHeader, pTITail);
4709 break;
4711 case TKIND_COCLASS:
4712 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4713 pTIHeader, pTITail);
4714 break;
4716 case TKIND_ALIAS:
4717 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4718 pTIHeader, pTITail);
4719 break;
4721 case TKIND_DISPATCH:
4722 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4723 pTIHeader, pTITail);
4724 break;
4726 case TKIND_MODULE:
4727 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4728 pTIHeader, pTITail);
4729 break;
4731 default:
4732 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4733 break;
4737 /* could get cFuncs, cVars and cImplTypes from here
4738 but we've already set those */
4739 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4740 X(06);
4741 X(16);
4742 X(18);
4743 X(1a);
4744 X(1e);
4745 X(24);
4746 X(26);
4747 X(2a);
4748 X(2c);
4749 X(2e);
4750 X(30);
4751 X(32);
4752 X(34);
4753 #undef X
4754 ++ppTypeInfoImpl;
4755 pBlk = (char*)pBlk + pBlkEntry[order].len;
4758 if(i != pTypeLibImpl->TypeInfoCount) {
4759 FIXME("Somehow processed %d TypeInfos\n", i);
4760 heap_free(pOtherTypeInfoBlks);
4761 return NULL;
4764 heap_free(pOtherTypeInfoBlks);
4765 return &pTypeLibImpl->ITypeLib2_iface;
4768 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4770 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4772 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4774 if(IsEqualIID(riid, &IID_IUnknown) ||
4775 IsEqualIID(riid,&IID_ITypeLib)||
4776 IsEqualIID(riid,&IID_ITypeLib2))
4778 *ppv = &This->ITypeLib2_iface;
4780 else if(IsEqualIID(riid, &IID_ICreateTypeLib) ||
4781 IsEqualIID(riid, &IID_ICreateTypeLib2))
4783 *ppv = &This->ICreateTypeLib2_iface;
4785 else
4787 *ppv = NULL;
4788 TRACE("-- Interface: E_NOINTERFACE\n");
4789 return E_NOINTERFACE;
4792 IUnknown_AddRef((IUnknown*)*ppv);
4793 return S_OK;
4796 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4798 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4799 ULONG ref = InterlockedIncrement(&This->ref);
4801 TRACE("(%p) ref=%u\n", This, ref);
4803 return ref;
4806 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4808 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4809 ULONG ref = InterlockedDecrement(&This->ref);
4811 TRACE("(%p) ref=%u\n",This, ref);
4813 if (!ref)
4815 TLBImpLib *pImpLib, *pImpLibNext;
4816 TLBRefType *ref_type;
4817 TLBString *tlbstr, *tlbstr_next;
4818 TLBGuid *tlbguid, *tlbguid_next;
4819 void *cursor2;
4820 int i;
4822 /* remove cache entry */
4823 if(This->path)
4825 TRACE("removing from cache list\n");
4826 EnterCriticalSection(&cache_section);
4827 if(This->entry.next)
4828 list_remove(&This->entry);
4829 LeaveCriticalSection(&cache_section);
4830 heap_free(This->path);
4832 TRACE(" destroying ITypeLib(%p)\n",This);
4834 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->string_list, TLBString, entry) {
4835 list_remove(&tlbstr->entry);
4836 SysFreeString(tlbstr->str);
4837 heap_free(tlbstr);
4840 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->name_list, TLBString, entry) {
4841 list_remove(&tlbstr->entry);
4842 SysFreeString(tlbstr->str);
4843 heap_free(tlbstr);
4846 LIST_FOR_EACH_ENTRY_SAFE(tlbguid, tlbguid_next, &This->guid_list, TLBGuid, entry) {
4847 list_remove(&tlbguid->entry);
4848 heap_free(tlbguid);
4851 TLB_FreeCustData(&This->custdata_list);
4853 for (i = 0; i < This->ctTypeDesc; i++)
4854 if (This->pTypeDesc[i].vt == VT_CARRAY)
4855 heap_free(This->pTypeDesc[i].u.lpadesc);
4857 heap_free(This->pTypeDesc);
4859 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4861 if (pImpLib->pImpTypeLib)
4862 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4863 SysFreeString(pImpLib->name);
4865 list_remove(&pImpLib->entry);
4866 heap_free(pImpLib);
4869 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4871 list_remove(&ref_type->entry);
4872 heap_free(ref_type);
4875 for (i = 0; i < This->TypeInfoCount; ++i){
4876 heap_free(This->typeinfos[i]->tdescAlias);
4877 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4879 heap_free(This->typeinfos);
4880 heap_free(This);
4881 return 0;
4884 return ref;
4887 /* ITypeLib::GetTypeInfoCount
4889 * Returns the number of type descriptions in the type library
4891 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4893 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4894 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4895 return This->TypeInfoCount;
4898 /* ITypeLib::GetTypeInfo
4900 * retrieves the specified type description in the library.
4902 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4903 ITypeLib2 *iface,
4904 UINT index,
4905 ITypeInfo **ppTInfo)
4907 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4909 TRACE("%p %u %p\n", This, index, ppTInfo);
4911 if(!ppTInfo)
4912 return E_INVALIDARG;
4914 if(index >= This->TypeInfoCount)
4915 return TYPE_E_ELEMENTNOTFOUND;
4917 *ppTInfo = (ITypeInfo *)&This->typeinfos[index]->ITypeInfo2_iface;
4918 ITypeInfo_AddRef(*ppTInfo);
4920 return S_OK;
4924 /* ITypeLibs::GetTypeInfoType
4926 * Retrieves the type of a type description.
4928 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4929 ITypeLib2 *iface,
4930 UINT index,
4931 TYPEKIND *pTKind)
4933 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4935 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4937 if(!pTKind)
4938 return E_INVALIDARG;
4940 if(index >= This->TypeInfoCount)
4941 return TYPE_E_ELEMENTNOTFOUND;
4943 *pTKind = This->typeinfos[index]->typekind;
4945 return S_OK;
4948 /* ITypeLib::GetTypeInfoOfGuid
4950 * Retrieves the type description that corresponds to the specified GUID.
4953 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4954 ITypeLib2 *iface,
4955 REFGUID guid,
4956 ITypeInfo **ppTInfo)
4958 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4959 int i;
4961 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4963 for(i = 0; i < This->TypeInfoCount; ++i){
4964 if(IsEqualIID(TLB_get_guid_null(This->typeinfos[i]->guid), guid)){
4965 *ppTInfo = (ITypeInfo *)&This->typeinfos[i]->ITypeInfo2_iface;
4966 ITypeInfo_AddRef(*ppTInfo);
4967 return S_OK;
4971 return TYPE_E_ELEMENTNOTFOUND;
4974 /* ITypeLib::GetLibAttr
4976 * Retrieves the structure that contains the library's attributes.
4979 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4980 ITypeLib2 *iface,
4981 LPTLIBATTR *attr)
4983 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4985 TRACE("(%p, %p)\n", This, attr);
4987 if (!attr) return E_INVALIDARG;
4989 *attr = heap_alloc(sizeof(**attr));
4990 if (!*attr) return E_OUTOFMEMORY;
4992 (*attr)->guid = *TLB_get_guid_null(This->guid);
4993 (*attr)->lcid = This->set_lcid;
4994 (*attr)->syskind = This->syskind;
4995 (*attr)->wMajorVerNum = This->ver_major;
4996 (*attr)->wMinorVerNum = This->ver_minor;
4997 (*attr)->wLibFlags = This->libflags;
4999 return S_OK;
5002 /* ITypeLib::GetTypeComp
5004 * Enables a client compiler to bind to a library's types, variables,
5005 * constants, and global functions.
5008 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
5009 ITypeLib2 *iface,
5010 ITypeComp **ppTComp)
5012 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5014 TRACE("(%p)->(%p)\n",This,ppTComp);
5015 *ppTComp = &This->ITypeComp_iface;
5016 ITypeComp_AddRef(*ppTComp);
5018 return S_OK;
5021 /* ITypeLib::GetDocumentation
5023 * Retrieves the library's documentation string, the complete Help file name
5024 * and path, and the context identifier for the library Help topic in the Help
5025 * file.
5027 * On a successful return all non-null BSTR pointers will have been set,
5028 * possibly to NULL.
5030 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
5031 ITypeLib2 *iface,
5032 INT index,
5033 BSTR *pBstrName,
5034 BSTR *pBstrDocString,
5035 DWORD *pdwHelpContext,
5036 BSTR *pBstrHelpFile)
5038 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5039 HRESULT result = E_INVALIDARG;
5040 ITypeInfo *pTInfo;
5042 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
5043 This, index,
5044 pBstrName, pBstrDocString,
5045 pdwHelpContext, pBstrHelpFile);
5047 if(index<0)
5049 /* documentation for the typelib */
5050 if(pBstrName)
5052 if (This->Name)
5054 if(!(*pBstrName = SysAllocString(TLB_get_bstr(This->Name))))
5055 goto memerr1;
5057 else
5058 *pBstrName = NULL;
5060 if(pBstrDocString)
5062 if (This->DocString)
5064 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->DocString))))
5065 goto memerr2;
5067 else
5068 *pBstrDocString = NULL;
5070 if(pdwHelpContext)
5072 *pdwHelpContext = This->dwHelpContext;
5074 if(pBstrHelpFile)
5076 if (This->HelpFile)
5078 if(!(*pBstrHelpFile = SysAllocString(TLB_get_bstr(This->HelpFile))))
5079 goto memerr3;
5081 else
5082 *pBstrHelpFile = NULL;
5085 result = S_OK;
5087 else
5089 /* for a typeinfo */
5090 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
5092 if(SUCCEEDED(result))
5094 result = ITypeInfo_GetDocumentation(pTInfo,
5095 MEMBERID_NIL,
5096 pBstrName,
5097 pBstrDocString,
5098 pdwHelpContext, pBstrHelpFile);
5100 ITypeInfo_Release(pTInfo);
5103 return result;
5104 memerr3:
5105 if (pBstrDocString) SysFreeString (*pBstrDocString);
5106 memerr2:
5107 if (pBstrName) SysFreeString (*pBstrName);
5108 memerr1:
5109 return STG_E_INSUFFICIENTMEMORY;
5112 /* ITypeLib::IsName
5114 * Indicates whether a passed-in string contains the name of a type or member
5115 * described in the library.
5118 static HRESULT WINAPI ITypeLib2_fnIsName(
5119 ITypeLib2 *iface,
5120 LPOLESTR szNameBuf,
5121 ULONG lHashVal,
5122 BOOL *pfName)
5124 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5125 int tic;
5126 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
5128 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
5129 pfName);
5131 *pfName=TRUE;
5132 for(tic = 0; tic < This->TypeInfoCount; ++tic){
5133 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5134 if(!TLB_str_memcmp(szNameBuf, pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5135 for(fdc = 0; fdc < pTInfo->cFuncs; ++fdc) {
5136 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
5137 int pc;
5138 if(!TLB_str_memcmp(szNameBuf, pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5139 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++){
5140 if(!TLB_str_memcmp(szNameBuf, pFInfo->pParamDesc[pc].Name, nNameBufLen))
5141 goto ITypeLib2_fnIsName_exit;
5144 for(vrc = 0; vrc < pTInfo->cVars; ++vrc){
5145 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
5146 if(!TLB_str_memcmp(szNameBuf, pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5150 *pfName=FALSE;
5152 ITypeLib2_fnIsName_exit:
5153 TRACE("(%p)slow! search for %s: %sfound!\n", This,
5154 debugstr_w(szNameBuf), *pfName ? "" : "NOT ");
5156 return S_OK;
5159 /* ITypeLib::FindName
5161 * Finds occurrences of a type description in a type library. This may be used
5162 * to quickly verify that a name exists in a type library.
5165 static HRESULT WINAPI ITypeLib2_fnFindName(
5166 ITypeLib2 *iface,
5167 LPOLESTR name,
5168 ULONG hash,
5169 ITypeInfo **ppTInfo,
5170 MEMBERID *memid,
5171 UINT16 *found)
5173 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5174 int tic;
5175 UINT count = 0;
5176 UINT len;
5178 TRACE("(%p)->(%s %u %p %p %p)\n", This, debugstr_w(name), hash, ppTInfo, memid, found);
5180 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
5181 return E_INVALIDARG;
5183 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
5184 for(tic = 0; count < *found && tic < This->TypeInfoCount; ++tic) {
5185 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5186 TLBVarDesc *var;
5187 UINT fdc;
5189 if(!TLB_str_memcmp(name, pTInfo->Name, len)) {
5190 memid[count] = MEMBERID_NIL;
5191 goto ITypeLib2_fnFindName_exit;
5194 for(fdc = 0; fdc < pTInfo->cFuncs; ++fdc) {
5195 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
5197 if(!TLB_str_memcmp(name, func->Name, len)) {
5198 memid[count] = func->funcdesc.memid;
5199 goto ITypeLib2_fnFindName_exit;
5203 var = TLB_get_vardesc_by_name(pTInfo->vardescs, pTInfo->cVars, name);
5204 if (var) {
5205 memid[count] = var->vardesc.memid;
5206 goto ITypeLib2_fnFindName_exit;
5209 continue;
5210 ITypeLib2_fnFindName_exit:
5211 ITypeInfo2_AddRef(&pTInfo->ITypeInfo2_iface);
5212 ppTInfo[count] = (ITypeInfo *)&pTInfo->ITypeInfo2_iface;
5213 count++;
5215 TRACE("found %d typeinfos\n", count);
5217 *found = count;
5219 return S_OK;
5222 /* ITypeLib::ReleaseTLibAttr
5224 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5227 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
5228 ITypeLib2 *iface,
5229 TLIBATTR *pTLibAttr)
5231 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5232 TRACE("(%p)->(%p)\n", This, pTLibAttr);
5233 heap_free(pTLibAttr);
5236 /* ITypeLib2::GetCustData
5238 * gets the custom data
5240 static HRESULT WINAPI ITypeLib2_fnGetCustData(
5241 ITypeLib2 * iface,
5242 REFGUID guid,
5243 VARIANT *pVarVal)
5245 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5246 TLBCustData *pCData;
5248 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
5250 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
5251 if(!pCData)
5252 return TYPE_E_ELEMENTNOTFOUND;
5254 VariantInit(pVarVal);
5255 VariantCopy(pVarVal, &pCData->data);
5257 return S_OK;
5260 /* ITypeLib2::GetLibStatistics
5262 * Returns statistics about a type library that are required for efficient
5263 * sizing of hash tables.
5266 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
5267 ITypeLib2 * iface,
5268 ULONG *pcUniqueNames,
5269 ULONG *pcchUniqueNames)
5271 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5273 FIXME("(%p): stub!\n", This);
5275 if(pcUniqueNames) *pcUniqueNames=1;
5276 if(pcchUniqueNames) *pcchUniqueNames=1;
5277 return S_OK;
5280 /* ITypeLib2::GetDocumentation2
5282 * Retrieves the library's documentation string, the complete Help file name
5283 * and path, the localization context to use, and the context ID for the
5284 * library Help topic in the Help file.
5287 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
5288 ITypeLib2 * iface,
5289 INT index,
5290 LCID lcid,
5291 BSTR *pbstrHelpString,
5292 DWORD *pdwHelpStringContext,
5293 BSTR *pbstrHelpStringDll)
5295 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5296 HRESULT result;
5297 ITypeInfo *pTInfo;
5299 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
5301 /* the help string should be obtained from the helpstringdll,
5302 * using the _DLLGetDocumentation function, based on the supplied
5303 * lcid. Nice to do sometime...
5305 if(index<0)
5307 /* documentation for the typelib */
5308 if(pbstrHelpString)
5309 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->DocString));
5310 if(pdwHelpStringContext)
5311 *pdwHelpStringContext=This->dwHelpContext;
5312 if(pbstrHelpStringDll)
5313 *pbstrHelpStringDll=SysAllocString(TLB_get_bstr(This->HelpStringDll));
5315 result = S_OK;
5317 else
5319 /* for a typeinfo */
5320 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
5322 if(SUCCEEDED(result))
5324 ITypeInfo2 * pTInfo2;
5325 result = ITypeInfo_QueryInterface(pTInfo,
5326 &IID_ITypeInfo2,
5327 (LPVOID*) &pTInfo2);
5329 if(SUCCEEDED(result))
5331 result = ITypeInfo2_GetDocumentation2(pTInfo2,
5332 MEMBERID_NIL,
5333 lcid,
5334 pbstrHelpString,
5335 pdwHelpStringContext,
5336 pbstrHelpStringDll);
5338 ITypeInfo2_Release(pTInfo2);
5341 ITypeInfo_Release(pTInfo);
5344 return result;
5347 static HRESULT TLB_copy_all_custdata(struct list *custdata_list, CUSTDATA *pCustData)
5349 TLBCustData *pCData;
5350 unsigned int ct;
5351 CUSTDATAITEM *cdi;
5353 ct = list_count(custdata_list);
5355 pCustData->prgCustData = CoTaskMemAlloc(ct * sizeof(CUSTDATAITEM));
5356 if(!pCustData->prgCustData)
5357 return E_OUTOFMEMORY;
5359 pCustData->cCustData = ct;
5361 cdi = pCustData->prgCustData;
5362 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
5363 cdi->guid = *TLB_get_guid_null(pCData->guid);
5364 VariantCopy(&cdi->varValue, &pCData->data);
5365 ++cdi;
5368 return S_OK;
5372 /* ITypeLib2::GetAllCustData
5374 * Gets all custom data items for the library.
5377 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
5378 ITypeLib2 * iface,
5379 CUSTDATA *pCustData)
5381 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5382 TRACE("(%p)->(%p)\n", This, pCustData);
5383 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
5386 static const ITypeLib2Vtbl tlbvt = {
5387 ITypeLib2_fnQueryInterface,
5388 ITypeLib2_fnAddRef,
5389 ITypeLib2_fnRelease,
5390 ITypeLib2_fnGetTypeInfoCount,
5391 ITypeLib2_fnGetTypeInfo,
5392 ITypeLib2_fnGetTypeInfoType,
5393 ITypeLib2_fnGetTypeInfoOfGuid,
5394 ITypeLib2_fnGetLibAttr,
5395 ITypeLib2_fnGetTypeComp,
5396 ITypeLib2_fnGetDocumentation,
5397 ITypeLib2_fnIsName,
5398 ITypeLib2_fnFindName,
5399 ITypeLib2_fnReleaseTLibAttr,
5401 ITypeLib2_fnGetCustData,
5402 ITypeLib2_fnGetLibStatistics,
5403 ITypeLib2_fnGetDocumentation2,
5404 ITypeLib2_fnGetAllCustData
5408 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5410 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5412 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
5415 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
5417 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5419 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
5422 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
5424 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5426 return ITypeLib2_Release(&This->ITypeLib2_iface);
5429 static HRESULT WINAPI ITypeLibComp_fnBind(
5430 ITypeComp * iface,
5431 OLECHAR * szName,
5432 ULONG lHash,
5433 WORD wFlags,
5434 ITypeInfo ** ppTInfo,
5435 DESCKIND * pDescKind,
5436 BINDPTR * pBindPtr)
5438 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5439 BOOL typemismatch = FALSE;
5440 int i;
5442 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5444 *pDescKind = DESCKIND_NONE;
5445 pBindPtr->lptcomp = NULL;
5446 *ppTInfo = NULL;
5448 for(i = 0; i < This->TypeInfoCount; ++i){
5449 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5450 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo->Name)));
5452 /* FIXME: check wFlags here? */
5453 /* FIXME: we should use a hash table to look this info up using lHash
5454 * instead of an O(n) search */
5455 if ((pTypeInfo->typekind == TKIND_ENUM) ||
5456 (pTypeInfo->typekind == TKIND_MODULE))
5458 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name->str, szName))
5460 *pDescKind = DESCKIND_TYPECOMP;
5461 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
5462 ITypeComp_AddRef(pBindPtr->lptcomp);
5463 TRACE("module or enum: %s\n", debugstr_w(szName));
5464 return S_OK;
5468 if ((pTypeInfo->typekind == TKIND_MODULE) ||
5469 (pTypeInfo->typekind == TKIND_ENUM))
5471 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5472 HRESULT hr;
5474 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5475 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
5477 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
5478 return S_OK;
5480 else if (hr == TYPE_E_TYPEMISMATCH)
5481 typemismatch = TRUE;
5484 if ((pTypeInfo->typekind == TKIND_COCLASS) &&
5485 (pTypeInfo->wTypeFlags & TYPEFLAG_FAPPOBJECT))
5487 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5488 HRESULT hr;
5489 ITypeInfo *subtypeinfo;
5490 BINDPTR subbindptr;
5491 DESCKIND subdesckind;
5493 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
5494 &subtypeinfo, &subdesckind, &subbindptr);
5495 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
5497 TYPEDESC tdesc_appobject;
5498 const VARDESC vardesc_appobject =
5500 -2, /* memid */
5501 NULL, /* lpstrSchema */
5503 0 /* oInst */
5506 /* ELEMDESC */
5508 /* TYPEDESC */
5510 &tdesc_appobject
5512 VT_PTR
5515 0, /* wVarFlags */
5516 VAR_STATIC /* varkind */
5519 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
5520 tdesc_appobject.vt = VT_USERDEFINED;
5522 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
5524 /* cleanup things filled in by Bind call so we can put our
5525 * application object data in there instead */
5526 switch (subdesckind)
5528 case DESCKIND_FUNCDESC:
5529 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
5530 break;
5531 case DESCKIND_VARDESC:
5532 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
5533 break;
5534 default:
5535 break;
5537 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
5539 if (pTypeInfo->hreftype == -1)
5540 FIXME("no hreftype for interface %p\n", pTypeInfo);
5542 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
5543 if (FAILED(hr))
5544 return hr;
5546 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5547 *ppTInfo = (ITypeInfo *)&pTypeInfo->ITypeInfo2_iface;
5548 ITypeInfo_AddRef(*ppTInfo);
5549 return S_OK;
5551 else if (hr == TYPE_E_TYPEMISMATCH)
5552 typemismatch = TRUE;
5556 if (typemismatch)
5558 TRACE("type mismatch %s\n", debugstr_w(szName));
5559 return TYPE_E_TYPEMISMATCH;
5561 else
5563 TRACE("name not found %s\n", debugstr_w(szName));
5564 return S_OK;
5568 static HRESULT WINAPI ITypeLibComp_fnBindType(
5569 ITypeComp * iface,
5570 OLECHAR * szName,
5571 ULONG lHash,
5572 ITypeInfo ** ppTInfo,
5573 ITypeComp ** ppTComp)
5575 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5576 ITypeInfoImpl *info;
5578 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5580 if(!szName || !ppTInfo || !ppTComp)
5581 return E_INVALIDARG;
5583 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, szName);
5584 if(!info){
5585 *ppTInfo = NULL;
5586 *ppTComp = NULL;
5587 return S_OK;
5590 *ppTInfo = (ITypeInfo *)&info->ITypeInfo2_iface;
5591 ITypeInfo_AddRef(*ppTInfo);
5592 *ppTComp = &info->ITypeComp_iface;
5593 ITypeComp_AddRef(*ppTComp);
5595 return S_OK;
5598 static const ITypeCompVtbl tlbtcvt =
5601 ITypeLibComp_fnQueryInterface,
5602 ITypeLibComp_fnAddRef,
5603 ITypeLibComp_fnRelease,
5605 ITypeLibComp_fnBind,
5606 ITypeLibComp_fnBindType
5609 /*================== ITypeInfo(2) Methods ===================================*/
5610 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5612 ITypeInfoImpl *pTypeInfoImpl;
5614 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5615 if (pTypeInfoImpl)
5617 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5618 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5619 pTypeInfoImpl->ICreateTypeInfo2_iface.lpVtbl = &CreateTypeInfo2Vtbl;
5620 pTypeInfoImpl->ref = 0;
5621 pTypeInfoImpl->hreftype = -1;
5622 pTypeInfoImpl->memidConstructor = MEMBERID_NIL;
5623 pTypeInfoImpl->memidDestructor = MEMBERID_NIL;
5624 pTypeInfoImpl->pcustdata_list = &pTypeInfoImpl->custdata_list;
5625 list_init(pTypeInfoImpl->pcustdata_list);
5627 TRACE("(%p)\n", pTypeInfoImpl);
5628 return pTypeInfoImpl;
5631 /* ITypeInfo::QueryInterface
5633 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5634 ITypeInfo2 *iface,
5635 REFIID riid,
5636 VOID **ppvObject)
5638 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5640 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5642 *ppvObject=NULL;
5643 if(IsEqualIID(riid, &IID_IUnknown) ||
5644 IsEqualIID(riid,&IID_ITypeInfo)||
5645 IsEqualIID(riid,&IID_ITypeInfo2))
5646 *ppvObject = This;
5647 else if(IsEqualIID(riid, &IID_ICreateTypeInfo) ||
5648 IsEqualIID(riid, &IID_ICreateTypeInfo2))
5649 *ppvObject = &This->ICreateTypeInfo2_iface;
5651 if(*ppvObject){
5652 ITypeInfo2_AddRef(iface);
5653 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5654 return S_OK;
5656 TRACE("-- Interface: E_NOINTERFACE\n");
5657 return E_NOINTERFACE;
5660 /* ITypeInfo::AddRef
5662 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5664 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5665 ULONG ref = InterlockedIncrement(&This->ref);
5667 TRACE("(%p)->ref is %u\n",This, ref);
5669 if (ref == 1 /* incremented from 0 */)
5670 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5672 return ref;
5675 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5677 UINT i;
5679 TRACE("destroying ITypeInfo(%p)\n",This);
5681 for (i = 0; i < This->cFuncs; ++i)
5683 int j;
5684 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5685 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5687 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5688 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5689 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5690 TLB_FreeCustData(&pFInfo->pParamDesc[j].custdata_list);
5692 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5693 heap_free(pFInfo->pParamDesc);
5694 TLB_FreeCustData(&pFInfo->custdata_list);
5696 heap_free(This->funcdescs);
5698 for(i = 0; i < This->cVars; ++i)
5700 TLBVarDesc *pVInfo = &This->vardescs[i];
5701 if (pVInfo->vardesc_create) {
5702 TLB_FreeVarDesc(pVInfo->vardesc_create);
5703 } else if (pVInfo->vardesc.varkind == VAR_CONST) {
5704 VariantClear(pVInfo->vardesc.u.lpvarValue);
5705 heap_free(pVInfo->vardesc.u.lpvarValue);
5707 TLB_FreeCustData(&pVInfo->custdata_list);
5709 heap_free(This->vardescs);
5711 if(This->impltypes){
5712 for (i = 0; i < This->cImplTypes; ++i){
5713 TLBImplType *pImpl = &This->impltypes[i];
5714 TLB_FreeCustData(&pImpl->custdata_list);
5716 heap_free(This->impltypes);
5719 TLB_FreeCustData(&This->custdata_list);
5721 heap_free(This);
5724 /* ITypeInfo::Release
5726 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5728 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5729 ULONG ref = InterlockedDecrement(&This->ref);
5731 TRACE("(%p)->(%u)\n",This, ref);
5733 if (!ref)
5735 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5736 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5737 if (not_attached_to_typelib)
5738 heap_free(This);
5739 /* otherwise This will be freed when typelib is freed */
5742 return ref;
5745 /* ITypeInfo::GetTypeAttr
5747 * Retrieves a TYPEATTR structure that contains the attributes of the type
5748 * description.
5751 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5752 LPTYPEATTR *ppTypeAttr)
5754 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5755 SIZE_T size;
5757 TRACE("(%p)\n",This);
5759 size = sizeof(**ppTypeAttr);
5760 if (This->typekind == TKIND_ALIAS && This->tdescAlias)
5761 size += TLB_SizeTypeDesc(This->tdescAlias, FALSE);
5763 *ppTypeAttr = heap_alloc(size);
5764 if (!*ppTypeAttr)
5765 return E_OUTOFMEMORY;
5767 (*ppTypeAttr)->guid = *TLB_get_guid_null(This->guid);
5768 (*ppTypeAttr)->lcid = This->lcid;
5769 (*ppTypeAttr)->memidConstructor = This->memidConstructor;
5770 (*ppTypeAttr)->memidDestructor = This->memidDestructor;
5771 (*ppTypeAttr)->lpstrSchema = This->lpstrSchema;
5772 (*ppTypeAttr)->cbSizeInstance = This->cbSizeInstance;
5773 (*ppTypeAttr)->typekind = This->typekind;
5774 (*ppTypeAttr)->cFuncs = This->cFuncs;
5775 (*ppTypeAttr)->cVars = This->cVars;
5776 (*ppTypeAttr)->cImplTypes = This->cImplTypes;
5777 (*ppTypeAttr)->cbSizeVft = This->cbSizeVft;
5778 (*ppTypeAttr)->cbAlignment = This->cbAlignment;
5779 (*ppTypeAttr)->wTypeFlags = This->wTypeFlags;
5780 (*ppTypeAttr)->wMajorVerNum = This->wMajorVerNum;
5781 (*ppTypeAttr)->wMinorVerNum = This->wMinorVerNum;
5782 (*ppTypeAttr)->idldescType = This->idldescType;
5784 if (This->tdescAlias)
5785 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5786 This->tdescAlias, *ppTypeAttr + 1);
5787 else{
5788 (*ppTypeAttr)->tdescAlias.vt = VT_EMPTY;
5789 (*ppTypeAttr)->tdescAlias.u.lptdesc = NULL;
5792 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5793 /* This should include all the inherited funcs */
5794 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / This->pTypeLib->ptr_size;
5795 /* This is always the size of IDispatch's vtbl */
5796 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5797 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5799 return S_OK;
5802 /* ITypeInfo::GetTypeComp
5804 * Retrieves the ITypeComp interface for the type description, which enables a
5805 * client compiler to bind to the type description's members.
5808 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5809 ITypeComp * *ppTComp)
5811 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5813 TRACE("(%p)->(%p)\n", This, ppTComp);
5815 *ppTComp = &This->ITypeComp_iface;
5816 ITypeComp_AddRef(*ppTComp);
5817 return S_OK;
5820 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5822 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5823 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5824 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5825 return size;
5828 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5830 *dest = *src;
5831 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5832 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5834 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5835 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5836 *buffer += sizeof(PARAMDESCEX);
5837 *pparamdescex_dest = *pparamdescex_src;
5838 pparamdescex_dest->cBytes = sizeof(PARAMDESCEX);
5839 VariantInit(&pparamdescex_dest->varDefaultValue);
5840 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5841 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5843 else
5844 dest->u.paramdesc.pparamdescex = NULL;
5845 return S_OK;
5848 static HRESULT TLB_SanitizeBSTR(BSTR str)
5850 UINT len = SysStringLen(str), i;
5851 for (i = 0; i < len; ++i)
5852 if (str[i] > 0x7f)
5853 str[i] = '?';
5854 return S_OK;
5857 static HRESULT TLB_SanitizeVariant(VARIANT *var)
5859 if (V_VT(var) == VT_INT)
5860 return VariantChangeType(var, var, 0, VT_I4);
5861 else if (V_VT(var) == VT_UINT)
5862 return VariantChangeType(var, var, 0, VT_UI4);
5863 else if (V_VT(var) == VT_BSTR)
5864 return TLB_SanitizeBSTR(V_BSTR(var));
5866 return S_OK;
5869 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5871 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5872 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5875 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5877 FUNCDESC *dest;
5878 char *buffer;
5879 SIZE_T size = sizeof(*src);
5880 SHORT i;
5881 HRESULT hr;
5883 size += sizeof(*src->lprgscode) * src->cScodes;
5884 size += TLB_SizeElemDesc(&src->elemdescFunc);
5885 for (i = 0; i < src->cParams; i++)
5887 size += sizeof(ELEMDESC);
5888 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5891 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5892 if (!dest) return E_OUTOFMEMORY;
5894 *dest = *src;
5895 if (dispinterface) /* overwrite funckind */
5896 dest->funckind = FUNC_DISPATCH;
5897 buffer = (char *)(dest + 1);
5899 dest->oVft = dest->oVft & 0xFFFC;
5901 if (dest->cScodes) {
5902 dest->lprgscode = (SCODE *)buffer;
5903 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5904 buffer += sizeof(*src->lprgscode) * src->cScodes;
5905 } else
5906 dest->lprgscode = NULL;
5908 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5909 if (FAILED(hr))
5911 SysFreeString((BSTR)dest);
5912 return hr;
5915 if (dest->cParams) {
5916 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5917 buffer += sizeof(ELEMDESC) * src->cParams;
5918 for (i = 0; i < src->cParams; i++)
5920 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5921 if (FAILED(hr))
5922 break;
5924 if (FAILED(hr))
5926 /* undo the above actions */
5927 for (i = i - 1; i >= 0; i--)
5928 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5929 TLB_FreeElemDesc(&dest->elemdescFunc);
5930 SysFreeString((BSTR)dest);
5931 return hr;
5933 } else
5934 dest->lprgelemdescParam = NULL;
5936 /* special treatment for dispinterfaces: this makes functions appear
5937 * to return their [retval] value when it is really returning an
5938 * HRESULT */
5939 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5941 if (dest->cParams &&
5942 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5944 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5945 if (elemdesc->tdesc.vt != VT_PTR)
5947 ERR("elemdesc should have started with VT_PTR instead of:\n");
5948 if (ERR_ON(ole))
5949 dump_ELEMDESC(elemdesc);
5950 return E_UNEXPECTED;
5953 /* copy last parameter to the return value. we are using a flat
5954 * buffer so there is no danger of leaking memory in
5955 * elemdescFunc */
5956 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5958 /* remove the last parameter */
5959 dest->cParams--;
5961 else
5962 /* otherwise this function is made to appear to have no return
5963 * value */
5964 dest->elemdescFunc.tdesc.vt = VT_VOID;
5968 *dest_ptr = dest;
5969 return S_OK;
5972 static void TLB_FreeVarDesc(VARDESC *var_desc)
5974 TLB_FreeElemDesc(&var_desc->elemdescVar);
5975 if (var_desc->varkind == VAR_CONST)
5976 VariantClear(var_desc->u.lpvarValue);
5977 SysFreeString((BSTR)var_desc);
5980 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5982 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5984 if (index >= This->cFuncs)
5985 return TYPE_E_ELEMENTNOTFOUND;
5987 *ppFuncDesc = &This->funcdescs[index].funcdesc;
5988 return S_OK;
5991 /* internal function to make the inherited interfaces' methods appear
5992 * part of the interface */
5993 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5994 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5996 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5997 HRESULT hr;
5998 UINT implemented_funcs = 0;
6000 if (funcs)
6001 *funcs = 0;
6002 else
6003 *hrefoffset = DISPATCH_HREF_OFFSET;
6005 if(This->impltypes)
6007 ITypeInfo *pSubTypeInfo;
6008 UINT sub_funcs;
6010 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
6011 if (FAILED(hr))
6012 return hr;
6014 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
6015 index,
6016 ppFuncDesc,
6017 &sub_funcs, hrefoffset);
6018 implemented_funcs += sub_funcs;
6019 ITypeInfo_Release(pSubTypeInfo);
6020 if (SUCCEEDED(hr))
6021 return hr;
6022 *hrefoffset += DISPATCH_HREF_OFFSET;
6025 if (funcs)
6026 *funcs = implemented_funcs + This->cFuncs;
6027 else
6028 *hrefoffset = 0;
6030 if (index < implemented_funcs)
6031 return E_INVALIDARG;
6032 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
6033 ppFuncDesc);
6036 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
6038 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
6039 while (TRUE)
6041 switch (pTypeDesc->vt)
6043 case VT_USERDEFINED:
6044 pTypeDesc->u.hreftype += hrefoffset;
6045 return;
6046 case VT_PTR:
6047 case VT_SAFEARRAY:
6048 pTypeDesc = pTypeDesc->u.lptdesc;
6049 break;
6050 case VT_CARRAY:
6051 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
6052 break;
6053 default:
6054 return;
6059 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
6061 SHORT i;
6062 for (i = 0; i < pFuncDesc->cParams; i++)
6063 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
6064 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
6067 /* ITypeInfo::GetFuncDesc
6069 * Retrieves the FUNCDESC structure that contains information about a
6070 * specified function.
6073 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
6074 LPFUNCDESC *ppFuncDesc)
6076 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6077 const FUNCDESC *internal_funcdesc;
6078 HRESULT hr;
6079 UINT hrefoffset = 0;
6081 TRACE("(%p) index %d\n", This, index);
6083 if (!ppFuncDesc)
6084 return E_INVALIDARG;
6086 if (This->needs_layout)
6087 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6089 if (This->typekind == TKIND_DISPATCH)
6090 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
6091 &internal_funcdesc, NULL,
6092 &hrefoffset);
6093 else
6094 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
6095 &internal_funcdesc);
6096 if (FAILED(hr))
6098 WARN("description for function %d not found\n", index);
6099 return hr;
6102 hr = TLB_AllocAndInitFuncDesc(
6103 internal_funcdesc,
6104 ppFuncDesc,
6105 This->typekind == TKIND_DISPATCH);
6107 if ((This->typekind == TKIND_DISPATCH) && hrefoffset)
6108 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
6110 TRACE("-- 0x%08x\n", hr);
6111 return hr;
6114 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
6116 VARDESC *dest;
6117 char *buffer;
6118 SIZE_T size = sizeof(*src);
6119 HRESULT hr;
6121 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
6122 if (src->varkind == VAR_CONST)
6123 size += sizeof(VARIANT);
6124 size += TLB_SizeElemDesc(&src->elemdescVar);
6126 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
6127 if (!dest) return E_OUTOFMEMORY;
6129 *dest = *src;
6130 buffer = (char *)(dest + 1);
6131 if (src->lpstrSchema)
6133 int len;
6134 dest->lpstrSchema = (LPOLESTR)buffer;
6135 len = strlenW(src->lpstrSchema);
6136 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
6137 buffer += (len + 1) * sizeof(WCHAR);
6140 if (src->varkind == VAR_CONST)
6142 HRESULT hr;
6144 dest->u.lpvarValue = (VARIANT *)buffer;
6145 *dest->u.lpvarValue = *src->u.lpvarValue;
6146 buffer += sizeof(VARIANT);
6147 VariantInit(dest->u.lpvarValue);
6148 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
6149 if (FAILED(hr))
6151 SysFreeString((BSTR)dest);
6152 return hr;
6155 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
6156 if (FAILED(hr))
6158 if (src->varkind == VAR_CONST)
6159 VariantClear(dest->u.lpvarValue);
6160 SysFreeString((BSTR)dest);
6161 return hr;
6163 *dest_ptr = dest;
6164 return S_OK;
6167 /* ITypeInfo::GetVarDesc
6169 * Retrieves a VARDESC structure that describes the specified variable.
6172 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
6173 LPVARDESC *ppVarDesc)
6175 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6176 const TLBVarDesc *pVDesc = &This->vardescs[index];
6178 TRACE("(%p) index %d\n", This, index);
6180 if(index >= This->cVars)
6181 return TYPE_E_ELEMENTNOTFOUND;
6183 if (This->needs_layout)
6184 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6186 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
6189 /* ITypeInfo_GetNames
6191 * Retrieves the variable with the specified member ID (or the name of the
6192 * property or method and its parameters) that correspond to the specified
6193 * function ID.
6195 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
6196 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
6198 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6199 const TLBFuncDesc *pFDesc;
6200 const TLBVarDesc *pVDesc;
6201 int i;
6202 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
6204 if(!rgBstrNames)
6205 return E_INVALIDARG;
6207 *pcNames = 0;
6209 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
6210 if(pFDesc)
6212 if(!cMaxNames || !pFDesc->Name)
6213 return S_OK;
6215 *rgBstrNames = SysAllocString(TLB_get_bstr(pFDesc->Name));
6216 ++(*pcNames);
6218 for(i = 0; i < pFDesc->funcdesc.cParams; ++i){
6219 if(*pcNames >= cMaxNames || !pFDesc->pParamDesc[i].Name)
6220 return S_OK;
6221 rgBstrNames[*pcNames] = SysAllocString(TLB_get_bstr(pFDesc->pParamDesc[i].Name));
6222 ++(*pcNames);
6224 return S_OK;
6227 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
6228 if(pVDesc)
6230 *rgBstrNames=SysAllocString(TLB_get_bstr(pVDesc->Name));
6231 *pcNames=1;
6233 else
6235 if(This->impltypes &&
6236 (This->typekind==TKIND_INTERFACE || This->typekind==TKIND_DISPATCH)) {
6237 /* recursive search */
6238 ITypeInfo *pTInfo;
6239 HRESULT result;
6240 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6241 if(SUCCEEDED(result))
6243 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
6244 ITypeInfo_Release(pTInfo);
6245 return result;
6247 WARN("Could not search inherited interface!\n");
6249 else
6251 WARN("no names found\n");
6253 *pcNames=0;
6254 return TYPE_E_ELEMENTNOTFOUND;
6256 return S_OK;
6260 /* ITypeInfo::GetRefTypeOfImplType
6262 * If a type description describes a COM class, it retrieves the type
6263 * description of the implemented interface types. For an interface,
6264 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6265 * if any exist.
6268 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
6269 ITypeInfo2 *iface,
6270 UINT index,
6271 HREFTYPE *pRefType)
6273 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6274 HRESULT hr = S_OK;
6276 TRACE("(%p) index %d\n", This, index);
6277 if (TRACE_ON(ole)) dump_TypeInfo(This);
6279 if(index==(UINT)-1)
6281 /* only valid on dual interfaces;
6282 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6285 if (This->wTypeFlags & TYPEFLAG_FDUAL)
6287 *pRefType = -2;
6289 else
6291 hr = TYPE_E_ELEMENTNOTFOUND;
6294 else if(index == 0 && This->typekind == TKIND_DISPATCH)
6296 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6297 *pRefType = This->pTypeLib->dispatch_href;
6299 else
6301 if(index >= This->cImplTypes)
6302 hr = TYPE_E_ELEMENTNOTFOUND;
6303 else{
6304 *pRefType = This->impltypes[index].hRef;
6305 if(This->typekind == TKIND_INTERFACE)
6306 *pRefType |= 0x2;
6310 if(TRACE_ON(ole))
6312 if(SUCCEEDED(hr))
6313 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
6314 else
6315 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
6318 return hr;
6321 /* ITypeInfo::GetImplTypeFlags
6323 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6324 * or base interface in a type description.
6326 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
6327 UINT index, INT *pImplTypeFlags)
6329 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6331 TRACE("(%p) index %d\n", This, index);
6333 if(!pImplTypeFlags)
6334 return E_INVALIDARG;
6336 if(This->typekind == TKIND_DISPATCH && index == 0){
6337 *pImplTypeFlags = 0;
6338 return S_OK;
6341 if(index >= This->cImplTypes)
6342 return TYPE_E_ELEMENTNOTFOUND;
6344 *pImplTypeFlags = This->impltypes[index].implflags;
6346 return S_OK;
6349 /* GetIDsOfNames
6350 * Maps between member names and member IDs, and parameter names and
6351 * parameter IDs.
6353 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
6354 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
6356 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6357 const TLBVarDesc *pVDesc;
6358 HRESULT ret=S_OK;
6359 UINT i, fdc;
6361 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
6362 cNames);
6364 /* init out parameters in case of failure */
6365 for (i = 0; i < cNames; i++)
6366 pMemId[i] = MEMBERID_NIL;
6368 for (fdc = 0; fdc < This->cFuncs; ++fdc) {
6369 int j;
6370 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
6371 if(!lstrcmpiW(*rgszNames, TLB_get_bstr(pFDesc->Name))) {
6372 if(cNames) *pMemId=pFDesc->funcdesc.memid;
6373 for(i=1; i < cNames; i++){
6374 for(j=0; j<pFDesc->funcdesc.cParams; j++)
6375 if(!lstrcmpiW(rgszNames[i],TLB_get_bstr(pFDesc->pParamDesc[j].Name)))
6376 break;
6377 if( j<pFDesc->funcdesc.cParams)
6378 pMemId[i]=j;
6379 else
6380 ret=DISP_E_UNKNOWNNAME;
6382 TRACE("-- 0x%08x\n", ret);
6383 return ret;
6386 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->cVars, *rgszNames);
6387 if(pVDesc){
6388 if(cNames)
6389 *pMemId = pVDesc->vardesc.memid;
6390 return ret;
6392 /* not found, see if it can be found in an inherited interface */
6393 if(This->impltypes) {
6394 /* recursive search */
6395 ITypeInfo *pTInfo;
6396 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6397 if(SUCCEEDED(ret)){
6398 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
6399 ITypeInfo_Release(pTInfo);
6400 return ret;
6402 WARN("Could not search inherited interface!\n");
6403 } else
6404 WARN("no names found\n");
6405 return DISP_E_UNKNOWNNAME;
6409 #ifdef __i386__
6411 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6412 __ASM_GLOBAL_FUNC( call_method,
6413 "pushl %ebp\n\t"
6414 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6415 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6416 "movl %esp,%ebp\n\t"
6417 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6418 "pushl %esi\n\t"
6419 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6420 "pushl %edi\n\t"
6421 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6422 "movl 12(%ebp),%edx\n\t"
6423 "movl %esp,%edi\n\t"
6424 "shll $2,%edx\n\t"
6425 "jz 1f\n\t"
6426 "subl %edx,%edi\n\t"
6427 "andl $~15,%edi\n\t"
6428 "movl %edi,%esp\n\t"
6429 "movl 12(%ebp),%ecx\n\t"
6430 "movl 16(%ebp),%esi\n\t"
6431 "cld\n\t"
6432 "rep; movsl\n"
6433 "1:\tcall *8(%ebp)\n\t"
6434 "subl %esp,%edi\n\t"
6435 "movl 20(%ebp),%ecx\n\t"
6436 "movl %edi,(%ecx)\n\t"
6437 "leal -8(%ebp),%esp\n\t"
6438 "popl %edi\n\t"
6439 __ASM_CFI(".cfi_same_value %edi\n\t")
6440 "popl %esi\n\t"
6441 __ASM_CFI(".cfi_same_value %esi\n\t")
6442 "popl %ebp\n\t"
6443 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6444 __ASM_CFI(".cfi_same_value %ebp\n\t")
6445 "ret" )
6447 /* same function but returning floating point */
6448 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
6450 /* ITypeInfo::Invoke
6452 * Invokes a method, or accesses a property of an object, that implements the
6453 * interface described by the type description.
6455 DWORD
6456 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
6457 DWORD res;
6458 int stack_offset;
6460 if (TRACE_ON(ole)) {
6461 int i;
6462 TRACE("Calling %p(",func);
6463 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
6464 if (nrargs > 30) TRACE("...");
6465 TRACE(")\n");
6468 switch (callconv) {
6469 case CC_STDCALL:
6470 case CC_CDECL:
6471 res = call_method( func, nrargs, args, &stack_offset );
6472 break;
6473 default:
6474 FIXME("unsupported calling convention %d\n",callconv);
6475 res = -1;
6476 break;
6478 TRACE("returns %08x\n",res);
6479 return res;
6482 #elif defined(__x86_64__)
6484 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
6485 __ASM_GLOBAL_FUNC( call_method,
6486 "pushq %rbp\n\t"
6487 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6488 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6489 "movq %rsp,%rbp\n\t"
6490 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6491 "pushq %rsi\n\t"
6492 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6493 "pushq %rdi\n\t"
6494 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6495 "movq %rcx,%rax\n\t"
6496 "movq $4,%rcx\n\t"
6497 "cmp %rcx,%rdx\n\t"
6498 "cmovgq %rdx,%rcx\n\t"
6499 "leaq 0(,%rcx,8),%rdx\n\t"
6500 "subq %rdx,%rsp\n\t"
6501 "andq $~15,%rsp\n\t"
6502 "movq %rsp,%rdi\n\t"
6503 "movq %r8,%rsi\n\t"
6504 "rep; movsq\n\t"
6505 "movq 0(%rsp),%rcx\n\t"
6506 "movq 8(%rsp),%rdx\n\t"
6507 "movq 16(%rsp),%r8\n\t"
6508 "movq 24(%rsp),%r9\n\t"
6509 "movq %rcx,%xmm0\n\t"
6510 "movq %rdx,%xmm1\n\t"
6511 "movq %r8,%xmm2\n\t"
6512 "movq %r9,%xmm3\n\t"
6513 "callq *%rax\n\t"
6514 "leaq -16(%rbp),%rsp\n\t"
6515 "popq %rdi\n\t"
6516 __ASM_CFI(".cfi_same_value %rdi\n\t")
6517 "popq %rsi\n\t"
6518 __ASM_CFI(".cfi_same_value %rsi\n\t")
6519 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6520 "popq %rbp\n\t"
6521 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6522 __ASM_CFI(".cfi_same_value %rbp\n\t")
6523 "ret")
6525 /* same function but returning floating point */
6526 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
6528 #endif /* __x86_64__ */
6530 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6532 HRESULT hr = S_OK;
6533 ITypeInfo *tinfo2 = NULL;
6534 TYPEATTR *tattr = NULL;
6536 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6537 if (hr)
6539 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6540 "hr = 0x%08x\n",
6541 tdesc->u.hreftype, hr);
6542 return hr;
6544 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6545 if (hr)
6547 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
6548 ITypeInfo_Release(tinfo2);
6549 return hr;
6552 switch (tattr->typekind)
6554 case TKIND_ENUM:
6555 *vt |= VT_I4;
6556 break;
6558 case TKIND_ALIAS:
6559 tdesc = &tattr->tdescAlias;
6560 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
6561 break;
6563 case TKIND_INTERFACE:
6564 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
6565 *vt |= VT_DISPATCH;
6566 else
6567 *vt |= VT_UNKNOWN;
6568 break;
6570 case TKIND_DISPATCH:
6571 *vt |= VT_DISPATCH;
6572 break;
6574 case TKIND_COCLASS:
6575 *vt |= VT_DISPATCH;
6576 break;
6578 case TKIND_RECORD:
6579 FIXME("TKIND_RECORD unhandled.\n");
6580 hr = E_NOTIMPL;
6581 break;
6583 case TKIND_UNION:
6584 FIXME("TKIND_UNION unhandled.\n");
6585 hr = E_NOTIMPL;
6586 break;
6588 default:
6589 FIXME("TKIND %d unhandled.\n",tattr->typekind);
6590 hr = E_NOTIMPL;
6591 break;
6593 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6594 ITypeInfo_Release(tinfo2);
6595 return hr;
6598 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6600 HRESULT hr = S_OK;
6602 /* enforce only one level of pointer indirection */
6603 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
6605 tdesc = tdesc->u.lptdesc;
6607 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6608 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6609 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6610 if ((tdesc->vt == VT_USERDEFINED) ||
6611 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
6613 VARTYPE vt_userdefined = 0;
6614 const TYPEDESC *tdesc_userdefined = tdesc;
6615 if (tdesc->vt == VT_PTR)
6617 vt_userdefined = VT_BYREF;
6618 tdesc_userdefined = tdesc->u.lptdesc;
6620 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
6621 if ((hr == S_OK) &&
6622 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
6623 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
6625 *vt |= vt_userdefined;
6626 return S_OK;
6629 *vt = VT_BYREF;
6632 switch (tdesc->vt)
6634 case VT_HRESULT:
6635 *vt |= VT_ERROR;
6636 break;
6637 case VT_USERDEFINED:
6638 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
6639 break;
6640 case VT_VOID:
6641 case VT_CARRAY:
6642 case VT_PTR:
6643 case VT_LPSTR:
6644 case VT_LPWSTR:
6645 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
6646 hr = DISP_E_BADVARTYPE;
6647 break;
6648 case VT_SAFEARRAY:
6649 *vt |= VT_ARRAY;
6650 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
6651 break;
6652 case VT_INT:
6653 *vt |= VT_I4;
6654 break;
6655 case VT_UINT:
6656 *vt |= VT_UI4;
6657 break;
6658 default:
6659 *vt |= tdesc->vt;
6660 break;
6662 return hr;
6665 static HRESULT get_iface_guid(ITypeInfo *tinfo, const TYPEDESC *tdesc, GUID *guid)
6667 ITypeInfo *tinfo2;
6668 TYPEATTR *tattr;
6669 HRESULT hres;
6671 hres = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6672 if(FAILED(hres))
6673 return hres;
6675 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6676 if(FAILED(hres)) {
6677 ITypeInfo_Release(tinfo2);
6678 return hres;
6681 switch(tattr->typekind) {
6682 case TKIND_ALIAS:
6683 hres = get_iface_guid(tinfo2, &tattr->tdescAlias, guid);
6684 break;
6686 case TKIND_INTERFACE:
6687 case TKIND_DISPATCH:
6688 *guid = tattr->guid;
6689 break;
6691 default:
6692 ERR("Unexpected typekind %d\n", tattr->typekind);
6693 hres = E_UNEXPECTED;
6696 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6697 ITypeInfo_Release(tinfo2);
6698 return hres;
6701 /***********************************************************************
6702 * DispCallFunc (OLEAUT32.@)
6704 * Invokes a function of the specified calling convention, passing the
6705 * specified arguments and returns the result.
6707 * PARAMS
6708 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6709 * oVft [I] The offset in the vtable. See notes.
6710 * cc [I] Calling convention of the function to call.
6711 * vtReturn [I] The return type of the function.
6712 * cActuals [I] Number of parameters.
6713 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6714 * prgpvarg [I] The arguments to pass.
6715 * pvargResult [O] The return value of the function. Can be NULL.
6717 * RETURNS
6718 * Success: S_OK.
6719 * Failure: HRESULT code.
6721 * NOTES
6722 * The HRESULT return value of this function is not affected by the return
6723 * value of the user supplied function, which is returned in pvargResult.
6725 * If pvInstance is NULL then a non-object function is to be called and oVft
6726 * is the address of the function to call.
6728 * The cc parameter can be one of the following values:
6729 *|CC_FASTCALL
6730 *|CC_CDECL
6731 *|CC_PASCAL
6732 *|CC_STDCALL
6733 *|CC_FPFASTCALL
6734 *|CC_SYSCALL
6735 *|CC_MPWCDECL
6736 *|CC_MPWPASCAL
6739 HRESULT WINAPI
6740 DispCallFunc(
6741 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
6742 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
6744 #ifdef __i386__
6745 int argspos, stack_offset;
6746 void *func;
6747 UINT i;
6748 DWORD *args;
6750 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6751 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6752 pvargResult, V_VT(pvargResult));
6754 if (cc != CC_STDCALL && cc != CC_CDECL)
6756 FIXME("unsupported calling convention %d\n",cc);
6757 return E_INVALIDARG;
6760 /* maximum size for an argument is sizeof(VARIANT) */
6761 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6763 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6764 argspos = 1;
6765 if (pvInstance)
6767 const FARPROC *vtable = *(FARPROC **)pvInstance;
6768 func = vtable[oVft/sizeof(void *)];
6769 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6771 else func = (void *)oVft;
6773 for (i = 0; i < cActuals; i++)
6775 VARIANT *arg = prgpvarg[i];
6777 switch (prgvt[i])
6779 case VT_EMPTY:
6780 break;
6781 case VT_I8:
6782 case VT_UI8:
6783 case VT_R8:
6784 case VT_DATE:
6785 case VT_CY:
6786 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6787 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6788 break;
6789 case VT_DECIMAL:
6790 case VT_VARIANT:
6791 memcpy( &args[argspos], arg, sizeof(*arg) );
6792 argspos += sizeof(*arg) / sizeof(DWORD);
6793 break;
6794 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6795 args[argspos++] = V_BOOL(arg);
6796 break;
6797 default:
6798 args[argspos++] = V_UI4(arg);
6799 break;
6801 TRACE("arg %u: type %d\n",i,prgvt[i]);
6802 dump_Variant(arg);
6805 switch (vtReturn)
6807 case VT_EMPTY:
6808 call_method( func, argspos - 1, args + 1, &stack_offset );
6809 break;
6810 case VT_R4:
6811 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6812 break;
6813 case VT_R8:
6814 case VT_DATE:
6815 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6816 break;
6817 case VT_DECIMAL:
6818 case VT_VARIANT:
6819 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6820 call_method( func, argspos, args, &stack_offset );
6821 break;
6822 case VT_I8:
6823 case VT_UI8:
6824 case VT_CY:
6825 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6826 break;
6827 case VT_HRESULT:
6828 WARN("invalid return type %u\n", vtReturn);
6829 heap_free( args );
6830 return E_INVALIDARG;
6831 default:
6832 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6833 break;
6835 heap_free( args );
6836 if (stack_offset && cc == CC_STDCALL)
6838 WARN( "stack pointer off by %d\n", stack_offset );
6839 return DISP_E_BADCALLEE;
6841 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6842 TRACE("retval: "); dump_Variant(pvargResult);
6843 return S_OK;
6845 #elif defined(__x86_64__)
6846 int argspos;
6847 UINT i;
6848 DWORD_PTR *args;
6849 void *func;
6851 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6852 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6853 pvargResult, V_VT(pvargResult));
6855 if (cc != CC_STDCALL && cc != CC_CDECL)
6857 FIXME("unsupported calling convention %d\n",cc);
6858 return E_INVALIDARG;
6861 /* maximum size for an argument is sizeof(DWORD_PTR) */
6862 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6864 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6865 argspos = 1;
6866 if (pvInstance)
6868 const FARPROC *vtable = *(FARPROC **)pvInstance;
6869 func = vtable[oVft/sizeof(void *)];
6870 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6872 else func = (void *)oVft;
6874 for (i = 0; i < cActuals; i++)
6876 VARIANT *arg = prgpvarg[i];
6878 switch (prgvt[i])
6880 case VT_DECIMAL:
6881 case VT_VARIANT:
6882 args[argspos++] = (ULONG_PTR)arg;
6883 break;
6884 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6885 args[argspos++] = V_BOOL(arg);
6886 break;
6887 default:
6888 args[argspos++] = V_UI8(arg);
6889 break;
6891 TRACE("arg %u: type %d\n",i,prgvt[i]);
6892 dump_Variant(arg);
6895 switch (vtReturn)
6897 case VT_R4:
6898 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6899 break;
6900 case VT_R8:
6901 case VT_DATE:
6902 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6903 break;
6904 case VT_DECIMAL:
6905 case VT_VARIANT:
6906 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6907 call_method( func, argspos, args );
6908 break;
6909 case VT_HRESULT:
6910 WARN("invalid return type %u\n", vtReturn);
6911 heap_free( args );
6912 return E_INVALIDARG;
6913 default:
6914 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6915 break;
6917 heap_free( args );
6918 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6919 TRACE("retval: "); dump_Variant(pvargResult);
6920 return S_OK;
6922 #else
6923 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6924 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6925 return E_NOTIMPL;
6926 #endif
6929 static inline BOOL func_restricted( const FUNCDESC *desc )
6931 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
6934 #define INVBUF_ELEMENT_SIZE \
6935 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6936 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6937 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6938 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6939 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6940 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6941 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6942 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6944 static HRESULT WINAPI ITypeInfo_fnInvoke(
6945 ITypeInfo2 *iface,
6946 VOID *pIUnk,
6947 MEMBERID memid,
6948 UINT16 wFlags,
6949 DISPPARAMS *pDispParams,
6950 VARIANT *pVarResult,
6951 EXCEPINFO *pExcepInfo,
6952 UINT *pArgErr)
6954 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6955 int i;
6956 unsigned int var_index;
6957 TYPEKIND type_kind;
6958 HRESULT hres;
6959 const TLBFuncDesc *pFuncInfo;
6960 UINT fdc;
6962 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6963 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6966 if( This->wTypeFlags & TYPEFLAG_FRESTRICTED )
6967 return DISP_E_MEMBERNOTFOUND;
6969 if (!pDispParams)
6971 ERR("NULL pDispParams not allowed\n");
6972 return E_INVALIDARG;
6975 dump_DispParms(pDispParams);
6977 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6979 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6980 pDispParams->cNamedArgs, pDispParams->cArgs);
6981 return E_INVALIDARG;
6984 /* we do this instead of using GetFuncDesc since it will return a fake
6985 * FUNCDESC for dispinterfaces and we want the real function description */
6986 for (fdc = 0; fdc < This->cFuncs; ++fdc){
6987 pFuncInfo = &This->funcdescs[fdc];
6988 if ((memid == pFuncInfo->funcdesc.memid) &&
6989 (wFlags & pFuncInfo->funcdesc.invkind) &&
6990 !func_restricted( &pFuncInfo->funcdesc ))
6991 break;
6994 if (fdc < This->cFuncs) {
6995 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6997 if (TRACE_ON(ole))
6999 TRACE("invoking:\n");
7000 dump_TLBFuncDescOne(pFuncInfo);
7003 switch (func_desc->funckind) {
7004 case FUNC_PUREVIRTUAL:
7005 case FUNC_VIRTUAL: {
7006 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
7007 VARIANT varresult;
7008 VARIANT retval; /* pointer for storing byref retvals in */
7009 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
7010 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
7011 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
7012 UINT cNamedArgs = pDispParams->cNamedArgs;
7013 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
7014 UINT vargs_converted=0;
7016 hres = S_OK;
7018 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
7020 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
7022 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
7023 hres = DISP_E_PARAMNOTFOUND;
7024 goto func_fail;
7028 if (func_desc->cParamsOpt < 0 && cNamedArgs)
7030 ERR("functions with the vararg attribute do not support named arguments\n");
7031 hres = DISP_E_NONAMEDARGS;
7032 goto func_fail;
7035 for (i = 0; i < func_desc->cParams; i++)
7037 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7038 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
7039 if (FAILED(hres))
7040 goto func_fail;
7043 TRACE("changing args\n");
7044 for (i = 0; i < func_desc->cParams; i++)
7046 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7047 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7048 VARIANTARG *src_arg;
7050 if (wParamFlags & PARAMFLAG_FLCID)
7052 VARIANTARG *arg;
7053 arg = prgpvarg[i] = &rgvarg[i];
7054 V_VT(arg) = VT_I4;
7055 V_I4(arg) = This->pTypeLib->lcid;
7056 continue;
7059 src_arg = NULL;
7061 if (cNamedArgs)
7063 USHORT j;
7064 for (j = 0; j < cNamedArgs; j++)
7065 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
7067 src_arg = &pDispParams->rgvarg[j];
7068 break;
7072 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
7074 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7075 vargs_converted++;
7078 if (wParamFlags & PARAMFLAG_FRETVAL)
7080 /* under most conditions the caller is not allowed to
7081 * pass in a dispparam arg in the index of what would be
7082 * the retval parameter. however, there is an exception
7083 * where the extra parameter is used in an extra
7084 * IDispatch::Invoke below */
7085 if ((i < pDispParams->cArgs) &&
7086 ((func_desc->cParams != 1) || !pVarResult ||
7087 !(func_desc->invkind & INVOKE_PROPERTYGET)))
7089 hres = DISP_E_BADPARAMCOUNT;
7090 break;
7093 /* note: this check is placed so that if the caller passes
7094 * in a VARIANTARG for the retval we just ignore it, like
7095 * native does */
7096 if (i == func_desc->cParams - 1)
7098 VARIANTARG *arg;
7099 arg = prgpvarg[i] = &rgvarg[i];
7100 memset(arg, 0, sizeof(*arg));
7101 V_VT(arg) = rgvt[i];
7102 memset(&retval, 0, sizeof(retval));
7103 V_BYREF(arg) = &retval;
7105 else
7107 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
7108 hres = E_UNEXPECTED;
7109 break;
7112 else if (src_arg)
7114 dump_Variant(src_arg);
7116 if(rgvt[i]!=V_VT(src_arg))
7118 if (rgvt[i] == VT_VARIANT)
7119 hres = VariantCopy(&rgvarg[i], src_arg);
7120 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
7122 if (rgvt[i] == V_VT(src_arg))
7123 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
7124 else
7126 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7127 if (wParamFlags & PARAMFLAG_FIN)
7128 hres = VariantCopy(&missing_arg[i], src_arg);
7129 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
7131 V_VT(&rgvarg[i]) = rgvt[i];
7133 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
7135 SAFEARRAY *a;
7136 SAFEARRAYBOUND bound;
7137 VARIANT *v;
7138 LONG j;
7139 bound.lLbound = 0;
7140 bound.cElements = pDispParams->cArgs-i;
7141 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
7143 ERR("SafeArrayCreate failed\n");
7144 break;
7146 hres = SafeArrayAccessData(a, (LPVOID)&v);
7147 if (hres != S_OK)
7149 ERR("SafeArrayAccessData failed with %x\n", hres);
7150 SafeArrayDestroy(a);
7151 break;
7153 for (j = 0; j < bound.cElements; j++)
7154 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
7155 hres = SafeArrayUnaccessData(a);
7156 if (hres != S_OK)
7158 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7159 SafeArrayDestroy(a);
7160 break;
7162 V_ARRAY(&rgvarg[i]) = a;
7163 V_VT(&rgvarg[i]) = rgvt[i];
7165 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
7167 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7168 if (wParamFlags & PARAMFLAG_FIN)
7169 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
7170 else
7171 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
7172 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
7173 V_VT(&rgvarg[i]) = rgvt[i];
7175 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
7177 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
7178 V_VT(&rgvarg[i]) = rgvt[i];
7180 else
7182 /* FIXME: this doesn't work for VT_BYREF arguments if
7183 * they are not the same type as in the paramdesc */
7184 V_VT(&rgvarg[i]) = V_VT(src_arg);
7185 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
7186 V_VT(&rgvarg[i]) = rgvt[i];
7189 if (FAILED(hres))
7191 ERR("failed to convert param %d to %s%s from %s%s\n", i,
7192 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
7193 debugstr_VT(src_arg), debugstr_VF(src_arg));
7194 break;
7196 prgpvarg[i] = &rgvarg[i];
7198 else
7200 prgpvarg[i] = src_arg;
7203 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
7204 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
7205 && V_UNKNOWN(prgpvarg[i])) {
7206 IUnknown *userdefined_iface;
7207 GUID guid;
7209 hres = get_iface_guid((ITypeInfo*)iface, tdesc->vt == VT_PTR ? tdesc->u.lptdesc : tdesc, &guid);
7210 if(FAILED(hres))
7211 break;
7213 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
7214 if(FAILED(hres)) {
7215 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
7216 break;
7219 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
7220 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
7223 else if (wParamFlags & PARAMFLAG_FOPT)
7225 VARIANTARG *arg;
7226 arg = prgpvarg[i] = &rgvarg[i];
7227 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7229 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
7230 if (FAILED(hres))
7231 break;
7233 else
7235 VARIANTARG *missing_arg;
7236 /* if the function wants a pointer to a variant then
7237 * set that up, otherwise just pass the VT_ERROR in
7238 * the argument by value */
7239 if (rgvt[i] & VT_BYREF)
7241 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
7242 V_VT(arg) = VT_VARIANT | VT_BYREF;
7243 V_VARIANTREF(arg) = missing_arg;
7245 else
7246 missing_arg = arg;
7247 V_VT(missing_arg) = VT_ERROR;
7248 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
7251 else
7253 hres = DISP_E_BADPARAMCOUNT;
7254 break;
7257 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7259 /* VT_VOID is a special case for return types, so it is not
7260 * handled in the general function */
7261 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
7262 V_VT(&varresult) = VT_EMPTY;
7263 else
7265 V_VT(&varresult) = 0;
7266 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
7267 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7270 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv,
7271 V_VT(&varresult), func_desc->cParams, rgvt,
7272 prgpvarg, &varresult);
7274 vargs_converted = 0;
7276 for (i = 0; i < func_desc->cParams; i++)
7278 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7279 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7281 if (wParamFlags & PARAMFLAG_FLCID)
7282 continue;
7283 else if (wParamFlags & PARAMFLAG_FRETVAL)
7285 if (TRACE_ON(ole))
7287 TRACE("[retval] value: ");
7288 dump_Variant(prgpvarg[i]);
7291 if (pVarResult)
7293 VariantInit(pVarResult);
7294 /* deref return value */
7295 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
7298 VARIANT_ClearInd(prgpvarg[i]);
7300 else if (vargs_converted < pDispParams->cArgs)
7302 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7303 if (wParamFlags & PARAMFLAG_FOUT)
7305 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
7307 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
7309 if (FAILED(hres))
7311 ERR("failed to convert param %d to vt %d\n", i,
7312 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
7313 break;
7317 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
7318 func_desc->cParamsOpt < 0 &&
7319 i == func_desc->cParams-1)
7321 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
7322 LONG j, ubound;
7323 VARIANT *v;
7324 hres = SafeArrayGetUBound(a, 1, &ubound);
7325 if (hres != S_OK)
7327 ERR("SafeArrayGetUBound failed with %x\n", hres);
7328 break;
7330 hres = SafeArrayAccessData(a, (LPVOID)&v);
7331 if (hres != S_OK)
7333 ERR("SafeArrayAccessData failed with %x\n", hres);
7334 break;
7336 for (j = 0; j <= ubound; j++)
7337 VariantClear(&v[j]);
7338 hres = SafeArrayUnaccessData(a);
7339 if (hres != S_OK)
7341 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7342 break;
7345 VariantClear(&rgvarg[i]);
7346 vargs_converted++;
7348 else if (wParamFlags & PARAMFLAG_FOPT)
7350 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7351 VariantClear(&rgvarg[i]);
7354 VariantClear(&missing_arg[i]);
7357 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
7359 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
7360 hres = DISP_E_EXCEPTION;
7361 if (pExcepInfo)
7363 IErrorInfo *pErrorInfo;
7364 pExcepInfo->scode = V_ERROR(&varresult);
7365 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
7367 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
7368 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
7369 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
7370 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
7372 IErrorInfo_Release(pErrorInfo);
7376 if (V_VT(&varresult) != VT_ERROR)
7378 TRACE("varresult value: ");
7379 dump_Variant(&varresult);
7381 if (pVarResult)
7383 VariantClear(pVarResult);
7384 *pVarResult = varresult;
7386 else
7387 VariantClear(&varresult);
7390 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
7391 (func_desc->invkind & INVOKE_PROPERTYGET) &&
7392 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
7393 (pDispParams->cArgs != 0))
7395 if (V_VT(pVarResult) == VT_DISPATCH)
7397 IDispatch *pDispatch = V_DISPATCH(pVarResult);
7398 /* Note: not VariantClear; we still need the dispatch
7399 * pointer to be valid */
7400 VariantInit(pVarResult);
7401 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
7402 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
7403 pDispParams, pVarResult, pExcepInfo, pArgErr);
7404 IDispatch_Release(pDispatch);
7406 else
7408 VariantClear(pVarResult);
7409 hres = DISP_E_NOTACOLLECTION;
7413 func_fail:
7414 heap_free(buffer);
7415 break;
7417 case FUNC_DISPATCH: {
7418 IDispatch *disp;
7420 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
7421 if (SUCCEEDED(hres)) {
7422 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7423 hres = IDispatch_Invoke(
7424 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
7425 pVarResult,pExcepInfo,pArgErr
7427 if (FAILED(hres))
7428 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
7429 IDispatch_Release(disp);
7430 } else
7431 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7432 break;
7434 default:
7435 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
7436 hres = E_FAIL;
7437 break;
7440 TRACE("-- 0x%08x\n", hres);
7441 return hres;
7443 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
7444 VARDESC *var_desc;
7446 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
7447 if(FAILED(hres)) return hres;
7449 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7450 dump_VARDESC(var_desc);
7451 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
7452 return E_NOTIMPL;
7455 /* not found, look for it in inherited interfaces */
7456 ITypeInfo2_GetTypeKind(iface, &type_kind);
7457 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
7458 if(This->impltypes) {
7459 /* recursive search */
7460 ITypeInfo *pTInfo;
7461 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7462 if(SUCCEEDED(hres)){
7463 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
7464 ITypeInfo_Release(pTInfo);
7465 return hres;
7467 WARN("Could not search inherited interface!\n");
7470 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
7471 return DISP_E_MEMBERNOTFOUND;
7474 /* ITypeInfo::GetDocumentation
7476 * Retrieves the documentation string, the complete Help file name and path,
7477 * and the context ID for the Help topic for a specified type description.
7479 * (Can be tested by the Visual Basic Editor in Word for instance.)
7481 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
7482 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
7483 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
7485 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7486 const TLBFuncDesc *pFDesc;
7487 const TLBVarDesc *pVDesc;
7488 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7489 " HelpContext(%p) HelpFile(%p)\n",
7490 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
7491 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7492 if(pBstrName)
7493 *pBstrName=SysAllocString(TLB_get_bstr(This->Name));
7494 if(pBstrDocString)
7495 *pBstrDocString=SysAllocString(TLB_get_bstr(This->DocString));
7496 if(pdwHelpContext)
7497 *pdwHelpContext=This->dwHelpContext;
7498 if(pBstrHelpFile)
7499 *pBstrHelpFile=SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7500 return S_OK;
7501 }else {/* for a member */
7502 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7503 if(pFDesc){
7504 if(pBstrName)
7505 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Name));
7506 if(pBstrDocString)
7507 *pBstrDocString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7508 if(pdwHelpContext)
7509 *pdwHelpContext=pFDesc->helpcontext;
7510 if(pBstrHelpFile)
7511 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7512 return S_OK;
7514 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
7515 if(pVDesc){
7516 if(pBstrName)
7517 *pBstrName = SysAllocString(TLB_get_bstr(pVDesc->Name));
7518 if(pBstrDocString)
7519 *pBstrDocString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7520 if(pdwHelpContext)
7521 *pdwHelpContext=pVDesc->HelpContext;
7522 if(pBstrHelpFile)
7523 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7524 return S_OK;
7528 if(This->impltypes &&
7529 (This->typekind==TKIND_INTERFACE || This->typekind==TKIND_DISPATCH)) {
7530 /* recursive search */
7531 ITypeInfo *pTInfo;
7532 HRESULT result;
7533 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7534 if(SUCCEEDED(result)) {
7535 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
7536 pBstrDocString, pdwHelpContext, pBstrHelpFile);
7537 ITypeInfo_Release(pTInfo);
7538 return result;
7540 WARN("Could not search inherited interface!\n");
7543 WARN("member %d not found\n", memid);
7544 return TYPE_E_ELEMENTNOTFOUND;
7547 /* ITypeInfo::GetDllEntry
7549 * Retrieves a description or specification of an entry point for a function
7550 * in a DLL.
7552 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
7553 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
7554 WORD *pwOrdinal)
7556 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7557 const TLBFuncDesc *pFDesc;
7559 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
7561 if (pBstrDllName) *pBstrDllName = NULL;
7562 if (pBstrName) *pBstrName = NULL;
7563 if (pwOrdinal) *pwOrdinal = 0;
7565 if (This->typekind != TKIND_MODULE)
7566 return TYPE_E_BADMODULEKIND;
7568 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7569 if(pFDesc){
7570 dump_TypeInfo(This);
7571 if (TRACE_ON(ole))
7572 dump_TLBFuncDescOne(pFDesc);
7574 if (pBstrDllName)
7575 *pBstrDllName = SysAllocString(TLB_get_bstr(This->DllName));
7577 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
7578 if (pBstrName)
7579 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Entry));
7580 if (pwOrdinal)
7581 *pwOrdinal = -1;
7582 return S_OK;
7584 if (pBstrName)
7585 *pBstrName = NULL;
7586 if (pwOrdinal)
7587 *pwOrdinal = LOWORD(pFDesc->Entry);
7588 return S_OK;
7590 return TYPE_E_ELEMENTNOTFOUND;
7593 /* internal function to make the inherited interfaces' methods appear
7594 * part of the interface */
7595 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7596 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7598 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7599 HRESULT hr;
7601 TRACE("%p, 0x%x\n", iface, *hRefType);
7603 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7605 ITypeInfo *pSubTypeInfo;
7607 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7608 if (FAILED(hr))
7609 return hr;
7611 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7612 hRefType, ppTInfo);
7613 ITypeInfo_Release(pSubTypeInfo);
7614 if (SUCCEEDED(hr))
7615 return hr;
7617 *hRefType -= DISPATCH_HREF_OFFSET;
7619 if (!(*hRefType & DISPATCH_HREF_MASK))
7620 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7621 else
7622 return E_FAIL;
7625 /* ITypeInfo::GetRefTypeInfo
7627 * If a type description references other type descriptions, it retrieves
7628 * the referenced type descriptions.
7630 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7631 ITypeInfo2 *iface,
7632 HREFTYPE hRefType,
7633 ITypeInfo **ppTInfo)
7635 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7636 HRESULT result = E_FAIL;
7638 if(!ppTInfo)
7639 return E_INVALIDARG;
7641 if ((INT)hRefType < 0) {
7642 ITypeInfoImpl *pTypeInfoImpl;
7644 if (!(This->wTypeFlags & TYPEFLAG_FDUAL) ||
7645 !(This->typekind == TKIND_INTERFACE ||
7646 This->typekind == TKIND_DISPATCH))
7647 return TYPE_E_ELEMENTNOTFOUND;
7649 /* when we meet a DUAL typeinfo, we must create the alternate
7650 * version of it.
7652 pTypeInfoImpl = ITypeInfoImpl_Constructor();
7654 *pTypeInfoImpl = *This;
7655 pTypeInfoImpl->ref = 0;
7656 list_init(&pTypeInfoImpl->custdata_list);
7658 if (This->typekind == TKIND_INTERFACE)
7659 pTypeInfoImpl->typekind = TKIND_DISPATCH;
7660 else
7661 pTypeInfoImpl->typekind = TKIND_INTERFACE;
7663 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface;
7664 /* the AddRef implicitly adds a reference to the parent typelib, which
7665 * stops the copied data from being destroyed until the new typeinfo's
7666 * refcount goes to zero, but we need to signal to the new instance to
7667 * not free its data structures when it is destroyed */
7668 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7670 ITypeInfo_AddRef(*ppTInfo);
7672 result = S_OK;
7673 } else if ((hRefType & DISPATCH_HREF_MASK) &&
7674 (This->typekind == TKIND_DISPATCH))
7676 HREFTYPE href_dispatch = hRefType;
7677 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
7678 } else {
7679 TLBRefType *ref_type;
7680 ITypeLib *pTLib = NULL;
7681 UINT i;
7683 if(!(hRefType & 0x1)){
7684 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
7686 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
7688 result = S_OK;
7689 *ppTInfo = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
7690 ITypeInfo_AddRef(*ppTInfo);
7691 goto end;
7696 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7698 if(ref_type->reference == (hRefType & (~0x3)))
7699 break;
7701 if(&ref_type->entry == &This->pTypeLib->ref_list)
7703 FIXME("Can't find pRefType for ref %x\n", hRefType);
7704 goto end;
7707 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7708 UINT Index;
7709 TRACE("internal reference\n");
7710 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7711 } else {
7712 if(ref_type->pImpTLInfo->pImpTypeLib) {
7713 TRACE("typeinfo in imported typelib that is already loaded\n");
7714 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
7715 ITypeLib_AddRef(pTLib);
7716 result = S_OK;
7717 } else {
7718 BSTR libnam;
7720 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7722 result = query_typelib_path(TLB_get_guid_null(ref_type->pImpTLInfo->guid),
7723 ref_type->pImpTLInfo->wVersionMajor,
7724 ref_type->pImpTLInfo->wVersionMinor,
7725 This->pTypeLib->syskind,
7726 ref_type->pImpTLInfo->lcid, &libnam, TRUE);
7727 if(FAILED(result))
7728 libnam = SysAllocString(ref_type->pImpTLInfo->name);
7730 result = LoadTypeLib(libnam, &pTLib);
7731 SysFreeString(libnam);
7733 if(SUCCEEDED(result)) {
7734 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
7735 ITypeLib_AddRef(pTLib);
7739 if(SUCCEEDED(result)) {
7740 if(ref_type->index == TLB_REF_USE_GUID)
7741 result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), ppTInfo);
7742 else
7743 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, ppTInfo);
7745 if (pTLib != NULL)
7746 ITypeLib_Release(pTLib);
7749 end:
7750 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
7751 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
7752 return result;
7755 /* ITypeInfo::AddressOfMember
7757 * Retrieves the addresses of static functions or variables, such as those
7758 * defined in a DLL.
7760 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
7761 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
7763 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7764 HRESULT hr;
7765 BSTR dll, entry;
7766 WORD ordinal;
7767 HMODULE module;
7769 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
7771 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
7772 if (FAILED(hr))
7773 return hr;
7775 module = LoadLibraryW(dll);
7776 if (!module)
7778 ERR("couldn't load %s\n", debugstr_w(dll));
7779 SysFreeString(dll);
7780 SysFreeString(entry);
7781 return STG_E_FILENOTFOUND;
7783 /* FIXME: store library somewhere where we can free it */
7785 if (entry)
7787 LPSTR entryA;
7788 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
7789 entryA = heap_alloc(len);
7790 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
7792 *ppv = GetProcAddress(module, entryA);
7793 if (!*ppv)
7794 ERR("function not found %s\n", debugstr_a(entryA));
7796 heap_free(entryA);
7798 else
7800 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7801 if (!*ppv)
7802 ERR("function not found %d\n", ordinal);
7805 SysFreeString(dll);
7806 SysFreeString(entry);
7808 if (!*ppv)
7809 return TYPE_E_DLLFUNCTIONNOTFOUND;
7811 return S_OK;
7814 /* ITypeInfo::CreateInstance
7816 * Creates a new instance of a type that describes a component object class
7817 * (coclass).
7819 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7820 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7822 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7823 HRESULT hr;
7824 TYPEATTR *pTA;
7826 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7828 *ppvObj = NULL;
7830 if(pOuterUnk)
7832 WARN("Not able to aggregate\n");
7833 return CLASS_E_NOAGGREGATION;
7836 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
7837 if(FAILED(hr)) return hr;
7839 if(pTA->typekind != TKIND_COCLASS)
7841 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7842 hr = E_INVALIDARG;
7843 goto end;
7846 hr = S_FALSE;
7847 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7849 IUnknown *pUnk;
7850 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7851 TRACE("GetActiveObject rets %08x\n", hr);
7852 if(hr == S_OK)
7854 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7855 IUnknown_Release(pUnk);
7859 if(hr != S_OK)
7860 hr = CoCreateInstance(&pTA->guid, NULL,
7861 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7862 riid, ppvObj);
7864 end:
7865 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
7866 return hr;
7869 /* ITypeInfo::GetMops
7871 * Retrieves marshalling information.
7873 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7874 BSTR *pBstrMops)
7876 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7877 FIXME("(%p %d) stub!\n", This, memid);
7878 *pBstrMops = NULL;
7879 return S_OK;
7882 /* ITypeInfo::GetContainingTypeLib
7884 * Retrieves the containing type library and the index of the type description
7885 * within that type library.
7887 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7888 ITypeLib * *ppTLib, UINT *pIndex)
7890 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7892 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7893 if (pIndex) {
7894 *pIndex=This->index;
7895 TRACE("returning pIndex=%d\n", *pIndex);
7898 if (ppTLib) {
7899 *ppTLib=(LPTYPELIB )(This->pTypeLib);
7900 ITypeLib_AddRef(*ppTLib);
7901 TRACE("returning ppTLib=%p\n", *ppTLib);
7904 return S_OK;
7907 /* ITypeInfo::ReleaseTypeAttr
7909 * Releases a TYPEATTR previously returned by Get
7912 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7913 TYPEATTR* pTypeAttr)
7915 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7916 TRACE("(%p)->(%p)\n", This, pTypeAttr);
7917 heap_free(pTypeAttr);
7920 /* ITypeInfo::ReleaseFuncDesc
7922 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7924 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7925 ITypeInfo2 *iface,
7926 FUNCDESC *pFuncDesc)
7928 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7929 SHORT i;
7931 TRACE("(%p)->(%p)\n", This, pFuncDesc);
7933 for (i = 0; i < pFuncDesc->cParams; i++)
7934 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7935 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7937 SysFreeString((BSTR)pFuncDesc);
7940 /* ITypeInfo::ReleaseVarDesc
7942 * Releases a VARDESC previously returned by GetVarDesc.
7944 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7945 VARDESC *pVarDesc)
7947 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7948 TRACE("(%p)->(%p)\n", This, pVarDesc);
7950 TLB_FreeVarDesc(pVarDesc);
7953 /* ITypeInfo2::GetTypeKind
7955 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7958 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7959 TYPEKIND *pTypeKind)
7961 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7962 *pTypeKind=This->typekind;
7963 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7964 return S_OK;
7967 /* ITypeInfo2::GetTypeFlags
7969 * Returns the type flags without any allocations. This returns a DWORD type
7970 * flag, which expands the type flags without growing the TYPEATTR (type
7971 * attribute).
7974 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7976 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7977 *pTypeFlags=This->wTypeFlags;
7978 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7979 return S_OK;
7982 /* ITypeInfo2::GetFuncIndexOfMemId
7983 * Binds to a specific member based on a known DISPID, where the member name
7984 * is not known (for example, when binding to a default member).
7987 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7988 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7990 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7991 UINT fdc;
7992 HRESULT result;
7994 for (fdc = 0; fdc < This->cFuncs; ++fdc){
7995 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
7996 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7997 break;
7999 if(fdc < This->cFuncs) {
8000 *pFuncIndex = fdc;
8001 result = S_OK;
8002 } else
8003 result = TYPE_E_ELEMENTNOTFOUND;
8005 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
8006 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
8007 return result;
8010 /* TypeInfo2::GetVarIndexOfMemId
8012 * Binds to a specific member based on a known DISPID, where the member name
8013 * is not known (for example, when binding to a default member).
8016 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
8017 MEMBERID memid, UINT *pVarIndex)
8019 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8020 TLBVarDesc *pVarInfo;
8022 TRACE("%p %d %p\n", iface, memid, pVarIndex);
8024 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
8025 if(!pVarInfo)
8026 return TYPE_E_ELEMENTNOTFOUND;
8028 *pVarIndex = (pVarInfo - This->vardescs);
8030 return S_OK;
8033 /* ITypeInfo2::GetCustData
8035 * Gets the custom data
8037 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
8038 ITypeInfo2 * iface,
8039 REFGUID guid,
8040 VARIANT *pVarVal)
8042 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8043 TLBCustData *pCData;
8045 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8047 if(!guid || !pVarVal)
8048 return E_INVALIDARG;
8050 pCData = TLB_get_custdata_by_guid(This->pcustdata_list, guid);
8052 VariantInit( pVarVal);
8053 if (pCData)
8054 VariantCopy( pVarVal, &pCData->data);
8055 else
8056 VariantClear( pVarVal );
8057 return S_OK;
8060 /* ITypeInfo2::GetFuncCustData
8062 * Gets the custom data
8064 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
8065 ITypeInfo2 * iface,
8066 UINT index,
8067 REFGUID guid,
8068 VARIANT *pVarVal)
8070 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8071 TLBCustData *pCData;
8072 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8074 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8076 if(index >= This->cFuncs)
8077 return TYPE_E_ELEMENTNOTFOUND;
8079 pCData = TLB_get_custdata_by_guid(&pFDesc->custdata_list, guid);
8080 if(!pCData)
8081 return TYPE_E_ELEMENTNOTFOUND;
8083 VariantInit(pVarVal);
8084 VariantCopy(pVarVal, &pCData->data);
8086 return S_OK;
8089 /* ITypeInfo2::GetParamCustData
8091 * Gets the custom data
8093 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
8094 ITypeInfo2 * iface,
8095 UINT indexFunc,
8096 UINT indexParam,
8097 REFGUID guid,
8098 VARIANT *pVarVal)
8100 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8101 TLBCustData *pCData;
8102 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8104 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
8105 debugstr_guid(guid), pVarVal);
8107 if(indexFunc >= This->cFuncs)
8108 return TYPE_E_ELEMENTNOTFOUND;
8110 if(indexParam >= pFDesc->funcdesc.cParams)
8111 return TYPE_E_ELEMENTNOTFOUND;
8113 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
8114 if(!pCData)
8115 return TYPE_E_ELEMENTNOTFOUND;
8117 VariantInit(pVarVal);
8118 VariantCopy(pVarVal, &pCData->data);
8120 return S_OK;
8123 /* ITypeInfo2::GetVarCustData
8125 * Gets the custom data
8127 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
8128 ITypeInfo2 * iface,
8129 UINT index,
8130 REFGUID guid,
8131 VARIANT *pVarVal)
8133 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8134 TLBCustData *pCData;
8135 TLBVarDesc *pVDesc = &This->vardescs[index];
8137 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8139 if(index >= This->cVars)
8140 return TYPE_E_ELEMENTNOTFOUND;
8142 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
8143 if(!pCData)
8144 return TYPE_E_ELEMENTNOTFOUND;
8146 VariantInit(pVarVal);
8147 VariantCopy(pVarVal, &pCData->data);
8149 return S_OK;
8152 /* ITypeInfo2::GetImplCustData
8154 * Gets the custom data
8156 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
8157 ITypeInfo2 * iface,
8158 UINT index,
8159 REFGUID guid,
8160 VARIANT *pVarVal)
8162 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8163 TLBCustData *pCData;
8164 TLBImplType *pRDesc = &This->impltypes[index];
8166 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8168 if(index >= This->cImplTypes)
8169 return TYPE_E_ELEMENTNOTFOUND;
8171 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
8172 if(!pCData)
8173 return TYPE_E_ELEMENTNOTFOUND;
8175 VariantInit(pVarVal);
8176 VariantCopy(pVarVal, &pCData->data);
8178 return S_OK;
8181 /* ITypeInfo2::GetDocumentation2
8183 * Retrieves the documentation string, the complete Help file name and path,
8184 * the localization context to use, and the context ID for the library Help
8185 * topic in the Help file.
8188 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
8189 ITypeInfo2 * iface,
8190 MEMBERID memid,
8191 LCID lcid,
8192 BSTR *pbstrHelpString,
8193 DWORD *pdwHelpStringContext,
8194 BSTR *pbstrHelpStringDll)
8196 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8197 const TLBFuncDesc *pFDesc;
8198 const TLBVarDesc *pVDesc;
8199 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8200 "HelpStringContext(%p) HelpStringDll(%p)\n",
8201 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
8202 pbstrHelpStringDll );
8203 /* the help string should be obtained from the helpstringdll,
8204 * using the _DLLGetDocumentation function, based on the supplied
8205 * lcid. Nice to do sometime...
8207 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
8208 if(pbstrHelpString)
8209 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->Name));
8210 if(pdwHelpStringContext)
8211 *pdwHelpStringContext=This->dwHelpStringContext;
8212 if(pbstrHelpStringDll)
8213 *pbstrHelpStringDll=
8214 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8215 return S_OK;
8216 }else {/* for a member */
8217 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
8218 if(pFDesc){
8219 if(pbstrHelpString)
8220 *pbstrHelpString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
8221 if(pdwHelpStringContext)
8222 *pdwHelpStringContext=pFDesc->HelpStringContext;
8223 if(pbstrHelpStringDll)
8224 *pbstrHelpStringDll=
8225 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8226 return S_OK;
8228 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
8229 if(pVDesc){
8230 if(pbstrHelpString)
8231 *pbstrHelpString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
8232 if(pdwHelpStringContext)
8233 *pdwHelpStringContext=pVDesc->HelpStringContext;
8234 if(pbstrHelpStringDll)
8235 *pbstrHelpStringDll=
8236 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8237 return S_OK;
8240 return TYPE_E_ELEMENTNOTFOUND;
8243 /* ITypeInfo2::GetAllCustData
8245 * Gets all custom data items for the Type info.
8248 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
8249 ITypeInfo2 * iface,
8250 CUSTDATA *pCustData)
8252 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8254 TRACE("%p %p\n", This, pCustData);
8256 return TLB_copy_all_custdata(This->pcustdata_list, pCustData);
8259 /* ITypeInfo2::GetAllFuncCustData
8261 * Gets all custom data items for the specified Function
8264 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
8265 ITypeInfo2 * iface,
8266 UINT index,
8267 CUSTDATA *pCustData)
8269 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8270 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8272 TRACE("%p %u %p\n", This, index, pCustData);
8274 if(index >= This->cFuncs)
8275 return TYPE_E_ELEMENTNOTFOUND;
8277 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
8280 /* ITypeInfo2::GetAllParamCustData
8282 * Gets all custom data items for the Functions
8285 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
8286 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
8288 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8289 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8291 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
8293 if(indexFunc >= This->cFuncs)
8294 return TYPE_E_ELEMENTNOTFOUND;
8296 if(indexParam >= pFDesc->funcdesc.cParams)
8297 return TYPE_E_ELEMENTNOTFOUND;
8299 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
8302 /* ITypeInfo2::GetAllVarCustData
8304 * Gets all custom data items for the specified Variable
8307 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
8308 UINT index, CUSTDATA *pCustData)
8310 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8311 TLBVarDesc * pVDesc = &This->vardescs[index];
8313 TRACE("%p %u %p\n", This, index, pCustData);
8315 if(index >= This->cVars)
8316 return TYPE_E_ELEMENTNOTFOUND;
8318 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
8321 /* ITypeInfo2::GetAllImplCustData
8323 * Gets all custom data items for the specified implementation type
8326 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
8327 ITypeInfo2 * iface,
8328 UINT index,
8329 CUSTDATA *pCustData)
8331 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8332 TLBImplType *pRDesc = &This->impltypes[index];
8334 TRACE("%p %u %p\n", This, index, pCustData);
8336 if(index >= This->cImplTypes)
8337 return TYPE_E_ELEMENTNOTFOUND;
8339 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
8342 static const ITypeInfo2Vtbl tinfvt =
8345 ITypeInfo_fnQueryInterface,
8346 ITypeInfo_fnAddRef,
8347 ITypeInfo_fnRelease,
8349 ITypeInfo_fnGetTypeAttr,
8350 ITypeInfo_fnGetTypeComp,
8351 ITypeInfo_fnGetFuncDesc,
8352 ITypeInfo_fnGetVarDesc,
8353 ITypeInfo_fnGetNames,
8354 ITypeInfo_fnGetRefTypeOfImplType,
8355 ITypeInfo_fnGetImplTypeFlags,
8356 ITypeInfo_fnGetIDsOfNames,
8357 ITypeInfo_fnInvoke,
8358 ITypeInfo_fnGetDocumentation,
8359 ITypeInfo_fnGetDllEntry,
8360 ITypeInfo_fnGetRefTypeInfo,
8361 ITypeInfo_fnAddressOfMember,
8362 ITypeInfo_fnCreateInstance,
8363 ITypeInfo_fnGetMops,
8364 ITypeInfo_fnGetContainingTypeLib,
8365 ITypeInfo_fnReleaseTypeAttr,
8366 ITypeInfo_fnReleaseFuncDesc,
8367 ITypeInfo_fnReleaseVarDesc,
8369 ITypeInfo2_fnGetTypeKind,
8370 ITypeInfo2_fnGetTypeFlags,
8371 ITypeInfo2_fnGetFuncIndexOfMemId,
8372 ITypeInfo2_fnGetVarIndexOfMemId,
8373 ITypeInfo2_fnGetCustData,
8374 ITypeInfo2_fnGetFuncCustData,
8375 ITypeInfo2_fnGetParamCustData,
8376 ITypeInfo2_fnGetVarCustData,
8377 ITypeInfo2_fnGetImplTypeCustData,
8378 ITypeInfo2_fnGetDocumentation2,
8379 ITypeInfo2_fnGetAllCustData,
8380 ITypeInfo2_fnGetAllFuncCustData,
8381 ITypeInfo2_fnGetAllParamCustData,
8382 ITypeInfo2_fnGetAllVarCustData,
8383 ITypeInfo2_fnGetAllImplTypeCustData,
8386 /******************************************************************************
8387 * CreateDispTypeInfo [OLEAUT32.31]
8389 * Build type information for an object so it can be called through an
8390 * IDispatch interface.
8392 * RETURNS
8393 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8394 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8396 * NOTES
8397 * This call allows an objects methods to be accessed through IDispatch, by
8398 * building an ITypeInfo object that IDispatch can use to call through.
8400 HRESULT WINAPI CreateDispTypeInfo(
8401 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
8402 LCID lcid, /* [I] Locale Id */
8403 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
8405 ITypeInfoImpl *pTIClass, *pTIIface;
8406 ITypeLibImpl *pTypeLibImpl;
8407 unsigned int param, func;
8408 TLBFuncDesc *pFuncDesc;
8409 TLBRefType *ref;
8411 TRACE("\n");
8412 pTypeLibImpl = TypeLibImpl_Constructor();
8413 if (!pTypeLibImpl) return E_FAIL;
8415 pTypeLibImpl->TypeInfoCount = 2;
8416 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
8418 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
8419 pTIIface->pTypeLib = pTypeLibImpl;
8420 pTIIface->index = 0;
8421 pTIIface->Name = NULL;
8422 pTIIface->dwHelpContext = -1;
8423 pTIIface->guid = NULL;
8424 pTIIface->lcid = lcid;
8425 pTIIface->typekind = TKIND_INTERFACE;
8426 pTIIface->wMajorVerNum = 0;
8427 pTIIface->wMinorVerNum = 0;
8428 pTIIface->cbAlignment = 2;
8429 pTIIface->cbSizeInstance = -1;
8430 pTIIface->cbSizeVft = -1;
8431 pTIIface->cFuncs = 0;
8432 pTIIface->cImplTypes = 0;
8433 pTIIface->cVars = 0;
8434 pTIIface->wTypeFlags = 0;
8435 pTIIface->hreftype = 0;
8437 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers);
8438 pFuncDesc = pTIIface->funcdescs;
8439 for(func = 0; func < pidata->cMembers; func++) {
8440 METHODDATA *md = pidata->pmethdata + func;
8441 pFuncDesc->Name = TLB_append_str(&pTypeLibImpl->name_list, md->szName);
8442 pFuncDesc->funcdesc.memid = md->dispid;
8443 pFuncDesc->funcdesc.lprgscode = NULL;
8444 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
8445 pFuncDesc->funcdesc.invkind = md->wFlags;
8446 pFuncDesc->funcdesc.callconv = md->cc;
8447 pFuncDesc->funcdesc.cParams = md->cArgs;
8448 pFuncDesc->funcdesc.cParamsOpt = 0;
8449 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
8450 pFuncDesc->funcdesc.cScodes = 0;
8451 pFuncDesc->funcdesc.wFuncFlags = 0;
8452 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
8453 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
8454 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
8455 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8456 md->cArgs * sizeof(ELEMDESC));
8457 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
8458 for(param = 0; param < md->cArgs; param++) {
8459 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
8460 pFuncDesc->pParamDesc[param].Name = TLB_append_str(&pTypeLibImpl->name_list, md->ppdata[param].szName);
8462 pFuncDesc->helpcontext = 0;
8463 pFuncDesc->HelpStringContext = 0;
8464 pFuncDesc->HelpString = NULL;
8465 pFuncDesc->Entry = NULL;
8466 list_init(&pFuncDesc->custdata_list);
8467 pTIIface->cFuncs++;
8468 ++pFuncDesc;
8471 dump_TypeInfo(pTIIface);
8473 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
8474 pTIClass->pTypeLib = pTypeLibImpl;
8475 pTIClass->index = 1;
8476 pTIClass->Name = NULL;
8477 pTIClass->dwHelpContext = -1;
8478 pTIClass->guid = NULL;
8479 pTIClass->lcid = lcid;
8480 pTIClass->typekind = TKIND_COCLASS;
8481 pTIClass->wMajorVerNum = 0;
8482 pTIClass->wMinorVerNum = 0;
8483 pTIClass->cbAlignment = 2;
8484 pTIClass->cbSizeInstance = -1;
8485 pTIClass->cbSizeVft = -1;
8486 pTIClass->cFuncs = 0;
8487 pTIClass->cImplTypes = 1;
8488 pTIClass->cVars = 0;
8489 pTIClass->wTypeFlags = 0;
8490 pTIClass->hreftype = sizeof(MSFT_TypeInfoBase);
8492 pTIClass->impltypes = TLBImplType_Alloc(1);
8494 ref = heap_alloc_zero(sizeof(*ref));
8495 ref->pImpTLInfo = TLB_REF_INTERNAL;
8496 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
8498 dump_TypeInfo(pTIClass);
8500 *pptinfo = (ITypeInfo *)&pTIClass->ITypeInfo2_iface;
8502 ITypeInfo_AddRef(*pptinfo);
8503 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
8505 return S_OK;
8509 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
8511 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8513 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, ppv);
8516 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
8518 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8520 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
8523 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
8525 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8527 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
8530 static HRESULT WINAPI ITypeComp_fnBind(
8531 ITypeComp * iface,
8532 OLECHAR * szName,
8533 ULONG lHash,
8534 WORD wFlags,
8535 ITypeInfo ** ppTInfo,
8536 DESCKIND * pDescKind,
8537 BINDPTR * pBindPtr)
8539 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8540 const TLBFuncDesc *pFDesc;
8541 const TLBVarDesc *pVDesc;
8542 HRESULT hr = DISP_E_MEMBERNOTFOUND;
8543 UINT fdc;
8545 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8547 *pDescKind = DESCKIND_NONE;
8548 pBindPtr->lpfuncdesc = NULL;
8549 *ppTInfo = NULL;
8551 for(fdc = 0; fdc < This->cFuncs; ++fdc){
8552 pFDesc = &This->funcdescs[fdc];
8553 if (!lstrcmpiW(TLB_get_bstr(pFDesc->Name), szName)) {
8554 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
8555 break;
8556 else
8557 /* name found, but wrong flags */
8558 hr = TYPE_E_TYPEMISMATCH;
8562 if (fdc < This->cFuncs)
8564 HRESULT hr = TLB_AllocAndInitFuncDesc(
8565 &pFDesc->funcdesc,
8566 &pBindPtr->lpfuncdesc,
8567 This->typekind == TKIND_DISPATCH);
8568 if (FAILED(hr))
8569 return hr;
8570 *pDescKind = DESCKIND_FUNCDESC;
8571 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8572 ITypeInfo_AddRef(*ppTInfo);
8573 return S_OK;
8574 } else {
8575 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->cVars, szName);
8576 if(pVDesc){
8577 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
8578 if (FAILED(hr))
8579 return hr;
8580 *pDescKind = DESCKIND_VARDESC;
8581 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8582 ITypeInfo_AddRef(*ppTInfo);
8583 return S_OK;
8587 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
8588 /* recursive search */
8589 ITypeInfo *pTInfo;
8590 ITypeComp *pTComp;
8591 HRESULT hr;
8592 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
8593 if (SUCCEEDED(hr))
8595 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
8596 ITypeInfo_Release(pTInfo);
8598 if (SUCCEEDED(hr))
8600 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8601 ITypeComp_Release(pTComp);
8602 if (SUCCEEDED(hr) && *pDescKind == DESCKIND_FUNCDESC &&
8603 This->typekind == TKIND_DISPATCH)
8605 FUNCDESC *tmp = pBindPtr->lpfuncdesc;
8606 hr = TLB_AllocAndInitFuncDesc(tmp, &pBindPtr->lpfuncdesc, TRUE);
8607 SysFreeString((BSTR)tmp);
8609 return hr;
8611 WARN("Could not search inherited interface!\n");
8613 if (hr == DISP_E_MEMBERNOTFOUND)
8614 hr = S_OK;
8615 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
8616 return hr;
8619 static HRESULT WINAPI ITypeComp_fnBindType(
8620 ITypeComp * iface,
8621 OLECHAR * szName,
8622 ULONG lHash,
8623 ITypeInfo ** ppTInfo,
8624 ITypeComp ** ppTComp)
8626 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
8628 /* strange behaviour (does nothing) but like the
8629 * original */
8631 if (!ppTInfo || !ppTComp)
8632 return E_POINTER;
8634 *ppTInfo = NULL;
8635 *ppTComp = NULL;
8637 return S_OK;
8640 static const ITypeCompVtbl tcompvt =
8643 ITypeComp_fnQueryInterface,
8644 ITypeComp_fnAddRef,
8645 ITypeComp_fnRelease,
8647 ITypeComp_fnBind,
8648 ITypeComp_fnBindType
8651 HRESULT WINAPI CreateTypeLib2(SYSKIND syskind, LPCOLESTR szFile,
8652 ICreateTypeLib2** ppctlib)
8654 ITypeLibImpl *This;
8655 HRESULT hres;
8657 TRACE("(%d,%s,%p)\n", syskind, debugstr_w(szFile), ppctlib);
8659 if (!szFile) return E_INVALIDARG;
8661 This = TypeLibImpl_Constructor();
8662 if (!This)
8663 return E_OUTOFMEMORY;
8665 This->lcid = GetSystemDefaultLCID();
8666 This->syskind = syskind;
8667 This->ptr_size = get_ptr_size(syskind);
8669 This->path = heap_alloc((lstrlenW(szFile) + 1) * sizeof(WCHAR));
8670 if (!This->path) {
8671 ITypeLib2_Release(&This->ITypeLib2_iface);
8672 return E_OUTOFMEMORY;
8674 lstrcpyW(This->path, szFile);
8676 hres = ITypeLib2_QueryInterface(&This->ITypeLib2_iface, &IID_ICreateTypeLib2, (LPVOID*)ppctlib);
8677 ITypeLib2_Release(&This->ITypeLib2_iface);
8678 return hres;
8681 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
8682 REFIID riid, void **object)
8684 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8686 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, object);
8689 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
8691 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8693 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
8696 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
8698 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8700 return ITypeLib2_Release(&This->ITypeLib2_iface);
8703 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
8704 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
8706 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8707 ITypeInfoImpl *info;
8708 HRESULT hres;
8710 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo);
8712 if (!ctinfo || !name)
8713 return E_INVALIDARG;
8715 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, name);
8716 if (info)
8717 return TYPE_E_NAMECONFLICT;
8719 if (This->typeinfos)
8720 This->typeinfos = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->typeinfos,
8721 sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1));
8722 else
8723 This->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*));
8725 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor();
8727 info->pTypeLib = This;
8728 info->Name = TLB_append_str(&This->name_list, name);
8729 info->index = This->TypeInfoCount;
8730 info->typekind = kind;
8731 info->cbAlignment = 4;
8733 switch(info->typekind) {
8734 case TKIND_ENUM:
8735 case TKIND_INTERFACE:
8736 case TKIND_DISPATCH:
8737 case TKIND_COCLASS:
8738 info->cbSizeInstance = This->ptr_size;
8739 break;
8740 case TKIND_RECORD:
8741 case TKIND_UNION:
8742 info->cbSizeInstance = 0;
8743 break;
8744 case TKIND_MODULE:
8745 info->cbSizeInstance = 2;
8746 break;
8747 case TKIND_ALIAS:
8748 info->cbSizeInstance = -0x75;
8749 break;
8750 default:
8751 FIXME("unrecognized typekind %d\n", info->typekind);
8752 info->cbSizeInstance = 0xdeadbeef;
8753 break;
8756 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface,
8757 &IID_ICreateTypeInfo, (void **)ctinfo);
8758 if (FAILED(hres)) {
8759 ITypeInfo2_Release(&info->ITypeInfo2_iface);
8760 return hres;
8763 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase);
8765 ++This->TypeInfoCount;
8767 return S_OK;
8770 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
8771 LPOLESTR name)
8773 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8775 TRACE("%p %s\n", This, wine_dbgstr_w(name));
8777 if (!name)
8778 return E_INVALIDARG;
8780 This->Name = TLB_append_str(&This->name_list, name);
8782 return S_OK;
8785 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
8786 WORD majorVerNum, WORD minorVerNum)
8788 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8790 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
8792 This->ver_major = majorVerNum;
8793 This->ver_minor = minorVerNum;
8795 return S_OK;
8798 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
8799 REFGUID guid)
8801 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8803 TRACE("%p %s\n", This, debugstr_guid(guid));
8805 This->guid = TLB_append_guid(&This->guid_list, guid, -2);
8807 return S_OK;
8810 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
8811 LPOLESTR doc)
8813 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8815 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
8817 if (!doc)
8818 return E_INVALIDARG;
8820 This->DocString = TLB_append_str(&This->string_list, doc);
8822 return S_OK;
8825 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
8826 LPOLESTR helpFileName)
8828 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8830 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
8832 if (!helpFileName)
8833 return E_INVALIDARG;
8835 This->HelpFile = TLB_append_str(&This->string_list, helpFileName);
8837 return S_OK;
8840 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
8841 DWORD helpContext)
8843 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8845 TRACE("%p %d\n", This, helpContext);
8847 This->dwHelpContext = helpContext;
8849 return S_OK;
8852 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
8853 LCID lcid)
8855 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8857 TRACE("%p %x\n", This, lcid);
8859 This->set_lcid = lcid;
8861 return S_OK;
8864 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
8865 UINT libFlags)
8867 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8869 TRACE("%p %x\n", This, libFlags);
8871 This->libflags = libFlags;
8873 return S_OK;
8876 typedef struct tagWMSFT_SegContents {
8877 DWORD len;
8878 void *data;
8879 } WMSFT_SegContents;
8881 typedef struct tagWMSFT_TLBFile {
8882 MSFT_Header header;
8883 WMSFT_SegContents typeinfo_seg;
8884 WMSFT_SegContents impfile_seg;
8885 WMSFT_SegContents impinfo_seg;
8886 WMSFT_SegContents ref_seg;
8887 WMSFT_SegContents guidhash_seg;
8888 WMSFT_SegContents guid_seg;
8889 WMSFT_SegContents namehash_seg;
8890 WMSFT_SegContents name_seg;
8891 WMSFT_SegContents string_seg;
8892 WMSFT_SegContents typdesc_seg;
8893 WMSFT_SegContents arraydesc_seg;
8894 WMSFT_SegContents custdata_seg;
8895 WMSFT_SegContents cdguids_seg;
8896 MSFT_SegDir segdir;
8897 WMSFT_SegContents aux_seg;
8898 } WMSFT_TLBFile;
8900 static HRESULT WMSFT_compile_strings(ITypeLibImpl *This,
8901 WMSFT_TLBFile *file)
8903 TLBString *str;
8904 UINT last_offs;
8905 char *data;
8907 file->string_seg.len = 0;
8908 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8909 int size;
8911 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str), NULL, 0, NULL, NULL);
8912 if (size == 0)
8913 return E_UNEXPECTED;
8915 size += sizeof(INT16);
8916 if (size % 4)
8917 size = (size + 4) & ~0x3;
8918 if (size < 8)
8919 size = 8;
8921 file->string_seg.len += size;
8923 /* temporarily use str->offset to store the length of the aligned,
8924 * converted string */
8925 str->offset = size;
8928 file->string_seg.data = data = heap_alloc(file->string_seg.len);
8930 last_offs = 0;
8931 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8932 int size;
8934 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8935 data + sizeof(INT16), file->string_seg.len - last_offs - sizeof(INT16), NULL, NULL);
8936 if (size == 0) {
8937 heap_free(file->string_seg.data);
8938 return E_UNEXPECTED;
8941 *((INT16*)data) = size;
8943 memset(data + sizeof(INT16) + size, 0x57, str->offset - size - sizeof(INT16));
8945 size = str->offset;
8946 data += size;
8947 str->offset = last_offs;
8948 last_offs += size;
8951 return S_OK;
8954 static HRESULT WMSFT_compile_names(ITypeLibImpl *This,
8955 WMSFT_TLBFile *file)
8957 TLBString *str;
8958 UINT last_offs;
8959 char *data;
8960 MSFT_NameIntro *last_intro = NULL;
8962 file->header.nametablecount = 0;
8963 file->header.nametablechars = 0;
8965 file->name_seg.len = 0;
8966 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8967 int size;
8969 size = strlenW(str->str);
8970 file->header.nametablechars += size;
8971 file->header.nametablecount++;
8973 size = WideCharToMultiByte(CP_ACP, 0, str->str, size, NULL, 0, NULL, NULL);
8974 if (size == 0)
8975 return E_UNEXPECTED;
8977 size += sizeof(MSFT_NameIntro);
8978 if (size % 4)
8979 size = (size + 4) & ~0x3;
8980 if (size < 8)
8981 size = 8;
8983 file->name_seg.len += size;
8985 /* temporarily use str->offset to store the length of the aligned,
8986 * converted string */
8987 str->offset = size;
8990 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
8991 file->name_seg.data = data = heap_alloc(file->name_seg.len+1);
8993 last_offs = 0;
8994 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8995 int size, hash;
8996 MSFT_NameIntro *intro = (MSFT_NameIntro*)data;
8998 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8999 data + sizeof(MSFT_NameIntro),
9000 file->name_seg.len - last_offs - sizeof(MSFT_NameIntro), NULL, NULL);
9001 if (size == 0) {
9002 heap_free(file->name_seg.data);
9003 return E_UNEXPECTED;
9005 data[sizeof(MSFT_NameIntro) + size] = '\0';
9007 intro->hreftype = -1; /* TODO? */
9008 intro->namelen = size & 0xFF;
9009 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9010 hash = LHashValOfNameSysA(This->syskind, This->lcid, data + sizeof(MSFT_NameIntro));
9011 intro->namelen |= hash << 16;
9012 intro->next_hash = ((DWORD*)file->namehash_seg.data)[hash & 0x7f];
9013 ((DWORD*)file->namehash_seg.data)[hash & 0x7f] = last_offs;
9015 memset(data + sizeof(MSFT_NameIntro) + size, 0x57,
9016 str->offset - size - sizeof(MSFT_NameIntro));
9018 /* update str->offset to actual value to use in other
9019 * compilation functions that require positions within
9020 * the string table */
9021 last_intro = intro;
9022 size = str->offset;
9023 data += size;
9024 str->offset = last_offs;
9025 last_offs += size;
9028 if(last_intro)
9029 last_intro->hreftype = 0; /* last one is 0? */
9031 return S_OK;
9034 static inline int hash_guid(GUID *guid)
9036 int i, hash = 0;
9038 for (i = 0; i < 8; i ++)
9039 hash ^= ((const short *)guid)[i];
9041 return hash & 0x1f;
9044 static HRESULT WMSFT_compile_guids(ITypeLibImpl *This, WMSFT_TLBFile *file)
9046 TLBGuid *guid;
9047 MSFT_GuidEntry *entry;
9048 DWORD offs;
9049 int hash_key, *guidhashtab;
9051 file->guid_seg.len = sizeof(MSFT_GuidEntry) * list_count(&This->guid_list);
9052 file->guid_seg.data = heap_alloc(file->guid_seg.len);
9054 entry = file->guid_seg.data;
9055 offs = 0;
9056 guidhashtab = file->guidhash_seg.data;
9057 LIST_FOR_EACH_ENTRY(guid, &This->guid_list, TLBGuid, entry){
9058 memcpy(&entry->guid, &guid->guid, sizeof(GUID));
9059 entry->hreftype = guid->hreftype;
9061 hash_key = hash_guid(&guid->guid);
9062 entry->next_hash = guidhashtab[hash_key];
9063 guidhashtab[hash_key] = offs;
9065 guid->offset = offs;
9066 offs += sizeof(MSFT_GuidEntry);
9067 ++entry;
9070 return S_OK;
9073 static DWORD WMSFT_encode_variant(VARIANT *value, WMSFT_TLBFile *file)
9075 VARIANT v = *value;
9076 VARTYPE arg_type = V_VT(value);
9077 int mask = 0;
9078 HRESULT hres;
9079 DWORD ret = file->custdata_seg.len;
9081 if(arg_type == VT_INT)
9082 arg_type = VT_I4;
9083 if(arg_type == VT_UINT)
9084 arg_type = VT_UI4;
9086 v = *value;
9087 if(V_VT(value) != arg_type) {
9088 hres = VariantChangeType(&v, value, 0, arg_type);
9089 if(FAILED(hres)){
9090 ERR("VariantChangeType failed: %08x\n", hres);
9091 return -1;
9095 /* Check if default value can be stored in-place */
9096 switch(arg_type){
9097 case VT_I4:
9098 case VT_UI4:
9099 mask = 0x3ffffff;
9100 if(V_UI4(&v) > 0x3ffffff)
9101 break;
9102 /* fall through */
9103 case VT_I1:
9104 case VT_UI1:
9105 case VT_BOOL:
9106 if(!mask)
9107 mask = 0xff;
9108 /* fall through */
9109 case VT_I2:
9110 case VT_UI2:
9111 if(!mask)
9112 mask = 0xffff;
9113 return ((0x80 + 0x4 * V_VT(value)) << 24) | (V_UI4(&v) & mask);
9116 /* have to allocate space in custdata_seg */
9117 switch(arg_type) {
9118 case VT_I4:
9119 case VT_R4:
9120 case VT_UI4:
9121 case VT_INT:
9122 case VT_UINT:
9123 case VT_HRESULT:
9124 case VT_PTR: {
9125 /* Construct the data to be allocated */
9126 int *data;
9128 if(file->custdata_seg.data){
9129 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + sizeof(int) * 2);
9130 data = (int *)(((char *)file->custdata_seg.data) + file->custdata_seg.len);
9131 file->custdata_seg.len += sizeof(int) * 2;
9132 }else{
9133 file->custdata_seg.len = sizeof(int) * 2;
9134 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9137 data[0] = V_VT(value) + (V_UI4(&v) << 16);
9138 data[1] = (V_UI4(&v) >> 16) + 0x57570000;
9140 /* TODO: Check if the encoded data is already present in custdata_seg */
9142 return ret;
9145 case VT_BSTR: {
9146 int i, len = (6+SysStringLen(V_BSTR(&v))+3) & ~0x3;
9147 char *data;
9149 if(file->custdata_seg.data){
9150 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + len);
9151 data = ((char *)file->custdata_seg.data) + file->custdata_seg.len;
9152 file->custdata_seg.len += len;
9153 }else{
9154 file->custdata_seg.len = len;
9155 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9158 *((unsigned short *)data) = V_VT(value);
9159 *((unsigned int *)(data+2)) = SysStringLen(V_BSTR(&v));
9160 for(i=0; i<SysStringLen(V_BSTR(&v)); i++) {
9161 if(V_BSTR(&v)[i] <= 0x7f)
9162 data[i+6] = V_BSTR(&v)[i];
9163 else
9164 data[i+6] = '?';
9166 WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], len-6, NULL, NULL);
9167 for(i=6+SysStringLen(V_BSTR(&v)); i<len; i++)
9168 data[i] = 0x57;
9170 /* TODO: Check if the encoded data is already present in custdata_seg */
9172 return ret;
9174 default:
9175 FIXME("Argument type not yet handled\n");
9176 return -1;
9180 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size);
9182 static DWORD WMSFT_append_arraydesc(ARRAYDESC *desc, WMSFT_TLBFile *file)
9184 DWORD offs = file->arraydesc_seg.len;
9185 DWORD *encoded;
9186 USHORT i;
9188 /* TODO: we should check for duplicates, but that's harder because each
9189 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9190 * at the library-level) */
9192 file->arraydesc_seg.len += (2 + desc->cDims * 2) * sizeof(DWORD);
9193 if(!file->arraydesc_seg.data)
9194 file->arraydesc_seg.data = heap_alloc(file->arraydesc_seg.len);
9195 else
9196 file->arraydesc_seg.data = heap_realloc(file->arraydesc_seg.data, file->arraydesc_seg.len);
9197 encoded = (DWORD*)((char *)file->arraydesc_seg.data) + offs;
9199 encoded[0] = WMSFT_append_typedesc(&desc->tdescElem, file, NULL, NULL);
9200 encoded[1] = desc->cDims | ((desc->cDims * 2 * sizeof(DWORD)) << 16);
9201 for(i = 0; i < desc->cDims; ++i){
9202 encoded[2 + i * 2] = desc->rgbounds[i].cElements;
9203 encoded[2 + i * 2 + 1] = desc->rgbounds[i].lLbound;
9206 return offs;
9209 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size)
9211 DWORD junk;
9212 INT16 junk2;
9213 DWORD offs = 0;
9214 DWORD encoded[2];
9215 VARTYPE vt, subtype;
9216 char *data;
9218 if(!desc)
9219 return -1;
9221 if(!out_mix)
9222 out_mix = &junk;
9223 if(!out_size)
9224 out_size = &junk2;
9226 vt = desc->vt & VT_TYPEMASK;
9228 if(vt == VT_PTR || vt == VT_SAFEARRAY){
9229 DWORD mix;
9230 encoded[1] = WMSFT_append_typedesc(desc->u.lptdesc, file, &mix, out_size);
9231 encoded[0] = desc->vt | ((mix | VT_BYREF) << 16);
9232 *out_mix = 0x7FFF;
9233 *out_size += 2 * sizeof(DWORD);
9234 }else if(vt == VT_CARRAY){
9235 encoded[0] = desc->vt | (0x7FFE << 16);
9236 encoded[1] = WMSFT_append_arraydesc(desc->u.lpadesc, file);
9237 *out_mix = 0x7FFE;
9238 }else if(vt == VT_USERDEFINED){
9239 encoded[0] = desc->vt | (0x7FFF << 16);
9240 encoded[1] = desc->u.hreftype;
9241 *out_mix = 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9242 }else{
9243 TRACE("Mixing in-place, VT: 0x%x\n", desc->vt);
9245 switch(vt){
9246 case VT_INT:
9247 subtype = VT_I4;
9248 break;
9249 case VT_UINT:
9250 subtype = VT_UI4;
9251 break;
9252 case VT_VOID:
9253 subtype = VT_EMPTY;
9254 break;
9255 default:
9256 subtype = vt;
9257 break;
9260 *out_mix = subtype;
9261 return 0x80000000 | (subtype << 16) | desc->vt;
9264 data = file->typdesc_seg.data;
9265 while(offs < file->typdesc_seg.len){
9266 if(!memcmp(&data[offs], encoded, sizeof(encoded)))
9267 return offs;
9268 offs += sizeof(encoded);
9271 file->typdesc_seg.len += sizeof(encoded);
9272 if(!file->typdesc_seg.data)
9273 data = file->typdesc_seg.data = heap_alloc(file->typdesc_seg.len);
9274 else
9275 data = file->typdesc_seg.data = heap_realloc(file->typdesc_seg.data, file->typdesc_seg.len);
9277 memcpy(&data[offs], encoded, sizeof(encoded));
9279 return offs;
9282 static DWORD WMSFT_compile_custdata(struct list *custdata_list, WMSFT_TLBFile *file)
9284 WMSFT_SegContents *cdguids_seg = &file->cdguids_seg;
9285 DWORD ret = cdguids_seg->len, offs;
9286 MSFT_CDGuid *cdguid = cdguids_seg->data;
9287 TLBCustData *cd;
9289 if(list_empty(custdata_list))
9290 return -1;
9292 cdguids_seg->len += sizeof(MSFT_CDGuid) * list_count(custdata_list);
9293 if(!cdguids_seg->data){
9294 cdguid = cdguids_seg->data = heap_alloc(cdguids_seg->len);
9295 }else
9296 cdguids_seg->data = heap_realloc(cdguids_seg->data, cdguids_seg->len);
9298 offs = ret + sizeof(MSFT_CDGuid);
9299 LIST_FOR_EACH_ENTRY(cd, custdata_list, TLBCustData, entry){
9300 cdguid->GuidOffset = cd->guid->offset;
9301 cdguid->DataOffset = WMSFT_encode_variant(&cd->data, file);
9302 cdguid->next = offs;
9303 offs += sizeof(MSFT_CDGuid);
9304 ++cdguid;
9307 --cdguid;
9308 cdguid->next = -1;
9310 return ret;
9313 static DWORD WMSFT_compile_typeinfo_aux(ITypeInfoImpl *info,
9314 WMSFT_TLBFile *file)
9316 WMSFT_SegContents *aux_seg = &file->aux_seg;
9317 DWORD ret = aux_seg->len, i, j, recorded_size = 0, extra_size = 0;
9318 MSFT_VarRecord *varrecord;
9319 MSFT_FuncRecord *funcrecord;
9320 MEMBERID *memid;
9321 DWORD *name, *offsets, offs;
9323 for(i = 0; i < info->cFuncs; ++i){
9324 TLBFuncDesc *desc = &info->funcdescs[i];
9326 recorded_size += 6 * sizeof(INT); /* mandatory fields */
9328 /* optional fields */
9329 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9330 if(!list_empty(&desc->custdata_list))
9331 recorded_size += 7 * sizeof(INT);
9332 else if(desc->HelpStringContext != 0)
9333 recorded_size += 6 * sizeof(INT);
9334 /* res9? resA? */
9335 else if(desc->Entry)
9336 recorded_size += 3 * sizeof(INT);
9337 else if(desc->HelpString)
9338 recorded_size += 2 * sizeof(INT);
9339 else if(desc->helpcontext)
9340 recorded_size += sizeof(INT);
9342 recorded_size += desc->funcdesc.cParams * sizeof(MSFT_ParameterInfo);
9344 for(j = 0; j < desc->funcdesc.cParams; ++j){
9345 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9346 recorded_size += desc->funcdesc.cParams * sizeof(INT);
9347 break;
9351 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9354 for(i = 0; i < info->cVars; ++i){
9355 TLBVarDesc *desc = &info->vardescs[i];
9357 recorded_size += 5 * sizeof(INT); /* mandatory fields */
9359 /* optional fields */
9360 if(desc->HelpStringContext != 0)
9361 recorded_size += 5 * sizeof(INT);
9362 else if(!list_empty(&desc->custdata_list))
9363 recorded_size += 4 * sizeof(INT);
9364 /* res9? */
9365 else if(desc->HelpString)
9366 recorded_size += 2 * sizeof(INT);
9367 else if(desc->HelpContext != 0)
9368 recorded_size += sizeof(INT);
9370 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9373 if(!recorded_size && !extra_size)
9374 return ret;
9376 extra_size += sizeof(INT); /* total aux size for this typeinfo */
9378 aux_seg->len += recorded_size + extra_size;
9380 aux_seg->len += sizeof(INT) * (info->cVars + info->cFuncs); /* offsets at the end */
9382 if(aux_seg->data)
9383 aux_seg->data = heap_realloc(aux_seg->data, aux_seg->len);
9384 else
9385 aux_seg->data = heap_alloc(aux_seg->len);
9387 *((DWORD*)((char *)aux_seg->data + ret)) = recorded_size;
9389 offsets = (DWORD*)((char *)aux_seg->data + ret + recorded_size + extra_size);
9390 offs = 0;
9392 funcrecord = (MSFT_FuncRecord*)(((char *)aux_seg->data) + ret + sizeof(INT));
9393 for(i = 0; i < info->cFuncs; ++i){
9394 TLBFuncDesc *desc = &info->funcdescs[i];
9395 DWORD size = 6 * sizeof(INT), paramdefault_size = 0, *paramdefault;
9397 funcrecord->funcdescsize = sizeof(desc->funcdesc) + desc->funcdesc.cParams * sizeof(ELEMDESC);
9398 funcrecord->DataType = WMSFT_append_typedesc(&desc->funcdesc.elemdescFunc.tdesc, file, NULL, &funcrecord->funcdescsize);
9399 funcrecord->Flags = desc->funcdesc.wFuncFlags;
9400 funcrecord->VtableOffset = desc->funcdesc.oVft;
9402 /* FKCCIC:
9403 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9404 * ^^^funckind
9405 * ^^^ ^invkind
9406 * ^has_cust_data
9407 * ^^^^callconv
9408 * ^has_param_defaults
9409 * ^oEntry_is_intresource
9411 funcrecord->FKCCIC =
9412 desc->funcdesc.funckind |
9413 (desc->funcdesc.invkind << 3) |
9414 (list_empty(&desc->custdata_list) ? 0 : 0x80) |
9415 (desc->funcdesc.callconv << 8);
9417 if(desc->Entry && desc->Entry != (TLBString*)-1 && IS_INTRESOURCE(desc->Entry))
9418 funcrecord->FKCCIC |= 0x2000;
9420 for(j = 0; j < desc->funcdesc.cParams; ++j){
9421 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9422 paramdefault_size = sizeof(INT) * desc->funcdesc.cParams;
9423 funcrecord->funcdescsize += sizeof(PARAMDESCEX);
9426 if(paramdefault_size > 0)
9427 funcrecord->FKCCIC |= 0x1000;
9429 funcrecord->nrargs = desc->funcdesc.cParams;
9430 funcrecord->nroargs = desc->funcdesc.cParamsOpt;
9432 /* optional fields */
9433 /* res9? resA? */
9434 if(!list_empty(&desc->custdata_list)){
9435 size += 7 * sizeof(INT);
9436 funcrecord->HelpContext = desc->helpcontext;
9437 if(desc->HelpString)
9438 funcrecord->oHelpString = desc->HelpString->offset;
9439 else
9440 funcrecord->oHelpString = -1;
9441 if(!desc->Entry)
9442 funcrecord->oEntry = -1;
9443 else if(IS_INTRESOURCE(desc->Entry))
9444 funcrecord->oEntry = LOWORD(desc->Entry);
9445 else
9446 funcrecord->oEntry = desc->Entry->offset;
9447 funcrecord->res9 = -1;
9448 funcrecord->resA = -1;
9449 funcrecord->HelpStringContext = desc->HelpStringContext;
9450 funcrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9451 }else if(desc->HelpStringContext != 0){
9452 size += 6 * sizeof(INT);
9453 funcrecord->HelpContext = desc->helpcontext;
9454 if(desc->HelpString)
9455 funcrecord->oHelpString = desc->HelpString->offset;
9456 else
9457 funcrecord->oHelpString = -1;
9458 if(!desc->Entry)
9459 funcrecord->oEntry = -1;
9460 else if(IS_INTRESOURCE(desc->Entry))
9461 funcrecord->oEntry = LOWORD(desc->Entry);
9462 else
9463 funcrecord->oEntry = desc->Entry->offset;
9464 funcrecord->res9 = -1;
9465 funcrecord->resA = -1;
9466 funcrecord->HelpStringContext = desc->HelpStringContext;
9467 }else if(desc->Entry){
9468 size += 3 * sizeof(INT);
9469 funcrecord->HelpContext = desc->helpcontext;
9470 if(desc->HelpString)
9471 funcrecord->oHelpString = desc->HelpString->offset;
9472 else
9473 funcrecord->oHelpString = -1;
9474 if(!desc->Entry)
9475 funcrecord->oEntry = -1;
9476 else if(IS_INTRESOURCE(desc->Entry))
9477 funcrecord->oEntry = LOWORD(desc->Entry);
9478 else
9479 funcrecord->oEntry = desc->Entry->offset;
9480 }else if(desc->HelpString){
9481 size += 2 * sizeof(INT);
9482 funcrecord->HelpContext = desc->helpcontext;
9483 funcrecord->oHelpString = desc->HelpString->offset;
9484 }else if(desc->helpcontext){
9485 size += sizeof(INT);
9486 funcrecord->HelpContext = desc->helpcontext;
9489 paramdefault = (DWORD*)((char *)funcrecord + size);
9490 size += paramdefault_size;
9492 for(j = 0; j < desc->funcdesc.cParams; ++j){
9493 MSFT_ParameterInfo *info = (MSFT_ParameterInfo*)(((char *)funcrecord) + size);
9495 info->DataType = WMSFT_append_typedesc(&desc->funcdesc.lprgelemdescParam[j].tdesc, file, NULL, &funcrecord->funcdescsize);
9496 if(desc->pParamDesc[j].Name)
9497 info->oName = desc->pParamDesc[j].Name->offset;
9498 else
9499 info->oName = -1;
9500 info->Flags = desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags;
9502 if(paramdefault_size){
9503 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
9504 *paramdefault = WMSFT_encode_variant(&desc->funcdesc.lprgelemdescParam[j].u.paramdesc.pparamdescex->varDefaultValue, file);
9505 else if(paramdefault_size)
9506 *paramdefault = -1;
9507 ++paramdefault;
9510 size += sizeof(MSFT_ParameterInfo);
9513 funcrecord->Info = size | (i << 16); /* is it just the index? */
9515 *offsets = offs;
9516 offs += size;
9517 ++offsets;
9519 funcrecord = (MSFT_FuncRecord*)(((char*)funcrecord) + size);
9522 varrecord = (MSFT_VarRecord*)funcrecord;
9523 for(i = 0; i < info->cVars; ++i){
9524 TLBVarDesc *desc = &info->vardescs[i];
9525 DWORD size = 5 * sizeof(INT);
9527 varrecord->vardescsize = sizeof(desc->vardesc);
9528 varrecord->DataType = WMSFT_append_typedesc(&desc->vardesc.elemdescVar.tdesc, file, NULL, &varrecord->vardescsize);
9529 varrecord->Flags = desc->vardesc.wVarFlags;
9530 varrecord->VarKind = desc->vardesc.varkind;
9532 if(desc->vardesc.varkind == VAR_CONST){
9533 varrecord->vardescsize += sizeof(VARIANT);
9534 varrecord->OffsValue = WMSFT_encode_variant(desc->vardesc.u.lpvarValue, file);
9535 }else
9536 varrecord->OffsValue = desc->vardesc.u.oInst;
9538 /* res9? */
9539 if(desc->HelpStringContext != 0){
9540 size += 5 * sizeof(INT);
9541 varrecord->HelpContext = desc->HelpContext;
9542 if(desc->HelpString)
9543 varrecord->HelpString = desc->HelpString->offset;
9544 else
9545 varrecord->HelpString = -1;
9546 varrecord->res9 = -1;
9547 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9548 varrecord->HelpStringContext = desc->HelpStringContext;
9549 }else if(!list_empty(&desc->custdata_list)){
9550 size += 4 * sizeof(INT);
9551 varrecord->HelpContext = desc->HelpContext;
9552 if(desc->HelpString)
9553 varrecord->HelpString = desc->HelpString->offset;
9554 else
9555 varrecord->HelpString = -1;
9556 varrecord->res9 = -1;
9557 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9558 }else if(desc->HelpString){
9559 size += 2 * sizeof(INT);
9560 varrecord->HelpContext = desc->HelpContext;
9561 if(desc->HelpString)
9562 varrecord->HelpString = desc->HelpString->offset;
9563 else
9564 varrecord->HelpString = -1;
9565 }else if(desc->HelpContext != 0){
9566 size += sizeof(INT);
9567 varrecord->HelpContext = desc->HelpContext;
9570 varrecord->Info = size | (i << 16);
9572 *offsets = offs;
9573 offs += size;
9574 ++offsets;
9576 varrecord = (MSFT_VarRecord*)(((char*)varrecord) + size);
9579 memid = (MEMBERID*)varrecord;
9580 for(i = 0; i < info->cFuncs; ++i){
9581 TLBFuncDesc *desc = &info->funcdescs[i];
9582 *memid = desc->funcdesc.memid;
9583 ++memid;
9585 for(i = 0; i < info->cVars; ++i){
9586 TLBVarDesc *desc = &info->vardescs[i];
9587 *memid = desc->vardesc.memid;
9588 ++memid;
9591 name = (UINT*)memid;
9592 for(i = 0; i < info->cFuncs; ++i){
9593 TLBFuncDesc *desc = &info->funcdescs[i];
9594 if(desc->Name)
9595 *name = desc->Name->offset;
9596 else
9597 *name = -1;
9598 ++name;
9600 for(i = 0; i < info->cVars; ++i){
9601 TLBVarDesc *desc = &info->vardescs[i];
9602 if(desc->Name)
9603 *name = desc->Name->offset;
9604 else
9605 *name = -1;
9606 ++name;
9609 return ret;
9612 typedef struct tagWMSFT_RefChunk {
9613 DWORD href;
9614 DWORD res04;
9615 DWORD res08;
9616 DWORD next;
9617 } WMSFT_RefChunk;
9619 static DWORD WMSFT_compile_typeinfo_ref(ITypeInfoImpl *info, WMSFT_TLBFile *file)
9621 DWORD offs = file->ref_seg.len, i;
9622 WMSFT_RefChunk *chunk;
9624 file->ref_seg.len += info->cImplTypes * sizeof(WMSFT_RefChunk);
9625 if(!file->ref_seg.data)
9626 file->ref_seg.data = heap_alloc(file->ref_seg.len);
9627 else
9628 file->ref_seg.data = heap_realloc(file->ref_seg.data, file->ref_seg.len);
9630 chunk = (WMSFT_RefChunk*)((char*)file->ref_seg.data + offs);
9632 for(i = 0; i < info->cImplTypes; ++i){
9633 chunk->href = info->impltypes[i].hRef;
9634 chunk->res04 = info->impltypes[i].implflags;
9635 chunk->res08 = -1;
9636 if(i < info->cImplTypes - 1)
9637 chunk->next = offs + sizeof(WMSFT_RefChunk) * (i + 1);
9638 else
9639 chunk->next = -1;
9640 ++chunk;
9643 return offs;
9646 static DWORD WMSFT_compile_typeinfo(ITypeInfoImpl *info, INT16 index, WMSFT_TLBFile *file, char *data)
9648 DWORD size;
9650 size = sizeof(MSFT_TypeInfoBase);
9652 if(data){
9653 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase*)data;
9654 if(info->wTypeFlags & TYPEFLAG_FDUAL)
9655 base->typekind = TKIND_DISPATCH;
9656 else
9657 base->typekind = info->typekind;
9658 base->typekind |= index << 16; /* TODO: There are some other flags here */
9659 base->typekind |= (info->cbAlignment << 11) | (info->cbAlignment << 6);
9660 base->memoffset = WMSFT_compile_typeinfo_aux(info, file);
9661 base->res2 = 0;
9662 base->res3 = 0;
9663 base->res4 = 3;
9664 base->res5 = 0;
9665 base->cElement = (info->cVars << 16) | info->cFuncs;
9666 base->res7 = 0;
9667 base->res8 = 0;
9668 base->res9 = 0;
9669 base->resA = 0;
9670 if(info->guid)
9671 base->posguid = info->guid->offset;
9672 else
9673 base->posguid = -1;
9674 base->flags = info->wTypeFlags;
9675 if(info->Name) {
9676 base->NameOffset = info->Name->offset;
9678 ((unsigned char*)file->name_seg.data)[info->Name->offset+9] = 0x38;
9679 *(HREFTYPE*)((unsigned char*)file->name_seg.data+info->Name->offset) = info->hreftype;
9680 }else {
9681 base->NameOffset = -1;
9683 base->version = (info->wMinorVerNum << 16) | info->wMajorVerNum;
9684 if(info->DocString)
9685 base->docstringoffs = info->DocString->offset;
9686 else
9687 base->docstringoffs = -1;
9688 base->helpstringcontext = info->dwHelpStringContext;
9689 base->helpcontext = info->dwHelpContext;
9690 base->oCustData = WMSFT_compile_custdata(info->pcustdata_list, file);
9691 base->cImplTypes = info->cImplTypes;
9692 base->cbSizeVft = info->cbSizeVft;
9693 base->size = info->cbSizeInstance;
9694 if(info->typekind == TKIND_COCLASS){
9695 base->datatype1 = WMSFT_compile_typeinfo_ref(info, file);
9696 }else if(info->typekind == TKIND_ALIAS){
9697 base->datatype1 = WMSFT_append_typedesc(info->tdescAlias, file, NULL, NULL);
9698 }else if(info->typekind == TKIND_MODULE){
9699 if(info->DllName)
9700 base->datatype1 = info->DllName->offset;
9701 else
9702 base->datatype1 = -1;
9703 }else{
9704 if(info->cImplTypes > 0)
9705 base->datatype1 = info->impltypes[0].hRef;
9706 else
9707 base->datatype1 = -1;
9709 base->datatype2 = index; /* FIXME: i think there's more here */
9710 base->res18 = 0;
9711 base->res19 = -1;
9714 return size;
9717 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl *This, WMSFT_TLBFile *file, DWORD *junk)
9719 UINT i;
9721 file->typeinfo_seg.len = 0;
9722 for(i = 0; i < This->TypeInfoCount; ++i){
9723 ITypeInfoImpl *info = This->typeinfos[i];
9724 *junk = file->typeinfo_seg.len;
9725 ++junk;
9726 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, NULL, NULL);
9729 file->typeinfo_seg.data = heap_alloc(file->typeinfo_seg.len);
9730 memset(file->typeinfo_seg.data, 0x96, file->typeinfo_seg.len);
9732 file->aux_seg.len = 0;
9733 file->aux_seg.data = NULL;
9735 file->typeinfo_seg.len = 0;
9736 for(i = 0; i < This->TypeInfoCount; ++i){
9737 ITypeInfoImpl *info = This->typeinfos[i];
9738 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, file,
9739 ((char *)file->typeinfo_seg.data) + file->typeinfo_seg.len);
9743 typedef struct tagWMSFT_ImpFile {
9744 INT guid_offs;
9745 LCID lcid;
9746 DWORD version;
9747 } WMSFT_ImpFile;
9749 static void WMSFT_compile_impfile(ITypeLibImpl *This, WMSFT_TLBFile *file)
9751 TLBImpLib *implib;
9752 WMSFT_ImpFile *impfile;
9753 char *data;
9754 DWORD last_offs = 0;
9756 file->impfile_seg.len = 0;
9757 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9758 int size = 0;
9760 if(implib->name){
9761 WCHAR *path = strrchrW(implib->name, '\\');
9762 if(path)
9763 ++path;
9764 else
9765 path = implib->name;
9766 size = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path), NULL, 0, NULL, NULL);
9767 if (size == 0)
9768 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9771 size += sizeof(INT16);
9772 if (size % 4)
9773 size = (size + 4) & ~0x3;
9774 if (size < 8)
9775 size = 8;
9777 file->impfile_seg.len += sizeof(WMSFT_ImpFile) + size;
9780 data = file->impfile_seg.data = heap_alloc(file->impfile_seg.len);
9782 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9783 int strlen = 0, size;
9785 impfile = (WMSFT_ImpFile*)data;
9786 impfile->guid_offs = implib->guid->offset;
9787 impfile->lcid = implib->lcid;
9788 impfile->version = (implib->wVersionMinor << 16) | implib->wVersionMajor;
9790 data += sizeof(WMSFT_ImpFile);
9792 if(implib->name){
9793 WCHAR *path= strrchrW(implib->name, '\\');
9794 if(path)
9795 ++path;
9796 else
9797 path = implib->name;
9798 strlen = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path),
9799 data + sizeof(INT16), file->impfile_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9800 if (strlen == 0)
9801 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9804 *((INT16*)data) = (strlen << 2) | 1; /* FIXME: is that a flag, or what? */
9806 size = strlen + sizeof(INT16);
9807 if (size % 4)
9808 size = (size + 4) & ~0x3;
9809 if (size < 8)
9810 size = 8;
9811 memset(data + sizeof(INT16) + strlen, 0x57, size - strlen - sizeof(INT16));
9813 data += size;
9814 implib->offset = last_offs;
9815 last_offs += size + sizeof(WMSFT_ImpFile);
9819 static void WMSFT_compile_impinfo(ITypeLibImpl *This, WMSFT_TLBFile *file)
9821 MSFT_ImpInfo *info;
9822 TLBRefType *ref_type;
9823 UINT i = 0;
9825 WMSFT_compile_impfile(This, file);
9827 file->impinfo_seg.len = sizeof(MSFT_ImpInfo) * list_count(&This->ref_list);
9828 info = file->impinfo_seg.data = heap_alloc(file->impinfo_seg.len);
9830 LIST_FOR_EACH_ENTRY(ref_type, &This->ref_list, TLBRefType, entry){
9831 info->flags = i | ((ref_type->tkind & 0xFF) << 24);
9832 if(ref_type->index == TLB_REF_USE_GUID){
9833 info->flags |= MSFT_IMPINFO_OFFSET_IS_GUID;
9834 info->oGuid = ref_type->guid->offset;
9835 }else
9836 info->oGuid = ref_type->index;
9837 info->oImpFile = ref_type->pImpTLInfo->offset;
9838 ++i;
9839 ++info;
9843 static void WMSFT_compile_guidhash(ITypeLibImpl *This, WMSFT_TLBFile *file)
9845 file->guidhash_seg.len = 0x80;
9846 file->guidhash_seg.data = heap_alloc(file->guidhash_seg.len);
9847 memset(file->guidhash_seg.data, 0xFF, file->guidhash_seg.len);
9850 static void WMSFT_compile_namehash(ITypeLibImpl *This, WMSFT_TLBFile *file)
9852 file->namehash_seg.len = 0x200;
9853 file->namehash_seg.data = heap_alloc(file->namehash_seg.len);
9854 memset(file->namehash_seg.data, 0xFF, file->namehash_seg.len);
9857 static void tmp_fill_segdir_seg(MSFT_pSeg *segdir, WMSFT_SegContents *contents, DWORD *running_offset)
9859 if(contents && contents->len){
9860 segdir->offset = *running_offset;
9861 segdir->length = contents->len;
9862 *running_offset += segdir->length;
9863 }else{
9864 segdir->offset = -1;
9865 segdir->length = 0;
9868 /* TODO: do these ever change? */
9869 segdir->res08 = -1;
9870 segdir->res0c = 0xf;
9873 static void WMSFT_write_segment(HANDLE outfile, WMSFT_SegContents *segment)
9875 DWORD written;
9876 if(segment)
9877 WriteFile(outfile, segment->data, segment->len, &written, NULL);
9880 static HRESULT WMSFT_fixup_typeinfos(ITypeLibImpl *This, WMSFT_TLBFile *file,
9881 DWORD file_len)
9883 DWORD i;
9884 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase *)file->typeinfo_seg.data;
9886 for(i = 0; i < This->TypeInfoCount; ++i){
9887 base->memoffset += file_len;
9888 ++base;
9891 return S_OK;
9894 static void WMSFT_free_file(WMSFT_TLBFile *file)
9896 HeapFree(GetProcessHeap(), 0, file->typeinfo_seg.data);
9897 HeapFree(GetProcessHeap(), 0, file->guidhash_seg.data);
9898 HeapFree(GetProcessHeap(), 0, file->guid_seg.data);
9899 HeapFree(GetProcessHeap(), 0, file->ref_seg.data);
9900 HeapFree(GetProcessHeap(), 0, file->impinfo_seg.data);
9901 HeapFree(GetProcessHeap(), 0, file->impfile_seg.data);
9902 HeapFree(GetProcessHeap(), 0, file->namehash_seg.data);
9903 HeapFree(GetProcessHeap(), 0, file->name_seg.data);
9904 HeapFree(GetProcessHeap(), 0, file->string_seg.data);
9905 HeapFree(GetProcessHeap(), 0, file->typdesc_seg.data);
9906 HeapFree(GetProcessHeap(), 0, file->arraydesc_seg.data);
9907 HeapFree(GetProcessHeap(), 0, file->custdata_seg.data);
9908 HeapFree(GetProcessHeap(), 0, file->cdguids_seg.data);
9909 HeapFree(GetProcessHeap(), 0, file->aux_seg.data);
9912 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
9914 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9915 WMSFT_TLBFile file;
9916 DWORD written, junk_size, junk_offs, running_offset;
9917 BOOL br;
9918 HANDLE outfile;
9919 HRESULT hres;
9920 DWORD *junk;
9921 UINT i;
9923 TRACE("%p\n", This);
9925 for(i = 0; i < This->TypeInfoCount; ++i)
9926 if(This->typeinfos[i]->needs_layout)
9927 ICreateTypeInfo2_LayOut(&This->typeinfos[i]->ICreateTypeInfo2_iface);
9929 memset(&file, 0, sizeof(file));
9931 file.header.magic1 = 0x5446534D;
9932 file.header.magic2 = 0x00010002;
9933 file.header.lcid = This->set_lcid ? This->set_lcid : MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
9934 file.header.lcid2 = This->set_lcid;
9935 file.header.varflags = 0x40 | This->syskind;
9936 if (This->HelpFile)
9937 file.header.varflags |= 0x10;
9938 if (This->HelpStringDll)
9939 file.header.varflags |= HELPDLLFLAG;
9940 file.header.version = (This->ver_minor << 16) | This->ver_major;
9941 file.header.flags = This->libflags;
9942 file.header.helpstringcontext = 0; /* TODO - SetHelpStringContext not implemented yet */
9943 file.header.helpcontext = This->dwHelpContext;
9944 file.header.res44 = 0x20;
9945 file.header.res48 = 0x80;
9946 file.header.dispatchpos = This->dispatch_href;
9948 WMSFT_compile_namehash(This, &file);
9949 /* do name and string compilation to get offsets for other compilations */
9950 hres = WMSFT_compile_names(This, &file);
9951 if (FAILED(hres)){
9952 WMSFT_free_file(&file);
9953 return hres;
9956 hres = WMSFT_compile_strings(This, &file);
9957 if (FAILED(hres)){
9958 WMSFT_free_file(&file);
9959 return hres;
9962 WMSFT_compile_guidhash(This, &file);
9963 hres = WMSFT_compile_guids(This, &file);
9964 if (FAILED(hres)){
9965 WMSFT_free_file(&file);
9966 return hres;
9969 if(This->HelpFile)
9970 file.header.helpfile = This->HelpFile->offset;
9971 else
9972 file.header.helpfile = -1;
9974 if(This->DocString)
9975 file.header.helpstring = This->DocString->offset;
9976 else
9977 file.header.helpstring = -1;
9979 /* do some more segment compilation */
9980 file.header.nimpinfos = list_count(&This->ref_list);
9981 file.header.nrtypeinfos = This->TypeInfoCount;
9983 if(This->Name)
9984 file.header.NameOffset = This->Name->offset;
9985 else
9986 file.header.NameOffset = -1;
9988 file.header.CustomDataOffset = -1; /* TODO SetCustData not impl yet */
9990 if(This->guid)
9991 file.header.posguid = This->guid->offset;
9992 else
9993 file.header.posguid = -1;
9995 junk_size = file.header.nrtypeinfos * sizeof(DWORD);
9996 if(file.header.varflags & HELPDLLFLAG)
9997 junk_size += sizeof(DWORD);
9998 if(junk_size){
9999 junk = heap_alloc_zero(junk_size);
10000 if(file.header.varflags & HELPDLLFLAG){
10001 *junk = This->HelpStringDll->offset;
10002 junk_offs = 1;
10003 }else
10004 junk_offs = 0;
10005 }else{
10006 junk = NULL;
10007 junk_offs = 0;
10010 WMSFT_compile_typeinfo_seg(This, &file, junk + junk_offs);
10011 WMSFT_compile_impinfo(This, &file);
10013 running_offset = 0;
10015 TRACE("header at: 0x%x\n", running_offset);
10016 running_offset += sizeof(file.header);
10018 TRACE("junk at: 0x%x\n", running_offset);
10019 running_offset += junk_size;
10021 TRACE("segdir at: 0x%x\n", running_offset);
10022 running_offset += sizeof(file.segdir);
10024 TRACE("typeinfo at: 0x%x\n", running_offset);
10025 tmp_fill_segdir_seg(&file.segdir.pTypeInfoTab, &file.typeinfo_seg, &running_offset);
10027 TRACE("guidhashtab at: 0x%x\n", running_offset);
10028 tmp_fill_segdir_seg(&file.segdir.pGuidHashTab, &file.guidhash_seg, &running_offset);
10030 TRACE("guidtab at: 0x%x\n", running_offset);
10031 tmp_fill_segdir_seg(&file.segdir.pGuidTab, &file.guid_seg, &running_offset);
10033 TRACE("reftab at: 0x%x\n", running_offset);
10034 tmp_fill_segdir_seg(&file.segdir.pRefTab, &file.ref_seg, &running_offset);
10036 TRACE("impinfo at: 0x%x\n", running_offset);
10037 tmp_fill_segdir_seg(&file.segdir.pImpInfo, &file.impinfo_seg, &running_offset);
10039 TRACE("impfiles at: 0x%x\n", running_offset);
10040 tmp_fill_segdir_seg(&file.segdir.pImpFiles, &file.impfile_seg, &running_offset);
10042 TRACE("namehashtab at: 0x%x\n", running_offset);
10043 tmp_fill_segdir_seg(&file.segdir.pNameHashTab, &file.namehash_seg, &running_offset);
10045 TRACE("nametab at: 0x%x\n", running_offset);
10046 tmp_fill_segdir_seg(&file.segdir.pNametab, &file.name_seg, &running_offset);
10048 TRACE("stringtab at: 0x%x\n", running_offset);
10049 tmp_fill_segdir_seg(&file.segdir.pStringtab, &file.string_seg, &running_offset);
10051 TRACE("typdesc at: 0x%x\n", running_offset);
10052 tmp_fill_segdir_seg(&file.segdir.pTypdescTab, &file.typdesc_seg, &running_offset);
10054 TRACE("arraydescriptions at: 0x%x\n", running_offset);
10055 tmp_fill_segdir_seg(&file.segdir.pArrayDescriptions, &file.arraydesc_seg, &running_offset);
10057 TRACE("custdata at: 0x%x\n", running_offset);
10058 tmp_fill_segdir_seg(&file.segdir.pCustData, &file.custdata_seg, &running_offset);
10060 TRACE("cdguids at: 0x%x\n", running_offset);
10061 tmp_fill_segdir_seg(&file.segdir.pCDGuids, &file.cdguids_seg, &running_offset);
10063 TRACE("res0e at: 0x%x\n", running_offset);
10064 tmp_fill_segdir_seg(&file.segdir.res0e, NULL, &running_offset);
10066 TRACE("res0f at: 0x%x\n", running_offset);
10067 tmp_fill_segdir_seg(&file.segdir.res0f, NULL, &running_offset);
10069 TRACE("aux_seg at: 0x%x\n", running_offset);
10071 WMSFT_fixup_typeinfos(This, &file, running_offset);
10073 outfile = CreateFileW(This->path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
10074 FILE_ATTRIBUTE_NORMAL, 0);
10075 if (outfile == INVALID_HANDLE_VALUE){
10076 WMSFT_free_file(&file);
10077 heap_free(junk);
10078 return TYPE_E_IOERROR;
10081 br = WriteFile(outfile, &file.header, sizeof(file.header), &written, NULL);
10082 if (!br) {
10083 WMSFT_free_file(&file);
10084 CloseHandle(outfile);
10085 heap_free(junk);
10086 return TYPE_E_IOERROR;
10089 br = WriteFile(outfile, junk, junk_size, &written, NULL);
10090 heap_free(junk);
10091 if (!br) {
10092 WMSFT_free_file(&file);
10093 CloseHandle(outfile);
10094 return TYPE_E_IOERROR;
10097 br = WriteFile(outfile, &file.segdir, sizeof(file.segdir), &written, NULL);
10098 if (!br) {
10099 WMSFT_free_file(&file);
10100 CloseHandle(outfile);
10101 return TYPE_E_IOERROR;
10104 WMSFT_write_segment(outfile, &file.typeinfo_seg);
10105 WMSFT_write_segment(outfile, &file.guidhash_seg);
10106 WMSFT_write_segment(outfile, &file.guid_seg);
10107 WMSFT_write_segment(outfile, &file.ref_seg);
10108 WMSFT_write_segment(outfile, &file.impinfo_seg);
10109 WMSFT_write_segment(outfile, &file.impfile_seg);
10110 WMSFT_write_segment(outfile, &file.namehash_seg);
10111 WMSFT_write_segment(outfile, &file.name_seg);
10112 WMSFT_write_segment(outfile, &file.string_seg);
10113 WMSFT_write_segment(outfile, &file.typdesc_seg);
10114 WMSFT_write_segment(outfile, &file.arraydesc_seg);
10115 WMSFT_write_segment(outfile, &file.custdata_seg);
10116 WMSFT_write_segment(outfile, &file.cdguids_seg);
10117 WMSFT_write_segment(outfile, &file.aux_seg);
10119 WMSFT_free_file(&file);
10121 CloseHandle(outfile);
10123 return S_OK;
10126 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
10127 LPOLESTR name)
10129 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10130 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
10131 return E_NOTIMPL;
10134 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
10135 REFGUID guid, VARIANT *varVal)
10137 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10138 FIXME("%p %s %p - stub\n", This, debugstr_guid(guid), varVal);
10139 return E_NOTIMPL;
10142 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
10143 ULONG helpStringContext)
10145 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10146 FIXME("%p %u - stub\n", This, helpStringContext);
10147 return E_NOTIMPL;
10150 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
10151 LPOLESTR filename)
10153 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10154 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
10156 if (!filename)
10157 return E_INVALIDARG;
10159 This->HelpStringDll = TLB_append_str(&This->string_list, filename);
10161 return S_OK;
10164 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
10165 ICreateTypeLib2_fnQueryInterface,
10166 ICreateTypeLib2_fnAddRef,
10167 ICreateTypeLib2_fnRelease,
10168 ICreateTypeLib2_fnCreateTypeInfo,
10169 ICreateTypeLib2_fnSetName,
10170 ICreateTypeLib2_fnSetVersion,
10171 ICreateTypeLib2_fnSetGuid,
10172 ICreateTypeLib2_fnSetDocString,
10173 ICreateTypeLib2_fnSetHelpFileName,
10174 ICreateTypeLib2_fnSetHelpContext,
10175 ICreateTypeLib2_fnSetLcid,
10176 ICreateTypeLib2_fnSetLibFlags,
10177 ICreateTypeLib2_fnSaveAllChanges,
10178 ICreateTypeLib2_fnDeleteTypeInfo,
10179 ICreateTypeLib2_fnSetCustData,
10180 ICreateTypeLib2_fnSetHelpStringContext,
10181 ICreateTypeLib2_fnSetHelpStringDll
10184 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
10185 REFIID riid, void **object)
10187 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10189 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, object);
10192 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
10194 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10196 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
10199 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
10201 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10203 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
10206 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
10207 REFGUID guid)
10209 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10211 TRACE("%p %s\n", This, debugstr_guid(guid));
10213 This->guid = TLB_append_guid(&This->pTypeLib->guid_list, guid, This->hreftype);
10215 return S_OK;
10218 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
10219 UINT typeFlags)
10221 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10222 WORD old_flags;
10223 HRESULT hres;
10225 TRACE("%p %x\n", This, typeFlags);
10227 if (typeFlags & TYPEFLAG_FDUAL) {
10228 static const WCHAR stdole2tlb[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10229 ITypeLib *stdole;
10230 ITypeInfo *dispatch;
10231 HREFTYPE hreftype;
10232 HRESULT hres;
10234 hres = LoadTypeLib(stdole2tlb, &stdole);
10235 if(FAILED(hres))
10236 return hres;
10238 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
10239 ITypeLib_Release(stdole);
10240 if(FAILED(hres))
10241 return hres;
10243 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
10244 ITypeInfo_Release(dispatch);
10245 if(FAILED(hres))
10246 return hres;
10249 old_flags = This->wTypeFlags;
10250 This->wTypeFlags = typeFlags;
10252 hres = ICreateTypeInfo2_LayOut(iface);
10253 if (FAILED(hres)) {
10254 This->wTypeFlags = old_flags;
10255 return hres;
10258 return S_OK;
10261 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
10262 LPOLESTR doc)
10264 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10266 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
10268 if (!doc)
10269 return E_INVALIDARG;
10271 This->DocString = TLB_append_str(&This->pTypeLib->string_list, doc);
10273 return S_OK;
10276 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
10277 DWORD helpContext)
10279 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10281 TRACE("%p %d\n", This, helpContext);
10283 This->dwHelpContext = helpContext;
10285 return S_OK;
10288 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
10289 WORD majorVerNum, WORD minorVerNum)
10291 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10293 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
10295 This->wMajorVerNum = majorVerNum;
10296 This->wMinorVerNum = minorVerNum;
10298 return S_OK;
10301 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
10302 ITypeInfo *typeInfo, HREFTYPE *refType)
10304 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10305 UINT index;
10306 ITypeLib *container;
10307 TLBRefType *ref_type;
10308 TLBImpLib *implib;
10309 TYPEATTR *typeattr;
10310 TLIBATTR *libattr;
10311 HRESULT hres;
10313 TRACE("%p %p %p\n", This, typeInfo, refType);
10315 if (!typeInfo || !refType)
10316 return E_INVALIDARG;
10318 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
10319 if (FAILED(hres))
10320 return hres;
10322 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
10323 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
10325 ITypeLib_Release(container);
10327 *refType = target->hreftype;
10329 return S_OK;
10332 hres = ITypeLib_GetLibAttr(container, &libattr);
10333 if (FAILED(hres)) {
10334 ITypeLib_Release(container);
10335 return hres;
10338 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
10339 if(IsEqualGUID(&implib->guid->guid, &libattr->guid) &&
10340 implib->lcid == libattr->lcid &&
10341 implib->wVersionMajor == libattr->wMajorVerNum &&
10342 implib->wVersionMinor == libattr->wMinorVerNum)
10343 break;
10346 if(&implib->entry == &This->pTypeLib->implib_list){
10347 implib = heap_alloc_zero(sizeof(TLBImpLib));
10349 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
10350 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
10351 implib->name = SysAllocString(our_container->path);
10352 }else{
10353 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
10354 libattr->wMinorVerNum, libattr->lcid, &implib->name);
10355 if(FAILED(hres)){
10356 implib->name = NULL;
10357 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres);
10361 implib->guid = TLB_append_guid(&This->pTypeLib->guid_list, &libattr->guid, 2);
10362 implib->lcid = libattr->lcid;
10363 implib->wVersionMajor = libattr->wMajorVerNum;
10364 implib->wVersionMinor = libattr->wMinorVerNum;
10366 list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
10369 ITypeLib_ReleaseTLibAttr(container, libattr);
10370 ITypeLib_Release(container);
10372 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
10373 if (FAILED(hres))
10374 return hres;
10376 index = 0;
10377 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
10378 if(ref_type->index == TLB_REF_USE_GUID &&
10379 IsEqualGUID(&ref_type->guid->guid, &typeattr->guid) &&
10380 ref_type->tkind == typeattr->typekind)
10381 break;
10382 ++index;
10385 if(&ref_type->entry == &This->pTypeLib->ref_list){
10386 ref_type = heap_alloc_zero(sizeof(TLBRefType));
10388 ref_type->tkind = typeattr->typekind;
10389 ref_type->pImpTLInfo = implib;
10390 ref_type->reference = index * sizeof(MSFT_ImpInfo);
10392 ref_type->index = TLB_REF_USE_GUID;
10394 ref_type->guid = TLB_append_guid(&This->pTypeLib->guid_list, &typeattr->guid, ref_type->reference+1);
10396 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
10399 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
10401 *refType = ref_type->reference | 0x1;
10403 if(IsEqualGUID(&ref_type->guid->guid, &IID_IDispatch))
10404 This->pTypeLib->dispatch_href = *refType;
10406 return S_OK;
10409 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
10410 UINT index, FUNCDESC *funcDesc)
10412 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10413 TLBFuncDesc tmp_func_desc, *func_desc;
10414 int buf_size, i;
10415 char *buffer;
10416 HRESULT hres;
10418 TRACE("%p %u %p\n", This, index, funcDesc);
10420 if (!funcDesc || funcDesc->oVft & 3)
10421 return E_INVALIDARG;
10423 switch (This->typekind) {
10424 case TKIND_MODULE:
10425 if (funcDesc->funckind != FUNC_STATIC)
10426 return TYPE_E_BADMODULEKIND;
10427 break;
10428 case TKIND_DISPATCH:
10429 if (funcDesc->funckind != FUNC_DISPATCH)
10430 return TYPE_E_BADMODULEKIND;
10431 break;
10432 default:
10433 if (funcDesc->funckind != FUNC_PUREVIRTUAL)
10434 return TYPE_E_BADMODULEKIND;
10437 if (index > This->cFuncs)
10438 return TYPE_E_ELEMENTNOTFOUND;
10440 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) &&
10441 !funcDesc->cParams)
10442 return TYPE_E_INCONSISTENTPROPFUNCS;
10444 #ifdef _WIN64
10445 if(This->pTypeLib->syskind == SYS_WIN64 &&
10446 funcDesc->oVft % 8 != 0)
10447 return E_INVALIDARG;
10448 #endif
10450 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc));
10451 TLBFuncDesc_Constructor(&tmp_func_desc);
10453 tmp_func_desc.funcdesc = *funcDesc;
10455 if (tmp_func_desc.funcdesc.oVft != 0)
10456 tmp_func_desc.funcdesc.oVft |= 1;
10458 if (funcDesc->cScodes) {
10459 tmp_func_desc.funcdesc.lprgscode = heap_alloc(sizeof(SCODE) * funcDesc->cScodes);
10460 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes);
10461 } else
10462 tmp_func_desc.funcdesc.lprgscode = NULL;
10464 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc);
10465 for (i = 0; i < funcDesc->cParams; ++i) {
10466 buf_size += sizeof(ELEMDESC);
10467 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i);
10469 tmp_func_desc.funcdesc.lprgelemdescParam = heap_alloc(buf_size);
10470 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams);
10472 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer);
10473 if (FAILED(hres)) {
10474 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10475 heap_free(tmp_func_desc.funcdesc.lprgscode);
10476 return hres;
10479 for (i = 0; i < funcDesc->cParams; ++i) {
10480 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i,
10481 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer);
10482 if (FAILED(hres)) {
10483 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10484 heap_free(tmp_func_desc.funcdesc.lprgscode);
10485 return hres;
10487 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT &&
10488 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT &&
10489 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){
10490 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
10491 if (FAILED(hres)) {
10492 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10493 heap_free(tmp_func_desc.funcdesc.lprgscode);
10494 return hres;
10499 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams);
10501 if (This->funcdescs) {
10502 This->funcdescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->funcdescs,
10503 sizeof(TLBFuncDesc) * (This->cFuncs + 1));
10505 if (index < This->cFuncs) {
10506 memmove(This->funcdescs + index + 1, This->funcdescs + index,
10507 (This->cFuncs - index) * sizeof(TLBFuncDesc));
10508 func_desc = This->funcdescs + index;
10509 } else
10510 func_desc = This->funcdescs + This->cFuncs;
10512 /* move custdata lists to the new memory location */
10513 for(i = 0; i < This->cFuncs + 1; ++i){
10514 if(index != i){
10515 TLBFuncDesc *fd = &This->funcdescs[i];
10516 if(fd->custdata_list.prev == fd->custdata_list.next)
10517 list_init(&fd->custdata_list);
10518 else{
10519 fd->custdata_list.prev->next = &fd->custdata_list;
10520 fd->custdata_list.next->prev = &fd->custdata_list;
10524 } else
10525 func_desc = This->funcdescs = heap_alloc(sizeof(TLBFuncDesc));
10527 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc));
10528 list_init(&func_desc->custdata_list);
10530 ++This->cFuncs;
10532 This->needs_layout = TRUE;
10534 return S_OK;
10537 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
10538 UINT index, HREFTYPE refType)
10540 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10541 TLBImplType *impl_type;
10542 HRESULT hres;
10544 TRACE("%p %u %d\n", This, index, refType);
10546 switch(This->typekind){
10547 case TKIND_COCLASS: {
10548 if (index == -1) {
10549 FIXME("Unhandled index: -1\n");
10550 return E_NOTIMPL;
10553 if(index != This->cImplTypes)
10554 return TYPE_E_ELEMENTNOTFOUND;
10556 break;
10558 case TKIND_INTERFACE:
10559 case TKIND_DISPATCH:
10560 if (index != 0 || This->cImplTypes)
10561 return TYPE_E_ELEMENTNOTFOUND;
10562 break;
10563 default:
10564 FIXME("Unimplemented typekind: %d\n", This->typekind);
10565 return E_NOTIMPL;
10568 if (This->impltypes){
10569 UINT i;
10571 This->impltypes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->impltypes,
10572 sizeof(TLBImplType) * (This->cImplTypes + 1));
10574 if (index < This->cImplTypes) {
10575 memmove(This->impltypes + index + 1, This->impltypes + index,
10576 (This->cImplTypes - index) * sizeof(TLBImplType));
10577 impl_type = This->impltypes + index;
10578 } else
10579 impl_type = This->impltypes + This->cImplTypes;
10581 /* move custdata lists to the new memory location */
10582 for(i = 0; i < This->cImplTypes + 1; ++i){
10583 if(index != i){
10584 TLBImplType *it = &This->impltypes[i];
10585 if(it->custdata_list.prev == it->custdata_list.next)
10586 list_init(&it->custdata_list);
10587 else{
10588 it->custdata_list.prev->next = &it->custdata_list;
10589 it->custdata_list.next->prev = &it->custdata_list;
10593 } else
10594 impl_type = This->impltypes = heap_alloc(sizeof(TLBImplType));
10596 memset(impl_type, 0, sizeof(TLBImplType));
10597 TLBImplType_Constructor(impl_type);
10598 impl_type->hRef = refType;
10600 ++This->cImplTypes;
10602 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
10603 This->wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
10605 hres = ICreateTypeInfo2_LayOut(iface);
10606 if (FAILED(hres))
10607 return hres;
10609 return S_OK;
10612 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
10613 UINT index, INT implTypeFlags)
10615 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10616 TLBImplType *impl_type = &This->impltypes[index];
10618 TRACE("%p %u %x\n", This, index, implTypeFlags);
10620 if (This->typekind != TKIND_COCLASS)
10621 return TYPE_E_BADMODULEKIND;
10623 if (index >= This->cImplTypes)
10624 return TYPE_E_ELEMENTNOTFOUND;
10626 impl_type->implflags = implTypeFlags;
10628 return S_OK;
10631 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
10632 WORD alignment)
10634 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10636 TRACE("%p %d\n", This, alignment);
10638 This->cbAlignment = alignment;
10640 return S_OK;
10643 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
10644 LPOLESTR schema)
10646 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10648 TRACE("%p %s\n", This, wine_dbgstr_w(schema));
10650 if (!schema)
10651 return E_INVALIDARG;
10653 This->Schema = TLB_append_str(&This->pTypeLib->string_list, schema);
10655 This->lpstrSchema = This->Schema->str;
10657 return S_OK;
10660 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
10661 UINT index, VARDESC *varDesc)
10663 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10664 TLBVarDesc *var_desc;
10666 TRACE("%p %u %p\n", This, index, varDesc);
10668 if (This->vardescs){
10669 UINT i;
10671 This->vardescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->vardescs,
10672 sizeof(TLBVarDesc) * (This->cVars + 1));
10674 if (index < This->cVars) {
10675 memmove(This->vardescs + index + 1, This->vardescs + index,
10676 (This->cVars - index) * sizeof(TLBVarDesc));
10677 var_desc = This->vardescs + index;
10678 } else
10679 var_desc = This->vardescs + This->cVars;
10681 /* move custdata lists to the new memory location */
10682 for(i = 0; i < This->cVars + 1; ++i){
10683 if(index != i){
10684 TLBVarDesc *var = &This->vardescs[i];
10685 if(var->custdata_list.prev == var->custdata_list.next)
10686 list_init(&var->custdata_list);
10687 else{
10688 var->custdata_list.prev->next = &var->custdata_list;
10689 var->custdata_list.next->prev = &var->custdata_list;
10693 } else
10694 var_desc = This->vardescs = heap_alloc_zero(sizeof(TLBVarDesc));
10696 TLBVarDesc_Constructor(var_desc);
10697 TLB_AllocAndInitVarDesc(varDesc, &var_desc->vardesc_create);
10698 var_desc->vardesc = *var_desc->vardesc_create;
10700 ++This->cVars;
10702 This->needs_layout = TRUE;
10704 return S_OK;
10707 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
10708 UINT index, LPOLESTR *names, UINT numNames)
10710 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10711 TLBFuncDesc *func_desc = &This->funcdescs[index];
10712 int i;
10714 TRACE("%p %u %p %u\n", This, index, names, numNames);
10716 if (!names)
10717 return E_INVALIDARG;
10719 if (index >= This->cFuncs || numNames == 0)
10720 return TYPE_E_ELEMENTNOTFOUND;
10722 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){
10723 if(numNames > func_desc->funcdesc.cParams)
10724 return TYPE_E_ELEMENTNOTFOUND;
10725 } else
10726 if(numNames > func_desc->funcdesc.cParams + 1)
10727 return TYPE_E_ELEMENTNOTFOUND;
10729 for(i = 0; i < This->cFuncs; ++i) {
10730 TLBFuncDesc *iter = &This->funcdescs[i];
10731 if (iter->Name && !strcmpW(TLB_get_bstr(iter->Name), *names)) {
10732 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10733 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10734 func_desc->funcdesc.invkind != iter->funcdesc.invkind)
10735 continue;
10736 return TYPE_E_AMBIGUOUSNAME;
10740 func_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *names);
10742 for (i = 1; i < numNames; ++i) {
10743 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1;
10744 par_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *(names + i));
10747 return S_OK;
10750 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
10751 UINT index, LPOLESTR name)
10753 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10755 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(name));
10757 if(!name)
10758 return E_INVALIDARG;
10760 if(index >= This->cVars)
10761 return TYPE_E_ELEMENTNOTFOUND;
10763 This->vardescs[index].Name = TLB_append_str(&This->pTypeLib->name_list, name);
10764 return S_OK;
10767 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
10768 TYPEDESC *tdescAlias)
10770 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10771 HRESULT hr;
10773 TRACE("%p %p\n", This, tdescAlias);
10775 if(!tdescAlias)
10776 return E_INVALIDARG;
10778 if(This->typekind != TKIND_ALIAS)
10779 return TYPE_E_BADMODULEKIND;
10781 hr = TLB_size_instance(This, This->pTypeLib->syskind, tdescAlias, &This->cbSizeInstance, &This->cbAlignment);
10782 if(FAILED(hr))
10783 return hr;
10785 heap_free(This->tdescAlias);
10786 This->tdescAlias = heap_alloc(TLB_SizeTypeDesc(tdescAlias, TRUE));
10787 TLB_CopyTypeDesc(NULL, tdescAlias, This->tdescAlias);
10789 return S_OK;
10792 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
10793 UINT index, LPOLESTR dllName, LPOLESTR procName)
10795 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10796 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
10797 return E_NOTIMPL;
10800 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
10801 UINT index, LPOLESTR docString)
10803 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10804 TLBFuncDesc *func_desc = &This->funcdescs[index];
10806 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10808 if(!docString)
10809 return E_INVALIDARG;
10811 if(index >= This->cFuncs)
10812 return TYPE_E_ELEMENTNOTFOUND;
10814 func_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10816 return S_OK;
10819 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
10820 UINT index, LPOLESTR docString)
10822 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10823 TLBVarDesc *var_desc = &This->vardescs[index];
10825 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10827 if(!docString)
10828 return E_INVALIDARG;
10830 if(index >= This->cVars)
10831 return TYPE_E_ELEMENTNOTFOUND;
10833 var_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10835 return S_OK;
10838 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
10839 UINT index, DWORD helpContext)
10841 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10842 TLBFuncDesc *func_desc = &This->funcdescs[index];
10844 TRACE("%p %u %d\n", This, index, helpContext);
10846 if(index >= This->cFuncs)
10847 return TYPE_E_ELEMENTNOTFOUND;
10849 func_desc->helpcontext = helpContext;
10851 return S_OK;
10854 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
10855 UINT index, DWORD helpContext)
10857 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10858 TLBVarDesc *var_desc = &This->vardescs[index];
10860 TRACE("%p %u %d\n", This, index, helpContext);
10862 if(index >= This->cVars)
10863 return TYPE_E_ELEMENTNOTFOUND;
10865 var_desc->HelpContext = helpContext;
10867 return S_OK;
10870 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
10871 UINT index, BSTR bstrMops)
10873 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10874 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
10875 return E_NOTIMPL;
10878 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
10879 IDLDESC *idlDesc)
10881 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10883 TRACE("%p %p\n", This, idlDesc);
10885 if (!idlDesc)
10886 return E_INVALIDARG;
10888 This->idldescType.dwReserved = idlDesc->dwReserved;
10889 This->idldescType.wIDLFlags = idlDesc->wIDLFlags;
10891 return S_OK;
10894 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
10896 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10897 ITypeInfo *tinfo;
10898 TLBFuncDesc *func_desc;
10899 UINT user_vft = 0, i, depth = 0;
10900 HRESULT hres = S_OK;
10902 TRACE("%p\n", This);
10904 This->needs_layout = FALSE;
10906 hres = ICreateTypeInfo2_QueryInterface(iface, &IID_ITypeInfo, (LPVOID*)&tinfo);
10907 if (FAILED(hres))
10908 return hres;
10910 if (This->typekind == TKIND_INTERFACE) {
10911 ITypeInfo *inh;
10912 TYPEATTR *attr;
10913 HREFTYPE inh_href;
10915 hres = ITypeInfo_GetRefTypeOfImplType(tinfo, 0, &inh_href);
10917 if (SUCCEEDED(hres)) {
10918 hres = ITypeInfo_GetRefTypeInfo(tinfo, inh_href, &inh);
10920 if (SUCCEEDED(hres)) {
10921 hres = ITypeInfo_GetTypeAttr(inh, &attr);
10922 if (FAILED(hres)) {
10923 ITypeInfo_Release(inh);
10924 ITypeInfo_Release(tinfo);
10925 return hres;
10927 This->cbSizeVft = attr->cbSizeVft;
10928 ITypeInfo_ReleaseTypeAttr(inh, attr);
10931 ++depth;
10932 hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href);
10933 if(SUCCEEDED(hres)){
10934 ITypeInfo *next;
10935 hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next);
10936 if(SUCCEEDED(hres)){
10937 ITypeInfo_Release(inh);
10938 inh = next;
10941 }while(SUCCEEDED(hres));
10942 hres = S_OK;
10944 ITypeInfo_Release(inh);
10945 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10946 This->cbSizeVft = 0;
10947 hres = S_OK;
10948 } else {
10949 ITypeInfo_Release(tinfo);
10950 return hres;
10952 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10953 This->cbSizeVft = 0;
10954 hres = S_OK;
10955 } else {
10956 ITypeInfo_Release(tinfo);
10957 return hres;
10959 } else if (This->typekind == TKIND_DISPATCH)
10960 This->cbSizeVft = 7 * This->pTypeLib->ptr_size;
10961 else
10962 This->cbSizeVft = 0;
10964 func_desc = This->funcdescs;
10965 i = 0;
10966 while (i < This->cFuncs) {
10967 if (!(func_desc->funcdesc.oVft & 0x1))
10968 func_desc->funcdesc.oVft = This->cbSizeVft;
10970 if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft)
10971 user_vft = func_desc->funcdesc.oVft & 0xFFFC;
10973 This->cbSizeVft += This->pTypeLib->ptr_size;
10975 if (func_desc->funcdesc.memid == MEMBERID_NIL) {
10976 TLBFuncDesc *iter;
10977 UINT j = 0;
10978 BOOL reset = FALSE;
10980 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i;
10982 iter = This->funcdescs;
10983 while (j < This->cFuncs) {
10984 if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) {
10985 if (!reset) {
10986 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->cFuncs;
10987 reset = TRUE;
10988 } else
10989 ++func_desc->funcdesc.memid;
10990 iter = This->funcdescs;
10991 j = 0;
10992 } else {
10993 ++iter;
10994 ++j;
10999 ++func_desc;
11000 ++i;
11003 if (user_vft > This->cbSizeVft)
11004 This->cbSizeVft = user_vft + This->pTypeLib->ptr_size;
11006 for(i = 0; i < This->cVars; ++i){
11007 TLBVarDesc *var_desc = &This->vardescs[i];
11008 if(var_desc->vardesc.memid == MEMBERID_NIL){
11009 UINT j = 0;
11010 BOOL reset = FALSE;
11011 TLBVarDesc *iter;
11013 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + i;
11015 iter = This->vardescs;
11016 while (j < This->cVars) {
11017 if (iter != var_desc && iter->vardesc.memid == var_desc->vardesc.memid) {
11018 if (!reset) {
11019 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + This->cVars;
11020 reset = TRUE;
11021 } else
11022 ++var_desc->vardesc.memid;
11023 iter = This->vardescs;
11024 j = 0;
11025 } else {
11026 ++iter;
11027 ++j;
11033 ITypeInfo_Release(tinfo);
11034 return hres;
11037 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
11038 UINT index)
11040 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11041 FIXME("%p %u - stub\n", This, index);
11042 return E_NOTIMPL;
11045 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
11046 MEMBERID memid, INVOKEKIND invKind)
11048 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11049 FIXME("%p %x %d - stub\n", This, memid, invKind);
11050 return E_NOTIMPL;
11053 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
11054 UINT index)
11056 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11057 FIXME("%p %u - stub\n", This, index);
11058 return E_NOTIMPL;
11061 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
11062 MEMBERID memid)
11064 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11065 FIXME("%p %x - stub\n", This, memid);
11066 return E_NOTIMPL;
11069 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
11070 UINT index)
11072 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11073 FIXME("%p %u - stub\n", This, index);
11074 return E_NOTIMPL;
11077 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
11078 REFGUID guid, VARIANT *varVal)
11080 TLBGuid *tlbguid;
11082 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11084 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
11086 if (!guid || !varVal)
11087 return E_INVALIDARG;
11089 tlbguid = TLB_append_guid(&This->pTypeLib->guid_list, guid, -1);
11091 return TLB_set_custdata(This->pcustdata_list, tlbguid, varVal);
11094 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
11095 UINT index, REFGUID guid, VARIANT *varVal)
11097 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11098 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11099 return E_NOTIMPL;
11102 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
11103 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
11105 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11106 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
11107 return E_NOTIMPL;
11110 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
11111 UINT index, REFGUID guid, VARIANT *varVal)
11113 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11114 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11115 return E_NOTIMPL;
11118 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
11119 UINT index, REFGUID guid, VARIANT *varVal)
11121 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11122 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11123 return E_NOTIMPL;
11126 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
11127 ULONG helpStringContext)
11129 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11131 TRACE("%p %u\n", This, helpStringContext);
11133 This->dwHelpStringContext = helpStringContext;
11135 return S_OK;
11138 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
11139 UINT index, ULONG helpStringContext)
11141 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11142 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11143 return E_NOTIMPL;
11146 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
11147 UINT index, ULONG helpStringContext)
11149 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11150 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11151 return E_NOTIMPL;
11154 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
11156 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11157 FIXME("%p - stub\n", This);
11158 return E_NOTIMPL;
11161 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
11162 LPOLESTR name)
11164 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11166 TRACE("%p %s\n", This, wine_dbgstr_w(name));
11168 if (!name)
11169 return E_INVALIDARG;
11171 This->Name = TLB_append_str(&This->pTypeLib->name_list, name);
11173 return S_OK;
11176 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
11177 ICreateTypeInfo2_fnQueryInterface,
11178 ICreateTypeInfo2_fnAddRef,
11179 ICreateTypeInfo2_fnRelease,
11180 ICreateTypeInfo2_fnSetGuid,
11181 ICreateTypeInfo2_fnSetTypeFlags,
11182 ICreateTypeInfo2_fnSetDocString,
11183 ICreateTypeInfo2_fnSetHelpContext,
11184 ICreateTypeInfo2_fnSetVersion,
11185 ICreateTypeInfo2_fnAddRefTypeInfo,
11186 ICreateTypeInfo2_fnAddFuncDesc,
11187 ICreateTypeInfo2_fnAddImplType,
11188 ICreateTypeInfo2_fnSetImplTypeFlags,
11189 ICreateTypeInfo2_fnSetAlignment,
11190 ICreateTypeInfo2_fnSetSchema,
11191 ICreateTypeInfo2_fnAddVarDesc,
11192 ICreateTypeInfo2_fnSetFuncAndParamNames,
11193 ICreateTypeInfo2_fnSetVarName,
11194 ICreateTypeInfo2_fnSetTypeDescAlias,
11195 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
11196 ICreateTypeInfo2_fnSetFuncDocString,
11197 ICreateTypeInfo2_fnSetVarDocString,
11198 ICreateTypeInfo2_fnSetFuncHelpContext,
11199 ICreateTypeInfo2_fnSetVarHelpContext,
11200 ICreateTypeInfo2_fnSetMops,
11201 ICreateTypeInfo2_fnSetTypeIdldesc,
11202 ICreateTypeInfo2_fnLayOut,
11203 ICreateTypeInfo2_fnDeleteFuncDesc,
11204 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
11205 ICreateTypeInfo2_fnDeleteVarDesc,
11206 ICreateTypeInfo2_fnDeleteVarDescByMemId,
11207 ICreateTypeInfo2_fnDeleteImplType,
11208 ICreateTypeInfo2_fnSetCustData,
11209 ICreateTypeInfo2_fnSetFuncCustData,
11210 ICreateTypeInfo2_fnSetParamCustData,
11211 ICreateTypeInfo2_fnSetVarCustData,
11212 ICreateTypeInfo2_fnSetImplTypeCustData,
11213 ICreateTypeInfo2_fnSetHelpStringContext,
11214 ICreateTypeInfo2_fnSetFuncHelpStringContext,
11215 ICreateTypeInfo2_fnSetVarHelpStringContext,
11216 ICreateTypeInfo2_fnInvalidate,
11217 ICreateTypeInfo2_fnSetName
11220 /******************************************************************************
11221 * ClearCustData (OLEAUT32.171)
11223 * Clear a custom data type's data.
11225 * PARAMS
11226 * lpCust [I] The custom data type instance
11228 * RETURNS
11229 * Nothing.
11231 void WINAPI ClearCustData(CUSTDATA *lpCust)
11233 if (lpCust && lpCust->cCustData)
11235 if (lpCust->prgCustData)
11237 DWORD i;
11239 for (i = 0; i < lpCust->cCustData; i++)
11240 VariantClear(&lpCust->prgCustData[i].varValue);
11242 CoTaskMemFree(lpCust->prgCustData);
11243 lpCust->prgCustData = NULL;
11245 lpCust->cCustData = 0;