oleaut32: LoadRegTypeLib() should check actual typelib version.
[wine.git] / dlls / oleaut32 / typelib.c
blobc77bc623dcfd8e45ca2cf6074a5f1b85ccbebee3
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 && (attr->wMajorVerNum != wVerMajor || attr->wMinorVerNum < wVerMinor))
547 ITypeLib_ReleaseTLibAttr(*ppTLib, attr);
548 ITypeLib_Release(*ppTLib);
549 *ppTLib = NULL;
550 res = TYPE_E_LIBNOTREGISTERED;
555 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
557 return res;
561 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
562 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
563 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
564 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
565 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
566 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
568 /******************************************************************************
569 * RegisterTypeLib [OLEAUT32.163]
570 * Adds information about a type library to the System Registry
571 * NOTES
572 * Docs: ITypeLib FAR * ptlib
573 * Docs: OLECHAR FAR* szFullPath
574 * Docs: OLECHAR FAR* szHelpDir
576 * RETURNS
577 * Success: S_OK
578 * Failure: Status
580 HRESULT WINAPI RegisterTypeLib(
581 ITypeLib * ptlib, /* [in] Pointer to the library*/
582 OLECHAR * szFullPath, /* [in] full Path of the library*/
583 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
584 may be NULL*/
586 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
587 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
588 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
589 HRESULT res;
590 TLIBATTR *attr;
591 WCHAR keyName[60];
592 WCHAR tmp[16];
593 HKEY key, subKey;
594 UINT types, tidx;
595 TYPEKIND kind;
596 DWORD disposition;
598 if (ptlib == NULL || szFullPath == NULL)
599 return E_INVALIDARG;
601 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
602 return E_FAIL;
604 #ifndef _WIN64
605 if (attr->syskind == SYS_WIN64) return TYPE_E_BADMODULEKIND;
606 #endif
608 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
610 res = S_OK;
611 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
612 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
614 LPOLESTR doc;
616 /* Set the human-readable name of the typelib */
617 if (FAILED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
618 res = E_FAIL;
619 else if (doc)
621 if (RegSetValueExW(key, NULL, 0, REG_SZ,
622 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
623 res = E_FAIL;
625 SysFreeString(doc);
628 /* Make up the name of the typelib path subkey */
629 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
631 /* Create the typelib path subkey */
632 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
633 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
635 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
636 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
637 res = E_FAIL;
639 RegCloseKey(subKey);
641 else
642 res = E_FAIL;
644 /* Create the flags subkey */
645 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
646 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
648 /* FIXME: is %u correct? */
649 static const WCHAR formatW[] = {'%','u',0};
650 WCHAR buf[20];
651 sprintfW(buf, formatW, attr->wLibFlags);
652 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
653 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
654 res = E_FAIL;
656 RegCloseKey(subKey);
658 else
659 res = E_FAIL;
661 /* create the helpdir subkey */
662 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
663 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
665 BOOL freeHelpDir = FALSE;
666 OLECHAR* pIndexStr;
668 /* if we created a new key, and helpDir was null, set the helpdir
669 to the directory which contains the typelib. However,
670 if we just opened an existing key, we leave the helpdir alone */
671 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
672 szHelpDir = SysAllocString(szFullPath);
673 pIndexStr = strrchrW(szHelpDir, '\\');
674 if (pIndexStr) {
675 *pIndexStr = 0;
677 freeHelpDir = TRUE;
680 /* if we have an szHelpDir, set it! */
681 if (szHelpDir != NULL) {
682 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
683 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
684 res = E_FAIL;
688 /* tidy up */
689 if (freeHelpDir) SysFreeString(szHelpDir);
690 RegCloseKey(subKey);
692 } else {
693 res = E_FAIL;
696 RegCloseKey(key);
698 else
699 res = E_FAIL;
701 /* register OLE Automation-compatible interfaces for this typelib */
702 types = ITypeLib_GetTypeInfoCount(ptlib);
703 for (tidx=0; tidx<types; tidx++) {
704 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
705 LPOLESTR name = NULL;
706 ITypeInfo *tinfo = NULL;
708 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
710 switch (kind) {
711 case TKIND_INTERFACE:
712 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
713 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
714 break;
716 case TKIND_DISPATCH:
717 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
718 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
719 break;
721 default:
722 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
723 break;
726 if (tinfo) {
727 TYPEATTR *tattr = NULL;
728 ITypeInfo_GetTypeAttr(tinfo, &tattr);
730 if (tattr) {
731 TRACE_(typelib)("guid=%s, flags=%04x (",
732 debugstr_guid(&tattr->guid),
733 tattr->wTypeFlags);
735 if (TRACE_ON(typelib)) {
736 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
737 XX(FAPPOBJECT);
738 XX(FCANCREATE);
739 XX(FLICENSED);
740 XX(FPREDECLID);
741 XX(FHIDDEN);
742 XX(FCONTROL);
743 XX(FDUAL);
744 XX(FNONEXTENSIBLE);
745 XX(FOLEAUTOMATION);
746 XX(FRESTRICTED);
747 XX(FAGGREGATABLE);
748 XX(FREPLACEABLE);
749 XX(FDISPATCHABLE);
750 XX(FREVERSEBIND);
751 XX(FPROXY);
752 #undef XX
753 MESSAGE("\n");
756 /* Register all dispinterfaces (which includes dual interfaces) and
757 oleautomation interfaces */
758 if ((kind == TKIND_INTERFACE && (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
759 kind == TKIND_DISPATCH)
761 /* register interface<->typelib coupling */
762 get_interface_key( &tattr->guid, keyName );
763 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
764 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
766 if (name)
767 RegSetValueExW(key, NULL, 0, REG_SZ,
768 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
770 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
771 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
772 RegSetValueExW(subKey, NULL, 0, REG_SZ,
773 (const BYTE *)PSOA, sizeof PSOA);
774 RegCloseKey(subKey);
777 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
778 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
779 RegSetValueExW(subKey, NULL, 0, REG_SZ,
780 (const BYTE *)PSOA, sizeof PSOA);
781 RegCloseKey(subKey);
784 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
785 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
787 WCHAR buffer[40];
788 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
789 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
791 StringFromGUID2(&attr->guid, buffer, 40);
792 RegSetValueExW(subKey, NULL, 0, REG_SZ,
793 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
794 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
795 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
796 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
797 RegCloseKey(subKey);
800 RegCloseKey(key);
804 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
807 ITypeInfo_Release(tinfo);
810 SysFreeString(name);
814 ITypeLib_ReleaseTLibAttr(ptlib, attr);
816 return res;
820 /******************************************************************************
821 * UnRegisterTypeLib [OLEAUT32.186]
822 * Removes information about a type library from the System Registry
823 * NOTES
825 * RETURNS
826 * Success: S_OK
827 * Failure: Status
829 HRESULT WINAPI UnRegisterTypeLib(
830 REFGUID libid, /* [in] Guid of the library */
831 WORD wVerMajor, /* [in] major version */
832 WORD wVerMinor, /* [in] minor version */
833 LCID lcid, /* [in] locale id */
834 SYSKIND syskind)
836 BSTR tlibPath = NULL;
837 DWORD tmpLength;
838 WCHAR keyName[60];
839 WCHAR subKeyName[50];
840 int result = S_OK;
841 DWORD i = 0;
842 BOOL deleteOtherStuff;
843 HKEY key = NULL;
844 HKEY subKey = NULL;
845 TYPEATTR* typeAttr = NULL;
846 TYPEKIND kind;
847 ITypeInfo* typeInfo = NULL;
848 ITypeLib* typeLib = NULL;
849 int numTypes;
851 TRACE("(IID: %s)\n",debugstr_guid(libid));
853 /* Create the path to the key */
854 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
856 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
858 TRACE("Unsupported syskind %i\n", syskind);
859 result = E_INVALIDARG;
860 goto end;
863 /* get the path to the typelib on disk */
864 if (query_typelib_path(libid, wVerMajor, wVerMinor, syskind, lcid, &tlibPath, FALSE) != S_OK) {
865 result = E_INVALIDARG;
866 goto end;
869 /* Try and open the key to the type library. */
870 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
871 result = E_INVALIDARG;
872 goto end;
875 /* Try and load the type library */
876 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib) != S_OK) {
877 result = TYPE_E_INVALIDSTATE;
878 goto end;
881 /* remove any types registered with this typelib */
882 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
883 for (i=0; i<numTypes; i++) {
884 /* get the kind of type */
885 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
886 goto enddeleteloop;
889 /* skip non-interfaces, and get type info for the type */
890 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
891 goto enddeleteloop;
893 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
894 goto enddeleteloop;
896 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
897 goto enddeleteloop;
900 if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
901 kind == TKIND_DISPATCH)
903 /* the path to the type */
904 get_interface_key( &typeAttr->guid, subKeyName );
906 /* Delete its bits */
907 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS)
908 goto enddeleteloop;
910 RegDeleteKeyW(subKey, ProxyStubClsidW);
911 RegDeleteKeyW(subKey, ProxyStubClsid32W);
912 RegDeleteKeyW(subKey, TypeLibW);
913 RegCloseKey(subKey);
914 subKey = NULL;
915 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
918 enddeleteloop:
919 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
920 typeAttr = NULL;
921 if (typeInfo) ITypeInfo_Release(typeInfo);
922 typeInfo = NULL;
925 /* Now, delete the type library path subkey */
926 get_lcid_subkey( lcid, syskind, subKeyName );
927 RegDeleteKeyW(key, subKeyName);
928 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
929 RegDeleteKeyW(key, subKeyName);
931 /* check if there is anything besides the FLAGS/HELPDIR keys.
932 If there is, we don't delete them */
933 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
934 deleteOtherStuff = TRUE;
935 i = 0;
936 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
937 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
939 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
940 if (!strcmpW(subKeyName, FLAGSW)) continue;
941 if (!strcmpW(subKeyName, HELPDIRW)) continue;
942 deleteOtherStuff = FALSE;
943 break;
946 /* only delete the other parts of the key if we're absolutely sure */
947 if (deleteOtherStuff) {
948 RegDeleteKeyW(key, FLAGSW);
949 RegDeleteKeyW(key, HELPDIRW);
950 RegCloseKey(key);
951 key = NULL;
953 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
954 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
955 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
958 end:
959 SysFreeString(tlibPath);
960 if (typeLib) ITypeLib_Release(typeLib);
961 if (subKey) RegCloseKey(subKey);
962 if (key) RegCloseKey(key);
963 return result;
966 /******************************************************************************
967 * RegisterTypeLibForUser [OLEAUT32.442]
968 * Adds information about a type library to the user registry
969 * NOTES
970 * Docs: ITypeLib FAR * ptlib
971 * Docs: OLECHAR FAR* szFullPath
972 * Docs: OLECHAR FAR* szHelpDir
974 * RETURNS
975 * Success: S_OK
976 * Failure: Status
978 HRESULT WINAPI RegisterTypeLibForUser(
979 ITypeLib * ptlib, /* [in] Pointer to the library*/
980 OLECHAR * szFullPath, /* [in] full Path of the library*/
981 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
982 may be NULL*/
984 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib,
985 debugstr_w(szFullPath), debugstr_w(szHelpDir));
986 return RegisterTypeLib(ptlib, szFullPath, szHelpDir);
989 /******************************************************************************
990 * UnRegisterTypeLibForUser [OLEAUT32.443]
991 * Removes information about a type library from the user registry
993 * RETURNS
994 * Success: S_OK
995 * Failure: Status
997 HRESULT WINAPI UnRegisterTypeLibForUser(
998 REFGUID libid, /* [in] GUID of the library */
999 WORD wVerMajor, /* [in] major version */
1000 WORD wVerMinor, /* [in] minor version */
1001 LCID lcid, /* [in] locale id */
1002 SYSKIND syskind)
1004 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
1005 debugstr_guid(libid), wVerMajor, wVerMinor, lcid, syskind);
1006 return UnRegisterTypeLib(libid, wVerMajor, wVerMinor, lcid, syskind);
1009 /*======================= ITypeLib implementation =======================*/
1011 typedef struct tagTLBGuid {
1012 GUID guid;
1013 INT hreftype;
1014 UINT offset;
1015 struct list entry;
1016 } TLBGuid;
1018 typedef struct tagTLBCustData
1020 TLBGuid *guid;
1021 VARIANT data;
1022 struct list entry;
1023 } TLBCustData;
1025 /* data structure for import typelibs */
1026 typedef struct tagTLBImpLib
1028 int offset; /* offset in the file (MSFT)
1029 offset in nametable (SLTG)
1030 just used to identify library while reading
1031 data from file */
1032 TLBGuid *guid; /* libid */
1033 BSTR name; /* name */
1035 LCID lcid; /* lcid of imported typelib */
1037 WORD wVersionMajor; /* major version number */
1038 WORD wVersionMinor; /* minor version number */
1040 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
1041 NULL if not yet loaded */
1042 struct list entry;
1043 } TLBImpLib;
1045 typedef struct tagTLBString {
1046 BSTR str;
1047 UINT offset;
1048 struct list entry;
1049 } TLBString;
1051 /* internal ITypeLib data */
1052 typedef struct tagITypeLibImpl
1054 ITypeLib2 ITypeLib2_iface;
1055 ITypeComp ITypeComp_iface;
1056 ICreateTypeLib2 ICreateTypeLib2_iface;
1057 LONG ref;
1058 TLBGuid *guid;
1059 LCID lcid;
1060 SYSKIND syskind;
1061 int ptr_size;
1062 WORD ver_major;
1063 WORD ver_minor;
1064 WORD libflags;
1065 LCID set_lcid;
1067 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1068 * exported to the application as a UNICODE string.
1070 struct list string_list;
1071 struct list name_list;
1072 struct list guid_list;
1074 const TLBString *Name;
1075 const TLBString *DocString;
1076 const TLBString *HelpFile;
1077 const TLBString *HelpStringDll;
1078 DWORD dwHelpContext;
1079 int TypeInfoCount; /* nr of typeinfo's in librarry */
1080 struct tagITypeInfoImpl **typeinfos;
1081 struct list custdata_list;
1082 struct list implib_list;
1083 int ctTypeDesc; /* number of items in type desc array */
1084 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1085 library. Only used while reading MSFT
1086 typelibs */
1087 struct list ref_list; /* list of ref types in this typelib */
1088 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1091 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1092 struct list entry;
1093 WCHAR *path;
1094 INT index;
1095 } ITypeLibImpl;
1097 static const ITypeLib2Vtbl tlbvt;
1098 static const ITypeCompVtbl tlbtcvt;
1099 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl;
1101 static inline ITypeLibImpl *impl_from_ITypeLib2(ITypeLib2 *iface)
1103 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeLib2_iface);
1106 static inline ITypeLibImpl *impl_from_ITypeLib(ITypeLib *iface)
1108 return impl_from_ITypeLib2((ITypeLib2*)iface);
1111 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1113 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeComp_iface);
1116 static inline ITypeLibImpl *impl_from_ICreateTypeLib2( ICreateTypeLib2 *iface )
1118 return CONTAINING_RECORD(iface, ITypeLibImpl, ICreateTypeLib2_iface);
1121 /* ITypeLib methods */
1122 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1123 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1125 /*======================= ITypeInfo implementation =======================*/
1127 /* data for referenced types */
1128 typedef struct tagTLBRefType
1130 INT index; /* Type index for internal ref or for external ref
1131 it the format is SLTG. -2 indicates to
1132 use guid */
1134 TYPEKIND tkind;
1135 TLBGuid *guid; /* guid of the referenced type */
1136 /* if index == TLB_REF_USE_GUID */
1138 HREFTYPE reference; /* The href of this ref */
1139 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1140 TLB_REF_INTERNAL for internal refs
1141 TLB_REF_NOT_FOUND for broken refs */
1143 struct list entry;
1144 } TLBRefType;
1146 #define TLB_REF_USE_GUID -2
1148 #define TLB_REF_INTERNAL (void*)-2
1149 #define TLB_REF_NOT_FOUND (void*)-1
1151 /* internal Parameter data */
1152 typedef struct tagTLBParDesc
1154 const TLBString *Name;
1155 struct list custdata_list;
1156 } TLBParDesc;
1158 /* internal Function data */
1159 typedef struct tagTLBFuncDesc
1161 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1162 const TLBString *Name; /* the name of this function */
1163 TLBParDesc *pParamDesc; /* array with param names and custom data */
1164 int helpcontext;
1165 int HelpStringContext;
1166 const TLBString *HelpString;
1167 const TLBString *Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1168 struct list custdata_list;
1169 } TLBFuncDesc;
1171 /* internal Variable data */
1172 typedef struct tagTLBVarDesc
1174 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1175 VARDESC *vardesc_create; /* additional data needed for storing VARDESC */
1176 const TLBString *Name; /* the name of this variable */
1177 int HelpContext;
1178 int HelpStringContext;
1179 const TLBString *HelpString;
1180 struct list custdata_list;
1181 } TLBVarDesc;
1183 /* internal implemented interface data */
1184 typedef struct tagTLBImplType
1186 HREFTYPE hRef; /* hRef of interface */
1187 int implflags; /* IMPLFLAG_*s */
1188 struct list custdata_list;
1189 } TLBImplType;
1191 /* internal TypeInfo data */
1192 typedef struct tagITypeInfoImpl
1194 ITypeInfo2 ITypeInfo2_iface;
1195 ITypeComp ITypeComp_iface;
1196 ICreateTypeInfo2 ICreateTypeInfo2_iface;
1197 LONG ref;
1198 BOOL not_attached_to_typelib;
1199 BOOL needs_layout;
1201 TLBGuid *guid;
1202 LCID lcid;
1203 MEMBERID memidConstructor;
1204 MEMBERID memidDestructor;
1205 LPOLESTR lpstrSchema;
1206 ULONG cbSizeInstance;
1207 TYPEKIND typekind;
1208 WORD cFuncs;
1209 WORD cVars;
1210 WORD cImplTypes;
1211 WORD cbSizeVft;
1212 WORD cbAlignment;
1213 WORD wTypeFlags;
1214 WORD wMajorVerNum;
1215 WORD wMinorVerNum;
1216 TYPEDESC *tdescAlias;
1217 IDLDESC idldescType;
1219 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1220 int index; /* index in this typelib; */
1221 HREFTYPE hreftype; /* hreftype for app object binding */
1222 /* type libs seem to store the doc strings in ascii
1223 * so why should we do it in unicode?
1225 const TLBString *Name;
1226 const TLBString *DocString;
1227 const TLBString *DllName;
1228 const TLBString *Schema;
1229 DWORD dwHelpContext;
1230 DWORD dwHelpStringContext;
1232 /* functions */
1233 TLBFuncDesc *funcdescs;
1235 /* variables */
1236 TLBVarDesc *vardescs;
1238 /* Implemented Interfaces */
1239 TLBImplType *impltypes;
1241 struct list *pcustdata_list;
1242 struct list custdata_list;
1243 } ITypeInfoImpl;
1245 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1247 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeComp_iface);
1250 static inline ITypeInfoImpl *impl_from_ITypeInfo2( ITypeInfo2 *iface )
1252 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeInfo2_iface);
1255 static inline ITypeInfoImpl *impl_from_ITypeInfo( ITypeInfo *iface )
1257 return impl_from_ITypeInfo2((ITypeInfo2*)iface);
1260 static inline ITypeInfoImpl *info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2 *iface )
1262 return CONTAINING_RECORD(iface, ITypeInfoImpl, ICreateTypeInfo2_iface);
1265 static const ITypeInfo2Vtbl tinfvt;
1266 static const ITypeCompVtbl tcompvt;
1267 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl;
1269 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1270 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1272 typedef struct tagTLBContext
1274 unsigned int oStart; /* start of TLB in file */
1275 unsigned int pos; /* current pos */
1276 unsigned int length; /* total length */
1277 void *mapping; /* memory mapping */
1278 MSFT_SegDir * pTblDir;
1279 ITypeLibImpl* pLibInfo;
1280 } TLBContext;
1283 static inline BSTR TLB_get_bstr(const TLBString *str)
1285 return str != NULL ? str->str : NULL;
1288 static inline int TLB_str_memcmp(void *left, const TLBString *str, DWORD len)
1290 if(!str)
1291 return 1;
1292 return memcmp(left, str->str, len);
1295 static inline const GUID *TLB_get_guidref(const TLBGuid *guid)
1297 return guid != NULL ? &guid->guid : NULL;
1300 static inline const GUID *TLB_get_guid_null(const TLBGuid *guid)
1302 return guid != NULL ? &guid->guid : &GUID_NULL;
1305 static int get_ptr_size(SYSKIND syskind)
1307 switch(syskind){
1308 case SYS_WIN64:
1309 return 8;
1310 case SYS_WIN32:
1311 case SYS_MAC:
1312 case SYS_WIN16:
1313 return 4;
1315 WARN("Unhandled syskind: 0x%x\n", syskind);
1316 return 4;
1320 debug
1322 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1323 if (pTD->vt & VT_RESERVED)
1324 szVarType += strlen(strcpy(szVarType, "reserved | "));
1325 if (pTD->vt & VT_BYREF)
1326 szVarType += strlen(strcpy(szVarType, "ref to "));
1327 if (pTD->vt & VT_ARRAY)
1328 szVarType += strlen(strcpy(szVarType, "array of "));
1329 if (pTD->vt & VT_VECTOR)
1330 szVarType += strlen(strcpy(szVarType, "vector of "));
1331 switch(pTD->vt & VT_TYPEMASK) {
1332 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1333 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1334 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1335 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1336 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1337 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1338 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1339 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1340 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1341 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1342 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1343 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1344 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1345 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1346 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1347 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1348 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1349 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1350 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1351 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1352 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1353 pTD->u.hreftype); break;
1354 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1355 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1356 case VT_PTR: sprintf(szVarType, "ptr to ");
1357 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1358 break;
1359 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1360 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1361 break;
1362 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1363 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1364 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1365 break;
1367 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1371 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1372 char buf[200];
1373 USHORT flags = edesc->u.paramdesc.wParamFlags;
1374 dump_TypeDesc(&edesc->tdesc,buf);
1375 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1376 MESSAGE("\t\tu.paramdesc.wParamFlags");
1377 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1378 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1379 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1380 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1381 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1382 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1383 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1384 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1385 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1387 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1388 int i;
1389 MESSAGE("memid is %08x\n",funcdesc->memid);
1390 for (i=0;i<funcdesc->cParams;i++) {
1391 MESSAGE("Param %d:\n",i);
1392 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1394 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1395 switch (funcdesc->funckind) {
1396 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1397 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1398 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1399 case FUNC_STATIC: MESSAGE("static");break;
1400 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1401 default: MESSAGE("unknown");break;
1403 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1404 switch (funcdesc->invkind) {
1405 case INVOKE_FUNC: MESSAGE("func");break;
1406 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1407 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1408 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1410 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1411 switch (funcdesc->callconv) {
1412 case CC_CDECL: MESSAGE("cdecl");break;
1413 case CC_PASCAL: MESSAGE("pascal");break;
1414 case CC_STDCALL: MESSAGE("stdcall");break;
1415 case CC_SYSCALL: MESSAGE("syscall");break;
1416 default:break;
1418 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1419 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1420 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1422 MESSAGE("\telemdescFunc (return value type):\n");
1423 dump_ELEMDESC(&funcdesc->elemdescFunc);
1426 static const char * const typekind_desc[] =
1428 "TKIND_ENUM",
1429 "TKIND_RECORD",
1430 "TKIND_MODULE",
1431 "TKIND_INTERFACE",
1432 "TKIND_DISPATCH",
1433 "TKIND_COCLASS",
1434 "TKIND_ALIAS",
1435 "TKIND_UNION",
1436 "TKIND_MAX"
1439 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1441 int i;
1442 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd->Name)), pfd->funcdesc.cParams);
1443 for (i=0;i<pfd->funcdesc.cParams;i++)
1444 MESSAGE("\tparm%d: %s\n",i,debugstr_w(TLB_get_bstr(pfd->pParamDesc[i].Name)));
1447 dump_FUNCDESC(&(pfd->funcdesc));
1449 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd->HelpString)));
1450 if(pfd->Entry == NULL)
1451 MESSAGE("\tentry: (null)\n");
1452 else if(pfd->Entry == (void*)-1)
1453 MESSAGE("\tentry: invalid\n");
1454 else if(IS_INTRESOURCE(pfd->Entry))
1455 MESSAGE("\tentry: %p\n", pfd->Entry);
1456 else
1457 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd->Entry)));
1459 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1461 while (n)
1463 dump_TLBFuncDescOne(pfd);
1464 ++pfd;
1465 --n;
1468 static void dump_TLBVarDesc(const TLBVarDesc * pvd, UINT n)
1470 while (n)
1472 TRACE_(typelib)("%s\n", debugstr_w(TLB_get_bstr(pvd->Name)));
1473 ++pvd;
1474 --n;
1478 static void dump_TLBImpLib(const TLBImpLib *import)
1480 TRACE_(typelib)("%s %s\n", debugstr_guid(TLB_get_guidref(import->guid)),
1481 debugstr_w(import->name));
1482 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1483 import->wVersionMinor, import->lcid, import->offset);
1486 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1488 TLBRefType *ref;
1490 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1492 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1493 if(ref->index == -1)
1494 TRACE_(typelib)("%s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
1495 else
1496 TRACE_(typelib)("type no: %d\n", ref->index);
1498 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1500 TRACE_(typelib)("in lib\n");
1501 dump_TLBImpLib(ref->pImpTLInfo);
1506 static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1508 if(!impl)
1509 return;
1510 while (n) {
1511 TRACE_(typelib)("implementing/inheriting interface hRef = %x implflags %x\n",
1512 impl->hRef, impl->implflags);
1513 ++impl;
1514 --n;
1518 static void dump_Variant(const VARIANT * pvar)
1520 SYSTEMTIME st;
1522 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1524 if (pvar)
1526 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1527 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1529 TRACE(",%p", V_BYREF(pvar));
1531 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1533 TRACE(",%p", V_ARRAY(pvar));
1535 else switch (V_TYPE(pvar))
1537 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1538 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1539 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1540 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1541 case VT_INT:
1542 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1543 case VT_UINT:
1544 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1545 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1546 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1547 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1548 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1549 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1550 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1551 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1552 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1553 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1554 V_CY(pvar).s.Lo); break;
1555 case VT_DATE:
1556 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1557 TRACE(",<invalid>");
1558 else
1559 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1560 st.wHour, st.wMinute, st.wSecond);
1561 break;
1562 case VT_ERROR:
1563 case VT_VOID:
1564 case VT_USERDEFINED:
1565 case VT_EMPTY:
1566 case VT_NULL: break;
1567 default: TRACE(",?"); break;
1570 TRACE("}\n");
1573 static void dump_DispParms(const DISPPARAMS * pdp)
1575 unsigned int index;
1577 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1579 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1581 TRACE("named args:\n");
1582 for (index = 0; index < pdp->cNamedArgs; index++)
1583 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1586 if (pdp->cArgs && pdp->rgvarg)
1588 TRACE("args:\n");
1589 for (index = 0; index < pdp->cArgs; index++)
1590 dump_Variant( &pdp->rgvarg[index] );
1594 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1596 TRACE("%p ref=%u\n", pty, pty->ref);
1597 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty->Name)), debugstr_w(TLB_get_bstr(pty->DocString)));
1598 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty->guid)));
1599 TRACE("kind:%s\n", typekind_desc[pty->typekind]);
1600 TRACE("fct:%u var:%u impl:%u\n", pty->cFuncs, pty->cVars, pty->cImplTypes);
1601 TRACE("wTypeFlags: 0x%04x\n", pty->wTypeFlags);
1602 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1603 if (pty->typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty->DllName)));
1604 if (TRACE_ON(ole))
1605 dump_TLBFuncDesc(pty->funcdescs, pty->cFuncs);
1606 dump_TLBVarDesc(pty->vardescs, pty->cVars);
1607 dump_TLBImplType(pty->impltypes, pty->cImplTypes);
1610 static void dump_VARDESC(const VARDESC *v)
1612 MESSAGE("memid %d\n",v->memid);
1613 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1614 MESSAGE("oInst %d\n",v->u.oInst);
1615 dump_ELEMDESC(&(v->elemdescVar));
1616 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1617 MESSAGE("varkind %d\n",v->varkind);
1620 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1622 /* VT_LPWSTR is largest type that, may appear in type description */
1623 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1624 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1625 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1626 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1627 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1628 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1629 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1630 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1633 static void TLB_abort(void)
1635 DebugBreak();
1638 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size)
1640 void *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
1641 if (!ret) ERR("cannot allocate memory\n");
1642 return ret;
1645 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size)
1647 void *ret = HeapAlloc(GetProcessHeap(), 0, size);
1648 if (!ret) ERR("cannot allocate memory\n");
1649 return ret;
1652 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr, unsigned size)
1654 return HeapReAlloc(GetProcessHeap(), 0, ptr, size);
1657 void heap_free(void *ptr)
1659 HeapFree(GetProcessHeap(), 0, ptr);
1662 /* returns the size required for a deep copy of a typedesc into a
1663 * flat buffer */
1664 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1666 SIZE_T size = 0;
1668 if (alloc_initial_space)
1669 size += sizeof(TYPEDESC);
1671 switch (tdesc->vt)
1673 case VT_PTR:
1674 case VT_SAFEARRAY:
1675 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1676 break;
1677 case VT_CARRAY:
1678 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1679 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1680 break;
1682 return size;
1685 /* deep copy a typedesc into a flat buffer */
1686 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1688 if (!dest)
1690 dest = buffer;
1691 buffer = (char *)buffer + sizeof(TYPEDESC);
1694 *dest = *src;
1696 switch (src->vt)
1698 case VT_PTR:
1699 case VT_SAFEARRAY:
1700 dest->u.lptdesc = buffer;
1701 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1702 break;
1703 case VT_CARRAY:
1704 dest->u.lpadesc = buffer;
1705 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1706 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1707 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1708 break;
1710 return buffer;
1713 /* free custom data allocated by MSFT_CustData */
1714 static inline void TLB_FreeCustData(struct list *custdata_list)
1716 TLBCustData *cd, *cdn;
1717 LIST_FOR_EACH_ENTRY_SAFE(cd, cdn, custdata_list, TLBCustData, entry)
1719 list_remove(&cd->entry);
1720 VariantClear(&cd->data);
1721 heap_free(cd);
1725 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1727 DWORD len;
1728 BSTR ret;
1730 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1731 ret = SysAllocStringLen(NULL, len - 1);
1732 if (!ret) return ret;
1733 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1734 return ret;
1737 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(TLBFuncDesc *funcdescs,
1738 UINT n, MEMBERID memid)
1740 while(n){
1741 if(funcdescs->funcdesc.memid == memid)
1742 return funcdescs;
1743 ++funcdescs;
1744 --n;
1746 return NULL;
1749 static inline TLBFuncDesc *TLB_get_funcdesc_by_name(TLBFuncDesc *funcdescs,
1750 UINT n, const OLECHAR *name)
1752 while(n){
1753 if(!lstrcmpiW(TLB_get_bstr(funcdescs->Name), name))
1754 return funcdescs;
1755 ++funcdescs;
1756 --n;
1758 return NULL;
1761 static inline TLBVarDesc *TLB_get_vardesc_by_memberid(TLBVarDesc *vardescs,
1762 UINT n, MEMBERID memid)
1764 while(n){
1765 if(vardescs->vardesc.memid == memid)
1766 return vardescs;
1767 ++vardescs;
1768 --n;
1770 return NULL;
1773 static inline TLBVarDesc *TLB_get_vardesc_by_name(TLBVarDesc *vardescs,
1774 UINT n, const OLECHAR *name)
1776 while(n){
1777 if(!lstrcmpiW(TLB_get_bstr(vardescs->Name), name))
1778 return vardescs;
1779 ++vardescs;
1780 --n;
1782 return NULL;
1785 static inline TLBCustData *TLB_get_custdata_by_guid(struct list *custdata_list, REFGUID guid)
1787 TLBCustData *cust_data;
1788 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1789 if(IsEqualIID(TLB_get_guid_null(cust_data->guid), guid))
1790 return cust_data;
1791 return NULL;
1794 static inline ITypeInfoImpl *TLB_get_typeinfo_by_name(ITypeInfoImpl **typeinfos,
1795 UINT n, const OLECHAR *name)
1797 while(n){
1798 if(!lstrcmpiW(TLB_get_bstr((*typeinfos)->Name), name))
1799 return *typeinfos;
1800 ++typeinfos;
1801 --n;
1803 return NULL;
1806 static void TLBVarDesc_Constructor(TLBVarDesc *var_desc)
1808 list_init(&var_desc->custdata_list);
1811 static TLBVarDesc *TLBVarDesc_Alloc(UINT n)
1813 TLBVarDesc *ret;
1815 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1816 if(!ret)
1817 return NULL;
1819 while(n){
1820 TLBVarDesc_Constructor(&ret[n-1]);
1821 --n;
1824 return ret;
1827 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1829 TLBParDesc *ret;
1831 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1832 if(!ret)
1833 return NULL;
1835 while(n){
1836 list_init(&ret[n-1].custdata_list);
1837 --n;
1840 return ret;
1843 static void TLBFuncDesc_Constructor(TLBFuncDesc *func_desc)
1845 list_init(&func_desc->custdata_list);
1848 static TLBFuncDesc *TLBFuncDesc_Alloc(UINT n)
1850 TLBFuncDesc *ret;
1852 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1853 if(!ret)
1854 return NULL;
1856 while(n){
1857 TLBFuncDesc_Constructor(&ret[n-1]);
1858 --n;
1861 return ret;
1864 static void TLBImplType_Constructor(TLBImplType *impl)
1866 list_init(&impl->custdata_list);
1869 static TLBImplType *TLBImplType_Alloc(UINT n)
1871 TLBImplType *ret;
1873 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1874 if(!ret)
1875 return NULL;
1877 while(n){
1878 TLBImplType_Constructor(&ret[n-1]);
1879 --n;
1882 return ret;
1885 static TLBGuid *TLB_append_guid(struct list *guid_list,
1886 const GUID *new_guid, HREFTYPE hreftype)
1888 TLBGuid *guid;
1890 LIST_FOR_EACH_ENTRY(guid, guid_list, TLBGuid, entry) {
1891 if (IsEqualGUID(&guid->guid, new_guid))
1892 return guid;
1895 guid = heap_alloc(sizeof(TLBGuid));
1896 if (!guid)
1897 return NULL;
1899 memcpy(&guid->guid, new_guid, sizeof(GUID));
1900 guid->hreftype = hreftype;
1902 list_add_tail(guid_list, &guid->entry);
1904 return guid;
1907 static HRESULT TLB_set_custdata(struct list *custdata_list, TLBGuid *tlbguid, VARIANT *var)
1909 TLBCustData *cust_data;
1911 switch(V_VT(var)){
1912 case VT_I4:
1913 case VT_R4:
1914 case VT_UI4:
1915 case VT_INT:
1916 case VT_UINT:
1917 case VT_HRESULT:
1918 case VT_BSTR:
1919 break;
1920 default:
1921 return DISP_E_BADVARTYPE;
1924 cust_data = TLB_get_custdata_by_guid(custdata_list, TLB_get_guid_null(tlbguid));
1926 if (!cust_data) {
1927 cust_data = heap_alloc(sizeof(TLBCustData));
1928 if (!cust_data)
1929 return E_OUTOFMEMORY;
1931 cust_data->guid = tlbguid;
1932 VariantInit(&cust_data->data);
1934 list_add_tail(custdata_list, &cust_data->entry);
1935 }else
1936 VariantClear(&cust_data->data);
1938 return VariantCopy(&cust_data->data, var);
1941 static TLBString *TLB_append_str(struct list *string_list, BSTR new_str)
1943 TLBString *str;
1945 if(!new_str)
1946 return NULL;
1948 LIST_FOR_EACH_ENTRY(str, string_list, TLBString, entry) {
1949 if (strcmpW(str->str, new_str) == 0)
1950 return str;
1953 str = heap_alloc(sizeof(TLBString));
1954 if (!str)
1955 return NULL;
1957 str->str = SysAllocString(new_str);
1958 if (!str->str) {
1959 heap_free(str);
1960 return NULL;
1963 list_add_tail(string_list, &str->entry);
1965 return str;
1968 static HRESULT TLB_get_size_from_hreftype(ITypeInfoImpl *info, HREFTYPE href,
1969 ULONG *size, WORD *align)
1971 ITypeInfo *other;
1972 TYPEATTR *attr;
1973 HRESULT hr;
1975 hr = ITypeInfo2_GetRefTypeInfo(&info->ITypeInfo2_iface, href, &other);
1976 if(FAILED(hr))
1977 return hr;
1979 hr = ITypeInfo_GetTypeAttr(other, &attr);
1980 if(FAILED(hr)){
1981 ITypeInfo_Release(other);
1982 return hr;
1985 if(size)
1986 *size = attr->cbSizeInstance;
1987 if(align)
1988 *align = attr->cbAlignment;
1990 ITypeInfo_ReleaseTypeAttr(other, attr);
1991 ITypeInfo_Release(other);
1993 return S_OK;
1996 static HRESULT TLB_size_instance(ITypeInfoImpl *info, SYSKIND sys,
1997 TYPEDESC *tdesc, ULONG *size, WORD *align)
1999 ULONG i, sub, ptr_size;
2000 HRESULT hr;
2002 ptr_size = get_ptr_size(sys);
2004 switch(tdesc->vt){
2005 case VT_VOID:
2006 *size = 0;
2007 break;
2008 case VT_I1:
2009 case VT_UI1:
2010 *size = 1;
2011 break;
2012 case VT_I2:
2013 case VT_BOOL:
2014 case VT_UI2:
2015 *size = 2;
2016 break;
2017 case VT_I4:
2018 case VT_R4:
2019 case VT_ERROR:
2020 case VT_UI4:
2021 case VT_INT:
2022 case VT_UINT:
2023 case VT_HRESULT:
2024 *size = 4;
2025 break;
2026 case VT_R8:
2027 case VT_I8:
2028 case VT_UI8:
2029 *size = 8;
2030 break;
2031 case VT_BSTR:
2032 case VT_DISPATCH:
2033 case VT_UNKNOWN:
2034 case VT_PTR:
2035 case VT_SAFEARRAY:
2036 case VT_LPSTR:
2037 case VT_LPWSTR:
2038 *size = ptr_size;
2039 break;
2040 case VT_DATE:
2041 *size = sizeof(DATE);
2042 break;
2043 case VT_VARIANT:
2044 *size = sizeof(VARIANT);
2045 #ifdef _WIN64
2046 if(sys == SYS_WIN32)
2047 *size -= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
2048 #endif
2049 break;
2050 case VT_DECIMAL:
2051 *size = sizeof(DECIMAL);
2052 break;
2053 case VT_CY:
2054 *size = sizeof(CY);
2055 break;
2056 case VT_CARRAY:
2057 *size = 0;
2058 for(i = 0; i < tdesc->u.lpadesc->cDims; ++i)
2059 *size += tdesc->u.lpadesc->rgbounds[i].cElements;
2060 hr = TLB_size_instance(info, sys, &tdesc->u.lpadesc->tdescElem, &sub, align);
2061 if(FAILED(hr))
2062 return hr;
2063 *size *= sub;
2064 return S_OK;
2065 case VT_USERDEFINED:
2066 return TLB_get_size_from_hreftype(info, tdesc->u.hreftype, size, align);
2067 default:
2068 FIXME("Unsized VT: 0x%x\n", tdesc->vt);
2069 return E_FAIL;
2072 if(align){
2073 if(*size < 4)
2074 *align = *size;
2075 else
2076 *align = 4;
2079 return S_OK;
2082 /**********************************************************************
2084 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2086 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
2088 return pcx->pos;
2091 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
2093 if (where != DO_NOT_SEEK)
2095 where += pcx->oStart;
2096 if (where > pcx->length)
2098 /* FIXME */
2099 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
2100 TLB_abort();
2102 pcx->pos = where;
2106 /* read function */
2107 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
2109 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2110 pcx->pos, count, pcx->oStart, pcx->length, where);
2112 MSFT_Seek(pcx, where);
2113 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
2114 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
2115 pcx->pos += count;
2116 return count;
2119 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
2120 LONG where )
2122 DWORD ret;
2124 ret = MSFT_Read(buffer, count, pcx, where);
2125 FromLEDWords(buffer, ret);
2127 return ret;
2130 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
2131 LONG where )
2133 DWORD ret;
2135 ret = MSFT_Read(buffer, count, pcx, where);
2136 FromLEWords(buffer, ret);
2138 return ret;
2141 static HRESULT MSFT_ReadAllGuids(TLBContext *pcx)
2143 TLBGuid *guid;
2144 MSFT_GuidEntry entry;
2145 int offs = 0;
2147 MSFT_Seek(pcx, pcx->pTblDir->pGuidTab.offset);
2148 while (1) {
2149 if (offs >= pcx->pTblDir->pGuidTab.length)
2150 return S_OK;
2152 MSFT_ReadLEWords(&entry, sizeof(MSFT_GuidEntry), pcx, DO_NOT_SEEK);
2154 guid = heap_alloc(sizeof(TLBGuid));
2156 guid->offset = offs;
2157 guid->guid = entry.guid;
2158 guid->hreftype = entry.hreftype;
2160 list_add_tail(&pcx->pLibInfo->guid_list, &guid->entry);
2162 offs += sizeof(MSFT_GuidEntry);
2166 static TLBGuid *MSFT_ReadGuid( int offset, TLBContext *pcx)
2168 TLBGuid *ret;
2170 LIST_FOR_EACH_ENTRY(ret, &pcx->pLibInfo->guid_list, TLBGuid, entry){
2171 if(ret->offset == offset){
2172 TRACE_(typelib)("%s\n", debugstr_guid(&ret->guid));
2173 return ret;
2177 return NULL;
2180 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
2182 MSFT_NameIntro niName;
2184 if (offset < 0)
2186 ERR_(typelib)("bad offset %d\n", offset);
2187 return -1;
2190 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
2191 pcx->pTblDir->pNametab.offset+offset);
2193 return niName.hreftype;
2196 static HRESULT MSFT_ReadAllNames(TLBContext *pcx)
2198 char *string;
2199 MSFT_NameIntro intro;
2200 INT16 len_piece;
2201 int offs = 0, lengthInChars;
2203 MSFT_Seek(pcx, pcx->pTblDir->pNametab.offset);
2204 while (1) {
2205 TLBString *tlbstr;
2207 if (offs >= pcx->pTblDir->pNametab.length)
2208 return S_OK;
2210 MSFT_ReadLEWords(&intro, sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2211 intro.namelen &= 0xFF;
2212 len_piece = intro.namelen + sizeof(MSFT_NameIntro);
2213 if(len_piece % 4)
2214 len_piece = (len_piece + 4) & ~0x3;
2215 if(len_piece < 8)
2216 len_piece = 8;
2218 string = heap_alloc(len_piece + 1);
2219 MSFT_Read(string, len_piece - sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2220 string[intro.namelen] = '\0';
2222 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2223 string, -1, NULL, 0);
2224 if (!lengthInChars) {
2225 heap_free(string);
2226 return E_UNEXPECTED;
2229 tlbstr = heap_alloc(sizeof(TLBString));
2231 tlbstr->offset = offs;
2232 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2233 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2235 heap_free(string);
2237 list_add_tail(&pcx->pLibInfo->name_list, &tlbstr->entry);
2239 offs += len_piece;
2243 static TLBString *MSFT_ReadName( TLBContext *pcx, int offset)
2245 TLBString *tlbstr;
2247 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->name_list, TLBString, entry) {
2248 if (tlbstr->offset == offset) {
2249 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2250 return tlbstr;
2254 return NULL;
2257 static TLBString *MSFT_ReadString( TLBContext *pcx, int offset)
2259 TLBString *tlbstr;
2261 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->string_list, TLBString, entry) {
2262 if (tlbstr->offset == offset) {
2263 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2264 return tlbstr;
2268 return NULL;
2272 * read a value and fill a VARIANT structure
2274 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
2276 int size;
2278 TRACE_(typelib)("\n");
2280 if(offset <0) { /* data are packed in here */
2281 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
2282 V_I4(pVar) = offset & 0x3ffffff;
2283 return;
2285 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
2286 pcx->pTblDir->pCustData.offset + offset );
2287 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
2288 switch (V_VT(pVar)){
2289 case VT_EMPTY: /* FIXME: is this right? */
2290 case VT_NULL: /* FIXME: is this right? */
2291 case VT_I2 : /* this should not happen */
2292 case VT_I4 :
2293 case VT_R4 :
2294 case VT_ERROR :
2295 case VT_BOOL :
2296 case VT_I1 :
2297 case VT_UI1 :
2298 case VT_UI2 :
2299 case VT_UI4 :
2300 case VT_INT :
2301 case VT_UINT :
2302 case VT_VOID : /* FIXME: is this right? */
2303 case VT_HRESULT :
2304 size=4; break;
2305 case VT_R8 :
2306 case VT_CY :
2307 case VT_DATE :
2308 case VT_I8 :
2309 case VT_UI8 :
2310 case VT_DECIMAL : /* FIXME: is this right? */
2311 case VT_FILETIME :
2312 size=8;break;
2313 /* pointer types with known behaviour */
2314 case VT_BSTR :{
2315 char * ptr;
2316 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
2317 if(size == -1){
2318 V_BSTR(pVar) = NULL;
2319 }else{
2320 ptr = heap_alloc_zero(size);
2321 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);
2322 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
2323 /* FIXME: do we need a AtoW conversion here? */
2324 V_UNION(pVar, bstrVal[size])='\0';
2325 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
2326 heap_free(ptr);
2329 size=-4; break;
2330 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2331 case VT_DISPATCH :
2332 case VT_VARIANT :
2333 case VT_UNKNOWN :
2334 case VT_PTR :
2335 case VT_SAFEARRAY :
2336 case VT_CARRAY :
2337 case VT_USERDEFINED :
2338 case VT_LPSTR :
2339 case VT_LPWSTR :
2340 case VT_BLOB :
2341 case VT_STREAM :
2342 case VT_STORAGE :
2343 case VT_STREAMED_OBJECT :
2344 case VT_STORED_OBJECT :
2345 case VT_BLOB_OBJECT :
2346 case VT_CF :
2347 case VT_CLSID :
2348 default:
2349 size=0;
2350 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2351 V_VT(pVar));
2354 if(size>0) /* (big|small) endian correct? */
2355 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
2356 return;
2359 * create a linked list with custom data
2361 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
2363 MSFT_CDGuid entry;
2364 TLBCustData* pNew;
2365 int count=0;
2367 TRACE_(typelib)("\n");
2369 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
2371 while(offset >=0){
2372 count++;
2373 pNew=heap_alloc_zero(sizeof(TLBCustData));
2374 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
2375 pNew->guid = MSFT_ReadGuid(entry.GuidOffset, pcx);
2376 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
2377 list_add_head(custdata_list, &pNew->entry);
2378 offset = entry.next;
2380 return count;
2383 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd)
2385 if(type <0)
2386 pTd->vt=type & VT_TYPEMASK;
2387 else
2388 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
2390 TRACE_(typelib)("vt type = %X\n", pTd->vt);
2393 static int TLB_is_propgetput(INVOKEKIND invkind)
2395 return (invkind == INVOKE_PROPERTYGET ||
2396 invkind == INVOKE_PROPERTYPUT ||
2397 invkind == INVOKE_PROPERTYPUTREF);
2400 static void
2401 MSFT_DoFuncs(TLBContext* pcx,
2402 ITypeInfoImpl* pTI,
2403 int cFuncs,
2404 int cVars,
2405 int offset,
2406 TLBFuncDesc** pptfd)
2409 * member information is stored in a data structure at offset
2410 * indicated by the memoffset field of the typeinfo structure
2411 * There are several distinctive parts.
2412 * The first part starts with a field that holds the total length
2413 * of this (first) part excluding this field. Then follow the records,
2414 * for each member there is one record.
2416 * The first entry is always the length of the record (including this
2417 * length word).
2418 * The rest of the record depends on the type of the member. If there is
2419 * a field indicating the member type (function, variable, interface, etc)
2420 * I have not found it yet. At this time we depend on the information
2421 * in the type info and the usual order how things are stored.
2423 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2424 * for each member;
2426 * Third is an equal sized array with file offsets to the name entry
2427 * of each member.
2429 * The fourth and last (?) part is an array with offsets to the records
2430 * in the first part of this file segment.
2433 int infolen, nameoffset, reclength, i;
2434 int recoffset = offset + sizeof(INT);
2436 char *recbuf = heap_alloc(0xffff);
2437 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2438 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2440 TRACE_(typelib)("\n");
2442 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2444 *pptfd = TLBFuncDesc_Alloc(cFuncs);
2445 ptfd = *pptfd;
2446 for ( i = 0; i < cFuncs ; i++ )
2448 int optional;
2450 /* name, eventually add to a hash table */
2451 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2452 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2454 /* read the function information record */
2455 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2457 reclength &= 0xffff;
2459 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2461 /* size without argument data */
2462 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2463 if (pFuncRec->FKCCIC & 0x1000)
2464 optional -= pFuncRec->nrargs * sizeof(INT);
2466 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2467 ptfd->helpcontext = pFuncRec->HelpContext;
2469 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2470 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2472 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2474 if (pFuncRec->FKCCIC & 0x2000 )
2476 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2477 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2478 ptfd->Entry = (TLBString*)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2480 else
2481 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2483 else
2484 ptfd->Entry = (TLBString*)-1;
2486 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2487 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2489 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2490 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2492 /* fill the FuncDesc Structure */
2493 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2494 offset + infolen + ( i + 1) * sizeof(INT));
2496 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2497 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2498 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2499 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2500 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2501 ptfd->funcdesc.oVft = pFuncRec->VtableOffset & ~1;
2502 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2504 /* nameoffset is sometimes -1 on the second half of a propget/propput
2505 * pair of functions */
2506 if ((nameoffset == -1) && (i > 0) &&
2507 TLB_is_propgetput(ptfd_prev->funcdesc.invkind) &&
2508 TLB_is_propgetput(ptfd->funcdesc.invkind))
2509 ptfd->Name = ptfd_prev->Name;
2510 else
2511 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2513 MSFT_GetTdesc(pcx,
2514 pFuncRec->DataType,
2515 &ptfd->funcdesc.elemdescFunc.tdesc);
2517 /* do the parameters/arguments */
2518 if(pFuncRec->nrargs)
2520 int j = 0;
2521 MSFT_ParameterInfo paraminfo;
2523 ptfd->funcdesc.lprgelemdescParam =
2524 heap_alloc_zero(pFuncRec->nrargs * (sizeof(ELEMDESC) + sizeof(PARAMDESCEX)));
2526 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2528 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2529 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2531 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2533 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2535 MSFT_GetTdesc(pcx,
2536 paraminfo.DataType,
2537 &elemdesc->tdesc);
2539 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2541 /* name */
2542 if (paraminfo.oName != -1)
2543 ptfd->pParamDesc[j].Name =
2544 MSFT_ReadName( pcx, paraminfo.oName );
2545 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(TLB_get_bstr(ptfd->pParamDesc[j].Name)));
2547 /* default value */
2548 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2549 (pFuncRec->FKCCIC & 0x1000) )
2551 INT* pInt = (INT *)((char *)pFuncRec +
2552 reclength -
2553 (pFuncRec->nrargs * 4) * sizeof(INT) );
2555 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2557 pParamDesc->pparamdescex = (PARAMDESCEX*)(ptfd->funcdesc.lprgelemdescParam+pFuncRec->nrargs)+j;
2558 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2560 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2561 pInt[j], pcx);
2563 else
2564 elemdesc->u.paramdesc.pparamdescex = NULL;
2566 /* custom info */
2567 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2568 j*sizeof(pFuncRec->oArgCustData[0])) &&
2569 pFuncRec->FKCCIC & 0x80 )
2571 MSFT_CustData(pcx,
2572 pFuncRec->oArgCustData[j],
2573 &ptfd->pParamDesc[j].custdata_list);
2576 /* SEEK value = jump to offset,
2577 * from there jump to the end of record,
2578 * go back by (j-1) arguments
2580 MSFT_ReadLEDWords( &paraminfo ,
2581 sizeof(MSFT_ParameterInfo), pcx,
2582 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2583 * sizeof(MSFT_ParameterInfo)));
2587 /* scode is not used: archaic win16 stuff FIXME: right? */
2588 ptfd->funcdesc.cScodes = 0 ;
2589 ptfd->funcdesc.lprgscode = NULL ;
2591 ptfd_prev = ptfd;
2592 ++ptfd;
2593 recoffset += reclength;
2595 heap_free(recbuf);
2598 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2599 int cVars, int offset, TLBVarDesc ** pptvd)
2601 int infolen, nameoffset, reclength;
2602 char recbuf[256];
2603 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2604 TLBVarDesc *ptvd;
2605 int i;
2606 int recoffset;
2608 TRACE_(typelib)("\n");
2610 ptvd = *pptvd = TLBVarDesc_Alloc(cVars);
2611 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2612 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2613 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2614 recoffset += offset+sizeof(INT);
2615 for(i=0;i<cVars;i++, ++ptvd){
2616 /* name, eventually add to a hash table */
2617 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2618 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2619 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2620 /* read the variable information record */
2621 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2622 reclength &= 0xff;
2623 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2625 /* optional data */
2626 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2627 ptvd->HelpContext = pVarRec->HelpContext;
2629 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2630 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2632 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2633 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2635 /* fill the VarDesc Structure */
2636 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2637 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2638 ptvd->vardesc.varkind = pVarRec->VarKind;
2639 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2640 MSFT_GetTdesc(pcx, pVarRec->DataType,
2641 &ptvd->vardesc.elemdescVar.tdesc);
2642 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2643 if(pVarRec->VarKind == VAR_CONST ){
2644 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2645 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2646 pVarRec->OffsValue, pcx);
2647 } else
2648 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2649 recoffset += reclength;
2653 /* process Implemented Interfaces of a com class */
2654 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2655 int offset)
2657 int i;
2658 MSFT_RefRecord refrec;
2659 TLBImplType *pImpl;
2661 TRACE_(typelib)("\n");
2663 pTI->impltypes = TLBImplType_Alloc(count);
2664 pImpl = pTI->impltypes;
2665 for(i=0;i<count;i++){
2666 if(offset<0) break; /* paranoia */
2667 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2668 pImpl->hRef = refrec.reftype;
2669 pImpl->implflags=refrec.flags;
2670 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2671 offset=refrec.onext;
2672 ++pImpl;
2676 #ifdef _WIN64
2677 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2678 * and some structures, and fix the alignment */
2679 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl *info)
2681 if(info->typekind == TKIND_ALIAS){
2682 switch(info->tdescAlias->vt){
2683 case VT_BSTR:
2684 case VT_DISPATCH:
2685 case VT_UNKNOWN:
2686 case VT_PTR:
2687 case VT_SAFEARRAY:
2688 case VT_LPSTR:
2689 case VT_LPWSTR:
2690 info->cbSizeInstance = sizeof(void*);
2691 info->cbAlignment = sizeof(void*);
2692 break;
2693 case VT_CARRAY:
2694 case VT_USERDEFINED:
2695 TLB_size_instance(info, SYS_WIN64, info->tdescAlias, &info->cbSizeInstance, &info->cbAlignment);
2696 break;
2697 case VT_VARIANT:
2698 info->cbSizeInstance = sizeof(VARIANT);
2699 info->cbAlignment = 8;
2700 default:
2701 if(info->cbSizeInstance < sizeof(void*))
2702 info->cbAlignment = info->cbSizeInstance;
2703 else
2704 info->cbAlignment = sizeof(void*);
2705 break;
2707 }else if(info->typekind == TKIND_INTERFACE ||
2708 info->typekind == TKIND_DISPATCH ||
2709 info->typekind == TKIND_COCLASS){
2710 info->cbSizeInstance = sizeof(void*);
2711 info->cbAlignment = sizeof(void*);
2714 #endif
2717 * process a typeinfo record
2719 static ITypeInfoImpl * MSFT_DoTypeInfo(
2720 TLBContext *pcx,
2721 int count,
2722 ITypeLibImpl * pLibInfo)
2724 MSFT_TypeInfoBase tiBase;
2725 ITypeInfoImpl *ptiRet;
2727 TRACE_(typelib)("count=%u\n", count);
2729 ptiRet = ITypeInfoImpl_Constructor();
2730 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2731 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2733 /* this is where we are coming from */
2734 ptiRet->pTypeLib = pLibInfo;
2735 ptiRet->index=count;
2737 ptiRet->guid = MSFT_ReadGuid(tiBase.posguid, pcx);
2738 ptiRet->lcid=pLibInfo->set_lcid; /* FIXME: correct? */
2739 ptiRet->lpstrSchema=NULL; /* reserved */
2740 ptiRet->cbSizeInstance=tiBase.size;
2741 ptiRet->typekind=tiBase.typekind & 0xF;
2742 ptiRet->cFuncs=LOWORD(tiBase.cElement);
2743 ptiRet->cVars=HIWORD(tiBase.cElement);
2744 ptiRet->cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2745 ptiRet->wTypeFlags=tiBase.flags;
2746 ptiRet->wMajorVerNum=LOWORD(tiBase.version);
2747 ptiRet->wMinorVerNum=HIWORD(tiBase.version);
2748 ptiRet->cImplTypes=tiBase.cImplTypes;
2749 ptiRet->cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2750 if(ptiRet->typekind == TKIND_ALIAS){
2751 TYPEDESC tmp;
2752 MSFT_GetTdesc(pcx, tiBase.datatype1, &tmp);
2753 ptiRet->tdescAlias = heap_alloc(TLB_SizeTypeDesc(&tmp, TRUE));
2754 TLB_CopyTypeDesc(NULL, &tmp, ptiRet->tdescAlias);
2757 /* FIXME: */
2758 /* IDLDESC idldescType; *//* never saw this one != zero */
2760 /* name, eventually add to a hash table */
2761 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2762 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2763 TRACE_(typelib)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet->Name)));
2764 /* help info */
2765 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2766 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2767 ptiRet->dwHelpContext=tiBase.helpcontext;
2769 if (ptiRet->typekind == TKIND_MODULE)
2770 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2772 /* note: InfoType's Help file and HelpStringDll come from the containing
2773 * library. Further HelpString and Docstring appear to be the same thing :(
2775 /* functions */
2776 if(ptiRet->cFuncs >0 )
2777 MSFT_DoFuncs(pcx, ptiRet, ptiRet->cFuncs,
2778 ptiRet->cVars,
2779 tiBase.memoffset, &ptiRet->funcdescs);
2780 /* variables */
2781 if(ptiRet->cVars >0 )
2782 MSFT_DoVars(pcx, ptiRet, ptiRet->cFuncs,
2783 ptiRet->cVars,
2784 tiBase.memoffset, &ptiRet->vardescs);
2785 if(ptiRet->cImplTypes >0 ) {
2786 switch(ptiRet->typekind)
2788 case TKIND_COCLASS:
2789 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->cImplTypes,
2790 tiBase.datatype1);
2791 break;
2792 case TKIND_DISPATCH:
2793 /* This is not -1 when the interface is a non-base dual interface or
2794 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2795 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2796 not this interface.
2799 if (tiBase.datatype1 != -1)
2801 ptiRet->impltypes = TLBImplType_Alloc(1);
2802 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2804 break;
2805 default:
2806 ptiRet->impltypes = TLBImplType_Alloc(1);
2807 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2808 break;
2811 MSFT_CustData(pcx, tiBase.oCustData, ptiRet->pcustdata_list);
2813 TRACE_(typelib)("%s guid: %s kind:%s\n",
2814 debugstr_w(TLB_get_bstr(ptiRet->Name)),
2815 debugstr_guid(TLB_get_guidref(ptiRet->guid)),
2816 typekind_desc[ptiRet->typekind]);
2817 if (TRACE_ON(typelib))
2818 dump_TypeInfo(ptiRet);
2820 return ptiRet;
2823 static HRESULT MSFT_ReadAllStrings(TLBContext *pcx)
2825 char *string;
2826 INT16 len_str, len_piece;
2827 int offs = 0, lengthInChars;
2829 MSFT_Seek(pcx, pcx->pTblDir->pStringtab.offset);
2830 while (1) {
2831 TLBString *tlbstr;
2833 if (offs >= pcx->pTblDir->pStringtab.length)
2834 return S_OK;
2836 MSFT_ReadLEWords(&len_str, sizeof(INT16), pcx, DO_NOT_SEEK);
2837 len_piece = len_str + sizeof(INT16);
2838 if(len_piece % 4)
2839 len_piece = (len_piece + 4) & ~0x3;
2840 if(len_piece < 8)
2841 len_piece = 8;
2843 string = heap_alloc(len_piece + 1);
2844 MSFT_Read(string, len_piece - sizeof(INT16), pcx, DO_NOT_SEEK);
2845 string[len_str] = '\0';
2847 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2848 string, -1, NULL, 0);
2849 if (!lengthInChars) {
2850 heap_free(string);
2851 return E_UNEXPECTED;
2854 tlbstr = heap_alloc(sizeof(TLBString));
2856 tlbstr->offset = offs;
2857 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2858 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2860 heap_free(string);
2862 list_add_tail(&pcx->pLibInfo->string_list, &tlbstr->entry);
2864 offs += len_piece;
2868 static HRESULT MSFT_ReadAllRefs(TLBContext *pcx)
2870 TLBRefType *ref;
2871 int offs = 0;
2873 MSFT_Seek(pcx, pcx->pTblDir->pImpInfo.offset);
2874 while (offs < pcx->pTblDir->pImpInfo.length) {
2875 MSFT_ImpInfo impinfo;
2876 TLBImpLib *pImpLib;
2878 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx, DO_NOT_SEEK);
2880 ref = heap_alloc_zero(sizeof(TLBRefType));
2881 list_add_tail(&pcx->pLibInfo->ref_list, &ref->entry);
2883 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2884 if(pImpLib->offset==impinfo.oImpFile)
2885 break;
2887 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2888 ref->reference = offs;
2889 ref->pImpTLInfo = pImpLib;
2890 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2891 ref->guid = MSFT_ReadGuid(impinfo.oGuid, pcx);
2892 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
2893 ref->index = TLB_REF_USE_GUID;
2894 } else
2895 ref->index = impinfo.oGuid;
2896 }else{
2897 ERR("Cannot find a reference\n");
2898 ref->reference = -1;
2899 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2902 offs += sizeof(impinfo);
2905 return S_OK;
2908 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2909 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2910 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2911 * tradeoff here.
2913 static struct list tlb_cache = LIST_INIT(tlb_cache);
2914 static CRITICAL_SECTION cache_section;
2915 static CRITICAL_SECTION_DEBUG cache_section_debug =
2917 0, 0, &cache_section,
2918 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2919 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2921 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2924 typedef struct TLB_PEFile
2926 IUnknown IUnknown_iface;
2927 LONG refs;
2928 HMODULE dll;
2929 HRSRC typelib_resource;
2930 HGLOBAL typelib_global;
2931 LPVOID typelib_base;
2932 } TLB_PEFile;
2934 static inline TLB_PEFile *pefile_impl_from_IUnknown(IUnknown *iface)
2936 return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2939 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2941 if (IsEqualIID(riid, &IID_IUnknown))
2943 *ppv = iface;
2944 IUnknown_AddRef(iface);
2945 return S_OK;
2947 *ppv = NULL;
2948 return E_NOINTERFACE;
2951 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2953 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2954 return InterlockedIncrement(&This->refs);
2957 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2959 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2960 ULONG refs = InterlockedDecrement(&This->refs);
2961 if (!refs)
2963 if (This->typelib_global)
2964 FreeResource(This->typelib_global);
2965 if (This->dll)
2966 FreeLibrary(This->dll);
2967 heap_free(This);
2969 return refs;
2972 static const IUnknownVtbl TLB_PEFile_Vtable =
2974 TLB_PEFile_QueryInterface,
2975 TLB_PEFile_AddRef,
2976 TLB_PEFile_Release
2979 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2981 TLB_PEFile *This;
2982 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2984 This = heap_alloc(sizeof(TLB_PEFile));
2985 if (!This)
2986 return E_OUTOFMEMORY;
2988 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
2989 This->refs = 1;
2990 This->dll = NULL;
2991 This->typelib_resource = NULL;
2992 This->typelib_global = NULL;
2993 This->typelib_base = NULL;
2995 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2996 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2998 if (This->dll)
3000 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
3001 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
3002 if (This->typelib_resource)
3004 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
3005 if (This->typelib_global)
3007 This->typelib_base = LockResource(This->typelib_global);
3009 if (This->typelib_base)
3011 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
3012 *ppBase = This->typelib_base;
3013 *ppFile = &This->IUnknown_iface;
3014 return S_OK;
3019 TRACE("No TYPELIB resource found\n");
3020 hr = E_FAIL;
3023 TLB_PEFile_Release(&This->IUnknown_iface);
3024 return hr;
3027 typedef struct TLB_NEFile
3029 IUnknown IUnknown_iface;
3030 LONG refs;
3031 LPVOID typelib_base;
3032 } TLB_NEFile;
3034 static inline TLB_NEFile *nefile_impl_from_IUnknown(IUnknown *iface)
3036 return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
3039 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3041 if (IsEqualIID(riid, &IID_IUnknown))
3043 *ppv = iface;
3044 IUnknown_AddRef(iface);
3045 return S_OK;
3047 *ppv = NULL;
3048 return E_NOINTERFACE;
3051 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
3053 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
3054 return InterlockedIncrement(&This->refs);
3057 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
3059 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
3060 ULONG refs = InterlockedDecrement(&This->refs);
3061 if (!refs)
3063 heap_free(This->typelib_base);
3064 heap_free(This);
3066 return refs;
3069 static const IUnknownVtbl TLB_NEFile_Vtable =
3071 TLB_NEFile_QueryInterface,
3072 TLB_NEFile_AddRef,
3073 TLB_NEFile_Release
3076 /***********************************************************************
3077 * read_xx_header [internal]
3079 static int read_xx_header( HFILE lzfd )
3081 IMAGE_DOS_HEADER mzh;
3082 char magic[3];
3084 LZSeek( lzfd, 0, SEEK_SET );
3085 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
3086 return 0;
3087 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
3088 return 0;
3090 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3091 if ( 2 != LZRead( lzfd, magic, 2 ) )
3092 return 0;
3094 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3096 if ( magic[0] == 'N' && magic[1] == 'E' )
3097 return IMAGE_OS2_SIGNATURE;
3098 if ( magic[0] == 'P' && magic[1] == 'E' )
3099 return IMAGE_NT_SIGNATURE;
3101 magic[2] = '\0';
3102 WARN("Can't handle %s files.\n", magic );
3103 return 0;
3107 /***********************************************************************
3108 * find_ne_resource [internal]
3110 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
3111 DWORD *resLen, DWORD *resOff )
3113 IMAGE_OS2_HEADER nehd;
3114 NE_TYPEINFO *typeInfo;
3115 NE_NAMEINFO *nameInfo;
3116 DWORD nehdoffset;
3117 LPBYTE resTab;
3118 DWORD resTabSize;
3119 int count;
3121 /* Read in NE header */
3122 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
3123 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
3125 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
3126 if ( !resTabSize )
3128 TRACE("No resources in NE dll\n" );
3129 return FALSE;
3132 /* Read in resource table */
3133 resTab = heap_alloc( resTabSize );
3134 if ( !resTab ) return FALSE;
3136 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
3137 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
3139 heap_free( resTab );
3140 return FALSE;
3143 /* Find resource */
3144 typeInfo = (NE_TYPEINFO *)(resTab + 2);
3146 if (!IS_INTRESOURCE(typeid)) /* named type */
3148 BYTE len = strlen( typeid );
3149 while (typeInfo->type_id)
3151 if (!(typeInfo->type_id & 0x8000))
3153 BYTE *p = resTab + typeInfo->type_id;
3154 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
3156 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3157 typeInfo->count * sizeof(NE_NAMEINFO));
3160 else /* numeric type id */
3162 WORD id = LOWORD(typeid) | 0x8000;
3163 while (typeInfo->type_id)
3165 if (typeInfo->type_id == id) goto found_type;
3166 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3167 typeInfo->count * sizeof(NE_NAMEINFO));
3170 TRACE("No typeid entry found for %p\n", typeid );
3171 heap_free( resTab );
3172 return FALSE;
3174 found_type:
3175 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
3177 if (!IS_INTRESOURCE(resid)) /* named resource */
3179 BYTE len = strlen( resid );
3180 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3182 BYTE *p = resTab + nameInfo->id;
3183 if (nameInfo->id & 0x8000) continue;
3184 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
3187 else /* numeric resource id */
3189 WORD id = LOWORD(resid) | 0x8000;
3190 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3191 if (nameInfo->id == id) goto found_name;
3193 TRACE("No resid entry found for %p\n", typeid );
3194 heap_free( resTab );
3195 return FALSE;
3197 found_name:
3198 /* Return resource data */
3199 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
3200 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
3202 heap_free( resTab );
3203 return TRUE;
3206 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
3208 HFILE lzfd = -1;
3209 OFSTRUCT ofs;
3210 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
3211 TLB_NEFile *This;
3213 This = heap_alloc(sizeof(TLB_NEFile));
3214 if (!This) return E_OUTOFMEMORY;
3216 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
3217 This->refs = 1;
3218 This->typelib_base = NULL;
3220 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
3221 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
3223 DWORD reslen, offset;
3224 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
3226 This->typelib_base = heap_alloc(reslen);
3227 if( !This->typelib_base )
3228 hr = E_OUTOFMEMORY;
3229 else
3231 LZSeek( lzfd, offset, SEEK_SET );
3232 reslen = LZRead( lzfd, This->typelib_base, reslen );
3233 LZClose( lzfd );
3234 *ppBase = This->typelib_base;
3235 *pdwTLBLength = reslen;
3236 *ppFile = &This->IUnknown_iface;
3237 return S_OK;
3242 if( lzfd >= 0) LZClose( lzfd );
3243 TLB_NEFile_Release(&This->IUnknown_iface);
3244 return hr;
3247 typedef struct TLB_Mapping
3249 IUnknown IUnknown_iface;
3250 LONG refs;
3251 HANDLE file;
3252 HANDLE mapping;
3253 LPVOID typelib_base;
3254 } TLB_Mapping;
3256 static inline TLB_Mapping *mapping_impl_from_IUnknown(IUnknown *iface)
3258 return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
3261 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3263 if (IsEqualIID(riid, &IID_IUnknown))
3265 *ppv = iface;
3266 IUnknown_AddRef(iface);
3267 return S_OK;
3269 *ppv = NULL;
3270 return E_NOINTERFACE;
3273 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
3275 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3276 return InterlockedIncrement(&This->refs);
3279 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
3281 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3282 ULONG refs = InterlockedDecrement(&This->refs);
3283 if (!refs)
3285 if (This->typelib_base)
3286 UnmapViewOfFile(This->typelib_base);
3287 if (This->mapping)
3288 CloseHandle(This->mapping);
3289 if (This->file != INVALID_HANDLE_VALUE)
3290 CloseHandle(This->file);
3291 heap_free(This);
3293 return refs;
3296 static const IUnknownVtbl TLB_Mapping_Vtable =
3298 TLB_Mapping_QueryInterface,
3299 TLB_Mapping_AddRef,
3300 TLB_Mapping_Release
3303 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
3305 TLB_Mapping *This;
3307 This = heap_alloc(sizeof(TLB_Mapping));
3308 if (!This)
3309 return E_OUTOFMEMORY;
3311 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
3312 This->refs = 1;
3313 This->file = INVALID_HANDLE_VALUE;
3314 This->mapping = NULL;
3315 This->typelib_base = NULL;
3317 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3318 if (INVALID_HANDLE_VALUE != This->file)
3320 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
3321 if (This->mapping)
3323 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
3324 if(This->typelib_base)
3326 /* retrieve file size */
3327 *pdwTLBLength = GetFileSize(This->file, NULL);
3328 *ppBase = This->typelib_base;
3329 *ppFile = &This->IUnknown_iface;
3330 return S_OK;
3335 IUnknown_Release(&This->IUnknown_iface);
3336 return TYPE_E_CANTLOADLIBRARY;
3339 /****************************************************************************
3340 * TLB_ReadTypeLib
3342 * find the type of the typelib file and map the typelib resource into
3343 * the memory
3346 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3347 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
3349 ITypeLibImpl *entry;
3350 HRESULT ret;
3351 INT index = 1;
3352 LPWSTR index_str, file = (LPWSTR)pszFileName;
3353 LPVOID pBase = NULL;
3354 DWORD dwTLBLength = 0;
3355 IUnknown *pFile = NULL;
3356 HANDLE h;
3358 *ppTypeLib = NULL;
3360 index_str = strrchrW(pszFileName, '\\');
3361 if(index_str && *++index_str != '\0')
3363 LPWSTR end_ptr;
3364 LONG idx = strtolW(index_str, &end_ptr, 10);
3365 if(*end_ptr == '\0')
3367 int str_len = index_str - pszFileName - 1;
3368 index = idx;
3369 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
3370 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
3371 file[str_len] = 0;
3375 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
3377 if(strchrW(file, '\\'))
3379 lstrcpyW(pszPath, file);
3381 else
3383 int len = GetSystemDirectoryW(pszPath, cchPath);
3384 pszPath[len] = '\\';
3385 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
3389 if(file != pszFileName) heap_free(file);
3391 h = CreateFileW(pszPath, GENERIC_READ, 0, NULL, OPEN_ALWAYS,
3392 FILE_ATTRIBUTE_NORMAL, NULL);
3393 if(h != INVALID_HANDLE_VALUE){
3394 FILE_NAME_INFORMATION *info;
3395 char data[MAX_PATH * sizeof(WCHAR) + sizeof(info->FileNameLength)];
3396 BOOL br;
3398 info = (FILE_NAME_INFORMATION*)data;
3399 /* GetFileInformationByHandleEx returns the path of the file without
3400 * WOW64 redirection */
3401 br = GetFileInformationByHandleEx(h, FileNameInfo, data, sizeof(data));
3402 if(br){
3403 info->FileName[info->FileNameLength / sizeof(WCHAR)] = 0;
3404 lstrcpynW(pszPath + 2, info->FileName, cchPath - 2);
3406 CloseHandle(h);
3409 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
3411 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3412 EnterCriticalSection(&cache_section);
3413 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
3415 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
3417 TRACE("cache hit\n");
3418 *ppTypeLib = &entry->ITypeLib2_iface;
3419 ITypeLib2_AddRef(*ppTypeLib);
3420 LeaveCriticalSection(&cache_section);
3421 return S_OK;
3424 LeaveCriticalSection(&cache_section);
3426 /* now actually load and parse the typelib */
3428 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3429 if (ret == TYPE_E_CANTLOADLIBRARY)
3430 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3431 if (ret == TYPE_E_CANTLOADLIBRARY)
3432 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
3433 if (SUCCEEDED(ret))
3435 if (dwTLBLength >= 4)
3437 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
3438 if (dwSignature == MSFT_SIGNATURE)
3439 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
3440 else if (dwSignature == SLTG_SIGNATURE)
3441 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
3442 else
3444 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
3445 ret = TYPE_E_CANTLOADLIBRARY;
3448 else
3449 ret = TYPE_E_CANTLOADLIBRARY;
3450 IUnknown_Release(pFile);
3453 if(*ppTypeLib) {
3454 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
3456 TRACE("adding to cache\n");
3457 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
3458 lstrcpyW(impl->path, pszPath);
3459 /* We should really canonicalise the path here. */
3460 impl->index = index;
3462 /* FIXME: check if it has added already in the meantime */
3463 EnterCriticalSection(&cache_section);
3464 list_add_head(&tlb_cache, &impl->entry);
3465 LeaveCriticalSection(&cache_section);
3466 ret = S_OK;
3468 else
3470 if(ret != E_FAIL)
3471 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
3473 ret = TYPE_E_CANTLOADLIBRARY;
3477 return ret;
3480 /*================== ITypeLib(2) Methods ===================================*/
3482 static ITypeLibImpl* TypeLibImpl_Constructor(void)
3484 ITypeLibImpl* pTypeLibImpl;
3486 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
3487 if (!pTypeLibImpl) return NULL;
3489 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3490 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3491 pTypeLibImpl->ICreateTypeLib2_iface.lpVtbl = &CreateTypeLib2Vtbl;
3492 pTypeLibImpl->ref = 1;
3494 list_init(&pTypeLibImpl->implib_list);
3495 list_init(&pTypeLibImpl->custdata_list);
3496 list_init(&pTypeLibImpl->name_list);
3497 list_init(&pTypeLibImpl->string_list);
3498 list_init(&pTypeLibImpl->guid_list);
3499 list_init(&pTypeLibImpl->ref_list);
3500 pTypeLibImpl->dispatch_href = -1;
3502 return pTypeLibImpl;
3505 /****************************************************************************
3506 * ITypeLib2_Constructor_MSFT
3508 * loading an MSFT typelib from an in-memory image
3510 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3512 TLBContext cx;
3513 LONG lPSegDir;
3514 MSFT_Header tlbHeader;
3515 MSFT_SegDir tlbSegDir;
3516 ITypeLibImpl * pTypeLibImpl;
3517 int i;
3519 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3521 pTypeLibImpl = TypeLibImpl_Constructor();
3522 if (!pTypeLibImpl) return NULL;
3524 /* get pointer to beginning of typelib data */
3525 cx.pos = 0;
3526 cx.oStart=0;
3527 cx.mapping = pLib;
3528 cx.pLibInfo = pTypeLibImpl;
3529 cx.length = dwTLBLength;
3531 /* read header */
3532 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
3533 TRACE_(typelib)("header:\n");
3534 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3535 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3536 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3537 return NULL;
3539 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3541 /* there is a small amount of information here until the next important
3542 * part:
3543 * the segment directory . Try to calculate the amount of data */
3544 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3546 /* now read the segment directory */
3547 TRACE("read segment directory (at %d)\n",lPSegDir);
3548 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3549 cx.pTblDir = &tlbSegDir;
3551 /* just check two entries */
3552 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3554 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3555 heap_free(pTypeLibImpl);
3556 return NULL;
3559 MSFT_ReadAllNames(&cx);
3560 MSFT_ReadAllStrings(&cx);
3561 MSFT_ReadAllGuids(&cx);
3563 /* now fill our internal data */
3564 /* TLIBATTR fields */
3565 pTypeLibImpl->guid = MSFT_ReadGuid(tlbHeader.posguid, &cx);
3567 pTypeLibImpl->syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3568 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3569 pTypeLibImpl->ver_major = LOWORD(tlbHeader.version);
3570 pTypeLibImpl->ver_minor = HIWORD(tlbHeader.version);
3571 pTypeLibImpl->libflags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
3573 pTypeLibImpl->set_lcid = tlbHeader.lcid2;
3574 pTypeLibImpl->lcid = tlbHeader.lcid;
3576 /* name, eventually add to a hash table */
3577 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3579 /* help info */
3580 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3581 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3583 if( tlbHeader.varflags & HELPDLLFLAG)
3585 int offset;
3586 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3587 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3590 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3592 /* custom data */
3593 if(tlbHeader.CustomDataOffset >= 0)
3595 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3598 /* fill in type descriptions */
3599 if(tlbSegDir.pTypdescTab.length > 0)
3601 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3602 INT16 td[4];
3603 pTypeLibImpl->ctTypeDesc = cTD;
3604 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3605 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3606 for(i=0; i<cTD; )
3608 /* FIXME: add several sanity checks here */
3609 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3610 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3612 /* FIXME: check safearray */
3613 if(td[3] < 0)
3614 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3615 else
3616 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3618 else if(td[0] == VT_CARRAY)
3620 /* array descr table here */
3621 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3623 else if(td[0] == VT_USERDEFINED)
3625 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3627 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3630 /* second time around to fill the array subscript info */
3631 for(i=0;i<cTD;i++)
3633 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3634 if(tlbSegDir.pArrayDescriptions.offset>0)
3636 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3637 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3639 if(td[1]<0)
3640 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3641 else
3642 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3644 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3646 for(j = 0; j<td[2]; j++)
3648 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3649 sizeof(INT), &cx, DO_NOT_SEEK);
3650 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3651 sizeof(INT), &cx, DO_NOT_SEEK);
3654 else
3656 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3657 ERR("didn't find array description data\n");
3662 /* imported type libs */
3663 if(tlbSegDir.pImpFiles.offset>0)
3665 TLBImpLib *pImpLib;
3666 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3667 UINT16 size;
3669 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3671 char *name;
3673 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3674 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3675 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3677 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3678 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3679 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3680 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3682 size >>= 2;
3683 name = heap_alloc_zero(size+1);
3684 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3685 pImpLib->name = TLB_MultiByteToBSTR(name);
3686 heap_free(name);
3688 pImpLib->guid = MSFT_ReadGuid(oGuid, &cx);
3689 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3691 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3695 MSFT_ReadAllRefs(&cx);
3697 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3699 /* type infos */
3700 if(tlbHeader.nrtypeinfos >= 0 )
3702 ITypeInfoImpl **ppTI;
3704 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3706 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3708 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3710 ++ppTI;
3711 (pTypeLibImpl->TypeInfoCount)++;
3715 #ifdef _WIN64
3716 if(pTypeLibImpl->syskind == SYS_WIN32){
3717 for(i = 0; i < pTypeLibImpl->TypeInfoCount; ++i)
3718 TLB_fix_32on64_typeinfo(pTypeLibImpl->typeinfos[i]);
3720 #endif
3722 TRACE("(%p)\n", pTypeLibImpl);
3723 return &pTypeLibImpl->ITypeLib2_iface;
3727 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3729 char b[3];
3730 int i;
3731 short s;
3733 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3734 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3735 return FALSE;
3738 guid->Data4[0] = s >> 8;
3739 guid->Data4[1] = s & 0xff;
3741 b[2] = '\0';
3742 for(i = 0; i < 6; i++) {
3743 memcpy(b, str + 24 + 2 * i, 2);
3744 guid->Data4[i + 2] = strtol(b, NULL, 16);
3746 return TRUE;
3749 static WORD SLTG_ReadString(const char *ptr, const TLBString **pStr, ITypeLibImpl *lib)
3751 WORD bytelen;
3752 DWORD len;
3753 BSTR tmp_str;
3755 *pStr = NULL;
3756 bytelen = *(const WORD*)ptr;
3757 if(bytelen == 0xffff) return 2;
3759 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3760 tmp_str = SysAllocStringLen(NULL, len);
3761 if (tmp_str) {
3762 MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, tmp_str, len);
3763 *pStr = TLB_append_str(&lib->string_list, tmp_str);
3764 SysFreeString(tmp_str);
3766 return bytelen + 2;
3769 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3771 WORD bytelen;
3773 *str = NULL;
3774 bytelen = *(const WORD*)ptr;
3775 if(bytelen == 0xffff) return 2;
3776 *str = heap_alloc(bytelen + 1);
3777 memcpy(*str, ptr + 2, bytelen);
3778 (*str)[bytelen] = '\0';
3779 return bytelen + 2;
3782 static TLBString *SLTG_ReadName(const char *pNameTable, int offset, ITypeLibImpl *lib)
3784 BSTR tmp_str;
3785 TLBString *tlbstr;
3787 LIST_FOR_EACH_ENTRY(tlbstr, &lib->name_list, TLBString, entry) {
3788 if (tlbstr->offset == offset)
3789 return tlbstr;
3792 tmp_str = TLB_MultiByteToBSTR(pNameTable + offset);
3793 tlbstr = TLB_append_str(&lib->name_list, tmp_str);
3794 SysFreeString(tmp_str);
3796 return tlbstr;
3799 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3801 char *ptr = pLibBlk;
3802 WORD w;
3804 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3805 FIXME("libblk magic = %04x\n", w);
3806 return 0;
3809 ptr += 6;
3810 if((w = *(WORD*)ptr) != 0xffff) {
3811 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3812 ptr += w;
3814 ptr += 2;
3816 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString, pTypeLibImpl);
3818 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile, pTypeLibImpl);
3820 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3821 ptr += 4;
3823 pTypeLibImpl->syskind = *(WORD*)ptr;
3824 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3825 ptr += 2;
3827 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3828 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3829 else
3830 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = 0;
3831 ptr += 2;
3833 ptr += 4; /* skip res12 */
3835 pTypeLibImpl->libflags = *(WORD*)ptr;
3836 ptr += 2;
3838 pTypeLibImpl->ver_major = *(WORD*)ptr;
3839 ptr += 2;
3841 pTypeLibImpl->ver_minor = *(WORD*)ptr;
3842 ptr += 2;
3844 pTypeLibImpl->guid = TLB_append_guid(&pTypeLibImpl->guid_list, (GUID*)ptr, -2);
3845 ptr += sizeof(GUID);
3847 return ptr - (char*)pLibBlk;
3850 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3851 typedef struct
3853 unsigned int num;
3854 HREFTYPE refs[1];
3855 } sltg_ref_lookup_t;
3857 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3858 HREFTYPE *typelib_ref)
3860 if(table && typeinfo_ref < table->num)
3862 *typelib_ref = table->refs[typeinfo_ref];
3863 return S_OK;
3866 ERR_(typelib)("Unable to find reference\n");
3867 *typelib_ref = -1;
3868 return E_FAIL;
3871 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3873 BOOL done = FALSE;
3875 while(!done) {
3876 if((*pType & 0xe00) == 0xe00) {
3877 pTD->vt = VT_PTR;
3878 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3879 pTD = pTD->u.lptdesc;
3881 switch(*pType & 0x3f) {
3882 case VT_PTR:
3883 pTD->vt = VT_PTR;
3884 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3885 pTD = pTD->u.lptdesc;
3886 break;
3888 case VT_USERDEFINED:
3889 pTD->vt = VT_USERDEFINED;
3890 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3891 done = TRUE;
3892 break;
3894 case VT_CARRAY:
3896 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3897 array */
3899 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3901 pTD->vt = VT_CARRAY;
3902 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3903 pTD->u.lpadesc->cDims = pSA->cDims;
3904 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3905 pSA->cDims * sizeof(SAFEARRAYBOUND));
3907 pTD = &pTD->u.lpadesc->tdescElem;
3908 break;
3911 case VT_SAFEARRAY:
3913 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3914 useful? */
3916 pType++;
3917 pTD->vt = VT_SAFEARRAY;
3918 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3919 pTD = pTD->u.lptdesc;
3920 break;
3922 default:
3923 pTD->vt = *pType & 0x3f;
3924 done = TRUE;
3925 break;
3927 pType++;
3929 return pType;
3932 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3933 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3935 /* Handle [in/out] first */
3936 if((*pType & 0xc000) == 0xc000)
3937 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3938 else if(*pType & 0x8000)
3939 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3940 else if(*pType & 0x4000)
3941 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3942 else
3943 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3945 if(*pType & 0x2000)
3946 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3948 if(*pType & 0x80)
3949 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3951 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3955 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3956 char *pNameTable)
3958 unsigned int ref;
3959 char *name;
3960 TLBRefType *ref_type;
3961 sltg_ref_lookup_t *table;
3962 HREFTYPE typelib_ref;
3964 if(pRef->magic != SLTG_REF_MAGIC) {
3965 FIXME("Ref magic = %x\n", pRef->magic);
3966 return NULL;
3968 name = ( (char*)pRef->names + pRef->number);
3970 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3971 table->num = pRef->number >> 3;
3973 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3975 /* We don't want the first href to be 0 */
3976 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3978 for(ref = 0; ref < pRef->number >> 3; ref++) {
3979 char *refname;
3980 unsigned int lib_offs, type_num;
3982 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3984 name += SLTG_ReadStringA(name, &refname);
3985 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3986 FIXME_(typelib)("Can't sscanf ref\n");
3987 if(lib_offs != 0xffff) {
3988 TLBImpLib *import;
3990 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
3991 if(import->offset == lib_offs)
3992 break;
3994 if(&import->entry == &pTL->implib_list) {
3995 char fname[MAX_PATH+1];
3996 int len;
3997 GUID tmpguid;
3999 import = heap_alloc_zero(sizeof(*import));
4000 import->offset = lib_offs;
4001 TLB_GUIDFromString( pNameTable + lib_offs + 4, &tmpguid);
4002 import->guid = TLB_append_guid(&pTL->guid_list, &tmpguid, 2);
4003 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
4004 &import->wVersionMajor,
4005 &import->wVersionMinor,
4006 &import->lcid, fname) != 4) {
4007 FIXME_(typelib)("can't sscanf ref %s\n",
4008 pNameTable + lib_offs + 40);
4010 len = strlen(fname);
4011 if(fname[len-1] != '#')
4012 FIXME("fname = %s\n", fname);
4013 fname[len-1] = '\0';
4014 import->name = TLB_MultiByteToBSTR(fname);
4015 list_add_tail(&pTL->implib_list, &import->entry);
4017 ref_type->pImpTLInfo = import;
4019 /* Store a reference to IDispatch */
4020 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid->guid, &IID_StdOle) && type_num == 4)
4021 pTL->dispatch_href = typelib_ref;
4023 } else { /* internal ref */
4024 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
4026 ref_type->reference = typelib_ref;
4027 ref_type->index = type_num;
4029 heap_free(refname);
4030 list_add_tail(&pTL->ref_list, &ref_type->entry);
4032 table->refs[ref] = typelib_ref;
4033 typelib_ref += 4;
4035 if((BYTE)*name != SLTG_REF_MAGIC)
4036 FIXME_(typelib)("End of ref block magic = %x\n", *name);
4037 dump_TLBRefType(pTL);
4038 return table;
4041 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
4042 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
4044 SLTG_ImplInfo *info;
4045 TLBImplType *pImplType;
4046 /* I don't really get this structure, usually it's 0x16 bytes
4047 long, but iuser.tlb contains some that are 0x18 bytes long.
4048 That's ok because we can use the next ptr to jump to the next
4049 one. But how do we know the length of the last one? The WORD
4050 at offs 0x8 might be the clue. For now I'm just assuming that
4051 the last one is the regular 0x16 bytes. */
4053 info = (SLTG_ImplInfo*)pBlk;
4054 while(1){
4055 pTI->cImplTypes++;
4056 if(info->next == 0xffff)
4057 break;
4058 info = (SLTG_ImplInfo*)(pBlk + info->next);
4061 info = (SLTG_ImplInfo*)pBlk;
4062 pTI->impltypes = TLBImplType_Alloc(pTI->cImplTypes);
4063 pImplType = pTI->impltypes;
4064 while(1) {
4065 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
4066 pImplType->implflags = info->impltypeflags;
4067 ++pImplType;
4069 if(info->next == 0xffff)
4070 break;
4071 if(OneOnly)
4072 FIXME_(typelib)("Interface inheriting more than one interface\n");
4073 info = (SLTG_ImplInfo*)(pBlk + info->next);
4075 info++; /* see comment at top of function */
4076 return (char*)info;
4079 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
4080 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4082 TLBVarDesc *pVarDesc;
4083 const TLBString *prevName = NULL;
4084 SLTG_Variable *pItem;
4085 unsigned short i;
4086 WORD *pType;
4088 pVarDesc = pTI->vardescs = TLBVarDesc_Alloc(cVars);
4090 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
4091 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
4093 pVarDesc->vardesc.memid = pItem->memid;
4095 if (pItem->magic != SLTG_VAR_MAGIC &&
4096 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
4097 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
4098 return;
4101 if (pItem->name == 0xfffe)
4102 pVarDesc->Name = prevName;
4103 else
4104 pVarDesc->Name = SLTG_ReadName(pNameTable, pItem->name, pTI->pTypeLib);
4106 TRACE_(typelib)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc->Name)));
4107 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
4108 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
4110 if(pItem->flags & 0x02)
4111 pType = &pItem->type;
4112 else
4113 pType = (WORD*)(pBlk + pItem->type);
4115 if (pItem->flags & ~0xda)
4116 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
4118 SLTG_DoElem(pType, pBlk,
4119 &pVarDesc->vardesc.elemdescVar, ref_lookup);
4121 if (TRACE_ON(typelib)) {
4122 char buf[300];
4123 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
4124 TRACE_(typelib)("elemdescVar: %s\n", buf);
4127 if (pItem->flags & 0x40) {
4128 TRACE_(typelib)("VAR_DISPATCH\n");
4129 pVarDesc->vardesc.varkind = VAR_DISPATCH;
4131 else if (pItem->flags & 0x10) {
4132 TRACE_(typelib)("VAR_CONST\n");
4133 pVarDesc->vardesc.varkind = VAR_CONST;
4134 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
4135 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
4136 if (pItem->flags & 0x08)
4137 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
4138 else {
4139 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
4141 case VT_LPSTR:
4142 case VT_LPWSTR:
4143 case VT_BSTR:
4145 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
4146 BSTR str;
4147 TRACE_(typelib)("len = %u\n", len);
4148 if (len == 0xffff) {
4149 str = NULL;
4150 } else {
4151 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
4152 str = SysAllocStringLen(NULL, alloc_len);
4153 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
4155 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
4156 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
4157 break;
4159 case VT_I2:
4160 case VT_UI2:
4161 case VT_I4:
4162 case VT_UI4:
4163 case VT_INT:
4164 case VT_UINT:
4165 V_INT(pVarDesc->vardesc.u.lpvarValue) =
4166 *(INT*)(pBlk + pItem->byte_offs);
4167 break;
4168 default:
4169 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
4173 else {
4174 TRACE_(typelib)("VAR_PERINSTANCE\n");
4175 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
4176 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
4179 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
4180 pVarDesc->vardesc.wVarFlags = pItem->varflags;
4182 if (pItem->flags & 0x80)
4183 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
4185 prevName = pVarDesc->Name;
4187 pTI->cVars = cVars;
4190 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
4191 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4193 SLTG_Function *pFunc;
4194 unsigned short i;
4195 TLBFuncDesc *pFuncDesc;
4197 pTI->funcdescs = TLBFuncDesc_Alloc(cFuncs);
4199 pFuncDesc = pTI->funcdescs;
4200 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
4201 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
4203 int param;
4204 WORD *pType, *pArg;
4206 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
4207 case SLTG_FUNCTION_MAGIC:
4208 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
4209 break;
4210 case SLTG_DISPATCH_FUNCTION_MAGIC:
4211 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
4212 break;
4213 case SLTG_STATIC_FUNCTION_MAGIC:
4214 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
4215 break;
4216 default:
4217 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
4218 continue;
4220 pFuncDesc->Name = SLTG_ReadName(pNameTable, pFunc->name, pTI->pTypeLib);
4222 pFuncDesc->funcdesc.memid = pFunc->dispid;
4223 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
4224 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
4225 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
4226 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
4227 pFuncDesc->funcdesc.oVft = pFunc->vtblpos & ~1;
4229 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
4230 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
4232 if(pFunc->retnextopt & 0x80)
4233 pType = &pFunc->rettype;
4234 else
4235 pType = (WORD*)(pBlk + pFunc->rettype);
4237 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
4239 pFuncDesc->funcdesc.lprgelemdescParam =
4240 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
4241 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
4243 pArg = (WORD*)(pBlk + pFunc->arg_off);
4245 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
4246 char *paramName = pNameTable + *pArg;
4247 BOOL HaveOffs;
4248 /* If arg type follows then paramName points to the 2nd
4249 letter of the name, else the next WORD is an offset to
4250 the arg type and paramName points to the first letter.
4251 So let's take one char off paramName and see if we're
4252 pointing at an alpha-numeric char. However if *pArg is
4253 0xffff or 0xfffe then the param has no name, the former
4254 meaning that the next WORD is the type, the latter
4255 meaning that the next WORD is an offset to the type. */
4257 HaveOffs = FALSE;
4258 if(*pArg == 0xffff)
4259 paramName = NULL;
4260 else if(*pArg == 0xfffe) {
4261 paramName = NULL;
4262 HaveOffs = TRUE;
4264 else if(paramName[-1] && !isalnum(paramName[-1]))
4265 HaveOffs = TRUE;
4267 pArg++;
4269 if(HaveOffs) { /* the next word is an offset to type */
4270 pType = (WORD*)(pBlk + *pArg);
4271 SLTG_DoElem(pType, pBlk,
4272 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4273 pArg++;
4274 } else {
4275 if(paramName)
4276 paramName--;
4277 pArg = SLTG_DoElem(pArg, pBlk,
4278 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4281 /* Are we an optional param ? */
4282 if(pFuncDesc->funcdesc.cParams - param <=
4283 pFuncDesc->funcdesc.cParamsOpt)
4284 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
4286 if(paramName) {
4287 pFuncDesc->pParamDesc[param].Name = SLTG_ReadName(pNameTable,
4288 paramName - pNameTable, pTI->pTypeLib);
4289 } else {
4290 pFuncDesc->pParamDesc[param].Name = pFuncDesc->Name;
4294 pTI->cFuncs = cFuncs;
4297 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
4298 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4299 SLTG_TypeInfoTail *pTITail)
4301 char *pFirstItem;
4302 sltg_ref_lookup_t *ref_lookup = NULL;
4304 if(pTIHeader->href_table != 0xffffffff) {
4305 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4306 pNameTable);
4309 pFirstItem = pBlk;
4311 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4312 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
4314 heap_free(ref_lookup);
4318 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
4319 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4320 const 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, TRUE, ref_lookup);
4336 if (pTITail->funcs_off != 0xffff)
4337 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4339 heap_free(ref_lookup);
4341 if (TRACE_ON(typelib))
4342 dump_TLBFuncDesc(pTI->funcdescs, pTI->cFuncs);
4345 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
4346 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4347 const SLTG_TypeInfoTail *pTITail)
4349 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4352 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
4353 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4354 const SLTG_TypeInfoTail *pTITail)
4356 WORD *pType;
4357 sltg_ref_lookup_t *ref_lookup = NULL;
4359 if (pTITail->simple_alias) {
4360 /* if simple alias, no more processing required */
4361 pTI->tdescAlias = heap_alloc_zero(sizeof(TYPEDESC));
4362 pTI->tdescAlias->vt = pTITail->tdescalias_vt;
4363 return;
4366 if(pTIHeader->href_table != 0xffffffff) {
4367 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4368 pNameTable);
4371 /* otherwise it is an offset to a type */
4372 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
4374 pTI->tdescAlias = heap_alloc(sizeof(TYPEDESC));
4375 SLTG_DoType(pType, pBlk, pTI->tdescAlias, ref_lookup);
4377 heap_free(ref_lookup);
4380 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
4381 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4382 const SLTG_TypeInfoTail *pTITail)
4384 sltg_ref_lookup_t *ref_lookup = NULL;
4385 if (pTIHeader->href_table != 0xffffffff)
4386 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4387 pNameTable);
4389 if (pTITail->vars_off != 0xffff)
4390 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4392 if (pTITail->funcs_off != 0xffff)
4393 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4395 if (pTITail->impls_off != 0xffff)
4396 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
4398 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4399 * of dispinterface functions including the IDispatch ones, so
4400 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4401 pTI->cbSizeVft = pTI->cFuncs * pTI->pTypeLib->ptr_size;
4403 heap_free(ref_lookup);
4404 if (TRACE_ON(typelib))
4405 dump_TLBFuncDesc(pTI->funcdescs, pTI->cFuncs);
4408 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
4409 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4410 const SLTG_TypeInfoTail *pTITail)
4412 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4415 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
4416 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4417 const SLTG_TypeInfoTail *pTITail)
4419 sltg_ref_lookup_t *ref_lookup = NULL;
4420 if (pTIHeader->href_table != 0xffffffff)
4421 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4422 pNameTable);
4424 if (pTITail->vars_off != 0xffff)
4425 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4427 if (pTITail->funcs_off != 0xffff)
4428 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4429 heap_free(ref_lookup);
4430 if (TRACE_ON(typelib))
4431 dump_TypeInfo(pTI);
4434 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4435 manageable copy of it into this */
4436 typedef struct {
4437 WORD small_no;
4438 char *index_name;
4439 char *other_name;
4440 WORD res1a;
4441 WORD name_offs;
4442 WORD more_bytes;
4443 char *extra;
4444 WORD res20;
4445 DWORD helpcontext;
4446 WORD res26;
4447 GUID uuid;
4448 } SLTG_InternalOtherTypeInfo;
4450 /****************************************************************************
4451 * ITypeLib2_Constructor_SLTG
4453 * loading a SLTG typelib from an in-memory image
4455 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
4457 ITypeLibImpl *pTypeLibImpl;
4458 SLTG_Header *pHeader;
4459 SLTG_BlkEntry *pBlkEntry;
4460 SLTG_Magic *pMagic;
4461 SLTG_Index *pIndex;
4462 SLTG_Pad9 *pPad9;
4463 LPVOID pBlk, pFirstBlk;
4464 SLTG_LibBlk *pLibBlk;
4465 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
4466 char *pAfterOTIBlks = NULL;
4467 char *pNameTable, *ptr;
4468 int i;
4469 DWORD len, order;
4470 ITypeInfoImpl **ppTypeInfoImpl;
4472 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
4475 pTypeLibImpl = TypeLibImpl_Constructor();
4476 if (!pTypeLibImpl) return NULL;
4478 pHeader = pLib;
4480 TRACE_(typelib)("header:\n");
4481 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
4482 pHeader->nrOfFileBlks );
4483 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
4484 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
4485 pHeader->SLTG_magic);
4486 return NULL;
4489 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4490 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
4492 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4493 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
4495 /* Next we have a magic block */
4496 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
4498 /* Let's see if we're still in sync */
4499 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
4500 sizeof(SLTG_COMPOBJ_MAGIC))) {
4501 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
4502 return NULL;
4504 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
4505 sizeof(SLTG_DIR_MAGIC))) {
4506 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
4507 return NULL;
4510 pIndex = (SLTG_Index*)(pMagic+1);
4512 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
4514 pFirstBlk = pPad9 + 1;
4516 /* We'll set up a ptr to the main library block, which is the last one. */
4518 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4519 pBlkEntry[order].next != 0;
4520 order = pBlkEntry[order].next - 1, i++) {
4521 pBlk = (char*)pBlk + pBlkEntry[order].len;
4523 pLibBlk = pBlk;
4525 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
4527 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4528 interspersed */
4530 len += 0x40;
4532 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4534 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
4537 ptr = (char*)pLibBlk + len;
4539 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4540 WORD w, extra;
4541 len = 0;
4543 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
4545 w = *(WORD*)(ptr + 2);
4546 if(w != 0xffff) {
4547 len += w;
4548 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
4549 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4550 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4552 w = *(WORD*)(ptr + 4 + len);
4553 if(w != 0xffff) {
4554 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4555 len += w;
4556 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4557 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4558 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4560 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4561 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4562 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4563 if(extra) {
4564 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4565 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4566 len += extra;
4568 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4569 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4570 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4571 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4572 len += sizeof(SLTG_OtherTypeInfo);
4573 ptr += len;
4576 pAfterOTIBlks = ptr;
4578 /* Skip this WORD and get the next DWORD */
4579 len = *(DWORD*)(pAfterOTIBlks + 2);
4581 /* Now add this to pLibBLk look at what we're pointing at and
4582 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4583 dust and we should be pointing at the beginning of the name
4584 table */
4586 pNameTable = (char*)pLibBlk + len;
4588 switch(*(WORD*)pNameTable) {
4589 case 0xffff:
4590 break;
4591 case 0x0200:
4592 pNameTable += 0x20;
4593 break;
4594 default:
4595 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4596 break;
4599 pNameTable += 0x216;
4601 pNameTable += 2;
4603 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4605 pTypeLibImpl->Name = SLTG_ReadName(pNameTable, pLibBlk->name, pTypeLibImpl);
4608 /* Hopefully we now have enough ptrs set up to actually read in
4609 some TypeInfos. It's not clear which order to do them in, so
4610 I'll just follow the links along the BlkEntry chain and read
4611 them in the order in which they are in the file */
4613 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4614 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4616 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4617 pBlkEntry[order].next != 0;
4618 order = pBlkEntry[order].next - 1, i++) {
4620 SLTG_TypeInfoHeader *pTIHeader;
4621 SLTG_TypeInfoTail *pTITail;
4622 SLTG_MemberHeader *pMemHeader;
4624 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4625 FIXME_(typelib)("Index strings don't match\n");
4626 heap_free(pOtherTypeInfoBlks);
4627 return NULL;
4630 pTIHeader = pBlk;
4631 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4632 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4633 heap_free(pOtherTypeInfoBlks);
4634 return NULL;
4636 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4637 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4638 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4640 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4641 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4642 (*ppTypeInfoImpl)->index = i;
4643 (*ppTypeInfoImpl)->Name = SLTG_ReadName(pNameTable, pOtherTypeInfoBlks[i].name_offs, pTypeLibImpl);
4644 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4645 (*ppTypeInfoImpl)->guid = TLB_append_guid(&pTypeLibImpl->guid_list, &pOtherTypeInfoBlks[i].uuid, 2);
4646 (*ppTypeInfoImpl)->typekind = pTIHeader->typekind;
4647 (*ppTypeInfoImpl)->wMajorVerNum = pTIHeader->major_version;
4648 (*ppTypeInfoImpl)->wMinorVerNum = pTIHeader->minor_version;
4649 (*ppTypeInfoImpl)->wTypeFlags =
4650 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4652 if((*ppTypeInfoImpl)->wTypeFlags & TYPEFLAG_FDUAL)
4653 (*ppTypeInfoImpl)->typekind = TKIND_DISPATCH;
4655 if((pTIHeader->typeflags1 & 7) != 2)
4656 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4657 if(pTIHeader->typeflags3 != 2)
4658 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4660 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4661 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl)->Name)),
4662 typekind_desc[pTIHeader->typekind],
4663 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl)->guid)),
4664 (*ppTypeInfoImpl)->wTypeFlags);
4666 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4668 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4670 (*ppTypeInfoImpl)->cbAlignment = pTITail->cbAlignment;
4671 (*ppTypeInfoImpl)->cbSizeInstance = pTITail->cbSizeInstance;
4672 (*ppTypeInfoImpl)->cbSizeVft = pTITail->cbSizeVft;
4674 switch(pTIHeader->typekind) {
4675 case TKIND_ENUM:
4676 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4677 pTIHeader, pTITail);
4678 break;
4680 case TKIND_RECORD:
4681 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4682 pTIHeader, pTITail);
4683 break;
4685 case TKIND_INTERFACE:
4686 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4687 pTIHeader, pTITail);
4688 break;
4690 case TKIND_COCLASS:
4691 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4692 pTIHeader, pTITail);
4693 break;
4695 case TKIND_ALIAS:
4696 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4697 pTIHeader, pTITail);
4698 break;
4700 case TKIND_DISPATCH:
4701 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4702 pTIHeader, pTITail);
4703 break;
4705 case TKIND_MODULE:
4706 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4707 pTIHeader, pTITail);
4708 break;
4710 default:
4711 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4712 break;
4716 /* could get cFuncs, cVars and cImplTypes from here
4717 but we've already set those */
4718 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4719 X(06);
4720 X(16);
4721 X(18);
4722 X(1a);
4723 X(1e);
4724 X(24);
4725 X(26);
4726 X(2a);
4727 X(2c);
4728 X(2e);
4729 X(30);
4730 X(32);
4731 X(34);
4732 #undef X
4733 ++ppTypeInfoImpl;
4734 pBlk = (char*)pBlk + pBlkEntry[order].len;
4737 if(i != pTypeLibImpl->TypeInfoCount) {
4738 FIXME("Somehow processed %d TypeInfos\n", i);
4739 heap_free(pOtherTypeInfoBlks);
4740 return NULL;
4743 heap_free(pOtherTypeInfoBlks);
4744 return &pTypeLibImpl->ITypeLib2_iface;
4747 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4749 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4751 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4753 if(IsEqualIID(riid, &IID_IUnknown) ||
4754 IsEqualIID(riid,&IID_ITypeLib)||
4755 IsEqualIID(riid,&IID_ITypeLib2))
4757 *ppv = &This->ITypeLib2_iface;
4759 else if(IsEqualIID(riid, &IID_ICreateTypeLib) ||
4760 IsEqualIID(riid, &IID_ICreateTypeLib2))
4762 *ppv = &This->ICreateTypeLib2_iface;
4764 else
4766 *ppv = NULL;
4767 TRACE("-- Interface: E_NOINTERFACE\n");
4768 return E_NOINTERFACE;
4771 IUnknown_AddRef((IUnknown*)*ppv);
4772 return S_OK;
4775 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4777 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4778 ULONG ref = InterlockedIncrement(&This->ref);
4780 TRACE("(%p) ref=%u\n", This, ref);
4782 return ref;
4785 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4787 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4788 ULONG ref = InterlockedDecrement(&This->ref);
4790 TRACE("(%p) ref=%u\n",This, ref);
4792 if (!ref)
4794 TLBImpLib *pImpLib, *pImpLibNext;
4795 TLBRefType *ref_type;
4796 TLBString *tlbstr, *tlbstr_next;
4797 TLBGuid *tlbguid, *tlbguid_next;
4798 void *cursor2;
4799 int i;
4801 /* remove cache entry */
4802 if(This->path)
4804 TRACE("removing from cache list\n");
4805 EnterCriticalSection(&cache_section);
4806 if(This->entry.next)
4807 list_remove(&This->entry);
4808 LeaveCriticalSection(&cache_section);
4809 heap_free(This->path);
4811 TRACE(" destroying ITypeLib(%p)\n",This);
4813 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->string_list, TLBString, entry) {
4814 list_remove(&tlbstr->entry);
4815 SysFreeString(tlbstr->str);
4816 heap_free(tlbstr);
4819 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->name_list, TLBString, entry) {
4820 list_remove(&tlbstr->entry);
4821 SysFreeString(tlbstr->str);
4822 heap_free(tlbstr);
4825 LIST_FOR_EACH_ENTRY_SAFE(tlbguid, tlbguid_next, &This->guid_list, TLBGuid, entry) {
4826 list_remove(&tlbguid->entry);
4827 heap_free(tlbguid);
4830 TLB_FreeCustData(&This->custdata_list);
4832 for (i = 0; i < This->ctTypeDesc; i++)
4833 if (This->pTypeDesc[i].vt == VT_CARRAY)
4834 heap_free(This->pTypeDesc[i].u.lpadesc);
4836 heap_free(This->pTypeDesc);
4838 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4840 if (pImpLib->pImpTypeLib)
4841 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4842 SysFreeString(pImpLib->name);
4844 list_remove(&pImpLib->entry);
4845 heap_free(pImpLib);
4848 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4850 list_remove(&ref_type->entry);
4851 heap_free(ref_type);
4854 for (i = 0; i < This->TypeInfoCount; ++i){
4855 heap_free(This->typeinfos[i]->tdescAlias);
4856 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4858 heap_free(This->typeinfos);
4859 heap_free(This);
4860 return 0;
4863 return ref;
4866 /* ITypeLib::GetTypeInfoCount
4868 * Returns the number of type descriptions in the type library
4870 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4872 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4873 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4874 return This->TypeInfoCount;
4877 /* ITypeLib::GetTypeInfo
4879 * retrieves the specified type description in the library.
4881 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4882 ITypeLib2 *iface,
4883 UINT index,
4884 ITypeInfo **ppTInfo)
4886 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4888 TRACE("%p %u %p\n", This, index, ppTInfo);
4890 if(!ppTInfo)
4891 return E_INVALIDARG;
4893 if(index >= This->TypeInfoCount)
4894 return TYPE_E_ELEMENTNOTFOUND;
4896 *ppTInfo = (ITypeInfo *)&This->typeinfos[index]->ITypeInfo2_iface;
4897 ITypeInfo_AddRef(*ppTInfo);
4899 return S_OK;
4903 /* ITypeLibs::GetTypeInfoType
4905 * Retrieves the type of a type description.
4907 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4908 ITypeLib2 *iface,
4909 UINT index,
4910 TYPEKIND *pTKind)
4912 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4914 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4916 if(!pTKind)
4917 return E_INVALIDARG;
4919 if(index >= This->TypeInfoCount)
4920 return TYPE_E_ELEMENTNOTFOUND;
4922 *pTKind = This->typeinfos[index]->typekind;
4924 return S_OK;
4927 /* ITypeLib::GetTypeInfoOfGuid
4929 * Retrieves the type description that corresponds to the specified GUID.
4932 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4933 ITypeLib2 *iface,
4934 REFGUID guid,
4935 ITypeInfo **ppTInfo)
4937 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4938 int i;
4940 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4942 for(i = 0; i < This->TypeInfoCount; ++i){
4943 if(IsEqualIID(TLB_get_guid_null(This->typeinfos[i]->guid), guid)){
4944 *ppTInfo = (ITypeInfo *)&This->typeinfos[i]->ITypeInfo2_iface;
4945 ITypeInfo_AddRef(*ppTInfo);
4946 return S_OK;
4950 return TYPE_E_ELEMENTNOTFOUND;
4953 /* ITypeLib::GetLibAttr
4955 * Retrieves the structure that contains the library's attributes.
4958 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4959 ITypeLib2 *iface,
4960 LPTLIBATTR *attr)
4962 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4964 TRACE("(%p, %p)\n", This, attr);
4966 if (!attr) return E_INVALIDARG;
4968 *attr = heap_alloc(sizeof(**attr));
4969 if (!*attr) return E_OUTOFMEMORY;
4971 (*attr)->guid = *TLB_get_guid_null(This->guid);
4972 (*attr)->lcid = This->set_lcid;
4973 (*attr)->syskind = This->syskind;
4974 (*attr)->wMajorVerNum = This->ver_major;
4975 (*attr)->wMinorVerNum = This->ver_minor;
4976 (*attr)->wLibFlags = This->libflags;
4978 return S_OK;
4981 /* ITypeLib::GetTypeComp
4983 * Enables a client compiler to bind to a library's types, variables,
4984 * constants, and global functions.
4987 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4988 ITypeLib2 *iface,
4989 ITypeComp **ppTComp)
4991 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4993 TRACE("(%p)->(%p)\n",This,ppTComp);
4994 *ppTComp = &This->ITypeComp_iface;
4995 ITypeComp_AddRef(*ppTComp);
4997 return S_OK;
5000 /* ITypeLib::GetDocumentation
5002 * Retrieves the library's documentation string, the complete Help file name
5003 * and path, and the context identifier for the library Help topic in the Help
5004 * file.
5006 * On a successful return all non-null BSTR pointers will have been set,
5007 * possibly to NULL.
5009 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
5010 ITypeLib2 *iface,
5011 INT index,
5012 BSTR *pBstrName,
5013 BSTR *pBstrDocString,
5014 DWORD *pdwHelpContext,
5015 BSTR *pBstrHelpFile)
5017 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5018 HRESULT result = E_INVALIDARG;
5019 ITypeInfo *pTInfo;
5021 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
5022 This, index,
5023 pBstrName, pBstrDocString,
5024 pdwHelpContext, pBstrHelpFile);
5026 if(index<0)
5028 /* documentation for the typelib */
5029 if(pBstrName)
5031 if (This->Name)
5033 if(!(*pBstrName = SysAllocString(TLB_get_bstr(This->Name))))
5034 goto memerr1;
5036 else
5037 *pBstrName = NULL;
5039 if(pBstrDocString)
5041 if (This->DocString)
5043 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->DocString))))
5044 goto memerr2;
5046 else
5047 *pBstrDocString = NULL;
5049 if(pdwHelpContext)
5051 *pdwHelpContext = This->dwHelpContext;
5053 if(pBstrHelpFile)
5055 if (This->HelpFile)
5057 if(!(*pBstrHelpFile = SysAllocString(TLB_get_bstr(This->HelpFile))))
5058 goto memerr3;
5060 else
5061 *pBstrHelpFile = NULL;
5064 result = S_OK;
5066 else
5068 /* for a typeinfo */
5069 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
5071 if(SUCCEEDED(result))
5073 result = ITypeInfo_GetDocumentation(pTInfo,
5074 MEMBERID_NIL,
5075 pBstrName,
5076 pBstrDocString,
5077 pdwHelpContext, pBstrHelpFile);
5079 ITypeInfo_Release(pTInfo);
5082 return result;
5083 memerr3:
5084 if (pBstrDocString) SysFreeString (*pBstrDocString);
5085 memerr2:
5086 if (pBstrName) SysFreeString (*pBstrName);
5087 memerr1:
5088 return STG_E_INSUFFICIENTMEMORY;
5091 /* ITypeLib::IsName
5093 * Indicates whether a passed-in string contains the name of a type or member
5094 * described in the library.
5097 static HRESULT WINAPI ITypeLib2_fnIsName(
5098 ITypeLib2 *iface,
5099 LPOLESTR szNameBuf,
5100 ULONG lHashVal,
5101 BOOL *pfName)
5103 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5104 int tic;
5105 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
5107 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
5108 pfName);
5110 *pfName=TRUE;
5111 for(tic = 0; tic < This->TypeInfoCount; ++tic){
5112 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5113 if(!TLB_str_memcmp(szNameBuf, pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5114 for(fdc = 0; fdc < pTInfo->cFuncs; ++fdc) {
5115 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
5116 int pc;
5117 if(!TLB_str_memcmp(szNameBuf, pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5118 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++){
5119 if(!TLB_str_memcmp(szNameBuf, pFInfo->pParamDesc[pc].Name, nNameBufLen))
5120 goto ITypeLib2_fnIsName_exit;
5123 for(vrc = 0; vrc < pTInfo->cVars; ++vrc){
5124 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
5125 if(!TLB_str_memcmp(szNameBuf, pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5129 *pfName=FALSE;
5131 ITypeLib2_fnIsName_exit:
5132 TRACE("(%p)slow! search for %s: %sfound!\n", This,
5133 debugstr_w(szNameBuf), *pfName ? "" : "NOT ");
5135 return S_OK;
5138 /* ITypeLib::FindName
5140 * Finds occurrences of a type description in a type library. This may be used
5141 * to quickly verify that a name exists in a type library.
5144 static HRESULT WINAPI ITypeLib2_fnFindName(
5145 ITypeLib2 *iface,
5146 LPOLESTR name,
5147 ULONG hash,
5148 ITypeInfo **ppTInfo,
5149 MEMBERID *memid,
5150 UINT16 *found)
5152 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5153 int tic;
5154 UINT count = 0;
5155 UINT len;
5157 TRACE("(%p)->(%s %u %p %p %p)\n", This, debugstr_w(name), hash, ppTInfo, memid, found);
5159 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
5160 return E_INVALIDARG;
5162 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
5163 for(tic = 0; tic < This->TypeInfoCount; ++tic) {
5164 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5165 TLBVarDesc *var;
5166 UINT fdc;
5168 if(!TLB_str_memcmp(name, pTInfo->Name, len)) goto ITypeLib2_fnFindName_exit;
5169 for(fdc = 0; fdc < pTInfo->cFuncs; ++fdc) {
5170 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
5171 int pc;
5173 if(!TLB_str_memcmp(name, func->Name, len)) goto ITypeLib2_fnFindName_exit;
5174 for(pc = 0; pc < func->funcdesc.cParams; pc++) {
5175 if(!TLB_str_memcmp(name, func->pParamDesc[pc].Name, len))
5176 goto ITypeLib2_fnFindName_exit;
5180 var = TLB_get_vardesc_by_name(pTInfo->vardescs, pTInfo->cVars, name);
5181 if (var)
5182 goto ITypeLib2_fnFindName_exit;
5184 continue;
5185 ITypeLib2_fnFindName_exit:
5186 ITypeInfo2_AddRef(&pTInfo->ITypeInfo2_iface);
5187 ppTInfo[count] = (ITypeInfo *)&pTInfo->ITypeInfo2_iface;
5188 count++;
5190 TRACE("found %d typeinfos\n", count);
5192 *found = count;
5194 return S_OK;
5197 /* ITypeLib::ReleaseTLibAttr
5199 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5202 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
5203 ITypeLib2 *iface,
5204 TLIBATTR *pTLibAttr)
5206 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5207 TRACE("(%p)->(%p)\n", This, pTLibAttr);
5208 heap_free(pTLibAttr);
5211 /* ITypeLib2::GetCustData
5213 * gets the custom data
5215 static HRESULT WINAPI ITypeLib2_fnGetCustData(
5216 ITypeLib2 * iface,
5217 REFGUID guid,
5218 VARIANT *pVarVal)
5220 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5221 TLBCustData *pCData;
5223 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
5225 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
5226 if(!pCData)
5227 return TYPE_E_ELEMENTNOTFOUND;
5229 VariantInit(pVarVal);
5230 VariantCopy(pVarVal, &pCData->data);
5232 return S_OK;
5235 /* ITypeLib2::GetLibStatistics
5237 * Returns statistics about a type library that are required for efficient
5238 * sizing of hash tables.
5241 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
5242 ITypeLib2 * iface,
5243 ULONG *pcUniqueNames,
5244 ULONG *pcchUniqueNames)
5246 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5248 FIXME("(%p): stub!\n", This);
5250 if(pcUniqueNames) *pcUniqueNames=1;
5251 if(pcchUniqueNames) *pcchUniqueNames=1;
5252 return S_OK;
5255 /* ITypeLib2::GetDocumentation2
5257 * Retrieves the library's documentation string, the complete Help file name
5258 * and path, the localization context to use, and the context ID for the
5259 * library Help topic in the Help file.
5262 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
5263 ITypeLib2 * iface,
5264 INT index,
5265 LCID lcid,
5266 BSTR *pbstrHelpString,
5267 DWORD *pdwHelpStringContext,
5268 BSTR *pbstrHelpStringDll)
5270 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5271 HRESULT result;
5272 ITypeInfo *pTInfo;
5274 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
5276 /* the help string should be obtained from the helpstringdll,
5277 * using the _DLLGetDocumentation function, based on the supplied
5278 * lcid. Nice to do sometime...
5280 if(index<0)
5282 /* documentation for the typelib */
5283 if(pbstrHelpString)
5284 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->DocString));
5285 if(pdwHelpStringContext)
5286 *pdwHelpStringContext=This->dwHelpContext;
5287 if(pbstrHelpStringDll)
5288 *pbstrHelpStringDll=SysAllocString(TLB_get_bstr(This->HelpStringDll));
5290 result = S_OK;
5292 else
5294 /* for a typeinfo */
5295 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
5297 if(SUCCEEDED(result))
5299 ITypeInfo2 * pTInfo2;
5300 result = ITypeInfo_QueryInterface(pTInfo,
5301 &IID_ITypeInfo2,
5302 (LPVOID*) &pTInfo2);
5304 if(SUCCEEDED(result))
5306 result = ITypeInfo2_GetDocumentation2(pTInfo2,
5307 MEMBERID_NIL,
5308 lcid,
5309 pbstrHelpString,
5310 pdwHelpStringContext,
5311 pbstrHelpStringDll);
5313 ITypeInfo2_Release(pTInfo2);
5316 ITypeInfo_Release(pTInfo);
5319 return result;
5322 static HRESULT TLB_copy_all_custdata(struct list *custdata_list, CUSTDATA *pCustData)
5324 TLBCustData *pCData;
5325 unsigned int ct;
5326 CUSTDATAITEM *cdi;
5328 ct = list_count(custdata_list);
5330 pCustData->prgCustData = heap_alloc_zero(ct * sizeof(CUSTDATAITEM));
5331 if(!pCustData->prgCustData)
5332 return E_OUTOFMEMORY;
5334 pCustData->cCustData = ct;
5336 cdi = pCustData->prgCustData;
5337 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
5338 cdi->guid = *TLB_get_guid_null(pCData->guid);
5339 VariantCopy(&cdi->varValue, &pCData->data);
5340 ++cdi;
5343 return S_OK;
5347 /* ITypeLib2::GetAllCustData
5349 * Gets all custom data items for the library.
5352 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
5353 ITypeLib2 * iface,
5354 CUSTDATA *pCustData)
5356 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5357 TRACE("(%p)->(%p)\n", This, pCustData);
5358 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
5361 static const ITypeLib2Vtbl tlbvt = {
5362 ITypeLib2_fnQueryInterface,
5363 ITypeLib2_fnAddRef,
5364 ITypeLib2_fnRelease,
5365 ITypeLib2_fnGetTypeInfoCount,
5366 ITypeLib2_fnGetTypeInfo,
5367 ITypeLib2_fnGetTypeInfoType,
5368 ITypeLib2_fnGetTypeInfoOfGuid,
5369 ITypeLib2_fnGetLibAttr,
5370 ITypeLib2_fnGetTypeComp,
5371 ITypeLib2_fnGetDocumentation,
5372 ITypeLib2_fnIsName,
5373 ITypeLib2_fnFindName,
5374 ITypeLib2_fnReleaseTLibAttr,
5376 ITypeLib2_fnGetCustData,
5377 ITypeLib2_fnGetLibStatistics,
5378 ITypeLib2_fnGetDocumentation2,
5379 ITypeLib2_fnGetAllCustData
5383 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5385 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5387 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
5390 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
5392 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5394 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
5397 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
5399 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5401 return ITypeLib2_Release(&This->ITypeLib2_iface);
5404 static HRESULT WINAPI ITypeLibComp_fnBind(
5405 ITypeComp * iface,
5406 OLECHAR * szName,
5407 ULONG lHash,
5408 WORD wFlags,
5409 ITypeInfo ** ppTInfo,
5410 DESCKIND * pDescKind,
5411 BINDPTR * pBindPtr)
5413 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5414 int typemismatch=0, i;
5416 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5418 *pDescKind = DESCKIND_NONE;
5419 pBindPtr->lptcomp = NULL;
5420 *ppTInfo = NULL;
5422 for(i = 0; i < This->TypeInfoCount; ++i){
5423 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5424 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo->Name)));
5426 /* FIXME: check wFlags here? */
5427 /* FIXME: we should use a hash table to look this info up using lHash
5428 * instead of an O(n) search */
5429 if ((pTypeInfo->typekind == TKIND_ENUM) ||
5430 (pTypeInfo->typekind == TKIND_MODULE))
5432 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name->str, szName))
5434 *pDescKind = DESCKIND_TYPECOMP;
5435 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
5436 ITypeComp_AddRef(pBindPtr->lptcomp);
5437 TRACE("module or enum: %s\n", debugstr_w(szName));
5438 return S_OK;
5442 if ((pTypeInfo->typekind == TKIND_MODULE) ||
5443 (pTypeInfo->typekind == TKIND_ENUM))
5445 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5446 HRESULT hr;
5448 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5449 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
5451 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
5452 return S_OK;
5454 else if (hr == TYPE_E_TYPEMISMATCH)
5455 typemismatch = 1;
5458 if ((pTypeInfo->typekind == TKIND_COCLASS) &&
5459 (pTypeInfo->wTypeFlags & TYPEFLAG_FAPPOBJECT))
5461 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5462 HRESULT hr;
5463 ITypeInfo *subtypeinfo;
5464 BINDPTR subbindptr;
5465 DESCKIND subdesckind;
5467 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
5468 &subtypeinfo, &subdesckind, &subbindptr);
5469 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
5471 TYPEDESC tdesc_appobject;
5472 const VARDESC vardesc_appobject =
5474 -2, /* memid */
5475 NULL, /* lpstrSchema */
5477 0 /* oInst */
5480 /* ELEMDESC */
5482 /* TYPEDESC */
5484 &tdesc_appobject
5486 VT_PTR
5489 0, /* wVarFlags */
5490 VAR_STATIC /* varkind */
5493 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
5494 tdesc_appobject.vt = VT_USERDEFINED;
5496 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
5498 /* cleanup things filled in by Bind call so we can put our
5499 * application object data in there instead */
5500 switch (subdesckind)
5502 case DESCKIND_FUNCDESC:
5503 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
5504 break;
5505 case DESCKIND_VARDESC:
5506 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
5507 break;
5508 default:
5509 break;
5511 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
5513 if (pTypeInfo->hreftype == -1)
5514 FIXME("no hreftype for interface %p\n", pTypeInfo);
5516 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
5517 if (FAILED(hr))
5518 return hr;
5520 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5521 *ppTInfo = (ITypeInfo *)&pTypeInfo->ITypeInfo2_iface;
5522 ITypeInfo_AddRef(*ppTInfo);
5523 return S_OK;
5525 else if (hr == TYPE_E_TYPEMISMATCH)
5526 typemismatch = 1;
5530 if (typemismatch)
5532 TRACE("type mismatch %s\n", debugstr_w(szName));
5533 return TYPE_E_TYPEMISMATCH;
5535 else
5537 TRACE("name not found %s\n", debugstr_w(szName));
5538 return S_OK;
5542 static HRESULT WINAPI ITypeLibComp_fnBindType(
5543 ITypeComp * iface,
5544 OLECHAR * szName,
5545 ULONG lHash,
5546 ITypeInfo ** ppTInfo,
5547 ITypeComp ** ppTComp)
5549 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5550 ITypeInfoImpl *info;
5552 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5554 if(!szName || !ppTInfo || !ppTComp)
5555 return E_INVALIDARG;
5557 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, szName);
5558 if(!info){
5559 *ppTInfo = NULL;
5560 *ppTComp = NULL;
5561 return S_OK;
5564 *ppTInfo = (ITypeInfo *)&info->ITypeInfo2_iface;
5565 ITypeInfo_AddRef(*ppTInfo);
5566 *ppTComp = &info->ITypeComp_iface;
5567 ITypeComp_AddRef(*ppTComp);
5569 return S_OK;
5572 static const ITypeCompVtbl tlbtcvt =
5575 ITypeLibComp_fnQueryInterface,
5576 ITypeLibComp_fnAddRef,
5577 ITypeLibComp_fnRelease,
5579 ITypeLibComp_fnBind,
5580 ITypeLibComp_fnBindType
5583 /*================== ITypeInfo(2) Methods ===================================*/
5584 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5586 ITypeInfoImpl *pTypeInfoImpl;
5588 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5589 if (pTypeInfoImpl)
5591 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5592 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5593 pTypeInfoImpl->ICreateTypeInfo2_iface.lpVtbl = &CreateTypeInfo2Vtbl;
5594 pTypeInfoImpl->ref = 0;
5595 pTypeInfoImpl->hreftype = -1;
5596 pTypeInfoImpl->memidConstructor = MEMBERID_NIL;
5597 pTypeInfoImpl->memidDestructor = MEMBERID_NIL;
5598 pTypeInfoImpl->pcustdata_list = &pTypeInfoImpl->custdata_list;
5599 list_init(pTypeInfoImpl->pcustdata_list);
5601 TRACE("(%p)\n", pTypeInfoImpl);
5602 return pTypeInfoImpl;
5605 /* ITypeInfo::QueryInterface
5607 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5608 ITypeInfo2 *iface,
5609 REFIID riid,
5610 VOID **ppvObject)
5612 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5614 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5616 *ppvObject=NULL;
5617 if(IsEqualIID(riid, &IID_IUnknown) ||
5618 IsEqualIID(riid,&IID_ITypeInfo)||
5619 IsEqualIID(riid,&IID_ITypeInfo2))
5620 *ppvObject = This;
5621 else if(IsEqualIID(riid, &IID_ICreateTypeInfo) ||
5622 IsEqualIID(riid, &IID_ICreateTypeInfo2))
5623 *ppvObject = &This->ICreateTypeInfo2_iface;
5625 if(*ppvObject){
5626 ITypeInfo2_AddRef(iface);
5627 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5628 return S_OK;
5630 TRACE("-- Interface: E_NOINTERFACE\n");
5631 return E_NOINTERFACE;
5634 /* ITypeInfo::AddRef
5636 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5638 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5639 ULONG ref = InterlockedIncrement(&This->ref);
5641 TRACE("(%p)->ref is %u\n",This, ref);
5643 if (ref == 1 /* incremented from 0 */)
5644 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5646 return ref;
5649 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5651 UINT i;
5653 TRACE("destroying ITypeInfo(%p)\n",This);
5655 for (i = 0; i < This->cFuncs; ++i)
5657 int j;
5658 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5659 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5661 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5662 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5663 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5664 TLB_FreeCustData(&pFInfo->pParamDesc[j].custdata_list);
5666 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5667 heap_free(pFInfo->pParamDesc);
5668 TLB_FreeCustData(&pFInfo->custdata_list);
5670 heap_free(This->funcdescs);
5672 for(i = 0; i < This->cVars; ++i)
5674 TLBVarDesc *pVInfo = &This->vardescs[i];
5675 if (pVInfo->vardesc_create) {
5676 TLB_FreeVarDesc(pVInfo->vardesc_create);
5677 } else if (pVInfo->vardesc.varkind == VAR_CONST) {
5678 VariantClear(pVInfo->vardesc.u.lpvarValue);
5679 heap_free(pVInfo->vardesc.u.lpvarValue);
5681 TLB_FreeCustData(&pVInfo->custdata_list);
5683 heap_free(This->vardescs);
5685 if(This->impltypes){
5686 for (i = 0; i < This->cImplTypes; ++i){
5687 TLBImplType *pImpl = &This->impltypes[i];
5688 TLB_FreeCustData(&pImpl->custdata_list);
5690 heap_free(This->impltypes);
5693 TLB_FreeCustData(&This->custdata_list);
5695 heap_free(This);
5698 /* ITypeInfo::Release
5700 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5702 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5703 ULONG ref = InterlockedDecrement(&This->ref);
5705 TRACE("(%p)->(%u)\n",This, ref);
5707 if (!ref)
5709 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5710 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5711 if (not_attached_to_typelib)
5712 heap_free(This);
5713 /* otherwise This will be freed when typelib is freed */
5716 return ref;
5719 /* ITypeInfo::GetTypeAttr
5721 * Retrieves a TYPEATTR structure that contains the attributes of the type
5722 * description.
5725 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5726 LPTYPEATTR *ppTypeAttr)
5728 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5729 SIZE_T size;
5731 TRACE("(%p)\n",This);
5733 size = sizeof(**ppTypeAttr);
5734 if (This->typekind == TKIND_ALIAS && This->tdescAlias)
5735 size += TLB_SizeTypeDesc(This->tdescAlias, FALSE);
5737 *ppTypeAttr = heap_alloc(size);
5738 if (!*ppTypeAttr)
5739 return E_OUTOFMEMORY;
5741 (*ppTypeAttr)->guid = *TLB_get_guid_null(This->guid);
5742 (*ppTypeAttr)->lcid = This->lcid;
5743 (*ppTypeAttr)->memidConstructor = This->memidConstructor;
5744 (*ppTypeAttr)->memidDestructor = This->memidDestructor;
5745 (*ppTypeAttr)->lpstrSchema = This->lpstrSchema;
5746 (*ppTypeAttr)->cbSizeInstance = This->cbSizeInstance;
5747 (*ppTypeAttr)->typekind = This->typekind;
5748 (*ppTypeAttr)->cFuncs = This->cFuncs;
5749 (*ppTypeAttr)->cVars = This->cVars;
5750 (*ppTypeAttr)->cImplTypes = This->cImplTypes;
5751 (*ppTypeAttr)->cbSizeVft = This->cbSizeVft;
5752 (*ppTypeAttr)->cbAlignment = This->cbAlignment;
5753 (*ppTypeAttr)->wTypeFlags = This->wTypeFlags;
5754 (*ppTypeAttr)->wMajorVerNum = This->wMajorVerNum;
5755 (*ppTypeAttr)->wMinorVerNum = This->wMinorVerNum;
5756 (*ppTypeAttr)->idldescType = This->idldescType;
5758 if (This->tdescAlias)
5759 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5760 This->tdescAlias, *ppTypeAttr + 1);
5761 else{
5762 (*ppTypeAttr)->tdescAlias.vt = VT_EMPTY;
5763 (*ppTypeAttr)->tdescAlias.u.lptdesc = NULL;
5766 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5767 /* This should include all the inherited funcs */
5768 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / This->pTypeLib->ptr_size;
5769 /* This is always the size of IDispatch's vtbl */
5770 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5771 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5773 return S_OK;
5776 /* ITypeInfo::GetTypeComp
5778 * Retrieves the ITypeComp interface for the type description, which enables a
5779 * client compiler to bind to the type description's members.
5782 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5783 ITypeComp * *ppTComp)
5785 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5787 TRACE("(%p)->(%p)\n", This, ppTComp);
5789 *ppTComp = &This->ITypeComp_iface;
5790 ITypeComp_AddRef(*ppTComp);
5791 return S_OK;
5794 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5796 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5797 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5798 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5799 return size;
5802 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5804 *dest = *src;
5805 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5806 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5808 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5809 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5810 *buffer += sizeof(PARAMDESCEX);
5811 *pparamdescex_dest = *pparamdescex_src;
5812 pparamdescex_dest->cBytes = sizeof(PARAMDESCEX);
5813 VariantInit(&pparamdescex_dest->varDefaultValue);
5814 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5815 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5817 else
5818 dest->u.paramdesc.pparamdescex = NULL;
5819 return S_OK;
5822 static HRESULT TLB_SanitizeBSTR(BSTR str)
5824 UINT len = SysStringLen(str), i;
5825 for (i = 0; i < len; ++i)
5826 if (str[i] > 0x7f)
5827 str[i] = '?';
5828 return S_OK;
5831 static HRESULT TLB_SanitizeVariant(VARIANT *var)
5833 if (V_VT(var) == VT_INT)
5834 return VariantChangeType(var, var, 0, VT_I4);
5835 else if (V_VT(var) == VT_UINT)
5836 return VariantChangeType(var, var, 0, VT_UI4);
5837 else if (V_VT(var) == VT_BSTR)
5838 return TLB_SanitizeBSTR(V_BSTR(var));
5840 return S_OK;
5843 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5845 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5846 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5849 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5851 FUNCDESC *dest;
5852 char *buffer;
5853 SIZE_T size = sizeof(*src);
5854 SHORT i;
5855 HRESULT hr;
5857 size += sizeof(*src->lprgscode) * src->cScodes;
5858 size += TLB_SizeElemDesc(&src->elemdescFunc);
5859 for (i = 0; i < src->cParams; i++)
5861 size += sizeof(ELEMDESC);
5862 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5865 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5866 if (!dest) return E_OUTOFMEMORY;
5868 *dest = *src;
5869 if (dispinterface) /* overwrite funckind */
5870 dest->funckind = FUNC_DISPATCH;
5871 buffer = (char *)(dest + 1);
5873 dest->oVft = dest->oVft & 0xFFFC;
5875 if (dest->cScodes) {
5876 dest->lprgscode = (SCODE *)buffer;
5877 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5878 buffer += sizeof(*src->lprgscode) * src->cScodes;
5879 } else
5880 dest->lprgscode = NULL;
5882 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5883 if (FAILED(hr))
5885 SysFreeString((BSTR)dest);
5886 return hr;
5889 if (dest->cParams) {
5890 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5891 buffer += sizeof(ELEMDESC) * src->cParams;
5892 for (i = 0; i < src->cParams; i++)
5894 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5895 if (FAILED(hr))
5896 break;
5898 if (FAILED(hr))
5900 /* undo the above actions */
5901 for (i = i - 1; i >= 0; i--)
5902 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5903 TLB_FreeElemDesc(&dest->elemdescFunc);
5904 SysFreeString((BSTR)dest);
5905 return hr;
5907 } else
5908 dest->lprgelemdescParam = NULL;
5910 /* special treatment for dispinterfaces: this makes functions appear
5911 * to return their [retval] value when it is really returning an
5912 * HRESULT */
5913 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5915 if (dest->cParams &&
5916 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5918 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5919 if (elemdesc->tdesc.vt != VT_PTR)
5921 ERR("elemdesc should have started with VT_PTR instead of:\n");
5922 if (ERR_ON(ole))
5923 dump_ELEMDESC(elemdesc);
5924 return E_UNEXPECTED;
5927 /* copy last parameter to the return value. we are using a flat
5928 * buffer so there is no danger of leaking memory in
5929 * elemdescFunc */
5930 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5932 /* remove the last parameter */
5933 dest->cParams--;
5935 else
5936 /* otherwise this function is made to appear to have no return
5937 * value */
5938 dest->elemdescFunc.tdesc.vt = VT_VOID;
5942 *dest_ptr = dest;
5943 return S_OK;
5946 static void TLB_FreeVarDesc(VARDESC *var_desc)
5948 TLB_FreeElemDesc(&var_desc->elemdescVar);
5949 if (var_desc->varkind == VAR_CONST)
5950 VariantClear(var_desc->u.lpvarValue);
5951 SysFreeString((BSTR)var_desc);
5954 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5956 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5958 if (index >= This->cFuncs)
5959 return TYPE_E_ELEMENTNOTFOUND;
5961 *ppFuncDesc = &This->funcdescs[index].funcdesc;
5962 return S_OK;
5965 /* internal function to make the inherited interfaces' methods appear
5966 * part of the interface */
5967 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5968 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5970 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5971 HRESULT hr;
5972 UINT implemented_funcs = 0;
5974 if (funcs)
5975 *funcs = 0;
5976 else
5977 *hrefoffset = DISPATCH_HREF_OFFSET;
5979 if(This->impltypes)
5981 ITypeInfo *pSubTypeInfo;
5982 UINT sub_funcs;
5984 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5985 if (FAILED(hr))
5986 return hr;
5988 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5989 index,
5990 ppFuncDesc,
5991 &sub_funcs, hrefoffset);
5992 implemented_funcs += sub_funcs;
5993 ITypeInfo_Release(pSubTypeInfo);
5994 if (SUCCEEDED(hr))
5995 return hr;
5996 *hrefoffset += DISPATCH_HREF_OFFSET;
5999 if (funcs)
6000 *funcs = implemented_funcs + This->cFuncs;
6001 else
6002 *hrefoffset = 0;
6004 if (index < implemented_funcs)
6005 return E_INVALIDARG;
6006 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
6007 ppFuncDesc);
6010 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
6012 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
6013 while (TRUE)
6015 switch (pTypeDesc->vt)
6017 case VT_USERDEFINED:
6018 pTypeDesc->u.hreftype += hrefoffset;
6019 return;
6020 case VT_PTR:
6021 case VT_SAFEARRAY:
6022 pTypeDesc = pTypeDesc->u.lptdesc;
6023 break;
6024 case VT_CARRAY:
6025 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
6026 break;
6027 default:
6028 return;
6033 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
6035 SHORT i;
6036 for (i = 0; i < pFuncDesc->cParams; i++)
6037 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
6038 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
6041 /* ITypeInfo::GetFuncDesc
6043 * Retrieves the FUNCDESC structure that contains information about a
6044 * specified function.
6047 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
6048 LPFUNCDESC *ppFuncDesc)
6050 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6051 const FUNCDESC *internal_funcdesc;
6052 HRESULT hr;
6053 UINT hrefoffset = 0;
6055 TRACE("(%p) index %d\n", This, index);
6057 if (!ppFuncDesc)
6058 return E_INVALIDARG;
6060 if (This->needs_layout)
6061 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6063 if (This->typekind == TKIND_DISPATCH)
6064 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
6065 &internal_funcdesc, NULL,
6066 &hrefoffset);
6067 else
6068 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
6069 &internal_funcdesc);
6070 if (FAILED(hr))
6072 WARN("description for function %d not found\n", index);
6073 return hr;
6076 hr = TLB_AllocAndInitFuncDesc(
6077 internal_funcdesc,
6078 ppFuncDesc,
6079 This->typekind == TKIND_DISPATCH);
6081 if ((This->typekind == TKIND_DISPATCH) && hrefoffset)
6082 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
6084 TRACE("-- 0x%08x\n", hr);
6085 return hr;
6088 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
6090 VARDESC *dest;
6091 char *buffer;
6092 SIZE_T size = sizeof(*src);
6093 HRESULT hr;
6095 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
6096 if (src->varkind == VAR_CONST)
6097 size += sizeof(VARIANT);
6098 size += TLB_SizeElemDesc(&src->elemdescVar);
6100 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
6101 if (!dest) return E_OUTOFMEMORY;
6103 *dest = *src;
6104 buffer = (char *)(dest + 1);
6105 if (src->lpstrSchema)
6107 int len;
6108 dest->lpstrSchema = (LPOLESTR)buffer;
6109 len = strlenW(src->lpstrSchema);
6110 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
6111 buffer += (len + 1) * sizeof(WCHAR);
6114 if (src->varkind == VAR_CONST)
6116 HRESULT hr;
6118 dest->u.lpvarValue = (VARIANT *)buffer;
6119 *dest->u.lpvarValue = *src->u.lpvarValue;
6120 buffer += sizeof(VARIANT);
6121 VariantInit(dest->u.lpvarValue);
6122 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
6123 if (FAILED(hr))
6125 SysFreeString((BSTR)dest);
6126 return hr;
6129 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
6130 if (FAILED(hr))
6132 if (src->varkind == VAR_CONST)
6133 VariantClear(dest->u.lpvarValue);
6134 SysFreeString((BSTR)dest);
6135 return hr;
6137 *dest_ptr = dest;
6138 return S_OK;
6141 /* ITypeInfo::GetVarDesc
6143 * Retrieves a VARDESC structure that describes the specified variable.
6146 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
6147 LPVARDESC *ppVarDesc)
6149 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6150 const TLBVarDesc *pVDesc = &This->vardescs[index];
6152 TRACE("(%p) index %d\n", This, index);
6154 if(index >= This->cVars)
6155 return TYPE_E_ELEMENTNOTFOUND;
6157 if (This->needs_layout)
6158 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6160 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
6163 /* ITypeInfo_GetNames
6165 * Retrieves the variable with the specified member ID (or the name of the
6166 * property or method and its parameters) that correspond to the specified
6167 * function ID.
6169 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
6170 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
6172 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6173 const TLBFuncDesc *pFDesc;
6174 const TLBVarDesc *pVDesc;
6175 int i;
6176 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
6178 if(!rgBstrNames)
6179 return E_INVALIDARG;
6181 *pcNames = 0;
6183 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
6184 if(pFDesc)
6186 if(!cMaxNames || !pFDesc->Name)
6187 return S_OK;
6189 *rgBstrNames = SysAllocString(TLB_get_bstr(pFDesc->Name));
6190 ++(*pcNames);
6192 for(i = 0; i < pFDesc->funcdesc.cParams; ++i){
6193 if(*pcNames >= cMaxNames || !pFDesc->pParamDesc[i].Name)
6194 return S_OK;
6195 rgBstrNames[*pcNames] = SysAllocString(TLB_get_bstr(pFDesc->pParamDesc[i].Name));
6196 ++(*pcNames);
6198 return S_OK;
6201 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
6202 if(pVDesc)
6204 *rgBstrNames=SysAllocString(TLB_get_bstr(pVDesc->Name));
6205 *pcNames=1;
6207 else
6209 if(This->impltypes &&
6210 (This->typekind==TKIND_INTERFACE || This->typekind==TKIND_DISPATCH)) {
6211 /* recursive search */
6212 ITypeInfo *pTInfo;
6213 HRESULT result;
6214 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6215 if(SUCCEEDED(result))
6217 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
6218 ITypeInfo_Release(pTInfo);
6219 return result;
6221 WARN("Could not search inherited interface!\n");
6223 else
6225 WARN("no names found\n");
6227 *pcNames=0;
6228 return TYPE_E_ELEMENTNOTFOUND;
6230 return S_OK;
6234 /* ITypeInfo::GetRefTypeOfImplType
6236 * If a type description describes a COM class, it retrieves the type
6237 * description of the implemented interface types. For an interface,
6238 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6239 * if any exist.
6242 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
6243 ITypeInfo2 *iface,
6244 UINT index,
6245 HREFTYPE *pRefType)
6247 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6248 HRESULT hr = S_OK;
6250 TRACE("(%p) index %d\n", This, index);
6251 if (TRACE_ON(ole)) dump_TypeInfo(This);
6253 if(index==(UINT)-1)
6255 /* only valid on dual interfaces;
6256 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6259 if (This->wTypeFlags & TYPEFLAG_FDUAL)
6261 *pRefType = -2;
6263 else
6265 hr = TYPE_E_ELEMENTNOTFOUND;
6268 else if(index == 0 && This->typekind == TKIND_DISPATCH)
6270 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6271 *pRefType = This->pTypeLib->dispatch_href;
6273 else
6275 if(index >= This->cImplTypes)
6276 hr = TYPE_E_ELEMENTNOTFOUND;
6277 else{
6278 *pRefType = This->impltypes[index].hRef;
6279 if(This->typekind == TKIND_INTERFACE)
6280 *pRefType |= 0x2;
6284 if(TRACE_ON(ole))
6286 if(SUCCEEDED(hr))
6287 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
6288 else
6289 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
6292 return hr;
6295 /* ITypeInfo::GetImplTypeFlags
6297 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6298 * or base interface in a type description.
6300 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
6301 UINT index, INT *pImplTypeFlags)
6303 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6305 TRACE("(%p) index %d\n", This, index);
6307 if(!pImplTypeFlags)
6308 return E_INVALIDARG;
6310 if(This->typekind == TKIND_DISPATCH && index == 0){
6311 *pImplTypeFlags = 0;
6312 return S_OK;
6315 if(index >= This->cImplTypes)
6316 return TYPE_E_ELEMENTNOTFOUND;
6318 *pImplTypeFlags = This->impltypes[index].implflags;
6320 return S_OK;
6323 /* GetIDsOfNames
6324 * Maps between member names and member IDs, and parameter names and
6325 * parameter IDs.
6327 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
6328 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
6330 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6331 const TLBVarDesc *pVDesc;
6332 HRESULT ret=S_OK;
6333 UINT i, fdc;
6335 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
6336 cNames);
6338 /* init out parameters in case of failure */
6339 for (i = 0; i < cNames; i++)
6340 pMemId[i] = MEMBERID_NIL;
6342 for (fdc = 0; fdc < This->cFuncs; ++fdc) {
6343 int j;
6344 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
6345 if(!lstrcmpiW(*rgszNames, TLB_get_bstr(pFDesc->Name))) {
6346 if(cNames) *pMemId=pFDesc->funcdesc.memid;
6347 for(i=1; i < cNames; i++){
6348 for(j=0; j<pFDesc->funcdesc.cParams; j++)
6349 if(!lstrcmpiW(rgszNames[i],TLB_get_bstr(pFDesc->pParamDesc[j].Name)))
6350 break;
6351 if( j<pFDesc->funcdesc.cParams)
6352 pMemId[i]=j;
6353 else
6354 ret=DISP_E_UNKNOWNNAME;
6356 TRACE("-- 0x%08x\n", ret);
6357 return ret;
6360 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->cVars, *rgszNames);
6361 if(pVDesc){
6362 if(cNames)
6363 *pMemId = pVDesc->vardesc.memid;
6364 return ret;
6366 /* not found, see if it can be found in an inherited interface */
6367 if(This->impltypes) {
6368 /* recursive search */
6369 ITypeInfo *pTInfo;
6370 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6371 if(SUCCEEDED(ret)){
6372 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
6373 ITypeInfo_Release(pTInfo);
6374 return ret;
6376 WARN("Could not search inherited interface!\n");
6377 } else
6378 WARN("no names found\n");
6379 return DISP_E_UNKNOWNNAME;
6383 #ifdef __i386__
6385 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6386 __ASM_GLOBAL_FUNC( call_method,
6387 "pushl %ebp\n\t"
6388 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6389 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6390 "movl %esp,%ebp\n\t"
6391 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6392 "pushl %esi\n\t"
6393 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6394 "pushl %edi\n\t"
6395 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6396 "movl 12(%ebp),%edx\n\t"
6397 "movl %esp,%edi\n\t"
6398 "shll $2,%edx\n\t"
6399 "jz 1f\n\t"
6400 "subl %edx,%edi\n\t"
6401 "andl $~15,%edi\n\t"
6402 "movl %edi,%esp\n\t"
6403 "movl 12(%ebp),%ecx\n\t"
6404 "movl 16(%ebp),%esi\n\t"
6405 "cld\n\t"
6406 "rep; movsl\n"
6407 "1:\tcall *8(%ebp)\n\t"
6408 "subl %esp,%edi\n\t"
6409 "movl 20(%ebp),%ecx\n\t"
6410 "movl %edi,(%ecx)\n\t"
6411 "leal -8(%ebp),%esp\n\t"
6412 "popl %edi\n\t"
6413 __ASM_CFI(".cfi_same_value %edi\n\t")
6414 "popl %esi\n\t"
6415 __ASM_CFI(".cfi_same_value %esi\n\t")
6416 "popl %ebp\n\t"
6417 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6418 __ASM_CFI(".cfi_same_value %ebp\n\t")
6419 "ret" )
6421 /* same function but returning floating point */
6422 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
6424 /* ITypeInfo::Invoke
6426 * Invokes a method, or accesses a property of an object, that implements the
6427 * interface described by the type description.
6429 DWORD
6430 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
6431 DWORD res;
6432 int stack_offset;
6434 if (TRACE_ON(ole)) {
6435 int i;
6436 TRACE("Calling %p(",func);
6437 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
6438 if (nrargs > 30) TRACE("...");
6439 TRACE(")\n");
6442 switch (callconv) {
6443 case CC_STDCALL:
6444 case CC_CDECL:
6445 res = call_method( func, nrargs, args, &stack_offset );
6446 break;
6447 default:
6448 FIXME("unsupported calling convention %d\n",callconv);
6449 res = -1;
6450 break;
6452 TRACE("returns %08x\n",res);
6453 return res;
6456 #elif defined(__x86_64__)
6458 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
6459 __ASM_GLOBAL_FUNC( call_method,
6460 "pushq %rbp\n\t"
6461 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6462 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6463 "movq %rsp,%rbp\n\t"
6464 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6465 "pushq %rsi\n\t"
6466 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6467 "pushq %rdi\n\t"
6468 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6469 "movq %rcx,%rax\n\t"
6470 "movq $4,%rcx\n\t"
6471 "cmp %rcx,%rdx\n\t"
6472 "cmovgq %rdx,%rcx\n\t"
6473 "leaq 0(,%rcx,8),%rdx\n\t"
6474 "subq %rdx,%rsp\n\t"
6475 "andq $~15,%rsp\n\t"
6476 "movq %rsp,%rdi\n\t"
6477 "movq %r8,%rsi\n\t"
6478 "rep; movsq\n\t"
6479 "movq 0(%rsp),%rcx\n\t"
6480 "movq 8(%rsp),%rdx\n\t"
6481 "movq 16(%rsp),%r8\n\t"
6482 "movq 24(%rsp),%r9\n\t"
6483 "movq %rcx,%xmm0\n\t"
6484 "movq %rdx,%xmm1\n\t"
6485 "movq %r8,%xmm2\n\t"
6486 "movq %r9,%xmm3\n\t"
6487 "callq *%rax\n\t"
6488 "leaq -16(%rbp),%rsp\n\t"
6489 "popq %rdi\n\t"
6490 __ASM_CFI(".cfi_same_value %rdi\n\t")
6491 "popq %rsi\n\t"
6492 __ASM_CFI(".cfi_same_value %rsi\n\t")
6493 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6494 "popq %rbp\n\t"
6495 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6496 __ASM_CFI(".cfi_same_value %rbp\n\t")
6497 "ret")
6499 /* same function but returning floating point */
6500 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
6502 #endif /* __x86_64__ */
6504 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6506 HRESULT hr = S_OK;
6507 ITypeInfo *tinfo2 = NULL;
6508 TYPEATTR *tattr = NULL;
6510 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6511 if (hr)
6513 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6514 "hr = 0x%08x\n",
6515 tdesc->u.hreftype, hr);
6516 return hr;
6518 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6519 if (hr)
6521 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
6522 ITypeInfo_Release(tinfo2);
6523 return hr;
6526 switch (tattr->typekind)
6528 case TKIND_ENUM:
6529 *vt |= VT_I4;
6530 break;
6532 case TKIND_ALIAS:
6533 tdesc = &tattr->tdescAlias;
6534 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
6535 break;
6537 case TKIND_INTERFACE:
6538 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
6539 *vt |= VT_DISPATCH;
6540 else
6541 *vt |= VT_UNKNOWN;
6542 break;
6544 case TKIND_DISPATCH:
6545 *vt |= VT_DISPATCH;
6546 break;
6548 case TKIND_COCLASS:
6549 *vt |= VT_DISPATCH;
6550 break;
6552 case TKIND_RECORD:
6553 FIXME("TKIND_RECORD unhandled.\n");
6554 hr = E_NOTIMPL;
6555 break;
6557 case TKIND_UNION:
6558 FIXME("TKIND_UNION unhandled.\n");
6559 hr = E_NOTIMPL;
6560 break;
6562 default:
6563 FIXME("TKIND %d unhandled.\n",tattr->typekind);
6564 hr = E_NOTIMPL;
6565 break;
6567 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6568 ITypeInfo_Release(tinfo2);
6569 return hr;
6572 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6574 HRESULT hr = S_OK;
6576 /* enforce only one level of pointer indirection */
6577 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
6579 tdesc = tdesc->u.lptdesc;
6581 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6582 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6583 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6584 if ((tdesc->vt == VT_USERDEFINED) ||
6585 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
6587 VARTYPE vt_userdefined = 0;
6588 const TYPEDESC *tdesc_userdefined = tdesc;
6589 if (tdesc->vt == VT_PTR)
6591 vt_userdefined = VT_BYREF;
6592 tdesc_userdefined = tdesc->u.lptdesc;
6594 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
6595 if ((hr == S_OK) &&
6596 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
6597 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
6599 *vt |= vt_userdefined;
6600 return S_OK;
6603 *vt = VT_BYREF;
6606 switch (tdesc->vt)
6608 case VT_HRESULT:
6609 *vt |= VT_ERROR;
6610 break;
6611 case VT_USERDEFINED:
6612 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
6613 break;
6614 case VT_VOID:
6615 case VT_CARRAY:
6616 case VT_PTR:
6617 case VT_LPSTR:
6618 case VT_LPWSTR:
6619 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
6620 hr = DISP_E_BADVARTYPE;
6621 break;
6622 case VT_SAFEARRAY:
6623 *vt |= VT_ARRAY;
6624 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
6625 break;
6626 case VT_INT:
6627 *vt |= VT_I4;
6628 break;
6629 case VT_UINT:
6630 *vt |= VT_UI4;
6631 break;
6632 default:
6633 *vt |= tdesc->vt;
6634 break;
6636 return hr;
6639 static HRESULT get_iface_guid(ITypeInfo *tinfo, const TYPEDESC *tdesc, GUID *guid)
6641 ITypeInfo *tinfo2;
6642 TYPEATTR *tattr;
6643 HRESULT hres;
6645 hres = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6646 if(FAILED(hres))
6647 return hres;
6649 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6650 if(FAILED(hres)) {
6651 ITypeInfo_Release(tinfo2);
6652 return hres;
6655 switch(tattr->typekind) {
6656 case TKIND_ALIAS:
6657 hres = get_iface_guid(tinfo2, &tattr->tdescAlias, guid);
6658 break;
6660 case TKIND_INTERFACE:
6661 case TKIND_DISPATCH:
6662 *guid = tattr->guid;
6663 break;
6665 default:
6666 ERR("Unexpected typekind %d\n", tattr->typekind);
6667 hres = E_UNEXPECTED;
6670 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6671 ITypeInfo_Release(tinfo2);
6672 return hres;
6675 /***********************************************************************
6676 * DispCallFunc (OLEAUT32.@)
6678 * Invokes a function of the specified calling convention, passing the
6679 * specified arguments and returns the result.
6681 * PARAMS
6682 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6683 * oVft [I] The offset in the vtable. See notes.
6684 * cc [I] Calling convention of the function to call.
6685 * vtReturn [I] The return type of the function.
6686 * cActuals [I] Number of parameters.
6687 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6688 * prgpvarg [I] The arguments to pass.
6689 * pvargResult [O] The return value of the function. Can be NULL.
6691 * RETURNS
6692 * Success: S_OK.
6693 * Failure: HRESULT code.
6695 * NOTES
6696 * The HRESULT return value of this function is not affected by the return
6697 * value of the user supplied function, which is returned in pvargResult.
6699 * If pvInstance is NULL then a non-object function is to be called and oVft
6700 * is the address of the function to call.
6702 * The cc parameter can be one of the following values:
6703 *|CC_FASTCALL
6704 *|CC_CDECL
6705 *|CC_PASCAL
6706 *|CC_STDCALL
6707 *|CC_FPFASTCALL
6708 *|CC_SYSCALL
6709 *|CC_MPWCDECL
6710 *|CC_MPWPASCAL
6713 HRESULT WINAPI
6714 DispCallFunc(
6715 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
6716 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
6718 #ifdef __i386__
6719 int argspos, stack_offset;
6720 void *func;
6721 UINT i;
6722 DWORD *args;
6724 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6725 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6726 pvargResult, V_VT(pvargResult));
6728 if (cc != CC_STDCALL && cc != CC_CDECL)
6730 FIXME("unsupported calling convention %d\n",cc);
6731 return E_INVALIDARG;
6734 /* maximum size for an argument is sizeof(VARIANT) */
6735 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6737 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6738 argspos = 1;
6739 if (pvInstance)
6741 const FARPROC *vtable = *(FARPROC **)pvInstance;
6742 func = vtable[oVft/sizeof(void *)];
6743 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6745 else func = (void *)oVft;
6747 for (i = 0; i < cActuals; i++)
6749 VARIANT *arg = prgpvarg[i];
6751 switch (prgvt[i])
6753 case VT_EMPTY:
6754 break;
6755 case VT_I8:
6756 case VT_UI8:
6757 case VT_R8:
6758 case VT_DATE:
6759 case VT_CY:
6760 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6761 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6762 break;
6763 case VT_DECIMAL:
6764 case VT_VARIANT:
6765 memcpy( &args[argspos], arg, sizeof(*arg) );
6766 argspos += sizeof(*arg) / sizeof(DWORD);
6767 break;
6768 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6769 args[argspos++] = V_BOOL(arg);
6770 break;
6771 default:
6772 args[argspos++] = V_UI4(arg);
6773 break;
6775 TRACE("arg %u: type %d\n",i,prgvt[i]);
6776 dump_Variant(arg);
6779 switch (vtReturn)
6781 case VT_EMPTY:
6782 call_method( func, argspos - 1, args + 1, &stack_offset );
6783 break;
6784 case VT_R4:
6785 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6786 break;
6787 case VT_R8:
6788 case VT_DATE:
6789 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6790 break;
6791 case VT_DECIMAL:
6792 case VT_VARIANT:
6793 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6794 call_method( func, argspos, args, &stack_offset );
6795 break;
6796 case VT_I8:
6797 case VT_UI8:
6798 case VT_CY:
6799 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6800 break;
6801 case VT_HRESULT:
6802 WARN("invalid return type %u\n", vtReturn);
6803 heap_free( args );
6804 return E_INVALIDARG;
6805 default:
6806 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6807 break;
6809 heap_free( args );
6810 if (stack_offset && cc == CC_STDCALL)
6812 WARN( "stack pointer off by %d\n", stack_offset );
6813 return DISP_E_BADCALLEE;
6815 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6816 TRACE("retval: "); dump_Variant(pvargResult);
6817 return S_OK;
6819 #elif defined(__x86_64__)
6820 int argspos;
6821 UINT i;
6822 DWORD_PTR *args;
6823 void *func;
6825 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6826 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6827 pvargResult, V_VT(pvargResult));
6829 if (cc != CC_STDCALL && cc != CC_CDECL)
6831 FIXME("unsupported calling convention %d\n",cc);
6832 return E_INVALIDARG;
6835 /* maximum size for an argument is sizeof(DWORD_PTR) */
6836 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6838 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6839 argspos = 1;
6840 if (pvInstance)
6842 const FARPROC *vtable = *(FARPROC **)pvInstance;
6843 func = vtable[oVft/sizeof(void *)];
6844 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6846 else func = (void *)oVft;
6848 for (i = 0; i < cActuals; i++)
6850 VARIANT *arg = prgpvarg[i];
6852 switch (prgvt[i])
6854 case VT_DECIMAL:
6855 case VT_VARIANT:
6856 args[argspos++] = (ULONG_PTR)arg;
6857 break;
6858 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6859 args[argspos++] = V_BOOL(arg);
6860 break;
6861 default:
6862 args[argspos++] = V_UI8(arg);
6863 break;
6865 TRACE("arg %u: type %d\n",i,prgvt[i]);
6866 dump_Variant(arg);
6869 switch (vtReturn)
6871 case VT_R4:
6872 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6873 break;
6874 case VT_R8:
6875 case VT_DATE:
6876 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6877 break;
6878 case VT_DECIMAL:
6879 case VT_VARIANT:
6880 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6881 call_method( func, argspos, args );
6882 break;
6883 case VT_HRESULT:
6884 WARN("invalid return type %u\n", vtReturn);
6885 heap_free( args );
6886 return E_INVALIDARG;
6887 default:
6888 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6889 break;
6891 heap_free( args );
6892 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6893 TRACE("retval: "); dump_Variant(pvargResult);
6894 return S_OK;
6896 #else
6897 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6898 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6899 return E_NOTIMPL;
6900 #endif
6903 static inline BOOL func_restricted( const FUNCDESC *desc )
6905 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
6908 #define INVBUF_ELEMENT_SIZE \
6909 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6910 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6911 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6912 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6913 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6914 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6915 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6916 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6918 static HRESULT WINAPI ITypeInfo_fnInvoke(
6919 ITypeInfo2 *iface,
6920 VOID *pIUnk,
6921 MEMBERID memid,
6922 UINT16 wFlags,
6923 DISPPARAMS *pDispParams,
6924 VARIANT *pVarResult,
6925 EXCEPINFO *pExcepInfo,
6926 UINT *pArgErr)
6928 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6929 int i;
6930 unsigned int var_index;
6931 TYPEKIND type_kind;
6932 HRESULT hres;
6933 const TLBFuncDesc *pFuncInfo;
6934 UINT fdc;
6936 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6937 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6940 if( This->wTypeFlags & TYPEFLAG_FRESTRICTED )
6941 return DISP_E_MEMBERNOTFOUND;
6943 if (!pDispParams)
6945 ERR("NULL pDispParams not allowed\n");
6946 return E_INVALIDARG;
6949 dump_DispParms(pDispParams);
6951 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6953 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6954 pDispParams->cNamedArgs, pDispParams->cArgs);
6955 return E_INVALIDARG;
6958 /* we do this instead of using GetFuncDesc since it will return a fake
6959 * FUNCDESC for dispinterfaces and we want the real function description */
6960 for (fdc = 0; fdc < This->cFuncs; ++fdc){
6961 pFuncInfo = &This->funcdescs[fdc];
6962 if ((memid == pFuncInfo->funcdesc.memid) &&
6963 (wFlags & pFuncInfo->funcdesc.invkind) &&
6964 !func_restricted( &pFuncInfo->funcdesc ))
6965 break;
6968 if (fdc < This->cFuncs) {
6969 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6971 if (TRACE_ON(ole))
6973 TRACE("invoking:\n");
6974 dump_TLBFuncDescOne(pFuncInfo);
6977 switch (func_desc->funckind) {
6978 case FUNC_PUREVIRTUAL:
6979 case FUNC_VIRTUAL: {
6980 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
6981 VARIANT varresult;
6982 VARIANT retval; /* pointer for storing byref retvals in */
6983 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6984 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6985 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6986 UINT cNamedArgs = pDispParams->cNamedArgs;
6987 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6988 UINT vargs_converted=0;
6990 hres = S_OK;
6992 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6994 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6996 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6997 hres = DISP_E_PARAMNOTFOUND;
6998 goto func_fail;
7002 if (func_desc->cParamsOpt < 0 && cNamedArgs)
7004 ERR("functions with the vararg attribute do not support named arguments\n");
7005 hres = DISP_E_NONAMEDARGS;
7006 goto func_fail;
7009 for (i = 0; i < func_desc->cParams; i++)
7011 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7012 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
7013 if (FAILED(hres))
7014 goto func_fail;
7017 TRACE("changing args\n");
7018 for (i = 0; i < func_desc->cParams; i++)
7020 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7021 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7022 VARIANTARG *src_arg;
7024 if (wParamFlags & PARAMFLAG_FLCID)
7026 VARIANTARG *arg;
7027 arg = prgpvarg[i] = &rgvarg[i];
7028 V_VT(arg) = VT_I4;
7029 V_I4(arg) = This->pTypeLib->lcid;
7030 continue;
7033 src_arg = NULL;
7035 if (cNamedArgs)
7037 USHORT j;
7038 for (j = 0; j < cNamedArgs; j++)
7039 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
7041 src_arg = &pDispParams->rgvarg[j];
7042 break;
7046 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
7048 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7049 vargs_converted++;
7052 if (wParamFlags & PARAMFLAG_FRETVAL)
7054 /* under most conditions the caller is not allowed to
7055 * pass in a dispparam arg in the index of what would be
7056 * the retval parameter. however, there is an exception
7057 * where the extra parameter is used in an extra
7058 * IDispatch::Invoke below */
7059 if ((i < pDispParams->cArgs) &&
7060 ((func_desc->cParams != 1) || !pVarResult ||
7061 !(func_desc->invkind & INVOKE_PROPERTYGET)))
7063 hres = DISP_E_BADPARAMCOUNT;
7064 break;
7067 /* note: this check is placed so that if the caller passes
7068 * in a VARIANTARG for the retval we just ignore it, like
7069 * native does */
7070 if (i == func_desc->cParams - 1)
7072 VARIANTARG *arg;
7073 arg = prgpvarg[i] = &rgvarg[i];
7074 memset(arg, 0, sizeof(*arg));
7075 V_VT(arg) = rgvt[i];
7076 memset(&retval, 0, sizeof(retval));
7077 V_BYREF(arg) = &retval;
7079 else
7081 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
7082 hres = E_UNEXPECTED;
7083 break;
7086 else if (src_arg)
7088 dump_Variant(src_arg);
7090 if(rgvt[i]!=V_VT(src_arg))
7092 if (rgvt[i] == VT_VARIANT)
7093 hres = VariantCopy(&rgvarg[i], src_arg);
7094 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
7096 if (rgvt[i] == V_VT(src_arg))
7097 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
7098 else
7100 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7101 if (wParamFlags & PARAMFLAG_FIN)
7102 hres = VariantCopy(&missing_arg[i], src_arg);
7103 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
7105 V_VT(&rgvarg[i]) = rgvt[i];
7107 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
7109 SAFEARRAY *a;
7110 SAFEARRAYBOUND bound;
7111 VARIANT *v;
7112 LONG j;
7113 bound.lLbound = 0;
7114 bound.cElements = pDispParams->cArgs-i;
7115 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
7117 ERR("SafeArrayCreate failed\n");
7118 break;
7120 hres = SafeArrayAccessData(a, (LPVOID)&v);
7121 if (hres != S_OK)
7123 ERR("SafeArrayAccessData failed with %x\n", hres);
7124 SafeArrayDestroy(a);
7125 break;
7127 for (j = 0; j < bound.cElements; j++)
7128 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
7129 hres = SafeArrayUnaccessData(a);
7130 if (hres != S_OK)
7132 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7133 SafeArrayDestroy(a);
7134 break;
7136 V_ARRAY(&rgvarg[i]) = a;
7137 V_VT(&rgvarg[i]) = rgvt[i];
7139 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
7141 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7142 if (wParamFlags & PARAMFLAG_FIN)
7143 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
7144 else
7145 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
7146 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
7147 V_VT(&rgvarg[i]) = rgvt[i];
7149 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
7151 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
7152 V_VT(&rgvarg[i]) = rgvt[i];
7154 else
7156 /* FIXME: this doesn't work for VT_BYREF arguments if
7157 * they are not the same type as in the paramdesc */
7158 V_VT(&rgvarg[i]) = V_VT(src_arg);
7159 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
7160 V_VT(&rgvarg[i]) = rgvt[i];
7163 if (FAILED(hres))
7165 ERR("failed to convert param %d to %s%s from %s%s\n", i,
7166 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
7167 debugstr_VT(src_arg), debugstr_VF(src_arg));
7168 break;
7170 prgpvarg[i] = &rgvarg[i];
7172 else
7174 prgpvarg[i] = src_arg;
7177 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
7178 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
7179 && V_UNKNOWN(prgpvarg[i])) {
7180 IUnknown *userdefined_iface;
7181 GUID guid;
7183 hres = get_iface_guid((ITypeInfo*)iface, tdesc->vt == VT_PTR ? tdesc->u.lptdesc : tdesc, &guid);
7184 if(FAILED(hres))
7185 break;
7187 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
7188 if(FAILED(hres)) {
7189 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
7190 break;
7193 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
7194 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
7197 else if (wParamFlags & PARAMFLAG_FOPT)
7199 VARIANTARG *arg;
7200 arg = prgpvarg[i] = &rgvarg[i];
7201 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7203 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
7204 if (FAILED(hres))
7205 break;
7207 else
7209 VARIANTARG *missing_arg;
7210 /* if the function wants a pointer to a variant then
7211 * set that up, otherwise just pass the VT_ERROR in
7212 * the argument by value */
7213 if (rgvt[i] & VT_BYREF)
7215 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
7216 V_VT(arg) = VT_VARIANT | VT_BYREF;
7217 V_VARIANTREF(arg) = missing_arg;
7219 else
7220 missing_arg = arg;
7221 V_VT(missing_arg) = VT_ERROR;
7222 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
7225 else
7227 hres = DISP_E_BADPARAMCOUNT;
7228 break;
7231 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7233 /* VT_VOID is a special case for return types, so it is not
7234 * handled in the general function */
7235 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
7236 V_VT(&varresult) = VT_EMPTY;
7237 else
7239 V_VT(&varresult) = 0;
7240 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
7241 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7244 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv,
7245 V_VT(&varresult), func_desc->cParams, rgvt,
7246 prgpvarg, &varresult);
7248 vargs_converted = 0;
7250 for (i = 0; i < func_desc->cParams; i++)
7252 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7253 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7255 if (wParamFlags & PARAMFLAG_FLCID)
7256 continue;
7257 else if (wParamFlags & PARAMFLAG_FRETVAL)
7259 if (TRACE_ON(ole))
7261 TRACE("[retval] value: ");
7262 dump_Variant(prgpvarg[i]);
7265 if (pVarResult)
7267 VariantInit(pVarResult);
7268 /* deref return value */
7269 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
7272 VARIANT_ClearInd(prgpvarg[i]);
7274 else if (vargs_converted < pDispParams->cArgs)
7276 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7277 if (wParamFlags & PARAMFLAG_FOUT)
7279 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
7281 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
7283 if (FAILED(hres))
7285 ERR("failed to convert param %d to vt %d\n", i,
7286 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
7287 break;
7291 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
7292 func_desc->cParamsOpt < 0 &&
7293 i == func_desc->cParams-1)
7295 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
7296 LONG j, ubound;
7297 VARIANT *v;
7298 hres = SafeArrayGetUBound(a, 1, &ubound);
7299 if (hres != S_OK)
7301 ERR("SafeArrayGetUBound failed with %x\n", hres);
7302 break;
7304 hres = SafeArrayAccessData(a, (LPVOID)&v);
7305 if (hres != S_OK)
7307 ERR("SafeArrayAccessData failed with %x\n", hres);
7308 break;
7310 for (j = 0; j <= ubound; j++)
7311 VariantClear(&v[j]);
7312 hres = SafeArrayUnaccessData(a);
7313 if (hres != S_OK)
7315 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7316 break;
7319 VariantClear(&rgvarg[i]);
7320 vargs_converted++;
7322 else if (wParamFlags & PARAMFLAG_FOPT)
7324 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7325 VariantClear(&rgvarg[i]);
7328 VariantClear(&missing_arg[i]);
7331 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
7333 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
7334 hres = DISP_E_EXCEPTION;
7335 if (pExcepInfo)
7337 IErrorInfo *pErrorInfo;
7338 pExcepInfo->scode = V_ERROR(&varresult);
7339 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
7341 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
7342 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
7343 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
7344 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
7346 IErrorInfo_Release(pErrorInfo);
7350 if (V_VT(&varresult) != VT_ERROR)
7352 TRACE("varresult value: ");
7353 dump_Variant(&varresult);
7355 if (pVarResult)
7357 VariantClear(pVarResult);
7358 *pVarResult = varresult;
7360 else
7361 VariantClear(&varresult);
7364 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
7365 (func_desc->invkind & INVOKE_PROPERTYGET) &&
7366 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
7367 (pDispParams->cArgs != 0))
7369 if (V_VT(pVarResult) == VT_DISPATCH)
7371 IDispatch *pDispatch = V_DISPATCH(pVarResult);
7372 /* Note: not VariantClear; we still need the dispatch
7373 * pointer to be valid */
7374 VariantInit(pVarResult);
7375 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
7376 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
7377 pDispParams, pVarResult, pExcepInfo, pArgErr);
7378 IDispatch_Release(pDispatch);
7380 else
7382 VariantClear(pVarResult);
7383 hres = DISP_E_NOTACOLLECTION;
7387 func_fail:
7388 heap_free(buffer);
7389 break;
7391 case FUNC_DISPATCH: {
7392 IDispatch *disp;
7394 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
7395 if (SUCCEEDED(hres)) {
7396 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7397 hres = IDispatch_Invoke(
7398 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
7399 pVarResult,pExcepInfo,pArgErr
7401 if (FAILED(hres))
7402 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
7403 IDispatch_Release(disp);
7404 } else
7405 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7406 break;
7408 default:
7409 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
7410 hres = E_FAIL;
7411 break;
7414 TRACE("-- 0x%08x\n", hres);
7415 return hres;
7417 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
7418 VARDESC *var_desc;
7420 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
7421 if(FAILED(hres)) return hres;
7423 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7424 dump_VARDESC(var_desc);
7425 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
7426 return E_NOTIMPL;
7429 /* not found, look for it in inherited interfaces */
7430 ITypeInfo2_GetTypeKind(iface, &type_kind);
7431 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
7432 if(This->impltypes) {
7433 /* recursive search */
7434 ITypeInfo *pTInfo;
7435 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7436 if(SUCCEEDED(hres)){
7437 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
7438 ITypeInfo_Release(pTInfo);
7439 return hres;
7441 WARN("Could not search inherited interface!\n");
7444 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
7445 return DISP_E_MEMBERNOTFOUND;
7448 /* ITypeInfo::GetDocumentation
7450 * Retrieves the documentation string, the complete Help file name and path,
7451 * and the context ID for the Help topic for a specified type description.
7453 * (Can be tested by the Visual Basic Editor in Word for instance.)
7455 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
7456 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
7457 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
7459 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7460 const TLBFuncDesc *pFDesc;
7461 const TLBVarDesc *pVDesc;
7462 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7463 " HelpContext(%p) HelpFile(%p)\n",
7464 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
7465 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7466 if(pBstrName)
7467 *pBstrName=SysAllocString(TLB_get_bstr(This->Name));
7468 if(pBstrDocString)
7469 *pBstrDocString=SysAllocString(TLB_get_bstr(This->DocString));
7470 if(pdwHelpContext)
7471 *pdwHelpContext=This->dwHelpContext;
7472 if(pBstrHelpFile)
7473 *pBstrHelpFile=SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7474 return S_OK;
7475 }else {/* for a member */
7476 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7477 if(pFDesc){
7478 if(pBstrName)
7479 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Name));
7480 if(pBstrDocString)
7481 *pBstrDocString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7482 if(pdwHelpContext)
7483 *pdwHelpContext=pFDesc->helpcontext;
7484 if(pBstrHelpFile)
7485 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7486 return S_OK;
7488 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
7489 if(pVDesc){
7490 if(pBstrName)
7491 *pBstrName = SysAllocString(TLB_get_bstr(pVDesc->Name));
7492 if(pBstrDocString)
7493 *pBstrDocString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7494 if(pdwHelpContext)
7495 *pdwHelpContext=pVDesc->HelpContext;
7496 if(pBstrHelpFile)
7497 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7498 return S_OK;
7502 if(This->impltypes &&
7503 (This->typekind==TKIND_INTERFACE || This->typekind==TKIND_DISPATCH)) {
7504 /* recursive search */
7505 ITypeInfo *pTInfo;
7506 HRESULT result;
7507 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7508 if(SUCCEEDED(result)) {
7509 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
7510 pBstrDocString, pdwHelpContext, pBstrHelpFile);
7511 ITypeInfo_Release(pTInfo);
7512 return result;
7514 WARN("Could not search inherited interface!\n");
7517 WARN("member %d not found\n", memid);
7518 return TYPE_E_ELEMENTNOTFOUND;
7521 /* ITypeInfo::GetDllEntry
7523 * Retrieves a description or specification of an entry point for a function
7524 * in a DLL.
7526 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
7527 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
7528 WORD *pwOrdinal)
7530 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7531 const TLBFuncDesc *pFDesc;
7533 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
7535 if (pBstrDllName) *pBstrDllName = NULL;
7536 if (pBstrName) *pBstrName = NULL;
7537 if (pwOrdinal) *pwOrdinal = 0;
7539 if (This->typekind != TKIND_MODULE)
7540 return TYPE_E_BADMODULEKIND;
7542 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7543 if(pFDesc){
7544 dump_TypeInfo(This);
7545 if (TRACE_ON(ole))
7546 dump_TLBFuncDescOne(pFDesc);
7548 if (pBstrDllName)
7549 *pBstrDllName = SysAllocString(TLB_get_bstr(This->DllName));
7551 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
7552 if (pBstrName)
7553 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Entry));
7554 if (pwOrdinal)
7555 *pwOrdinal = -1;
7556 return S_OK;
7558 if (pBstrName)
7559 *pBstrName = NULL;
7560 if (pwOrdinal)
7561 *pwOrdinal = LOWORD(pFDesc->Entry);
7562 return S_OK;
7564 return TYPE_E_ELEMENTNOTFOUND;
7567 /* internal function to make the inherited interfaces' methods appear
7568 * part of the interface */
7569 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7570 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7572 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7573 HRESULT hr;
7575 TRACE("%p, 0x%x\n", iface, *hRefType);
7577 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7579 ITypeInfo *pSubTypeInfo;
7581 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7582 if (FAILED(hr))
7583 return hr;
7585 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7586 hRefType, ppTInfo);
7587 ITypeInfo_Release(pSubTypeInfo);
7588 if (SUCCEEDED(hr))
7589 return hr;
7591 *hRefType -= DISPATCH_HREF_OFFSET;
7593 if (!(*hRefType & DISPATCH_HREF_MASK))
7594 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7595 else
7596 return E_FAIL;
7599 /* ITypeInfo::GetRefTypeInfo
7601 * If a type description references other type descriptions, it retrieves
7602 * the referenced type descriptions.
7604 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7605 ITypeInfo2 *iface,
7606 HREFTYPE hRefType,
7607 ITypeInfo **ppTInfo)
7609 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7610 HRESULT result = E_FAIL;
7612 if(!ppTInfo)
7613 return E_INVALIDARG;
7615 if ((INT)hRefType < 0) {
7616 ITypeInfoImpl *pTypeInfoImpl;
7618 if (!(This->wTypeFlags & TYPEFLAG_FDUAL) ||
7619 !(This->typekind == TKIND_INTERFACE ||
7620 This->typekind == TKIND_DISPATCH))
7621 return TYPE_E_ELEMENTNOTFOUND;
7623 /* when we meet a DUAL typeinfo, we must create the alternate
7624 * version of it.
7626 pTypeInfoImpl = ITypeInfoImpl_Constructor();
7628 *pTypeInfoImpl = *This;
7629 pTypeInfoImpl->ref = 0;
7630 list_init(&pTypeInfoImpl->custdata_list);
7632 if (This->typekind == TKIND_INTERFACE)
7633 pTypeInfoImpl->typekind = TKIND_DISPATCH;
7634 else
7635 pTypeInfoImpl->typekind = TKIND_INTERFACE;
7637 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface;
7638 /* the AddRef implicitly adds a reference to the parent typelib, which
7639 * stops the copied data from being destroyed until the new typeinfo's
7640 * refcount goes to zero, but we need to signal to the new instance to
7641 * not free its data structures when it is destroyed */
7642 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7644 ITypeInfo_AddRef(*ppTInfo);
7646 result = S_OK;
7647 } else if ((hRefType & DISPATCH_HREF_MASK) &&
7648 (This->typekind == TKIND_DISPATCH))
7650 HREFTYPE href_dispatch = hRefType;
7651 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
7652 } else {
7653 TLBRefType *ref_type;
7654 ITypeLib *pTLib = NULL;
7655 UINT i;
7657 if(!(hRefType & 0x1)){
7658 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
7660 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
7662 result = S_OK;
7663 *ppTInfo = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
7664 ITypeInfo_AddRef(*ppTInfo);
7665 goto end;
7670 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7672 if(ref_type->reference == (hRefType & (~0x3)))
7673 break;
7675 if(&ref_type->entry == &This->pTypeLib->ref_list)
7677 FIXME("Can't find pRefType for ref %x\n", hRefType);
7678 goto end;
7681 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7682 UINT Index;
7683 TRACE("internal reference\n");
7684 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7685 } else {
7686 if(ref_type->pImpTLInfo->pImpTypeLib) {
7687 TRACE("typeinfo in imported typelib that is already loaded\n");
7688 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
7689 ITypeLib_AddRef(pTLib);
7690 result = S_OK;
7691 } else {
7692 BSTR libnam;
7694 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7696 result = query_typelib_path(TLB_get_guid_null(ref_type->pImpTLInfo->guid),
7697 ref_type->pImpTLInfo->wVersionMajor,
7698 ref_type->pImpTLInfo->wVersionMinor,
7699 This->pTypeLib->syskind,
7700 ref_type->pImpTLInfo->lcid, &libnam, TRUE);
7701 if(FAILED(result))
7702 libnam = SysAllocString(ref_type->pImpTLInfo->name);
7704 result = LoadTypeLib(libnam, &pTLib);
7705 SysFreeString(libnam);
7707 if(SUCCEEDED(result)) {
7708 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
7709 ITypeLib_AddRef(pTLib);
7713 if(SUCCEEDED(result)) {
7714 if(ref_type->index == TLB_REF_USE_GUID)
7715 result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), ppTInfo);
7716 else
7717 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, ppTInfo);
7719 if (pTLib != NULL)
7720 ITypeLib_Release(pTLib);
7723 end:
7724 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
7725 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
7726 return result;
7729 /* ITypeInfo::AddressOfMember
7731 * Retrieves the addresses of static functions or variables, such as those
7732 * defined in a DLL.
7734 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
7735 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
7737 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7738 HRESULT hr;
7739 BSTR dll, entry;
7740 WORD ordinal;
7741 HMODULE module;
7743 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
7745 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
7746 if (FAILED(hr))
7747 return hr;
7749 module = LoadLibraryW(dll);
7750 if (!module)
7752 ERR("couldn't load %s\n", debugstr_w(dll));
7753 SysFreeString(dll);
7754 SysFreeString(entry);
7755 return STG_E_FILENOTFOUND;
7757 /* FIXME: store library somewhere where we can free it */
7759 if (entry)
7761 LPSTR entryA;
7762 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
7763 entryA = heap_alloc(len);
7764 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
7766 *ppv = GetProcAddress(module, entryA);
7767 if (!*ppv)
7768 ERR("function not found %s\n", debugstr_a(entryA));
7770 heap_free(entryA);
7772 else
7774 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7775 if (!*ppv)
7776 ERR("function not found %d\n", ordinal);
7779 SysFreeString(dll);
7780 SysFreeString(entry);
7782 if (!*ppv)
7783 return TYPE_E_DLLFUNCTIONNOTFOUND;
7785 return S_OK;
7788 /* ITypeInfo::CreateInstance
7790 * Creates a new instance of a type that describes a component object class
7791 * (coclass).
7793 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7794 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7796 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7797 HRESULT hr;
7798 TYPEATTR *pTA;
7800 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7802 *ppvObj = NULL;
7804 if(pOuterUnk)
7806 WARN("Not able to aggregate\n");
7807 return CLASS_E_NOAGGREGATION;
7810 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
7811 if(FAILED(hr)) return hr;
7813 if(pTA->typekind != TKIND_COCLASS)
7815 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7816 hr = E_INVALIDARG;
7817 goto end;
7820 hr = S_FALSE;
7821 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7823 IUnknown *pUnk;
7824 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7825 TRACE("GetActiveObject rets %08x\n", hr);
7826 if(hr == S_OK)
7828 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7829 IUnknown_Release(pUnk);
7833 if(hr != S_OK)
7834 hr = CoCreateInstance(&pTA->guid, NULL,
7835 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7836 riid, ppvObj);
7838 end:
7839 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
7840 return hr;
7843 /* ITypeInfo::GetMops
7845 * Retrieves marshalling information.
7847 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7848 BSTR *pBstrMops)
7850 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7851 FIXME("(%p %d) stub!\n", This, memid);
7852 *pBstrMops = NULL;
7853 return S_OK;
7856 /* ITypeInfo::GetContainingTypeLib
7858 * Retrieves the containing type library and the index of the type description
7859 * within that type library.
7861 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7862 ITypeLib * *ppTLib, UINT *pIndex)
7864 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7866 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7867 if (pIndex) {
7868 *pIndex=This->index;
7869 TRACE("returning pIndex=%d\n", *pIndex);
7872 if (ppTLib) {
7873 *ppTLib=(LPTYPELIB )(This->pTypeLib);
7874 ITypeLib_AddRef(*ppTLib);
7875 TRACE("returning ppTLib=%p\n", *ppTLib);
7878 return S_OK;
7881 /* ITypeInfo::ReleaseTypeAttr
7883 * Releases a TYPEATTR previously returned by Get
7886 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7887 TYPEATTR* pTypeAttr)
7889 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7890 TRACE("(%p)->(%p)\n", This, pTypeAttr);
7891 heap_free(pTypeAttr);
7894 /* ITypeInfo::ReleaseFuncDesc
7896 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7898 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7899 ITypeInfo2 *iface,
7900 FUNCDESC *pFuncDesc)
7902 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7903 SHORT i;
7905 TRACE("(%p)->(%p)\n", This, pFuncDesc);
7907 for (i = 0; i < pFuncDesc->cParams; i++)
7908 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7909 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7911 SysFreeString((BSTR)pFuncDesc);
7914 /* ITypeInfo::ReleaseVarDesc
7916 * Releases a VARDESC previously returned by GetVarDesc.
7918 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7919 VARDESC *pVarDesc)
7921 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7922 TRACE("(%p)->(%p)\n", This, pVarDesc);
7924 TLB_FreeVarDesc(pVarDesc);
7927 /* ITypeInfo2::GetTypeKind
7929 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7932 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7933 TYPEKIND *pTypeKind)
7935 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7936 *pTypeKind=This->typekind;
7937 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7938 return S_OK;
7941 /* ITypeInfo2::GetTypeFlags
7943 * Returns the type flags without any allocations. This returns a DWORD type
7944 * flag, which expands the type flags without growing the TYPEATTR (type
7945 * attribute).
7948 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7950 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7951 *pTypeFlags=This->wTypeFlags;
7952 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7953 return S_OK;
7956 /* ITypeInfo2::GetFuncIndexOfMemId
7957 * Binds to a specific member based on a known DISPID, where the member name
7958 * is not known (for example, when binding to a default member).
7961 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7962 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7964 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7965 UINT fdc;
7966 HRESULT result;
7968 for (fdc = 0; fdc < This->cFuncs; ++fdc){
7969 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
7970 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7971 break;
7973 if(fdc < This->cFuncs) {
7974 *pFuncIndex = fdc;
7975 result = S_OK;
7976 } else
7977 result = TYPE_E_ELEMENTNOTFOUND;
7979 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7980 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7981 return result;
7984 /* TypeInfo2::GetVarIndexOfMemId
7986 * Binds to a specific member based on a known DISPID, where the member name
7987 * is not known (for example, when binding to a default member).
7990 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7991 MEMBERID memid, UINT *pVarIndex)
7993 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7994 TLBVarDesc *pVarInfo;
7996 TRACE("%p %d %p\n", iface, memid, pVarIndex);
7998 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
7999 if(!pVarInfo)
8000 return TYPE_E_ELEMENTNOTFOUND;
8002 *pVarIndex = (pVarInfo - This->vardescs);
8004 return S_OK;
8007 /* ITypeInfo2::GetCustData
8009 * Gets the custom data
8011 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
8012 ITypeInfo2 * iface,
8013 REFGUID guid,
8014 VARIANT *pVarVal)
8016 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8017 TLBCustData *pCData;
8019 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8021 if(!guid || !pVarVal)
8022 return E_INVALIDARG;
8024 pCData = TLB_get_custdata_by_guid(This->pcustdata_list, guid);
8026 VariantInit( pVarVal);
8027 if (pCData)
8028 VariantCopy( pVarVal, &pCData->data);
8029 else
8030 VariantClear( pVarVal );
8031 return S_OK;
8034 /* ITypeInfo2::GetFuncCustData
8036 * Gets the custom data
8038 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
8039 ITypeInfo2 * iface,
8040 UINT index,
8041 REFGUID guid,
8042 VARIANT *pVarVal)
8044 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8045 TLBCustData *pCData;
8046 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8048 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8050 if(index >= This->cFuncs)
8051 return TYPE_E_ELEMENTNOTFOUND;
8053 pCData = TLB_get_custdata_by_guid(&pFDesc->custdata_list, guid);
8054 if(!pCData)
8055 return TYPE_E_ELEMENTNOTFOUND;
8057 VariantInit(pVarVal);
8058 VariantCopy(pVarVal, &pCData->data);
8060 return S_OK;
8063 /* ITypeInfo2::GetParamCustData
8065 * Gets the custom data
8067 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
8068 ITypeInfo2 * iface,
8069 UINT indexFunc,
8070 UINT indexParam,
8071 REFGUID guid,
8072 VARIANT *pVarVal)
8074 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8075 TLBCustData *pCData;
8076 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8078 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
8079 debugstr_guid(guid), pVarVal);
8081 if(indexFunc >= This->cFuncs)
8082 return TYPE_E_ELEMENTNOTFOUND;
8084 if(indexParam >= pFDesc->funcdesc.cParams)
8085 return TYPE_E_ELEMENTNOTFOUND;
8087 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
8088 if(!pCData)
8089 return TYPE_E_ELEMENTNOTFOUND;
8091 VariantInit(pVarVal);
8092 VariantCopy(pVarVal, &pCData->data);
8094 return S_OK;
8097 /* ITypeInfo2::GetVarCustData
8099 * Gets the custom data
8101 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
8102 ITypeInfo2 * iface,
8103 UINT index,
8104 REFGUID guid,
8105 VARIANT *pVarVal)
8107 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8108 TLBCustData *pCData;
8109 TLBVarDesc *pVDesc = &This->vardescs[index];
8111 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8113 if(index >= This->cVars)
8114 return TYPE_E_ELEMENTNOTFOUND;
8116 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
8117 if(!pCData)
8118 return TYPE_E_ELEMENTNOTFOUND;
8120 VariantInit(pVarVal);
8121 VariantCopy(pVarVal, &pCData->data);
8123 return S_OK;
8126 /* ITypeInfo2::GetImplCustData
8128 * Gets the custom data
8130 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
8131 ITypeInfo2 * iface,
8132 UINT index,
8133 REFGUID guid,
8134 VARIANT *pVarVal)
8136 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8137 TLBCustData *pCData;
8138 TLBImplType *pRDesc = &This->impltypes[index];
8140 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8142 if(index >= This->cImplTypes)
8143 return TYPE_E_ELEMENTNOTFOUND;
8145 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
8146 if(!pCData)
8147 return TYPE_E_ELEMENTNOTFOUND;
8149 VariantInit(pVarVal);
8150 VariantCopy(pVarVal, &pCData->data);
8152 return S_OK;
8155 /* ITypeInfo2::GetDocumentation2
8157 * Retrieves the documentation string, the complete Help file name and path,
8158 * the localization context to use, and the context ID for the library Help
8159 * topic in the Help file.
8162 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
8163 ITypeInfo2 * iface,
8164 MEMBERID memid,
8165 LCID lcid,
8166 BSTR *pbstrHelpString,
8167 DWORD *pdwHelpStringContext,
8168 BSTR *pbstrHelpStringDll)
8170 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8171 const TLBFuncDesc *pFDesc;
8172 const TLBVarDesc *pVDesc;
8173 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8174 "HelpStringContext(%p) HelpStringDll(%p)\n",
8175 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
8176 pbstrHelpStringDll );
8177 /* the help string should be obtained from the helpstringdll,
8178 * using the _DLLGetDocumentation function, based on the supplied
8179 * lcid. Nice to do sometime...
8181 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
8182 if(pbstrHelpString)
8183 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->Name));
8184 if(pdwHelpStringContext)
8185 *pdwHelpStringContext=This->dwHelpStringContext;
8186 if(pbstrHelpStringDll)
8187 *pbstrHelpStringDll=
8188 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8189 return S_OK;
8190 }else {/* for a member */
8191 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
8192 if(pFDesc){
8193 if(pbstrHelpString)
8194 *pbstrHelpString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
8195 if(pdwHelpStringContext)
8196 *pdwHelpStringContext=pFDesc->HelpStringContext;
8197 if(pbstrHelpStringDll)
8198 *pbstrHelpStringDll=
8199 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8200 return S_OK;
8202 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
8203 if(pVDesc){
8204 if(pbstrHelpString)
8205 *pbstrHelpString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
8206 if(pdwHelpStringContext)
8207 *pdwHelpStringContext=pVDesc->HelpStringContext;
8208 if(pbstrHelpStringDll)
8209 *pbstrHelpStringDll=
8210 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8211 return S_OK;
8214 return TYPE_E_ELEMENTNOTFOUND;
8217 /* ITypeInfo2::GetAllCustData
8219 * Gets all custom data items for the Type info.
8222 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
8223 ITypeInfo2 * iface,
8224 CUSTDATA *pCustData)
8226 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8228 TRACE("%p %p\n", This, pCustData);
8230 return TLB_copy_all_custdata(This->pcustdata_list, pCustData);
8233 /* ITypeInfo2::GetAllFuncCustData
8235 * Gets all custom data items for the specified Function
8238 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
8239 ITypeInfo2 * iface,
8240 UINT index,
8241 CUSTDATA *pCustData)
8243 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8244 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8246 TRACE("%p %u %p\n", This, index, pCustData);
8248 if(index >= This->cFuncs)
8249 return TYPE_E_ELEMENTNOTFOUND;
8251 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
8254 /* ITypeInfo2::GetAllParamCustData
8256 * Gets all custom data items for the Functions
8259 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
8260 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
8262 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8263 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8265 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
8267 if(indexFunc >= This->cFuncs)
8268 return TYPE_E_ELEMENTNOTFOUND;
8270 if(indexParam >= pFDesc->funcdesc.cParams)
8271 return TYPE_E_ELEMENTNOTFOUND;
8273 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
8276 /* ITypeInfo2::GetAllVarCustData
8278 * Gets all custom data items for the specified Variable
8281 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
8282 UINT index, CUSTDATA *pCustData)
8284 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8285 TLBVarDesc * pVDesc = &This->vardescs[index];
8287 TRACE("%p %u %p\n", This, index, pCustData);
8289 if(index >= This->cVars)
8290 return TYPE_E_ELEMENTNOTFOUND;
8292 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
8295 /* ITypeInfo2::GetAllImplCustData
8297 * Gets all custom data items for the specified implementation type
8300 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
8301 ITypeInfo2 * iface,
8302 UINT index,
8303 CUSTDATA *pCustData)
8305 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8306 TLBImplType *pRDesc = &This->impltypes[index];
8308 TRACE("%p %u %p\n", This, index, pCustData);
8310 if(index >= This->cImplTypes)
8311 return TYPE_E_ELEMENTNOTFOUND;
8313 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
8316 static const ITypeInfo2Vtbl tinfvt =
8319 ITypeInfo_fnQueryInterface,
8320 ITypeInfo_fnAddRef,
8321 ITypeInfo_fnRelease,
8323 ITypeInfo_fnGetTypeAttr,
8324 ITypeInfo_fnGetTypeComp,
8325 ITypeInfo_fnGetFuncDesc,
8326 ITypeInfo_fnGetVarDesc,
8327 ITypeInfo_fnGetNames,
8328 ITypeInfo_fnGetRefTypeOfImplType,
8329 ITypeInfo_fnGetImplTypeFlags,
8330 ITypeInfo_fnGetIDsOfNames,
8331 ITypeInfo_fnInvoke,
8332 ITypeInfo_fnGetDocumentation,
8333 ITypeInfo_fnGetDllEntry,
8334 ITypeInfo_fnGetRefTypeInfo,
8335 ITypeInfo_fnAddressOfMember,
8336 ITypeInfo_fnCreateInstance,
8337 ITypeInfo_fnGetMops,
8338 ITypeInfo_fnGetContainingTypeLib,
8339 ITypeInfo_fnReleaseTypeAttr,
8340 ITypeInfo_fnReleaseFuncDesc,
8341 ITypeInfo_fnReleaseVarDesc,
8343 ITypeInfo2_fnGetTypeKind,
8344 ITypeInfo2_fnGetTypeFlags,
8345 ITypeInfo2_fnGetFuncIndexOfMemId,
8346 ITypeInfo2_fnGetVarIndexOfMemId,
8347 ITypeInfo2_fnGetCustData,
8348 ITypeInfo2_fnGetFuncCustData,
8349 ITypeInfo2_fnGetParamCustData,
8350 ITypeInfo2_fnGetVarCustData,
8351 ITypeInfo2_fnGetImplTypeCustData,
8352 ITypeInfo2_fnGetDocumentation2,
8353 ITypeInfo2_fnGetAllCustData,
8354 ITypeInfo2_fnGetAllFuncCustData,
8355 ITypeInfo2_fnGetAllParamCustData,
8356 ITypeInfo2_fnGetAllVarCustData,
8357 ITypeInfo2_fnGetAllImplTypeCustData,
8360 /******************************************************************************
8361 * CreateDispTypeInfo [OLEAUT32.31]
8363 * Build type information for an object so it can be called through an
8364 * IDispatch interface.
8366 * RETURNS
8367 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8368 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8370 * NOTES
8371 * This call allows an objects methods to be accessed through IDispatch, by
8372 * building an ITypeInfo object that IDispatch can use to call through.
8374 HRESULT WINAPI CreateDispTypeInfo(
8375 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
8376 LCID lcid, /* [I] Locale Id */
8377 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
8379 ITypeInfoImpl *pTIClass, *pTIIface;
8380 ITypeLibImpl *pTypeLibImpl;
8381 unsigned int param, func;
8382 TLBFuncDesc *pFuncDesc;
8383 TLBRefType *ref;
8385 TRACE("\n");
8386 pTypeLibImpl = TypeLibImpl_Constructor();
8387 if (!pTypeLibImpl) return E_FAIL;
8389 pTypeLibImpl->TypeInfoCount = 2;
8390 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
8392 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
8393 pTIIface->pTypeLib = pTypeLibImpl;
8394 pTIIface->index = 0;
8395 pTIIface->Name = NULL;
8396 pTIIface->dwHelpContext = -1;
8397 pTIIface->guid = NULL;
8398 pTIIface->lcid = lcid;
8399 pTIIface->typekind = TKIND_INTERFACE;
8400 pTIIface->wMajorVerNum = 0;
8401 pTIIface->wMinorVerNum = 0;
8402 pTIIface->cbAlignment = 2;
8403 pTIIface->cbSizeInstance = -1;
8404 pTIIface->cbSizeVft = -1;
8405 pTIIface->cFuncs = 0;
8406 pTIIface->cImplTypes = 0;
8407 pTIIface->cVars = 0;
8408 pTIIface->wTypeFlags = 0;
8409 pTIIface->hreftype = 0;
8411 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers);
8412 pFuncDesc = pTIIface->funcdescs;
8413 for(func = 0; func < pidata->cMembers; func++) {
8414 METHODDATA *md = pidata->pmethdata + func;
8415 pFuncDesc->Name = TLB_append_str(&pTypeLibImpl->name_list, md->szName);
8416 pFuncDesc->funcdesc.memid = md->dispid;
8417 pFuncDesc->funcdesc.lprgscode = NULL;
8418 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
8419 pFuncDesc->funcdesc.invkind = md->wFlags;
8420 pFuncDesc->funcdesc.callconv = md->cc;
8421 pFuncDesc->funcdesc.cParams = md->cArgs;
8422 pFuncDesc->funcdesc.cParamsOpt = 0;
8423 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
8424 pFuncDesc->funcdesc.cScodes = 0;
8425 pFuncDesc->funcdesc.wFuncFlags = 0;
8426 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
8427 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
8428 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
8429 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8430 md->cArgs * sizeof(ELEMDESC));
8431 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
8432 for(param = 0; param < md->cArgs; param++) {
8433 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
8434 pFuncDesc->pParamDesc[param].Name = TLB_append_str(&pTypeLibImpl->name_list, md->ppdata[param].szName);
8436 pFuncDesc->helpcontext = 0;
8437 pFuncDesc->HelpStringContext = 0;
8438 pFuncDesc->HelpString = NULL;
8439 pFuncDesc->Entry = NULL;
8440 list_init(&pFuncDesc->custdata_list);
8441 pTIIface->cFuncs++;
8442 ++pFuncDesc;
8445 dump_TypeInfo(pTIIface);
8447 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
8448 pTIClass->pTypeLib = pTypeLibImpl;
8449 pTIClass->index = 1;
8450 pTIClass->Name = NULL;
8451 pTIClass->dwHelpContext = -1;
8452 pTIClass->guid = NULL;
8453 pTIClass->lcid = lcid;
8454 pTIClass->typekind = TKIND_COCLASS;
8455 pTIClass->wMajorVerNum = 0;
8456 pTIClass->wMinorVerNum = 0;
8457 pTIClass->cbAlignment = 2;
8458 pTIClass->cbSizeInstance = -1;
8459 pTIClass->cbSizeVft = -1;
8460 pTIClass->cFuncs = 0;
8461 pTIClass->cImplTypes = 1;
8462 pTIClass->cVars = 0;
8463 pTIClass->wTypeFlags = 0;
8464 pTIClass->hreftype = sizeof(MSFT_TypeInfoBase);
8466 pTIClass->impltypes = TLBImplType_Alloc(1);
8468 ref = heap_alloc_zero(sizeof(*ref));
8469 ref->pImpTLInfo = TLB_REF_INTERNAL;
8470 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
8472 dump_TypeInfo(pTIClass);
8474 *pptinfo = (ITypeInfo *)&pTIClass->ITypeInfo2_iface;
8476 ITypeInfo_AddRef(*pptinfo);
8477 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
8479 return S_OK;
8483 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
8485 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8487 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, ppv);
8490 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
8492 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8494 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
8497 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
8499 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8501 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
8504 static HRESULT WINAPI ITypeComp_fnBind(
8505 ITypeComp * iface,
8506 OLECHAR * szName,
8507 ULONG lHash,
8508 WORD wFlags,
8509 ITypeInfo ** ppTInfo,
8510 DESCKIND * pDescKind,
8511 BINDPTR * pBindPtr)
8513 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8514 const TLBFuncDesc *pFDesc;
8515 const TLBVarDesc *pVDesc;
8516 HRESULT hr = DISP_E_MEMBERNOTFOUND;
8517 UINT fdc;
8519 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8521 *pDescKind = DESCKIND_NONE;
8522 pBindPtr->lpfuncdesc = NULL;
8523 *ppTInfo = NULL;
8525 for(fdc = 0; fdc < This->cFuncs; ++fdc){
8526 pFDesc = &This->funcdescs[fdc];
8527 if (!lstrcmpiW(TLB_get_bstr(pFDesc->Name), szName)) {
8528 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
8529 break;
8530 else
8531 /* name found, but wrong flags */
8532 hr = TYPE_E_TYPEMISMATCH;
8536 if (fdc < This->cFuncs)
8538 HRESULT hr = TLB_AllocAndInitFuncDesc(
8539 &pFDesc->funcdesc,
8540 &pBindPtr->lpfuncdesc,
8541 This->typekind == TKIND_DISPATCH);
8542 if (FAILED(hr))
8543 return hr;
8544 *pDescKind = DESCKIND_FUNCDESC;
8545 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8546 ITypeInfo_AddRef(*ppTInfo);
8547 return S_OK;
8548 } else {
8549 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->cVars, szName);
8550 if(pVDesc){
8551 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
8552 if (FAILED(hr))
8553 return hr;
8554 *pDescKind = DESCKIND_VARDESC;
8555 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8556 ITypeInfo_AddRef(*ppTInfo);
8557 return S_OK;
8561 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
8562 /* recursive search */
8563 ITypeInfo *pTInfo;
8564 ITypeComp *pTComp;
8565 HRESULT hr;
8566 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
8567 if (SUCCEEDED(hr))
8569 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
8570 ITypeInfo_Release(pTInfo);
8572 if (SUCCEEDED(hr))
8574 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8575 ITypeComp_Release(pTComp);
8576 if (SUCCEEDED(hr) && *pDescKind == DESCKIND_FUNCDESC &&
8577 This->typekind == TKIND_DISPATCH)
8579 FUNCDESC *tmp = pBindPtr->lpfuncdesc;
8580 hr = TLB_AllocAndInitFuncDesc(tmp, &pBindPtr->lpfuncdesc, TRUE);
8581 SysFreeString((BSTR)tmp);
8583 return hr;
8585 WARN("Could not search inherited interface!\n");
8587 if (hr == DISP_E_MEMBERNOTFOUND)
8588 hr = S_OK;
8589 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
8590 return hr;
8593 static HRESULT WINAPI ITypeComp_fnBindType(
8594 ITypeComp * iface,
8595 OLECHAR * szName,
8596 ULONG lHash,
8597 ITypeInfo ** ppTInfo,
8598 ITypeComp ** ppTComp)
8600 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
8602 /* strange behaviour (does nothing) but like the
8603 * original */
8605 if (!ppTInfo || !ppTComp)
8606 return E_POINTER;
8608 *ppTInfo = NULL;
8609 *ppTComp = NULL;
8611 return S_OK;
8614 static const ITypeCompVtbl tcompvt =
8617 ITypeComp_fnQueryInterface,
8618 ITypeComp_fnAddRef,
8619 ITypeComp_fnRelease,
8621 ITypeComp_fnBind,
8622 ITypeComp_fnBindType
8625 HRESULT WINAPI CreateTypeLib2(SYSKIND syskind, LPCOLESTR szFile,
8626 ICreateTypeLib2** ppctlib)
8628 ITypeLibImpl *This;
8629 HRESULT hres;
8631 TRACE("(%d,%s,%p)\n", syskind, debugstr_w(szFile), ppctlib);
8633 if (!szFile) return E_INVALIDARG;
8635 This = TypeLibImpl_Constructor();
8636 if (!This)
8637 return E_OUTOFMEMORY;
8639 This->lcid = GetSystemDefaultLCID();
8640 This->syskind = syskind;
8641 This->ptr_size = get_ptr_size(syskind);
8643 This->path = heap_alloc((lstrlenW(szFile) + 1) * sizeof(WCHAR));
8644 if (!This->path) {
8645 ITypeLib2_Release(&This->ITypeLib2_iface);
8646 return E_OUTOFMEMORY;
8648 lstrcpyW(This->path, szFile);
8650 hres = ITypeLib2_QueryInterface(&This->ITypeLib2_iface, &IID_ICreateTypeLib2, (LPVOID*)ppctlib);
8651 ITypeLib2_Release(&This->ITypeLib2_iface);
8652 return hres;
8655 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
8656 REFIID riid, void **object)
8658 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8660 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, object);
8663 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
8665 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8667 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
8670 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
8672 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8674 return ITypeLib2_Release(&This->ITypeLib2_iface);
8677 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
8678 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
8680 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8681 ITypeInfoImpl *info;
8682 HRESULT hres;
8684 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo);
8686 if (!ctinfo || !name)
8687 return E_INVALIDARG;
8689 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, name);
8690 if (info)
8691 return TYPE_E_NAMECONFLICT;
8693 if (This->typeinfos)
8694 This->typeinfos = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->typeinfos,
8695 sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1));
8696 else
8697 This->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*));
8699 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor();
8701 info->pTypeLib = This;
8702 info->Name = TLB_append_str(&This->name_list, name);
8703 info->index = This->TypeInfoCount;
8704 info->typekind = kind;
8705 info->cbAlignment = 4;
8707 switch(info->typekind) {
8708 case TKIND_ENUM:
8709 case TKIND_INTERFACE:
8710 case TKIND_DISPATCH:
8711 case TKIND_COCLASS:
8712 info->cbSizeInstance = This->ptr_size;
8713 break;
8714 case TKIND_RECORD:
8715 case TKIND_UNION:
8716 info->cbSizeInstance = 0;
8717 break;
8718 case TKIND_MODULE:
8719 info->cbSizeInstance = 2;
8720 break;
8721 case TKIND_ALIAS:
8722 info->cbSizeInstance = -0x75;
8723 break;
8724 default:
8725 FIXME("unrecognized typekind %d\n", info->typekind);
8726 info->cbSizeInstance = 0xdeadbeef;
8727 break;
8730 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface,
8731 &IID_ICreateTypeInfo, (void **)ctinfo);
8732 if (FAILED(hres)) {
8733 ITypeInfo2_Release(&info->ITypeInfo2_iface);
8734 return hres;
8737 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase);
8739 ++This->TypeInfoCount;
8741 return S_OK;
8744 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
8745 LPOLESTR name)
8747 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8749 TRACE("%p %s\n", This, wine_dbgstr_w(name));
8751 if (!name)
8752 return E_INVALIDARG;
8754 This->Name = TLB_append_str(&This->name_list, name);
8756 return S_OK;
8759 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
8760 WORD majorVerNum, WORD minorVerNum)
8762 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8764 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
8766 This->ver_major = majorVerNum;
8767 This->ver_minor = minorVerNum;
8769 return S_OK;
8772 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
8773 REFGUID guid)
8775 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8777 TRACE("%p %s\n", This, debugstr_guid(guid));
8779 This->guid = TLB_append_guid(&This->guid_list, guid, -2);
8781 return S_OK;
8784 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
8785 LPOLESTR doc)
8787 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8789 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
8791 if (!doc)
8792 return E_INVALIDARG;
8794 This->DocString = TLB_append_str(&This->string_list, doc);
8796 return S_OK;
8799 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
8800 LPOLESTR helpFileName)
8802 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8804 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
8806 if (!helpFileName)
8807 return E_INVALIDARG;
8809 This->HelpFile = TLB_append_str(&This->string_list, helpFileName);
8811 return S_OK;
8814 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
8815 DWORD helpContext)
8817 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8819 TRACE("%p %d\n", This, helpContext);
8821 This->dwHelpContext = helpContext;
8823 return S_OK;
8826 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
8827 LCID lcid)
8829 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8831 TRACE("%p %x\n", This, lcid);
8833 This->set_lcid = lcid;
8835 return S_OK;
8838 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
8839 UINT libFlags)
8841 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8843 TRACE("%p %x\n", This, libFlags);
8845 This->libflags = libFlags;
8847 return S_OK;
8850 typedef struct tagWMSFT_SegContents {
8851 DWORD len;
8852 void *data;
8853 } WMSFT_SegContents;
8855 typedef struct tagWMSFT_TLBFile {
8856 MSFT_Header header;
8857 WMSFT_SegContents typeinfo_seg;
8858 WMSFT_SegContents impfile_seg;
8859 WMSFT_SegContents impinfo_seg;
8860 WMSFT_SegContents ref_seg;
8861 WMSFT_SegContents guidhash_seg;
8862 WMSFT_SegContents guid_seg;
8863 WMSFT_SegContents namehash_seg;
8864 WMSFT_SegContents name_seg;
8865 WMSFT_SegContents string_seg;
8866 WMSFT_SegContents typdesc_seg;
8867 WMSFT_SegContents arraydesc_seg;
8868 WMSFT_SegContents custdata_seg;
8869 WMSFT_SegContents cdguids_seg;
8870 MSFT_SegDir segdir;
8871 WMSFT_SegContents aux_seg;
8872 } WMSFT_TLBFile;
8874 static HRESULT WMSFT_compile_strings(ITypeLibImpl *This,
8875 WMSFT_TLBFile *file)
8877 TLBString *str;
8878 UINT last_offs;
8879 char *data;
8881 file->string_seg.len = 0;
8882 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8883 int size;
8885 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str), NULL, 0, NULL, NULL);
8886 if (size == 0)
8887 return E_UNEXPECTED;
8889 size += sizeof(INT16);
8890 if (size % 4)
8891 size = (size + 4) & ~0x3;
8892 if (size < 8)
8893 size = 8;
8895 file->string_seg.len += size;
8897 /* temporarily use str->offset to store the length of the aligned,
8898 * converted string */
8899 str->offset = size;
8902 file->string_seg.data = data = heap_alloc(file->string_seg.len);
8904 last_offs = 0;
8905 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8906 int size;
8908 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8909 data + sizeof(INT16), file->string_seg.len - last_offs - sizeof(INT16), NULL, NULL);
8910 if (size == 0) {
8911 heap_free(file->string_seg.data);
8912 return E_UNEXPECTED;
8915 *((INT16*)data) = size;
8917 memset(data + sizeof(INT16) + size, 0x57, str->offset - size - sizeof(INT16));
8919 size = str->offset;
8920 data += size;
8921 str->offset = last_offs;
8922 last_offs += size;
8925 return S_OK;
8928 static HRESULT WMSFT_compile_names(ITypeLibImpl *This,
8929 WMSFT_TLBFile *file)
8931 TLBString *str;
8932 UINT last_offs;
8933 char *data;
8934 MSFT_NameIntro *last_intro = NULL;
8936 file->header.nametablecount = 0;
8937 file->header.nametablechars = 0;
8939 file->name_seg.len = 0;
8940 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8941 int size;
8943 size = strlenW(str->str);
8944 file->header.nametablechars += size;
8945 file->header.nametablecount++;
8947 size = WideCharToMultiByte(CP_ACP, 0, str->str, size, NULL, 0, NULL, NULL);
8948 if (size == 0)
8949 return E_UNEXPECTED;
8951 size += sizeof(MSFT_NameIntro);
8952 if (size % 4)
8953 size = (size + 4) & ~0x3;
8954 if (size < 8)
8955 size = 8;
8957 file->name_seg.len += size;
8959 /* temporarily use str->offset to store the length of the aligned,
8960 * converted string */
8961 str->offset = size;
8964 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
8965 file->name_seg.data = data = heap_alloc(file->name_seg.len+1);
8967 last_offs = 0;
8968 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8969 int size, hash;
8970 MSFT_NameIntro *intro = (MSFT_NameIntro*)data;
8972 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8973 data + sizeof(MSFT_NameIntro),
8974 file->name_seg.len - last_offs - sizeof(MSFT_NameIntro), NULL, NULL);
8975 if (size == 0) {
8976 heap_free(file->name_seg.data);
8977 return E_UNEXPECTED;
8979 data[sizeof(MSFT_NameIntro) + size] = '\0';
8981 intro->hreftype = -1; /* TODO? */
8982 intro->namelen = size & 0xFF;
8983 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
8984 hash = LHashValOfNameSysA(This->syskind, This->lcid, data + sizeof(MSFT_NameIntro));
8985 intro->namelen |= hash << 16;
8986 intro->next_hash = ((DWORD*)file->namehash_seg.data)[hash & 0x7f];
8987 ((DWORD*)file->namehash_seg.data)[hash & 0x7f] = last_offs;
8989 memset(data + sizeof(MSFT_NameIntro) + size, 0x57,
8990 str->offset - size - sizeof(MSFT_NameIntro));
8992 /* update str->offset to actual value to use in other
8993 * compilation functions that require positions within
8994 * the string table */
8995 last_intro = intro;
8996 size = str->offset;
8997 data += size;
8998 str->offset = last_offs;
8999 last_offs += size;
9002 if(last_intro)
9003 last_intro->hreftype = 0; /* last one is 0? */
9005 return S_OK;
9008 static inline int hash_guid(GUID *guid)
9010 int i, hash = 0;
9012 for (i = 0; i < 8; i ++)
9013 hash ^= ((const short *)guid)[i];
9015 return hash & 0x1f;
9018 static HRESULT WMSFT_compile_guids(ITypeLibImpl *This, WMSFT_TLBFile *file)
9020 TLBGuid *guid;
9021 MSFT_GuidEntry *entry;
9022 DWORD offs;
9023 int hash_key, *guidhashtab;
9025 file->guid_seg.len = sizeof(MSFT_GuidEntry) * list_count(&This->guid_list);
9026 file->guid_seg.data = heap_alloc(file->guid_seg.len);
9028 entry = file->guid_seg.data;
9029 offs = 0;
9030 guidhashtab = file->guidhash_seg.data;
9031 LIST_FOR_EACH_ENTRY(guid, &This->guid_list, TLBGuid, entry){
9032 memcpy(&entry->guid, &guid->guid, sizeof(GUID));
9033 entry->hreftype = guid->hreftype;
9035 hash_key = hash_guid(&guid->guid);
9036 entry->next_hash = guidhashtab[hash_key];
9037 guidhashtab[hash_key] = offs;
9039 guid->offset = offs;
9040 offs += sizeof(MSFT_GuidEntry);
9041 ++entry;
9044 return S_OK;
9047 static DWORD WMSFT_encode_variant(VARIANT *value, WMSFT_TLBFile *file)
9049 VARIANT v = *value;
9050 VARTYPE arg_type = V_VT(value);
9051 int mask = 0;
9052 HRESULT hres;
9053 DWORD ret = file->custdata_seg.len;
9055 if(arg_type == VT_INT)
9056 arg_type = VT_I4;
9057 if(arg_type == VT_UINT)
9058 arg_type = VT_UI4;
9060 v = *value;
9061 if(V_VT(value) != arg_type) {
9062 hres = VariantChangeType(&v, value, 0, arg_type);
9063 if(FAILED(hres)){
9064 ERR("VariantChangeType failed: %08x\n", hres);
9065 return -1;
9069 /* Check if default value can be stored in-place */
9070 switch(arg_type){
9071 case VT_I4:
9072 case VT_UI4:
9073 mask = 0x3ffffff;
9074 if(V_UI4(&v) > 0x3ffffff)
9075 break;
9076 /* fall through */
9077 case VT_I1:
9078 case VT_UI1:
9079 case VT_BOOL:
9080 if(!mask)
9081 mask = 0xff;
9082 /* fall through */
9083 case VT_I2:
9084 case VT_UI2:
9085 if(!mask)
9086 mask = 0xffff;
9087 return ((0x80 + 0x4 * V_VT(value)) << 24) | (V_UI4(&v) & mask);
9090 /* have to allocate space in custdata_seg */
9091 switch(arg_type) {
9092 case VT_I4:
9093 case VT_R4:
9094 case VT_UI4:
9095 case VT_INT:
9096 case VT_UINT:
9097 case VT_HRESULT:
9098 case VT_PTR: {
9099 /* Construct the data to be allocated */
9100 int *data;
9102 if(file->custdata_seg.data){
9103 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + sizeof(int) * 2);
9104 data = (int *)(((char *)file->custdata_seg.data) + file->custdata_seg.len);
9105 file->custdata_seg.len += sizeof(int) * 2;
9106 }else{
9107 file->custdata_seg.len = sizeof(int) * 2;
9108 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9111 data[0] = V_VT(value) + (V_UI4(&v) << 16);
9112 data[1] = (V_UI4(&v) >> 16) + 0x57570000;
9114 /* TODO: Check if the encoded data is already present in custdata_seg */
9116 return ret;
9119 case VT_BSTR: {
9120 int i, len = (6+SysStringLen(V_BSTR(&v))+3) & ~0x3;
9121 char *data;
9123 if(file->custdata_seg.data){
9124 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + len);
9125 data = ((char *)file->custdata_seg.data) + file->custdata_seg.len;
9126 file->custdata_seg.len += len;
9127 }else{
9128 file->custdata_seg.len = len;
9129 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9132 *((unsigned short *)data) = V_VT(value);
9133 *((unsigned int *)(data+2)) = SysStringLen(V_BSTR(&v));
9134 for(i=0; i<SysStringLen(V_BSTR(&v)); i++) {
9135 if(V_BSTR(&v)[i] <= 0x7f)
9136 data[i+6] = V_BSTR(&v)[i];
9137 else
9138 data[i+6] = '?';
9140 WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], len-6, NULL, NULL);
9141 for(i=6+SysStringLen(V_BSTR(&v)); i<len; i++)
9142 data[i] = 0x57;
9144 /* TODO: Check if the encoded data is already present in custdata_seg */
9146 return ret;
9148 default:
9149 FIXME("Argument type not yet handled\n");
9150 return -1;
9154 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size);
9156 static DWORD WMSFT_append_arraydesc(ARRAYDESC *desc, WMSFT_TLBFile *file)
9158 DWORD offs = file->arraydesc_seg.len;
9159 DWORD *encoded;
9160 USHORT i;
9162 /* TODO: we should check for duplicates, but that's harder because each
9163 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9164 * at the library-level) */
9166 file->arraydesc_seg.len += (2 + desc->cDims * 2) * sizeof(DWORD);
9167 if(!file->arraydesc_seg.data)
9168 file->arraydesc_seg.data = heap_alloc(file->arraydesc_seg.len);
9169 else
9170 file->arraydesc_seg.data = heap_realloc(file->arraydesc_seg.data, file->arraydesc_seg.len);
9171 encoded = (DWORD*)((char *)file->arraydesc_seg.data) + offs;
9173 encoded[0] = WMSFT_append_typedesc(&desc->tdescElem, file, NULL, NULL);
9174 encoded[1] = desc->cDims | ((desc->cDims * 2 * sizeof(DWORD)) << 16);
9175 for(i = 0; i < desc->cDims; ++i){
9176 encoded[2 + i * 2] = desc->rgbounds[i].cElements;
9177 encoded[2 + i * 2 + 1] = desc->rgbounds[i].lLbound;
9180 return offs;
9183 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size)
9185 DWORD junk;
9186 INT16 junk2;
9187 DWORD offs = 0;
9188 DWORD encoded[2];
9189 VARTYPE vt, subtype;
9190 char *data;
9192 if(!desc)
9193 return -1;
9195 if(!out_mix)
9196 out_mix = &junk;
9197 if(!out_size)
9198 out_size = &junk2;
9200 vt = desc->vt & VT_TYPEMASK;
9202 if(vt == VT_PTR || vt == VT_SAFEARRAY){
9203 DWORD mix;
9204 encoded[1] = WMSFT_append_typedesc(desc->u.lptdesc, file, &mix, out_size);
9205 encoded[0] = desc->vt | ((mix | VT_BYREF) << 16);
9206 *out_mix = 0x7FFF;
9207 *out_size += 2 * sizeof(DWORD);
9208 }else if(vt == VT_CARRAY){
9209 encoded[0] = desc->vt | (0x7FFE << 16);
9210 encoded[1] = WMSFT_append_arraydesc(desc->u.lpadesc, file);
9211 *out_mix = 0x7FFE;
9212 }else if(vt == VT_USERDEFINED){
9213 encoded[0] = desc->vt | (0x7FFF << 16);
9214 encoded[1] = desc->u.hreftype;
9215 *out_mix = 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9216 }else{
9217 TRACE("Mixing in-place, VT: 0x%x\n", desc->vt);
9219 switch(vt){
9220 case VT_INT:
9221 subtype = VT_I4;
9222 break;
9223 case VT_UINT:
9224 subtype = VT_UI4;
9225 break;
9226 case VT_VOID:
9227 subtype = VT_EMPTY;
9228 break;
9229 default:
9230 subtype = vt;
9231 break;
9234 *out_mix = subtype;
9235 return 0x80000000 | (subtype << 16) | desc->vt;
9238 data = file->typdesc_seg.data;
9239 while(offs < file->typdesc_seg.len){
9240 if(!memcmp(&data[offs], encoded, sizeof(encoded)))
9241 return offs;
9242 offs += sizeof(encoded);
9245 file->typdesc_seg.len += sizeof(encoded);
9246 if(!file->typdesc_seg.data)
9247 data = file->typdesc_seg.data = heap_alloc(file->typdesc_seg.len);
9248 else
9249 data = file->typdesc_seg.data = heap_realloc(file->typdesc_seg.data, file->typdesc_seg.len);
9251 memcpy(&data[offs], encoded, sizeof(encoded));
9253 return offs;
9256 static DWORD WMSFT_compile_custdata(struct list *custdata_list, WMSFT_TLBFile *file)
9258 WMSFT_SegContents *cdguids_seg = &file->cdguids_seg;
9259 DWORD ret = cdguids_seg->len, offs;
9260 MSFT_CDGuid *cdguid = cdguids_seg->data;
9261 TLBCustData *cd;
9263 if(list_empty(custdata_list))
9264 return -1;
9266 cdguids_seg->len += sizeof(MSFT_CDGuid) * list_count(custdata_list);
9267 if(!cdguids_seg->data){
9268 cdguid = cdguids_seg->data = heap_alloc(cdguids_seg->len);
9269 }else
9270 cdguids_seg->data = heap_realloc(cdguids_seg->data, cdguids_seg->len);
9272 offs = ret + sizeof(MSFT_CDGuid);
9273 LIST_FOR_EACH_ENTRY(cd, custdata_list, TLBCustData, entry){
9274 cdguid->GuidOffset = cd->guid->offset;
9275 cdguid->DataOffset = WMSFT_encode_variant(&cd->data, file);
9276 cdguid->next = offs;
9277 offs += sizeof(MSFT_CDGuid);
9278 ++cdguid;
9281 --cdguid;
9282 cdguid->next = -1;
9284 return ret;
9287 static DWORD WMSFT_compile_typeinfo_aux(ITypeInfoImpl *info,
9288 WMSFT_TLBFile *file)
9290 WMSFT_SegContents *aux_seg = &file->aux_seg;
9291 DWORD ret = aux_seg->len, i, j, recorded_size = 0, extra_size = 0;
9292 MSFT_VarRecord *varrecord;
9293 MSFT_FuncRecord *funcrecord;
9294 MEMBERID *memid;
9295 DWORD *name, *offsets, offs;
9297 for(i = 0; i < info->cFuncs; ++i){
9298 TLBFuncDesc *desc = &info->funcdescs[i];
9300 recorded_size += 6 * sizeof(INT); /* mandatory fields */
9302 /* optional fields */
9303 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9304 if(!list_empty(&desc->custdata_list))
9305 recorded_size += 7 * sizeof(INT);
9306 else if(desc->HelpStringContext != 0)
9307 recorded_size += 6 * sizeof(INT);
9308 /* res9? resA? */
9309 else if(desc->Entry)
9310 recorded_size += 3 * sizeof(INT);
9311 else if(desc->HelpString)
9312 recorded_size += 2 * sizeof(INT);
9313 else if(desc->helpcontext)
9314 recorded_size += sizeof(INT);
9316 recorded_size += desc->funcdesc.cParams * sizeof(MSFT_ParameterInfo);
9318 for(j = 0; j < desc->funcdesc.cParams; ++j){
9319 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9320 recorded_size += desc->funcdesc.cParams * sizeof(INT);
9321 break;
9325 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9328 for(i = 0; i < info->cVars; ++i){
9329 TLBVarDesc *desc = &info->vardescs[i];
9331 recorded_size += 5 * sizeof(INT); /* mandatory fields */
9333 /* optional fields */
9334 if(desc->HelpStringContext != 0)
9335 recorded_size += 5 * sizeof(INT);
9336 else if(!list_empty(&desc->custdata_list))
9337 recorded_size += 4 * sizeof(INT);
9338 /* res9? */
9339 else if(desc->HelpString)
9340 recorded_size += 2 * sizeof(INT);
9341 else if(desc->HelpContext != 0)
9342 recorded_size += sizeof(INT);
9344 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9347 if(!recorded_size && !extra_size)
9348 return ret;
9350 extra_size += sizeof(INT); /* total aux size for this typeinfo */
9352 aux_seg->len += recorded_size + extra_size;
9354 aux_seg->len += sizeof(INT) * (info->cVars + info->cFuncs); /* offsets at the end */
9356 if(aux_seg->data)
9357 aux_seg->data = heap_realloc(aux_seg->data, aux_seg->len);
9358 else
9359 aux_seg->data = heap_alloc(aux_seg->len);
9361 *((DWORD*)((char *)aux_seg->data + ret)) = recorded_size;
9363 offsets = (DWORD*)((char *)aux_seg->data + ret + recorded_size + extra_size);
9364 offs = 0;
9366 funcrecord = (MSFT_FuncRecord*)(((char *)aux_seg->data) + ret + sizeof(INT));
9367 for(i = 0; i < info->cFuncs; ++i){
9368 TLBFuncDesc *desc = &info->funcdescs[i];
9369 DWORD size = 6 * sizeof(INT), paramdefault_size = 0, *paramdefault;
9371 funcrecord->funcdescsize = sizeof(desc->funcdesc) + desc->funcdesc.cParams * sizeof(ELEMDESC);
9372 funcrecord->DataType = WMSFT_append_typedesc(&desc->funcdesc.elemdescFunc.tdesc, file, NULL, &funcrecord->funcdescsize);
9373 funcrecord->Flags = desc->funcdesc.wFuncFlags;
9374 funcrecord->VtableOffset = desc->funcdesc.oVft;
9376 /* FKCCIC:
9377 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9378 * ^^^funckind
9379 * ^^^ ^invkind
9380 * ^has_cust_data
9381 * ^^^^callconv
9382 * ^has_param_defaults
9383 * ^oEntry_is_intresource
9385 funcrecord->FKCCIC =
9386 desc->funcdesc.funckind |
9387 (desc->funcdesc.invkind << 3) |
9388 (list_empty(&desc->custdata_list) ? 0 : 0x80) |
9389 (desc->funcdesc.callconv << 8);
9391 if(desc->Entry && desc->Entry != (TLBString*)-1 && IS_INTRESOURCE(desc->Entry))
9392 funcrecord->FKCCIC |= 0x2000;
9394 for(j = 0; j < desc->funcdesc.cParams; ++j){
9395 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9396 paramdefault_size = sizeof(INT) * desc->funcdesc.cParams;
9397 funcrecord->funcdescsize += sizeof(PARAMDESCEX);
9400 if(paramdefault_size > 0)
9401 funcrecord->FKCCIC |= 0x1000;
9403 funcrecord->nrargs = desc->funcdesc.cParams;
9404 funcrecord->nroargs = desc->funcdesc.cParamsOpt;
9406 /* optional fields */
9407 /* res9? resA? */
9408 if(!list_empty(&desc->custdata_list)){
9409 size += 7 * sizeof(INT);
9410 funcrecord->HelpContext = desc->helpcontext;
9411 if(desc->HelpString)
9412 funcrecord->oHelpString = desc->HelpString->offset;
9413 else
9414 funcrecord->oHelpString = -1;
9415 if(!desc->Entry)
9416 funcrecord->oEntry = -1;
9417 else if(IS_INTRESOURCE(desc->Entry))
9418 funcrecord->oEntry = LOWORD(desc->Entry);
9419 else
9420 funcrecord->oEntry = desc->Entry->offset;
9421 funcrecord->res9 = -1;
9422 funcrecord->resA = -1;
9423 funcrecord->HelpStringContext = desc->HelpStringContext;
9424 funcrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9425 }else if(desc->HelpStringContext != 0){
9426 size += 6 * sizeof(INT);
9427 funcrecord->HelpContext = desc->helpcontext;
9428 if(desc->HelpString)
9429 funcrecord->oHelpString = desc->HelpString->offset;
9430 else
9431 funcrecord->oHelpString = -1;
9432 if(!desc->Entry)
9433 funcrecord->oEntry = -1;
9434 else if(IS_INTRESOURCE(desc->Entry))
9435 funcrecord->oEntry = LOWORD(desc->Entry);
9436 else
9437 funcrecord->oEntry = desc->Entry->offset;
9438 funcrecord->res9 = -1;
9439 funcrecord->resA = -1;
9440 funcrecord->HelpStringContext = desc->HelpStringContext;
9441 }else if(desc->Entry){
9442 size += 3 * sizeof(INT);
9443 funcrecord->HelpContext = desc->helpcontext;
9444 if(desc->HelpString)
9445 funcrecord->oHelpString = desc->HelpString->offset;
9446 else
9447 funcrecord->oHelpString = -1;
9448 if(!desc->Entry)
9449 funcrecord->oEntry = -1;
9450 else if(IS_INTRESOURCE(desc->Entry))
9451 funcrecord->oEntry = LOWORD(desc->Entry);
9452 else
9453 funcrecord->oEntry = desc->Entry->offset;
9454 }else if(desc->HelpString){
9455 size += 2 * sizeof(INT);
9456 funcrecord->HelpContext = desc->helpcontext;
9457 funcrecord->oHelpString = desc->HelpString->offset;
9458 }else if(desc->helpcontext){
9459 size += sizeof(INT);
9460 funcrecord->HelpContext = desc->helpcontext;
9463 paramdefault = (DWORD*)((char *)funcrecord + size);
9464 size += paramdefault_size;
9466 for(j = 0; j < desc->funcdesc.cParams; ++j){
9467 MSFT_ParameterInfo *info = (MSFT_ParameterInfo*)(((char *)funcrecord) + size);
9469 info->DataType = WMSFT_append_typedesc(&desc->funcdesc.lprgelemdescParam[j].tdesc, file, NULL, &funcrecord->funcdescsize);
9470 if(desc->pParamDesc[j].Name)
9471 info->oName = desc->pParamDesc[j].Name->offset;
9472 else
9473 info->oName = -1;
9474 info->Flags = desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags;
9476 if(paramdefault_size){
9477 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
9478 *paramdefault = WMSFT_encode_variant(&desc->funcdesc.lprgelemdescParam[j].u.paramdesc.pparamdescex->varDefaultValue, file);
9479 else if(paramdefault_size)
9480 *paramdefault = -1;
9481 ++paramdefault;
9484 size += sizeof(MSFT_ParameterInfo);
9487 funcrecord->Info = size | (i << 16); /* is it just the index? */
9489 *offsets = offs;
9490 offs += size;
9491 ++offsets;
9493 funcrecord = (MSFT_FuncRecord*)(((char*)funcrecord) + size);
9496 varrecord = (MSFT_VarRecord*)funcrecord;
9497 for(i = 0; i < info->cVars; ++i){
9498 TLBVarDesc *desc = &info->vardescs[i];
9499 DWORD size = 5 * sizeof(INT);
9501 varrecord->vardescsize = sizeof(desc->vardesc);
9502 varrecord->DataType = WMSFT_append_typedesc(&desc->vardesc.elemdescVar.tdesc, file, NULL, &varrecord->vardescsize);
9503 varrecord->Flags = desc->vardesc.wVarFlags;
9504 varrecord->VarKind = desc->vardesc.varkind;
9506 if(desc->vardesc.varkind == VAR_CONST){
9507 varrecord->vardescsize += sizeof(VARIANT);
9508 varrecord->OffsValue = WMSFT_encode_variant(desc->vardesc.u.lpvarValue, file);
9509 }else
9510 varrecord->OffsValue = desc->vardesc.u.oInst;
9512 /* res9? */
9513 if(desc->HelpStringContext != 0){
9514 size += 5 * sizeof(INT);
9515 varrecord->HelpContext = desc->HelpContext;
9516 if(desc->HelpString)
9517 varrecord->HelpString = desc->HelpString->offset;
9518 else
9519 varrecord->HelpString = -1;
9520 varrecord->res9 = -1;
9521 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9522 varrecord->HelpStringContext = desc->HelpStringContext;
9523 }else if(!list_empty(&desc->custdata_list)){
9524 size += 4 * sizeof(INT);
9525 varrecord->HelpContext = desc->HelpContext;
9526 if(desc->HelpString)
9527 varrecord->HelpString = desc->HelpString->offset;
9528 else
9529 varrecord->HelpString = -1;
9530 varrecord->res9 = -1;
9531 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9532 }else if(desc->HelpString){
9533 size += 2 * sizeof(INT);
9534 varrecord->HelpContext = desc->HelpContext;
9535 if(desc->HelpString)
9536 varrecord->HelpString = desc->HelpString->offset;
9537 else
9538 varrecord->HelpString = -1;
9539 }else if(desc->HelpContext != 0){
9540 size += sizeof(INT);
9541 varrecord->HelpContext = desc->HelpContext;
9544 varrecord->Info = size | (i << 16);
9546 *offsets = offs;
9547 offs += size;
9548 ++offsets;
9550 varrecord = (MSFT_VarRecord*)(((char*)varrecord) + size);
9553 memid = (MEMBERID*)varrecord;
9554 for(i = 0; i < info->cFuncs; ++i){
9555 TLBFuncDesc *desc = &info->funcdescs[i];
9556 *memid = desc->funcdesc.memid;
9557 ++memid;
9559 for(i = 0; i < info->cVars; ++i){
9560 TLBVarDesc *desc = &info->vardescs[i];
9561 *memid = desc->vardesc.memid;
9562 ++memid;
9565 name = (UINT*)memid;
9566 for(i = 0; i < info->cFuncs; ++i){
9567 TLBFuncDesc *desc = &info->funcdescs[i];
9568 if(desc->Name)
9569 *name = desc->Name->offset;
9570 else
9571 *name = -1;
9572 ++name;
9574 for(i = 0; i < info->cVars; ++i){
9575 TLBVarDesc *desc = &info->vardescs[i];
9576 if(desc->Name)
9577 *name = desc->Name->offset;
9578 else
9579 *name = -1;
9580 ++name;
9583 return ret;
9586 typedef struct tagWMSFT_RefChunk {
9587 DWORD href;
9588 DWORD res04;
9589 DWORD res08;
9590 DWORD next;
9591 } WMSFT_RefChunk;
9593 static DWORD WMSFT_compile_typeinfo_ref(ITypeInfoImpl *info, WMSFT_TLBFile *file)
9595 DWORD offs = file->ref_seg.len, i;
9596 WMSFT_RefChunk *chunk;
9598 file->ref_seg.len += info->cImplTypes * sizeof(WMSFT_RefChunk);
9599 if(!file->ref_seg.data)
9600 file->ref_seg.data = heap_alloc(file->ref_seg.len);
9601 else
9602 file->ref_seg.data = heap_realloc(file->ref_seg.data, file->ref_seg.len);
9604 chunk = (WMSFT_RefChunk*)((char*)file->ref_seg.data + offs);
9606 for(i = 0; i < info->cImplTypes; ++i){
9607 chunk->href = info->impltypes[i].hRef;
9608 chunk->res04 = info->impltypes[i].implflags;
9609 chunk->res08 = -1;
9610 if(i < info->cImplTypes - 1)
9611 chunk->next = offs + sizeof(WMSFT_RefChunk) * (i + 1);
9612 else
9613 chunk->next = -1;
9614 ++chunk;
9617 return offs;
9620 static DWORD WMSFT_compile_typeinfo(ITypeInfoImpl *info, INT16 index, WMSFT_TLBFile *file, char *data)
9622 DWORD size;
9624 size = sizeof(MSFT_TypeInfoBase);
9626 if(data){
9627 MSFT_TypeInfoBase *base = (void*)data;
9628 if(info->wTypeFlags & TYPEFLAG_FDUAL)
9629 base->typekind = TKIND_DISPATCH;
9630 else
9631 base->typekind = info->typekind;
9632 base->typekind |= index << 16; /* TODO: There are some other flags here */
9633 base->typekind |= (info->cbAlignment << 11) | (info->cbAlignment << 6);
9634 base->memoffset = WMSFT_compile_typeinfo_aux(info, file);
9635 base->res2 = 0;
9636 base->res3 = 0;
9637 base->res4 = 3;
9638 base->res5 = 0;
9639 base->cElement = (info->cVars << 16) | info->cFuncs;
9640 base->res7 = 0;
9641 base->res8 = 0;
9642 base->res9 = 0;
9643 base->resA = 0;
9644 if(info->guid)
9645 base->posguid = info->guid->offset;
9646 else
9647 base->posguid = -1;
9648 base->flags = info->wTypeFlags;
9649 if(info->Name) {
9650 base->NameOffset = info->Name->offset;
9652 ((unsigned char*)file->name_seg.data)[info->Name->offset+9] = 0x38;
9653 *(HREFTYPE*)((unsigned char*)file->name_seg.data+info->Name->offset) = info->hreftype;
9654 }else {
9655 base->NameOffset = -1;
9657 base->version = (info->wMinorVerNum << 16) | info->wMajorVerNum;
9658 if(info->DocString)
9659 base->docstringoffs = info->DocString->offset;
9660 else
9661 base->docstringoffs = -1;
9662 base->helpstringcontext = info->dwHelpStringContext;
9663 base->helpcontext = info->dwHelpContext;
9664 base->oCustData = WMSFT_compile_custdata(info->pcustdata_list, file);
9665 base->cImplTypes = info->cImplTypes;
9666 base->cbSizeVft = info->cbSizeVft;
9667 base->size = info->cbSizeInstance;
9668 if(info->typekind == TKIND_COCLASS){
9669 base->datatype1 = WMSFT_compile_typeinfo_ref(info, file);
9670 }else if(info->typekind == TKIND_ALIAS){
9671 base->datatype1 = WMSFT_append_typedesc(info->tdescAlias, file, NULL, NULL);
9672 }else if(info->typekind == TKIND_MODULE){
9673 if(info->DllName)
9674 base->datatype1 = info->DllName->offset;
9675 else
9676 base->datatype1 = -1;
9677 }else{
9678 if(info->cImplTypes > 0)
9679 base->datatype1 = info->impltypes[0].hRef;
9680 else
9681 base->datatype1 = -1;
9683 base->datatype2 = index; /* FIXME: i think there's more here */
9684 base->res18 = 0;
9685 base->res19 = -1;
9688 return size;
9691 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl *This, WMSFT_TLBFile *file, DWORD *junk)
9693 UINT i;
9695 file->typeinfo_seg.len = 0;
9696 for(i = 0; i < This->TypeInfoCount; ++i){
9697 ITypeInfoImpl *info = This->typeinfos[i];
9698 *junk = file->typeinfo_seg.len;
9699 ++junk;
9700 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, NULL, NULL);
9703 file->typeinfo_seg.data = heap_alloc(file->typeinfo_seg.len);
9704 memset(file->typeinfo_seg.data, 0x96, file->typeinfo_seg.len);
9706 file->aux_seg.len = 0;
9707 file->aux_seg.data = NULL;
9709 file->typeinfo_seg.len = 0;
9710 for(i = 0; i < This->TypeInfoCount; ++i){
9711 ITypeInfoImpl *info = This->typeinfos[i];
9712 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, file,
9713 ((char *)file->typeinfo_seg.data) + file->typeinfo_seg.len);
9717 typedef struct tagWMSFT_ImpFile {
9718 INT guid_offs;
9719 LCID lcid;
9720 DWORD version;
9721 } WMSFT_ImpFile;
9723 static void WMSFT_compile_impfile(ITypeLibImpl *This, WMSFT_TLBFile *file)
9725 TLBImpLib *implib;
9726 WMSFT_ImpFile *impfile;
9727 char *data;
9728 DWORD last_offs = 0;
9730 file->impfile_seg.len = 0;
9731 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9732 int size = 0;
9734 if(implib->name){
9735 WCHAR *path = strrchrW(implib->name, '\\');
9736 if(path)
9737 ++path;
9738 else
9739 path = implib->name;
9740 size = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path), NULL, 0, NULL, NULL);
9741 if (size == 0)
9742 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9745 size += sizeof(INT16);
9746 if (size % 4)
9747 size = (size + 4) & ~0x3;
9748 if (size < 8)
9749 size = 8;
9751 file->impfile_seg.len += sizeof(WMSFT_ImpFile) + size;
9754 data = file->impfile_seg.data = heap_alloc(file->impfile_seg.len);
9756 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9757 int strlen = 0, size;
9759 impfile = (WMSFT_ImpFile*)data;
9760 impfile->guid_offs = implib->guid->offset;
9761 impfile->lcid = implib->lcid;
9762 impfile->version = (implib->wVersionMinor << 16) | implib->wVersionMajor;
9764 data += sizeof(WMSFT_ImpFile);
9766 if(implib->name){
9767 WCHAR *path= strrchrW(implib->name, '\\');
9768 if(path)
9769 ++path;
9770 else
9771 path = implib->name;
9772 strlen = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path),
9773 data + sizeof(INT16), file->impfile_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9774 if (strlen == 0)
9775 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9778 *((INT16*)data) = (strlen << 2) | 1; /* FIXME: is that a flag, or what? */
9780 size = strlen + sizeof(INT16);
9781 if (size % 4)
9782 size = (size + 4) & ~0x3;
9783 if (size < 8)
9784 size = 8;
9785 memset(data + sizeof(INT16) + strlen, 0x57, size - strlen - sizeof(INT16));
9787 data += size;
9788 implib->offset = last_offs;
9789 last_offs += size + sizeof(WMSFT_ImpFile);
9793 static void WMSFT_compile_impinfo(ITypeLibImpl *This, WMSFT_TLBFile *file)
9795 MSFT_ImpInfo *info;
9796 TLBRefType *ref_type;
9797 UINT i = 0;
9799 WMSFT_compile_impfile(This, file);
9801 file->impinfo_seg.len = sizeof(MSFT_ImpInfo) * list_count(&This->ref_list);
9802 info = file->impinfo_seg.data = heap_alloc(file->impinfo_seg.len);
9804 LIST_FOR_EACH_ENTRY(ref_type, &This->ref_list, TLBRefType, entry){
9805 info->flags = i | ((ref_type->tkind & 0xFF) << 24);
9806 if(ref_type->index == TLB_REF_USE_GUID){
9807 info->flags |= MSFT_IMPINFO_OFFSET_IS_GUID;
9808 info->oGuid = ref_type->guid->offset;
9809 }else
9810 info->oGuid = ref_type->index;
9811 info->oImpFile = ref_type->pImpTLInfo->offset;
9812 ++i;
9813 ++info;
9817 static void WMSFT_compile_guidhash(ITypeLibImpl *This, WMSFT_TLBFile *file)
9819 file->guidhash_seg.len = 0x80;
9820 file->guidhash_seg.data = heap_alloc(file->guidhash_seg.len);
9821 memset(file->guidhash_seg.data, 0xFF, file->guidhash_seg.len);
9824 static void WMSFT_compile_namehash(ITypeLibImpl *This, WMSFT_TLBFile *file)
9826 file->namehash_seg.len = 0x200;
9827 file->namehash_seg.data = heap_alloc(file->namehash_seg.len);
9828 memset(file->namehash_seg.data, 0xFF, file->namehash_seg.len);
9831 static void tmp_fill_segdir_seg(MSFT_pSeg *segdir, WMSFT_SegContents *contents, DWORD *running_offset)
9833 if(contents && contents->len){
9834 segdir->offset = *running_offset;
9835 segdir->length = contents->len;
9836 *running_offset += segdir->length;
9837 }else{
9838 segdir->offset = -1;
9839 segdir->length = 0;
9842 /* TODO: do these ever change? */
9843 segdir->res08 = -1;
9844 segdir->res0c = 0xf;
9847 static void WMSFT_write_segment(HANDLE outfile, WMSFT_SegContents *segment)
9849 DWORD written;
9850 if(segment)
9851 WriteFile(outfile, segment->data, segment->len, &written, NULL);
9854 static HRESULT WMSFT_fixup_typeinfos(ITypeLibImpl *This, WMSFT_TLBFile *file,
9855 DWORD file_len)
9857 DWORD i;
9858 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase *)file->typeinfo_seg.data;
9860 for(i = 0; i < This->TypeInfoCount; ++i){
9861 base->memoffset += file_len;
9862 ++base;
9865 return S_OK;
9868 static void WMSFT_free_file(WMSFT_TLBFile *file)
9870 HeapFree(GetProcessHeap(), 0, file->typeinfo_seg.data);
9871 HeapFree(GetProcessHeap(), 0, file->guidhash_seg.data);
9872 HeapFree(GetProcessHeap(), 0, file->guid_seg.data);
9873 HeapFree(GetProcessHeap(), 0, file->ref_seg.data);
9874 HeapFree(GetProcessHeap(), 0, file->impinfo_seg.data);
9875 HeapFree(GetProcessHeap(), 0, file->impfile_seg.data);
9876 HeapFree(GetProcessHeap(), 0, file->namehash_seg.data);
9877 HeapFree(GetProcessHeap(), 0, file->name_seg.data);
9878 HeapFree(GetProcessHeap(), 0, file->string_seg.data);
9879 HeapFree(GetProcessHeap(), 0, file->typdesc_seg.data);
9880 HeapFree(GetProcessHeap(), 0, file->arraydesc_seg.data);
9881 HeapFree(GetProcessHeap(), 0, file->custdata_seg.data);
9882 HeapFree(GetProcessHeap(), 0, file->cdguids_seg.data);
9883 HeapFree(GetProcessHeap(), 0, file->aux_seg.data);
9886 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
9888 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9889 WMSFT_TLBFile file;
9890 DWORD written, junk_size, junk_offs, running_offset;
9891 BOOL br;
9892 HANDLE outfile;
9893 HRESULT hres;
9894 DWORD *junk;
9895 UINT i;
9897 TRACE("%p\n", This);
9899 for(i = 0; i < This->TypeInfoCount; ++i)
9900 if(This->typeinfos[i]->needs_layout)
9901 ICreateTypeInfo2_LayOut(&This->typeinfos[i]->ICreateTypeInfo2_iface);
9903 memset(&file, 0, sizeof(file));
9905 file.header.magic1 = 0x5446534D;
9906 file.header.magic2 = 0x00010002;
9907 file.header.lcid = This->set_lcid ? This->set_lcid : MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
9908 file.header.lcid2 = This->set_lcid;
9909 file.header.varflags = 0x40 | This->syskind;
9910 if (This->HelpFile)
9911 file.header.varflags |= 0x10;
9912 if (This->HelpStringDll)
9913 file.header.varflags |= HELPDLLFLAG;
9914 file.header.version = (This->ver_minor << 16) | This->ver_major;
9915 file.header.flags = This->libflags;
9916 file.header.helpstringcontext = 0; /* TODO - SetHelpStringContext not implemented yet */
9917 file.header.helpcontext = This->dwHelpContext;
9918 file.header.res44 = 0x20;
9919 file.header.res48 = 0x80;
9920 file.header.dispatchpos = This->dispatch_href;
9922 WMSFT_compile_namehash(This, &file);
9923 /* do name and string compilation to get offsets for other compilations */
9924 hres = WMSFT_compile_names(This, &file);
9925 if (FAILED(hres)){
9926 WMSFT_free_file(&file);
9927 return hres;
9930 hres = WMSFT_compile_strings(This, &file);
9931 if (FAILED(hres)){
9932 WMSFT_free_file(&file);
9933 return hres;
9936 WMSFT_compile_guidhash(This, &file);
9937 hres = WMSFT_compile_guids(This, &file);
9938 if (FAILED(hres)){
9939 WMSFT_free_file(&file);
9940 return hres;
9943 if(This->HelpFile)
9944 file.header.helpfile = This->HelpFile->offset;
9945 else
9946 file.header.helpfile = -1;
9948 if(This->DocString)
9949 file.header.helpstring = This->DocString->offset;
9950 else
9951 file.header.helpstring = -1;
9953 /* do some more segment compilation */
9954 file.header.nimpinfos = list_count(&This->ref_list);
9955 file.header.nrtypeinfos = This->TypeInfoCount;
9957 if(This->Name)
9958 file.header.NameOffset = This->Name->offset;
9959 else
9960 file.header.NameOffset = -1;
9962 file.header.CustomDataOffset = -1; /* TODO SetCustData not impl yet */
9964 if(This->guid)
9965 file.header.posguid = This->guid->offset;
9966 else
9967 file.header.posguid = -1;
9969 junk_size = file.header.nrtypeinfos * sizeof(DWORD);
9970 if(file.header.varflags & HELPDLLFLAG)
9971 junk_size += sizeof(DWORD);
9972 if(junk_size){
9973 junk = heap_alloc_zero(junk_size);
9974 if(file.header.varflags & HELPDLLFLAG){
9975 *junk = This->HelpStringDll->offset;
9976 junk_offs = 1;
9977 }else
9978 junk_offs = 0;
9979 }else{
9980 junk = NULL;
9981 junk_offs = 0;
9984 WMSFT_compile_typeinfo_seg(This, &file, junk + junk_offs);
9985 WMSFT_compile_impinfo(This, &file);
9987 running_offset = 0;
9989 TRACE("header at: 0x%x\n", running_offset);
9990 running_offset += sizeof(file.header);
9992 TRACE("junk at: 0x%x\n", running_offset);
9993 running_offset += junk_size;
9995 TRACE("segdir at: 0x%x\n", running_offset);
9996 running_offset += sizeof(file.segdir);
9998 TRACE("typeinfo at: 0x%x\n", running_offset);
9999 tmp_fill_segdir_seg(&file.segdir.pTypeInfoTab, &file.typeinfo_seg, &running_offset);
10001 TRACE("guidhashtab at: 0x%x\n", running_offset);
10002 tmp_fill_segdir_seg(&file.segdir.pGuidHashTab, &file.guidhash_seg, &running_offset);
10004 TRACE("guidtab at: 0x%x\n", running_offset);
10005 tmp_fill_segdir_seg(&file.segdir.pGuidTab, &file.guid_seg, &running_offset);
10007 TRACE("reftab at: 0x%x\n", running_offset);
10008 tmp_fill_segdir_seg(&file.segdir.pRefTab, &file.ref_seg, &running_offset);
10010 TRACE("impinfo at: 0x%x\n", running_offset);
10011 tmp_fill_segdir_seg(&file.segdir.pImpInfo, &file.impinfo_seg, &running_offset);
10013 TRACE("impfiles at: 0x%x\n", running_offset);
10014 tmp_fill_segdir_seg(&file.segdir.pImpFiles, &file.impfile_seg, &running_offset);
10016 TRACE("namehashtab at: 0x%x\n", running_offset);
10017 tmp_fill_segdir_seg(&file.segdir.pNameHashTab, &file.namehash_seg, &running_offset);
10019 TRACE("nametab at: 0x%x\n", running_offset);
10020 tmp_fill_segdir_seg(&file.segdir.pNametab, &file.name_seg, &running_offset);
10022 TRACE("stringtab at: 0x%x\n", running_offset);
10023 tmp_fill_segdir_seg(&file.segdir.pStringtab, &file.string_seg, &running_offset);
10025 TRACE("typdesc at: 0x%x\n", running_offset);
10026 tmp_fill_segdir_seg(&file.segdir.pTypdescTab, &file.typdesc_seg, &running_offset);
10028 TRACE("arraydescriptions at: 0x%x\n", running_offset);
10029 tmp_fill_segdir_seg(&file.segdir.pArrayDescriptions, &file.arraydesc_seg, &running_offset);
10031 TRACE("custdata at: 0x%x\n", running_offset);
10032 tmp_fill_segdir_seg(&file.segdir.pCustData, &file.custdata_seg, &running_offset);
10034 TRACE("cdguids at: 0x%x\n", running_offset);
10035 tmp_fill_segdir_seg(&file.segdir.pCDGuids, &file.cdguids_seg, &running_offset);
10037 TRACE("res0e at: 0x%x\n", running_offset);
10038 tmp_fill_segdir_seg(&file.segdir.res0e, NULL, &running_offset);
10040 TRACE("res0f at: 0x%x\n", running_offset);
10041 tmp_fill_segdir_seg(&file.segdir.res0f, NULL, &running_offset);
10043 TRACE("aux_seg at: 0x%x\n", running_offset);
10045 WMSFT_fixup_typeinfos(This, &file, running_offset);
10047 outfile = CreateFileW(This->path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
10048 FILE_ATTRIBUTE_NORMAL, 0);
10049 if (outfile == INVALID_HANDLE_VALUE){
10050 WMSFT_free_file(&file);
10051 heap_free(junk);
10052 return TYPE_E_IOERROR;
10055 br = WriteFile(outfile, &file.header, sizeof(file.header), &written, NULL);
10056 if (!br) {
10057 WMSFT_free_file(&file);
10058 CloseHandle(outfile);
10059 heap_free(junk);
10060 return TYPE_E_IOERROR;
10063 br = WriteFile(outfile, junk, junk_size, &written, NULL);
10064 heap_free(junk);
10065 if (!br) {
10066 WMSFT_free_file(&file);
10067 CloseHandle(outfile);
10068 return TYPE_E_IOERROR;
10071 br = WriteFile(outfile, &file.segdir, sizeof(file.segdir), &written, NULL);
10072 if (!br) {
10073 WMSFT_free_file(&file);
10074 CloseHandle(outfile);
10075 return TYPE_E_IOERROR;
10078 WMSFT_write_segment(outfile, &file.typeinfo_seg);
10079 WMSFT_write_segment(outfile, &file.guidhash_seg);
10080 WMSFT_write_segment(outfile, &file.guid_seg);
10081 WMSFT_write_segment(outfile, &file.ref_seg);
10082 WMSFT_write_segment(outfile, &file.impinfo_seg);
10083 WMSFT_write_segment(outfile, &file.impfile_seg);
10084 WMSFT_write_segment(outfile, &file.namehash_seg);
10085 WMSFT_write_segment(outfile, &file.name_seg);
10086 WMSFT_write_segment(outfile, &file.string_seg);
10087 WMSFT_write_segment(outfile, &file.typdesc_seg);
10088 WMSFT_write_segment(outfile, &file.arraydesc_seg);
10089 WMSFT_write_segment(outfile, &file.custdata_seg);
10090 WMSFT_write_segment(outfile, &file.cdguids_seg);
10091 WMSFT_write_segment(outfile, &file.aux_seg);
10093 WMSFT_free_file(&file);
10095 CloseHandle(outfile);
10097 return S_OK;
10100 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
10101 LPOLESTR name)
10103 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10104 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
10105 return E_NOTIMPL;
10108 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
10109 REFGUID guid, VARIANT *varVal)
10111 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10112 FIXME("%p %s %p - stub\n", This, debugstr_guid(guid), varVal);
10113 return E_NOTIMPL;
10116 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
10117 ULONG helpStringContext)
10119 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10120 FIXME("%p %u - stub\n", This, helpStringContext);
10121 return E_NOTIMPL;
10124 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
10125 LPOLESTR filename)
10127 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10128 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
10130 if (!filename)
10131 return E_INVALIDARG;
10133 This->HelpStringDll = TLB_append_str(&This->string_list, filename);
10135 return S_OK;
10138 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
10139 ICreateTypeLib2_fnQueryInterface,
10140 ICreateTypeLib2_fnAddRef,
10141 ICreateTypeLib2_fnRelease,
10142 ICreateTypeLib2_fnCreateTypeInfo,
10143 ICreateTypeLib2_fnSetName,
10144 ICreateTypeLib2_fnSetVersion,
10145 ICreateTypeLib2_fnSetGuid,
10146 ICreateTypeLib2_fnSetDocString,
10147 ICreateTypeLib2_fnSetHelpFileName,
10148 ICreateTypeLib2_fnSetHelpContext,
10149 ICreateTypeLib2_fnSetLcid,
10150 ICreateTypeLib2_fnSetLibFlags,
10151 ICreateTypeLib2_fnSaveAllChanges,
10152 ICreateTypeLib2_fnDeleteTypeInfo,
10153 ICreateTypeLib2_fnSetCustData,
10154 ICreateTypeLib2_fnSetHelpStringContext,
10155 ICreateTypeLib2_fnSetHelpStringDll
10158 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
10159 REFIID riid, void **object)
10161 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10163 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, object);
10166 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
10168 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10170 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
10173 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
10175 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10177 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
10180 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
10181 REFGUID guid)
10183 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10185 TRACE("%p %s\n", This, debugstr_guid(guid));
10187 This->guid = TLB_append_guid(&This->pTypeLib->guid_list, guid, This->hreftype);
10189 return S_OK;
10192 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
10193 UINT typeFlags)
10195 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10196 WORD old_flags;
10197 HRESULT hres;
10199 TRACE("%p %x\n", This, typeFlags);
10201 if (typeFlags & TYPEFLAG_FDUAL) {
10202 static const WCHAR stdole2tlb[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10203 ITypeLib *stdole;
10204 ITypeInfo *dispatch;
10205 HREFTYPE hreftype;
10206 HRESULT hres;
10208 hres = LoadTypeLib(stdole2tlb, &stdole);
10209 if(FAILED(hres))
10210 return hres;
10212 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
10213 ITypeLib_Release(stdole);
10214 if(FAILED(hres))
10215 return hres;
10217 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
10218 ITypeInfo_Release(dispatch);
10219 if(FAILED(hres))
10220 return hres;
10223 old_flags = This->wTypeFlags;
10224 This->wTypeFlags = typeFlags;
10226 hres = ICreateTypeInfo2_LayOut(iface);
10227 if (FAILED(hres)) {
10228 This->wTypeFlags = old_flags;
10229 return hres;
10232 return S_OK;
10235 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
10236 LPOLESTR doc)
10238 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10240 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
10242 if (!doc)
10243 return E_INVALIDARG;
10245 This->DocString = TLB_append_str(&This->pTypeLib->string_list, doc);
10247 return S_OK;
10250 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
10251 DWORD helpContext)
10253 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10255 TRACE("%p %d\n", This, helpContext);
10257 This->dwHelpContext = helpContext;
10259 return S_OK;
10262 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
10263 WORD majorVerNum, WORD minorVerNum)
10265 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10267 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
10269 This->wMajorVerNum = majorVerNum;
10270 This->wMinorVerNum = minorVerNum;
10272 return S_OK;
10275 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
10276 ITypeInfo *typeInfo, HREFTYPE *refType)
10278 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10279 UINT index;
10280 ITypeLib *container;
10281 TLBRefType *ref_type;
10282 TLBImpLib *implib;
10283 TYPEATTR *typeattr;
10284 TLIBATTR *libattr;
10285 HRESULT hres;
10287 TRACE("%p %p %p\n", This, typeInfo, refType);
10289 if (!typeInfo || !refType)
10290 return E_INVALIDARG;
10292 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
10293 if (FAILED(hres))
10294 return hres;
10296 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
10297 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
10299 ITypeLib_Release(container);
10301 *refType = target->hreftype;
10303 return S_OK;
10306 hres = ITypeLib_GetLibAttr(container, &libattr);
10307 if (FAILED(hres)) {
10308 ITypeLib_Release(container);
10309 return hres;
10312 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
10313 if(IsEqualGUID(&implib->guid->guid, &libattr->guid) &&
10314 implib->lcid == libattr->lcid &&
10315 implib->wVersionMajor == libattr->wMajorVerNum &&
10316 implib->wVersionMinor == libattr->wMinorVerNum)
10317 break;
10320 if(&implib->entry == &This->pTypeLib->implib_list){
10321 implib = heap_alloc_zero(sizeof(TLBImpLib));
10323 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
10324 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
10325 implib->name = SysAllocString(our_container->path);
10326 }else{
10327 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
10328 libattr->wMinorVerNum, libattr->lcid, &implib->name);
10329 if(FAILED(hres)){
10330 implib->name = NULL;
10331 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres);
10335 implib->guid = TLB_append_guid(&This->pTypeLib->guid_list, &libattr->guid, 2);
10336 implib->lcid = libattr->lcid;
10337 implib->wVersionMajor = libattr->wMajorVerNum;
10338 implib->wVersionMinor = libattr->wMinorVerNum;
10340 list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
10343 ITypeLib_ReleaseTLibAttr(container, libattr);
10344 ITypeLib_Release(container);
10346 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
10347 if (FAILED(hres))
10348 return hres;
10350 index = 0;
10351 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
10352 if(ref_type->index == TLB_REF_USE_GUID &&
10353 IsEqualGUID(&ref_type->guid->guid, &typeattr->guid) &&
10354 ref_type->tkind == typeattr->typekind)
10355 break;
10356 ++index;
10359 if(&ref_type->entry == &This->pTypeLib->ref_list){
10360 ref_type = heap_alloc_zero(sizeof(TLBRefType));
10362 ref_type->tkind = typeattr->typekind;
10363 ref_type->pImpTLInfo = implib;
10364 ref_type->reference = index * sizeof(MSFT_ImpInfo);
10366 ref_type->index = TLB_REF_USE_GUID;
10368 ref_type->guid = TLB_append_guid(&This->pTypeLib->guid_list, &typeattr->guid, ref_type->reference+1);
10370 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
10373 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
10375 *refType = ref_type->reference | 0x1;
10377 if(IsEqualGUID(&ref_type->guid->guid, &IID_IDispatch))
10378 This->pTypeLib->dispatch_href = *refType;
10380 return S_OK;
10383 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
10384 UINT index, FUNCDESC *funcDesc)
10386 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10387 TLBFuncDesc tmp_func_desc, *func_desc;
10388 int buf_size, i;
10389 char *buffer;
10390 HRESULT hres;
10392 TRACE("%p %u %p\n", This, index, funcDesc);
10394 if (!funcDesc || funcDesc->oVft & 3)
10395 return E_INVALIDARG;
10397 switch (This->typekind) {
10398 case TKIND_MODULE:
10399 if (funcDesc->funckind != FUNC_STATIC)
10400 return TYPE_E_BADMODULEKIND;
10401 break;
10402 case TKIND_DISPATCH:
10403 if (funcDesc->funckind != FUNC_DISPATCH)
10404 return TYPE_E_BADMODULEKIND;
10405 break;
10406 default:
10407 if (funcDesc->funckind != FUNC_PUREVIRTUAL)
10408 return TYPE_E_BADMODULEKIND;
10411 if (index > This->cFuncs)
10412 return TYPE_E_ELEMENTNOTFOUND;
10414 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) &&
10415 !funcDesc->cParams)
10416 return TYPE_E_INCONSISTENTPROPFUNCS;
10418 #ifdef _WIN64
10419 if(This->pTypeLib->syskind == SYS_WIN64 &&
10420 funcDesc->oVft % 8 != 0)
10421 return E_INVALIDARG;
10422 #endif
10424 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc));
10425 TLBFuncDesc_Constructor(&tmp_func_desc);
10427 tmp_func_desc.funcdesc = *funcDesc;
10429 if (tmp_func_desc.funcdesc.oVft != 0)
10430 tmp_func_desc.funcdesc.oVft |= 1;
10432 if (funcDesc->cScodes) {
10433 tmp_func_desc.funcdesc.lprgscode = heap_alloc(sizeof(SCODE) * funcDesc->cScodes);
10434 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes);
10435 } else
10436 tmp_func_desc.funcdesc.lprgscode = NULL;
10438 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc);
10439 for (i = 0; i < funcDesc->cParams; ++i) {
10440 buf_size += sizeof(ELEMDESC);
10441 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i);
10443 tmp_func_desc.funcdesc.lprgelemdescParam = heap_alloc(buf_size);
10444 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams);
10446 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer);
10447 if (FAILED(hres)) {
10448 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10449 heap_free(tmp_func_desc.funcdesc.lprgscode);
10450 return hres;
10453 for (i = 0; i < funcDesc->cParams; ++i) {
10454 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i,
10455 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer);
10456 if (FAILED(hres)) {
10457 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10458 heap_free(tmp_func_desc.funcdesc.lprgscode);
10459 return hres;
10461 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT &&
10462 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT &&
10463 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){
10464 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
10465 if (FAILED(hres)) {
10466 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10467 heap_free(tmp_func_desc.funcdesc.lprgscode);
10468 return hres;
10473 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams);
10475 if (This->funcdescs) {
10476 This->funcdescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->funcdescs,
10477 sizeof(TLBFuncDesc) * (This->cFuncs + 1));
10479 if (index < This->cFuncs) {
10480 memmove(This->funcdescs + index + 1, This->funcdescs + index,
10481 (This->cFuncs - index) * sizeof(TLBFuncDesc));
10482 func_desc = This->funcdescs + index;
10483 } else
10484 func_desc = This->funcdescs + This->cFuncs;
10486 /* move custdata lists to the new memory location */
10487 for(i = 0; i < This->cFuncs + 1; ++i){
10488 if(index != i){
10489 TLBFuncDesc *fd = &This->funcdescs[i];
10490 if(fd->custdata_list.prev == fd->custdata_list.next)
10491 list_init(&fd->custdata_list);
10492 else{
10493 fd->custdata_list.prev->next = &fd->custdata_list;
10494 fd->custdata_list.next->prev = &fd->custdata_list;
10498 } else
10499 func_desc = This->funcdescs = heap_alloc(sizeof(TLBFuncDesc));
10501 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc));
10502 list_init(&func_desc->custdata_list);
10504 ++This->cFuncs;
10506 This->needs_layout = TRUE;
10508 return S_OK;
10511 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
10512 UINT index, HREFTYPE refType)
10514 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10515 TLBImplType *impl_type;
10516 HRESULT hres;
10518 TRACE("%p %u %d\n", This, index, refType);
10520 switch(This->typekind){
10521 case TKIND_COCLASS: {
10522 if (index == -1) {
10523 FIXME("Unhandled index: -1\n");
10524 return E_NOTIMPL;
10527 if(index != This->cImplTypes)
10528 return TYPE_E_ELEMENTNOTFOUND;
10530 break;
10532 case TKIND_INTERFACE:
10533 case TKIND_DISPATCH:
10534 if (index != 0 || This->cImplTypes)
10535 return TYPE_E_ELEMENTNOTFOUND;
10536 break;
10537 default:
10538 FIXME("Unimplemented typekind: %d\n", This->typekind);
10539 return E_NOTIMPL;
10542 if (This->impltypes){
10543 UINT i;
10545 This->impltypes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->impltypes,
10546 sizeof(TLBImplType) * (This->cImplTypes + 1));
10548 if (index < This->cImplTypes) {
10549 memmove(This->impltypes + index + 1, This->impltypes + index,
10550 (This->cImplTypes - index) * sizeof(TLBImplType));
10551 impl_type = This->impltypes + index;
10552 } else
10553 impl_type = This->impltypes + This->cImplTypes;
10555 /* move custdata lists to the new memory location */
10556 for(i = 0; i < This->cImplTypes + 1; ++i){
10557 if(index != i){
10558 TLBImplType *it = &This->impltypes[i];
10559 if(it->custdata_list.prev == it->custdata_list.next)
10560 list_init(&it->custdata_list);
10561 else{
10562 it->custdata_list.prev->next = &it->custdata_list;
10563 it->custdata_list.next->prev = &it->custdata_list;
10567 } else
10568 impl_type = This->impltypes = heap_alloc(sizeof(TLBImplType));
10570 memset(impl_type, 0, sizeof(TLBImplType));
10571 TLBImplType_Constructor(impl_type);
10572 impl_type->hRef = refType;
10574 ++This->cImplTypes;
10576 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
10577 This->wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
10579 hres = ICreateTypeInfo2_LayOut(iface);
10580 if (FAILED(hres))
10581 return hres;
10583 return S_OK;
10586 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
10587 UINT index, INT implTypeFlags)
10589 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10590 TLBImplType *impl_type = &This->impltypes[index];
10592 TRACE("%p %u %x\n", This, index, implTypeFlags);
10594 if (This->typekind != TKIND_COCLASS)
10595 return TYPE_E_BADMODULEKIND;
10597 if (index >= This->cImplTypes)
10598 return TYPE_E_ELEMENTNOTFOUND;
10600 impl_type->implflags = implTypeFlags;
10602 return S_OK;
10605 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
10606 WORD alignment)
10608 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10610 TRACE("%p %d\n", This, alignment);
10612 This->cbAlignment = alignment;
10614 return S_OK;
10617 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
10618 LPOLESTR schema)
10620 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10622 TRACE("%p %s\n", This, wine_dbgstr_w(schema));
10624 if (!schema)
10625 return E_INVALIDARG;
10627 This->Schema = TLB_append_str(&This->pTypeLib->string_list, schema);
10629 This->lpstrSchema = This->Schema->str;
10631 return S_OK;
10634 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
10635 UINT index, VARDESC *varDesc)
10637 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10638 TLBVarDesc *var_desc;
10640 TRACE("%p %u %p\n", This, index, varDesc);
10642 if (This->vardescs){
10643 UINT i;
10645 This->vardescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->vardescs,
10646 sizeof(TLBVarDesc) * (This->cVars + 1));
10648 if (index < This->cVars) {
10649 memmove(This->vardescs + index + 1, This->vardescs + index,
10650 (This->cVars - index) * sizeof(TLBVarDesc));
10651 var_desc = This->vardescs + index;
10652 } else
10653 var_desc = This->vardescs + This->cVars;
10655 /* move custdata lists to the new memory location */
10656 for(i = 0; i < This->cVars + 1; ++i){
10657 if(index != i){
10658 TLBVarDesc *var = &This->vardescs[i];
10659 if(var->custdata_list.prev == var->custdata_list.next)
10660 list_init(&var->custdata_list);
10661 else{
10662 var->custdata_list.prev->next = &var->custdata_list;
10663 var->custdata_list.next->prev = &var->custdata_list;
10667 } else
10668 var_desc = This->vardescs = heap_alloc_zero(sizeof(TLBVarDesc));
10670 TLBVarDesc_Constructor(var_desc);
10671 TLB_AllocAndInitVarDesc(varDesc, &var_desc->vardesc_create);
10672 var_desc->vardesc = *var_desc->vardesc_create;
10674 ++This->cVars;
10676 This->needs_layout = TRUE;
10678 return S_OK;
10681 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
10682 UINT index, LPOLESTR *names, UINT numNames)
10684 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10685 TLBFuncDesc *func_desc = &This->funcdescs[index];
10686 int i;
10688 TRACE("%p %u %p %u\n", This, index, names, numNames);
10690 if (!names)
10691 return E_INVALIDARG;
10693 if (index >= This->cFuncs || numNames == 0)
10694 return TYPE_E_ELEMENTNOTFOUND;
10696 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){
10697 if(numNames > func_desc->funcdesc.cParams)
10698 return TYPE_E_ELEMENTNOTFOUND;
10699 } else
10700 if(numNames > func_desc->funcdesc.cParams + 1)
10701 return TYPE_E_ELEMENTNOTFOUND;
10703 for(i = 0; i < This->cFuncs; ++i) {
10704 TLBFuncDesc *iter = &This->funcdescs[i];
10705 if (iter->Name && !strcmpW(TLB_get_bstr(iter->Name), *names)) {
10706 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10707 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10708 func_desc->funcdesc.invkind != iter->funcdesc.invkind)
10709 continue;
10710 return TYPE_E_AMBIGUOUSNAME;
10714 func_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *names);
10716 for (i = 1; i < numNames; ++i) {
10717 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1;
10718 par_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *(names + i));
10721 return S_OK;
10724 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
10725 UINT index, LPOLESTR name)
10727 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10729 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(name));
10731 if(!name)
10732 return E_INVALIDARG;
10734 if(index >= This->cVars)
10735 return TYPE_E_ELEMENTNOTFOUND;
10737 This->vardescs[index].Name = TLB_append_str(&This->pTypeLib->name_list, name);
10738 return S_OK;
10741 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
10742 TYPEDESC *tdescAlias)
10744 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10745 HRESULT hr;
10747 TRACE("%p %p\n", This, tdescAlias);
10749 if(!tdescAlias)
10750 return E_INVALIDARG;
10752 if(This->typekind != TKIND_ALIAS)
10753 return TYPE_E_BADMODULEKIND;
10755 hr = TLB_size_instance(This, This->pTypeLib->syskind, tdescAlias, &This->cbSizeInstance, &This->cbAlignment);
10756 if(FAILED(hr))
10757 return hr;
10759 heap_free(This->tdescAlias);
10760 This->tdescAlias = heap_alloc(TLB_SizeTypeDesc(tdescAlias, TRUE));
10761 TLB_CopyTypeDesc(NULL, tdescAlias, This->tdescAlias);
10763 return S_OK;
10766 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
10767 UINT index, LPOLESTR dllName, LPOLESTR procName)
10769 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10770 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
10771 return E_NOTIMPL;
10774 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
10775 UINT index, LPOLESTR docString)
10777 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10778 TLBFuncDesc *func_desc = &This->funcdescs[index];
10780 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10782 if(!docString)
10783 return E_INVALIDARG;
10785 if(index >= This->cFuncs)
10786 return TYPE_E_ELEMENTNOTFOUND;
10788 func_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10790 return S_OK;
10793 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
10794 UINT index, LPOLESTR docString)
10796 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10797 TLBVarDesc *var_desc = &This->vardescs[index];
10799 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10801 if(!docString)
10802 return E_INVALIDARG;
10804 if(index >= This->cVars)
10805 return TYPE_E_ELEMENTNOTFOUND;
10807 var_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10809 return S_OK;
10812 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
10813 UINT index, DWORD helpContext)
10815 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10816 TLBFuncDesc *func_desc = &This->funcdescs[index];
10818 TRACE("%p %u %d\n", This, index, helpContext);
10820 if(index >= This->cFuncs)
10821 return TYPE_E_ELEMENTNOTFOUND;
10823 func_desc->helpcontext = helpContext;
10825 return S_OK;
10828 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
10829 UINT index, DWORD helpContext)
10831 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10832 TLBVarDesc *var_desc = &This->vardescs[index];
10834 TRACE("%p %u %d\n", This, index, helpContext);
10836 if(index >= This->cVars)
10837 return TYPE_E_ELEMENTNOTFOUND;
10839 var_desc->HelpContext = helpContext;
10841 return S_OK;
10844 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
10845 UINT index, BSTR bstrMops)
10847 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10848 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
10849 return E_NOTIMPL;
10852 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
10853 IDLDESC *idlDesc)
10855 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10857 TRACE("%p %p\n", This, idlDesc);
10859 if (!idlDesc)
10860 return E_INVALIDARG;
10862 This->idldescType.dwReserved = idlDesc->dwReserved;
10863 This->idldescType.wIDLFlags = idlDesc->wIDLFlags;
10865 return S_OK;
10868 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
10870 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10871 ITypeInfo *tinfo;
10872 TLBFuncDesc *func_desc;
10873 UINT user_vft = 0, i, depth = 0;
10874 HRESULT hres = S_OK;
10876 TRACE("%p\n", This);
10878 This->needs_layout = FALSE;
10880 hres = ICreateTypeInfo2_QueryInterface(iface, &IID_ITypeInfo, (LPVOID*)&tinfo);
10881 if (FAILED(hres))
10882 return hres;
10884 if (This->typekind == TKIND_INTERFACE) {
10885 ITypeInfo *inh;
10886 TYPEATTR *attr;
10887 HREFTYPE inh_href;
10889 hres = ITypeInfo_GetRefTypeOfImplType(tinfo, 0, &inh_href);
10891 if (SUCCEEDED(hres)) {
10892 hres = ITypeInfo_GetRefTypeInfo(tinfo, inh_href, &inh);
10894 if (SUCCEEDED(hres)) {
10895 hres = ITypeInfo_GetTypeAttr(inh, &attr);
10896 if (FAILED(hres)) {
10897 ITypeInfo_Release(inh);
10898 ITypeInfo_Release(tinfo);
10899 return hres;
10901 This->cbSizeVft = attr->cbSizeVft;
10902 ITypeInfo_ReleaseTypeAttr(inh, attr);
10905 ++depth;
10906 hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href);
10907 if(SUCCEEDED(hres)){
10908 ITypeInfo *next;
10909 hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next);
10910 if(SUCCEEDED(hres)){
10911 ITypeInfo_Release(inh);
10912 inh = next;
10915 }while(SUCCEEDED(hres));
10916 hres = S_OK;
10918 ITypeInfo_Release(inh);
10919 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10920 This->cbSizeVft = 0;
10921 hres = S_OK;
10922 } else {
10923 ITypeInfo_Release(tinfo);
10924 return hres;
10926 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10927 This->cbSizeVft = 0;
10928 hres = S_OK;
10929 } else {
10930 ITypeInfo_Release(tinfo);
10931 return hres;
10933 } else if (This->typekind == TKIND_DISPATCH)
10934 This->cbSizeVft = 7 * This->pTypeLib->ptr_size;
10935 else
10936 This->cbSizeVft = 0;
10938 func_desc = This->funcdescs;
10939 i = 0;
10940 while (i < This->cFuncs) {
10941 if (!(func_desc->funcdesc.oVft & 0x1))
10942 func_desc->funcdesc.oVft = This->cbSizeVft;
10944 if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft)
10945 user_vft = func_desc->funcdesc.oVft & 0xFFFC;
10947 This->cbSizeVft += This->pTypeLib->ptr_size;
10949 if (func_desc->funcdesc.memid == MEMBERID_NIL) {
10950 TLBFuncDesc *iter;
10951 UINT j = 0;
10952 BOOL reset = FALSE;
10954 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i;
10956 iter = This->funcdescs;
10957 while (j < This->cFuncs) {
10958 if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) {
10959 if (!reset) {
10960 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->cFuncs;
10961 reset = TRUE;
10962 } else
10963 ++func_desc->funcdesc.memid;
10964 iter = This->funcdescs;
10965 j = 0;
10966 } else {
10967 ++iter;
10968 ++j;
10973 ++func_desc;
10974 ++i;
10977 if (user_vft > This->cbSizeVft)
10978 This->cbSizeVft = user_vft + This->pTypeLib->ptr_size;
10980 for(i = 0; i < This->cVars; ++i){
10981 TLBVarDesc *var_desc = &This->vardescs[i];
10982 if(var_desc->vardesc.memid == MEMBERID_NIL){
10983 UINT j = 0;
10984 BOOL reset = FALSE;
10985 TLBVarDesc *iter;
10987 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + i;
10989 iter = This->vardescs;
10990 while (j < This->cVars) {
10991 if (iter != var_desc && iter->vardesc.memid == var_desc->vardesc.memid) {
10992 if (!reset) {
10993 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + This->cVars;
10994 reset = TRUE;
10995 } else
10996 ++var_desc->vardesc.memid;
10997 iter = This->vardescs;
10998 j = 0;
10999 } else {
11000 ++iter;
11001 ++j;
11007 ITypeInfo_Release(tinfo);
11008 return hres;
11011 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
11012 UINT index)
11014 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11015 FIXME("%p %u - stub\n", This, index);
11016 return E_NOTIMPL;
11019 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
11020 MEMBERID memid, INVOKEKIND invKind)
11022 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11023 FIXME("%p %x %d - stub\n", This, memid, invKind);
11024 return E_NOTIMPL;
11027 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
11028 UINT index)
11030 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11031 FIXME("%p %u - stub\n", This, index);
11032 return E_NOTIMPL;
11035 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
11036 MEMBERID memid)
11038 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11039 FIXME("%p %x - stub\n", This, memid);
11040 return E_NOTIMPL;
11043 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
11044 UINT index)
11046 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11047 FIXME("%p %u - stub\n", This, index);
11048 return E_NOTIMPL;
11051 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
11052 REFGUID guid, VARIANT *varVal)
11054 TLBGuid *tlbguid;
11056 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11058 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
11060 if (!guid || !varVal)
11061 return E_INVALIDARG;
11063 tlbguid = TLB_append_guid(&This->pTypeLib->guid_list, guid, -1);
11065 return TLB_set_custdata(This->pcustdata_list, tlbguid, varVal);
11068 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
11069 UINT index, REFGUID guid, VARIANT *varVal)
11071 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11072 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11073 return E_NOTIMPL;
11076 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
11077 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
11079 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11080 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
11081 return E_NOTIMPL;
11084 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
11085 UINT index, REFGUID guid, VARIANT *varVal)
11087 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11088 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11089 return E_NOTIMPL;
11092 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
11093 UINT index, REFGUID guid, VARIANT *varVal)
11095 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11096 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11097 return E_NOTIMPL;
11100 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
11101 ULONG helpStringContext)
11103 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11105 TRACE("%p %u\n", This, helpStringContext);
11107 This->dwHelpStringContext = helpStringContext;
11109 return S_OK;
11112 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
11113 UINT index, ULONG helpStringContext)
11115 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11116 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11117 return E_NOTIMPL;
11120 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
11121 UINT index, ULONG helpStringContext)
11123 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11124 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11125 return E_NOTIMPL;
11128 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
11130 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11131 FIXME("%p - stub\n", This);
11132 return E_NOTIMPL;
11135 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
11136 LPOLESTR name)
11138 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11140 TRACE("%p %s\n", This, wine_dbgstr_w(name));
11142 if (!name)
11143 return E_INVALIDARG;
11145 This->Name = TLB_append_str(&This->pTypeLib->name_list, name);
11147 return S_OK;
11150 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
11151 ICreateTypeInfo2_fnQueryInterface,
11152 ICreateTypeInfo2_fnAddRef,
11153 ICreateTypeInfo2_fnRelease,
11154 ICreateTypeInfo2_fnSetGuid,
11155 ICreateTypeInfo2_fnSetTypeFlags,
11156 ICreateTypeInfo2_fnSetDocString,
11157 ICreateTypeInfo2_fnSetHelpContext,
11158 ICreateTypeInfo2_fnSetVersion,
11159 ICreateTypeInfo2_fnAddRefTypeInfo,
11160 ICreateTypeInfo2_fnAddFuncDesc,
11161 ICreateTypeInfo2_fnAddImplType,
11162 ICreateTypeInfo2_fnSetImplTypeFlags,
11163 ICreateTypeInfo2_fnSetAlignment,
11164 ICreateTypeInfo2_fnSetSchema,
11165 ICreateTypeInfo2_fnAddVarDesc,
11166 ICreateTypeInfo2_fnSetFuncAndParamNames,
11167 ICreateTypeInfo2_fnSetVarName,
11168 ICreateTypeInfo2_fnSetTypeDescAlias,
11169 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
11170 ICreateTypeInfo2_fnSetFuncDocString,
11171 ICreateTypeInfo2_fnSetVarDocString,
11172 ICreateTypeInfo2_fnSetFuncHelpContext,
11173 ICreateTypeInfo2_fnSetVarHelpContext,
11174 ICreateTypeInfo2_fnSetMops,
11175 ICreateTypeInfo2_fnSetTypeIdldesc,
11176 ICreateTypeInfo2_fnLayOut,
11177 ICreateTypeInfo2_fnDeleteFuncDesc,
11178 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
11179 ICreateTypeInfo2_fnDeleteVarDesc,
11180 ICreateTypeInfo2_fnDeleteVarDescByMemId,
11181 ICreateTypeInfo2_fnDeleteImplType,
11182 ICreateTypeInfo2_fnSetCustData,
11183 ICreateTypeInfo2_fnSetFuncCustData,
11184 ICreateTypeInfo2_fnSetParamCustData,
11185 ICreateTypeInfo2_fnSetVarCustData,
11186 ICreateTypeInfo2_fnSetImplTypeCustData,
11187 ICreateTypeInfo2_fnSetHelpStringContext,
11188 ICreateTypeInfo2_fnSetFuncHelpStringContext,
11189 ICreateTypeInfo2_fnSetVarHelpStringContext,
11190 ICreateTypeInfo2_fnInvalidate,
11191 ICreateTypeInfo2_fnSetName
11194 /******************************************************************************
11195 * ClearCustData (OLEAUT32.171)
11197 * Clear a custom data type's data.
11199 * PARAMS
11200 * lpCust [I] The custom data type instance
11202 * RETURNS
11203 * Nothing.
11205 void WINAPI ClearCustData(CUSTDATA *lpCust)
11207 if (lpCust && lpCust->cCustData)
11209 if (lpCust->prgCustData)
11211 DWORD i;
11213 for (i = 0; i < lpCust->cCustData; i++)
11214 VariantClear(&lpCust->prgCustData[i].varValue);
11216 /* FIXME - Should be using a per-thread IMalloc */
11217 heap_free(lpCust->prgCustData);
11218 lpCust->prgCustData = NULL;
11220 lpCust->cCustData = 0;