oleaut32: Correct TRACE statement.
[wine.git] / dlls / oleaut32 / typelib.c
blob18c1e1974508f03043b75c04751eaf5d65e12495
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);
290 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
291 static HRESULT query_typelib_path( REFGUID guid, WORD wMaj, WORD wMin,
292 SYSKIND syskind, LCID lcid, LPBSTR path )
294 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
295 LCID myLCID = lcid;
296 HKEY hkey;
297 WCHAR buffer[60];
298 WCHAR Path[MAX_PATH];
299 LONG res;
301 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
303 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
304 get_typelib_key( guid, wMaj, wMin, buffer );
306 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
307 if (res == ERROR_FILE_NOT_FOUND)
309 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
310 return TYPE_E_LIBNOTREGISTERED;
312 else if (res != ERROR_SUCCESS)
314 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
315 return TYPE_E_REGISTRYACCESS;
318 while (hr != S_OK)
320 LONG dwPathLen = sizeof(Path);
322 get_lcid_subkey( myLCID, syskind, buffer );
324 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
326 if (!lcid)
327 break;
328 else if (myLCID == lcid)
330 /* try with sub-langid */
331 myLCID = SUBLANGID(lcid);
333 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
335 /* try with system langid */
336 myLCID = 0;
338 else
340 break;
343 else
345 *path = SysAllocString( Path );
346 hr = S_OK;
349 RegCloseKey( hkey );
350 TRACE_(typelib)("-- 0x%08x\n", hr);
351 return hr;
354 /****************************************************************************
355 * QueryPathOfRegTypeLib [OLEAUT32.164]
357 * Gets the path to a registered type library.
359 * PARAMS
360 * guid [I] referenced guid
361 * wMaj [I] major version
362 * wMin [I] minor version
363 * lcid [I] locale id
364 * path [O] path of typelib
366 * RETURNS
367 * Success: S_OK.
368 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
369 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
370 * opened.
372 HRESULT WINAPI QueryPathOfRegTypeLib( REFGUID guid, WORD wMaj, WORD wMin, LCID lcid, LPBSTR path )
374 #ifdef _WIN64
375 HRESULT hres = query_typelib_path( guid, wMaj, wMin, SYS_WIN64, lcid, path );
376 if(SUCCEEDED(hres))
377 return hres;
378 #endif
379 return query_typelib_path( guid, wMaj, wMin, SYS_WIN32, lcid, path );
382 /******************************************************************************
383 * CreateTypeLib [OLEAUT32.160] creates a typelib
385 * RETURNS
386 * Success: S_OK
387 * Failure: Status
389 HRESULT WINAPI CreateTypeLib(
390 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
392 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
393 return E_FAIL;
396 /******************************************************************************
397 * LoadTypeLib [OLEAUT32.161]
399 * Loads a type library
401 * PARAMS
402 * szFile [I] Name of file to load from.
403 * pptLib [O] Pointer that receives ITypeLib object on success.
405 * RETURNS
406 * Success: S_OK
407 * Failure: Status
409 * SEE
410 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
412 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
414 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
415 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
418 /******************************************************************************
419 * LoadTypeLibEx [OLEAUT32.183]
421 * Loads and optionally registers a type library
423 * RETURNS
424 * Success: S_OK
425 * Failure: Status
427 HRESULT WINAPI LoadTypeLibEx(
428 LPCOLESTR szFile, /* [in] Name of file to load from */
429 REGKIND regkind, /* [in] Specify kind of registration */
430 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
432 WCHAR szPath[MAX_PATH+1];
433 HRESULT res;
435 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
437 *pptLib = NULL;
439 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
441 if (SUCCEEDED(res))
442 switch(regkind)
444 case REGKIND_DEFAULT:
445 /* don't register typelibs supplied with full path. Experimentation confirms the following */
446 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
447 (szFile[0] && (szFile[1] == ':'))) break;
448 /* else fall-through */
450 case REGKIND_REGISTER:
451 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
453 ITypeLib_Release(*pptLib);
454 *pptLib = 0;
456 break;
457 case REGKIND_NONE:
458 break;
461 TRACE(" returns %08x\n",res);
462 return res;
465 /******************************************************************************
466 * LoadRegTypeLib [OLEAUT32.162]
468 * Loads a registered type library.
470 * PARAMS
471 * rguid [I] GUID of the registered type library.
472 * wVerMajor [I] major version.
473 * wVerMinor [I] minor version.
474 * lcid [I] locale ID.
475 * ppTLib [O] pointer that receives an ITypeLib object on success.
477 * RETURNS
478 * Success: S_OK.
479 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
480 * LoadTypeLib.
482 HRESULT WINAPI LoadRegTypeLib(
483 REFGUID rguid,
484 WORD wVerMajor,
485 WORD wVerMinor,
486 LCID lcid,
487 ITypeLib **ppTLib)
489 BSTR bstr=NULL;
490 HRESULT res;
492 *ppTLib = NULL;
494 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
496 if(SUCCEEDED(res))
498 res= LoadTypeLib(bstr, ppTLib);
499 SysFreeString(bstr);
502 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
504 return res;
508 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
509 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
510 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
511 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
512 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
513 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
515 /******************************************************************************
516 * RegisterTypeLib [OLEAUT32.163]
517 * Adds information about a type library to the System Registry
518 * NOTES
519 * Docs: ITypeLib FAR * ptlib
520 * Docs: OLECHAR FAR* szFullPath
521 * Docs: OLECHAR FAR* szHelpDir
523 * RETURNS
524 * Success: S_OK
525 * Failure: Status
527 HRESULT WINAPI RegisterTypeLib(
528 ITypeLib * ptlib, /* [in] Pointer to the library*/
529 OLECHAR * szFullPath, /* [in] full Path of the library*/
530 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
531 may be NULL*/
533 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
534 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
535 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
536 HRESULT res;
537 TLIBATTR *attr;
538 WCHAR keyName[60];
539 WCHAR tmp[16];
540 HKEY key, subKey;
541 UINT types, tidx;
542 TYPEKIND kind;
543 DWORD disposition;
545 if (ptlib == NULL || szFullPath == NULL)
546 return E_INVALIDARG;
548 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
549 return E_FAIL;
551 #ifndef _WIN64
552 if (attr->syskind == SYS_WIN64) return TYPE_E_BADMODULEKIND;
553 #endif
555 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
557 res = S_OK;
558 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
559 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
561 LPOLESTR doc;
563 /* Set the human-readable name of the typelib */
564 if (FAILED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
565 res = E_FAIL;
566 else if (doc)
568 if (RegSetValueExW(key, NULL, 0, REG_SZ,
569 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
570 res = E_FAIL;
572 SysFreeString(doc);
575 /* Make up the name of the typelib path subkey */
576 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
578 /* Create the typelib path subkey */
579 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
580 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
582 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
583 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
584 res = E_FAIL;
586 RegCloseKey(subKey);
588 else
589 res = E_FAIL;
591 /* Create the flags subkey */
592 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
593 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
595 /* FIXME: is %u correct? */
596 static const WCHAR formatW[] = {'%','u',0};
597 WCHAR buf[20];
598 sprintfW(buf, formatW, attr->wLibFlags);
599 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
600 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
601 res = E_FAIL;
603 RegCloseKey(subKey);
605 else
606 res = E_FAIL;
608 /* create the helpdir subkey */
609 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
610 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
612 BOOL freeHelpDir = FALSE;
613 OLECHAR* pIndexStr;
615 /* if we created a new key, and helpDir was null, set the helpdir
616 to the directory which contains the typelib. However,
617 if we just opened an existing key, we leave the helpdir alone */
618 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
619 szHelpDir = SysAllocString(szFullPath);
620 pIndexStr = strrchrW(szHelpDir, '\\');
621 if (pIndexStr) {
622 *pIndexStr = 0;
624 freeHelpDir = TRUE;
627 /* if we have an szHelpDir, set it! */
628 if (szHelpDir != NULL) {
629 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
630 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
631 res = E_FAIL;
635 /* tidy up */
636 if (freeHelpDir) SysFreeString(szHelpDir);
637 RegCloseKey(subKey);
639 } else {
640 res = E_FAIL;
643 RegCloseKey(key);
645 else
646 res = E_FAIL;
648 /* register OLE Automation-compatible interfaces for this typelib */
649 types = ITypeLib_GetTypeInfoCount(ptlib);
650 for (tidx=0; tidx<types; tidx++) {
651 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
652 LPOLESTR name = NULL;
653 ITypeInfo *tinfo = NULL;
655 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
657 switch (kind) {
658 case TKIND_INTERFACE:
659 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
660 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
661 break;
663 case TKIND_DISPATCH:
664 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
665 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
666 break;
668 default:
669 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
670 break;
673 if (tinfo) {
674 TYPEATTR *tattr = NULL;
675 ITypeInfo_GetTypeAttr(tinfo, &tattr);
677 if (tattr) {
678 TRACE_(typelib)("guid=%s, flags=%04x (",
679 debugstr_guid(&tattr->guid),
680 tattr->wTypeFlags);
682 if (TRACE_ON(typelib)) {
683 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
684 XX(FAPPOBJECT);
685 XX(FCANCREATE);
686 XX(FLICENSED);
687 XX(FPREDECLID);
688 XX(FHIDDEN);
689 XX(FCONTROL);
690 XX(FDUAL);
691 XX(FNONEXTENSIBLE);
692 XX(FOLEAUTOMATION);
693 XX(FRESTRICTED);
694 XX(FAGGREGATABLE);
695 XX(FREPLACEABLE);
696 XX(FDISPATCHABLE);
697 XX(FREVERSEBIND);
698 XX(FPROXY);
699 #undef XX
700 MESSAGE("\n");
703 /* Register all dispinterfaces (which includes dual interfaces) and
704 oleautomation interfaces */
705 if ((kind == TKIND_INTERFACE && (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
706 kind == TKIND_DISPATCH)
708 /* register interface<->typelib coupling */
709 get_interface_key( &tattr->guid, keyName );
710 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
711 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
713 if (name)
714 RegSetValueExW(key, NULL, 0, REG_SZ,
715 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
717 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
718 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
719 RegSetValueExW(subKey, NULL, 0, REG_SZ,
720 (const BYTE *)PSOA, sizeof PSOA);
721 RegCloseKey(subKey);
724 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
725 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
726 RegSetValueExW(subKey, NULL, 0, REG_SZ,
727 (const BYTE *)PSOA, sizeof PSOA);
728 RegCloseKey(subKey);
731 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
732 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
734 WCHAR buffer[40];
735 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
736 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
738 StringFromGUID2(&attr->guid, buffer, 40);
739 RegSetValueExW(subKey, NULL, 0, REG_SZ,
740 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
741 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
742 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
743 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
744 RegCloseKey(subKey);
747 RegCloseKey(key);
751 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
754 ITypeInfo_Release(tinfo);
757 SysFreeString(name);
761 ITypeLib_ReleaseTLibAttr(ptlib, attr);
763 return res;
767 /******************************************************************************
768 * UnRegisterTypeLib [OLEAUT32.186]
769 * Removes information about a type library from the System Registry
770 * NOTES
772 * RETURNS
773 * Success: S_OK
774 * Failure: Status
776 HRESULT WINAPI UnRegisterTypeLib(
777 REFGUID libid, /* [in] Guid of the library */
778 WORD wVerMajor, /* [in] major version */
779 WORD wVerMinor, /* [in] minor version */
780 LCID lcid, /* [in] locale id */
781 SYSKIND syskind)
783 BSTR tlibPath = NULL;
784 DWORD tmpLength;
785 WCHAR keyName[60];
786 WCHAR subKeyName[50];
787 int result = S_OK;
788 DWORD i = 0;
789 BOOL deleteOtherStuff;
790 HKEY key = NULL;
791 HKEY subKey = NULL;
792 TYPEATTR* typeAttr = NULL;
793 TYPEKIND kind;
794 ITypeInfo* typeInfo = NULL;
795 ITypeLib* typeLib = NULL;
796 int numTypes;
798 TRACE("(IID: %s)\n",debugstr_guid(libid));
800 /* Create the path to the key */
801 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
803 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
805 TRACE("Unsupported syskind %i\n", syskind);
806 result = E_INVALIDARG;
807 goto end;
810 /* get the path to the typelib on disk */
811 if (query_typelib_path(libid, wVerMajor, wVerMinor, syskind, lcid, &tlibPath) != S_OK) {
812 result = E_INVALIDARG;
813 goto end;
816 /* Try and open the key to the type library. */
817 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
818 result = E_INVALIDARG;
819 goto end;
822 /* Try and load the type library */
823 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib) != S_OK) {
824 result = TYPE_E_INVALIDSTATE;
825 goto end;
828 /* remove any types registered with this typelib */
829 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
830 for (i=0; i<numTypes; i++) {
831 /* get the kind of type */
832 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
833 goto enddeleteloop;
836 /* skip non-interfaces, and get type info for the type */
837 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
838 goto enddeleteloop;
840 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
841 goto enddeleteloop;
843 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
844 goto enddeleteloop;
847 if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
848 kind == TKIND_DISPATCH)
850 /* the path to the type */
851 get_interface_key( &typeAttr->guid, subKeyName );
853 /* Delete its bits */
854 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS)
855 goto enddeleteloop;
857 RegDeleteKeyW(subKey, ProxyStubClsidW);
858 RegDeleteKeyW(subKey, ProxyStubClsid32W);
859 RegDeleteKeyW(subKey, TypeLibW);
860 RegCloseKey(subKey);
861 subKey = NULL;
862 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
865 enddeleteloop:
866 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
867 typeAttr = NULL;
868 if (typeInfo) ITypeInfo_Release(typeInfo);
869 typeInfo = NULL;
872 /* Now, delete the type library path subkey */
873 get_lcid_subkey( lcid, syskind, subKeyName );
874 RegDeleteKeyW(key, subKeyName);
875 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
876 RegDeleteKeyW(key, subKeyName);
878 /* check if there is anything besides the FLAGS/HELPDIR keys.
879 If there is, we don't delete them */
880 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
881 deleteOtherStuff = TRUE;
882 i = 0;
883 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
884 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
886 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
887 if (!strcmpW(subKeyName, FLAGSW)) continue;
888 if (!strcmpW(subKeyName, HELPDIRW)) continue;
889 deleteOtherStuff = FALSE;
890 break;
893 /* only delete the other parts of the key if we're absolutely sure */
894 if (deleteOtherStuff) {
895 RegDeleteKeyW(key, FLAGSW);
896 RegDeleteKeyW(key, HELPDIRW);
897 RegCloseKey(key);
898 key = NULL;
900 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
901 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
902 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
905 end:
906 SysFreeString(tlibPath);
907 if (typeLib) ITypeLib_Release(typeLib);
908 if (subKey) RegCloseKey(subKey);
909 if (key) RegCloseKey(key);
910 return result;
913 /******************************************************************************
914 * RegisterTypeLibForUser [OLEAUT32.442]
915 * Adds information about a type library to the user registry
916 * NOTES
917 * Docs: ITypeLib FAR * ptlib
918 * Docs: OLECHAR FAR* szFullPath
919 * Docs: OLECHAR FAR* szHelpDir
921 * RETURNS
922 * Success: S_OK
923 * Failure: Status
925 HRESULT WINAPI RegisterTypeLibForUser(
926 ITypeLib * ptlib, /* [in] Pointer to the library*/
927 OLECHAR * szFullPath, /* [in] full Path of the library*/
928 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
929 may be NULL*/
931 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib,
932 debugstr_w(szFullPath), debugstr_w(szHelpDir));
933 return RegisterTypeLib(ptlib, szFullPath, szHelpDir);
936 /******************************************************************************
937 * UnRegisterTypeLibForUser [OLEAUT32.443]
938 * Removes information about a type library from the user registry
940 * RETURNS
941 * Success: S_OK
942 * Failure: Status
944 HRESULT WINAPI UnRegisterTypeLibForUser(
945 REFGUID libid, /* [in] GUID of the library */
946 WORD wVerMajor, /* [in] major version */
947 WORD wVerMinor, /* [in] minor version */
948 LCID lcid, /* [in] locale id */
949 SYSKIND syskind)
951 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
952 debugstr_guid(libid), wVerMajor, wVerMinor, lcid, syskind);
953 return UnRegisterTypeLib(libid, wVerMajor, wVerMinor, lcid, syskind);
956 /*======================= ITypeLib implementation =======================*/
958 typedef struct tagTLBGuid {
959 GUID guid;
960 INT hreftype;
961 UINT offset;
962 struct list entry;
963 } TLBGuid;
965 typedef struct tagTLBCustData
967 TLBGuid *guid;
968 VARIANT data;
969 struct list entry;
970 } TLBCustData;
972 /* data structure for import typelibs */
973 typedef struct tagTLBImpLib
975 int offset; /* offset in the file (MSFT)
976 offset in nametable (SLTG)
977 just used to identify library while reading
978 data from file */
979 TLBGuid *guid; /* libid */
980 BSTR name; /* name */
982 LCID lcid; /* lcid of imported typelib */
984 WORD wVersionMajor; /* major version number */
985 WORD wVersionMinor; /* minor version number */
987 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
988 NULL if not yet loaded */
989 struct list entry;
990 } TLBImpLib;
992 typedef struct tagTLBString {
993 BSTR str;
994 UINT offset;
995 struct list entry;
996 } TLBString;
998 /* internal ITypeLib data */
999 typedef struct tagITypeLibImpl
1001 ITypeLib2 ITypeLib2_iface;
1002 ITypeComp ITypeComp_iface;
1003 ICreateTypeLib2 ICreateTypeLib2_iface;
1004 LONG ref;
1005 TLBGuid *guid;
1006 LCID lcid;
1007 SYSKIND syskind;
1008 int ptr_size;
1009 WORD ver_major;
1010 WORD ver_minor;
1011 WORD libflags;
1012 LCID set_lcid;
1014 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1015 * exported to the application as a UNICODE string.
1017 struct list string_list;
1018 struct list name_list;
1019 struct list guid_list;
1021 const TLBString *Name;
1022 const TLBString *DocString;
1023 const TLBString *HelpFile;
1024 const TLBString *HelpStringDll;
1025 DWORD dwHelpContext;
1026 int TypeInfoCount; /* nr of typeinfo's in librarry */
1027 struct tagITypeInfoImpl **typeinfos;
1028 struct list custdata_list;
1029 struct list implib_list;
1030 int ctTypeDesc; /* number of items in type desc array */
1031 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1032 library. Only used while reading MSFT
1033 typelibs */
1034 struct list ref_list; /* list of ref types in this typelib */
1035 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1038 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1039 struct list entry;
1040 WCHAR *path;
1041 INT index;
1042 } ITypeLibImpl;
1044 static const ITypeLib2Vtbl tlbvt;
1045 static const ITypeCompVtbl tlbtcvt;
1046 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl;
1048 static inline ITypeLibImpl *impl_from_ITypeLib2(ITypeLib2 *iface)
1050 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeLib2_iface);
1053 static inline ITypeLibImpl *impl_from_ITypeLib(ITypeLib *iface)
1055 return impl_from_ITypeLib2((ITypeLib2*)iface);
1058 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1060 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeComp_iface);
1063 static inline ITypeLibImpl *impl_from_ICreateTypeLib2( ICreateTypeLib2 *iface )
1065 return CONTAINING_RECORD(iface, ITypeLibImpl, ICreateTypeLib2_iface);
1068 /* ITypeLib methods */
1069 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1070 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1072 /*======================= ITypeInfo implementation =======================*/
1074 /* data for referenced types */
1075 typedef struct tagTLBRefType
1077 INT index; /* Type index for internal ref or for external ref
1078 it the format is SLTG. -2 indicates to
1079 use guid */
1081 TYPEKIND tkind;
1082 TLBGuid *guid; /* guid of the referenced type */
1083 /* if index == TLB_REF_USE_GUID */
1085 HREFTYPE reference; /* The href of this ref */
1086 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1087 TLB_REF_INTERNAL for internal refs
1088 TLB_REF_NOT_FOUND for broken refs */
1090 struct list entry;
1091 } TLBRefType;
1093 #define TLB_REF_USE_GUID -2
1095 #define TLB_REF_INTERNAL (void*)-2
1096 #define TLB_REF_NOT_FOUND (void*)-1
1098 /* internal Parameter data */
1099 typedef struct tagTLBParDesc
1101 const TLBString *Name;
1102 struct list custdata_list;
1103 } TLBParDesc;
1105 /* internal Function data */
1106 typedef struct tagTLBFuncDesc
1108 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1109 const TLBString *Name; /* the name of this function */
1110 TLBParDesc *pParamDesc; /* array with param names and custom data */
1111 int helpcontext;
1112 int HelpStringContext;
1113 const TLBString *HelpString;
1114 const TLBString *Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1115 struct list custdata_list;
1116 } TLBFuncDesc;
1118 /* internal Variable data */
1119 typedef struct tagTLBVarDesc
1121 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1122 VARDESC *vardesc_create; /* additional data needed for storing VARDESC */
1123 const TLBString *Name; /* the name of this variable */
1124 int HelpContext;
1125 int HelpStringContext;
1126 const TLBString *HelpString;
1127 struct list custdata_list;
1128 } TLBVarDesc;
1130 /* internal implemented interface data */
1131 typedef struct tagTLBImplType
1133 HREFTYPE hRef; /* hRef of interface */
1134 int implflags; /* IMPLFLAG_*s */
1135 struct list custdata_list;
1136 } TLBImplType;
1138 /* internal TypeInfo data */
1139 typedef struct tagITypeInfoImpl
1141 ITypeInfo2 ITypeInfo2_iface;
1142 ITypeComp ITypeComp_iface;
1143 ICreateTypeInfo2 ICreateTypeInfo2_iface;
1144 LONG ref;
1145 BOOL not_attached_to_typelib;
1146 BOOL needs_layout;
1148 TLBGuid *guid;
1149 LCID lcid;
1150 MEMBERID memidConstructor;
1151 MEMBERID memidDestructor;
1152 LPOLESTR lpstrSchema;
1153 ULONG cbSizeInstance;
1154 TYPEKIND typekind;
1155 WORD cFuncs;
1156 WORD cVars;
1157 WORD cImplTypes;
1158 WORD cbSizeVft;
1159 WORD cbAlignment;
1160 WORD wTypeFlags;
1161 WORD wMajorVerNum;
1162 WORD wMinorVerNum;
1163 TYPEDESC *tdescAlias;
1164 IDLDESC idldescType;
1166 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1167 int index; /* index in this typelib; */
1168 HREFTYPE hreftype; /* hreftype for app object binding */
1169 /* type libs seem to store the doc strings in ascii
1170 * so why should we do it in unicode?
1172 const TLBString *Name;
1173 const TLBString *DocString;
1174 const TLBString *DllName;
1175 const TLBString *Schema;
1176 DWORD dwHelpContext;
1177 DWORD dwHelpStringContext;
1179 /* functions */
1180 TLBFuncDesc *funcdescs;
1182 /* variables */
1183 TLBVarDesc *vardescs;
1185 /* Implemented Interfaces */
1186 TLBImplType *impltypes;
1188 struct list *pcustdata_list;
1189 struct list custdata_list;
1190 } ITypeInfoImpl;
1192 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1194 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeComp_iface);
1197 static inline ITypeInfoImpl *impl_from_ITypeInfo2( ITypeInfo2 *iface )
1199 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeInfo2_iface);
1202 static inline ITypeInfoImpl *impl_from_ITypeInfo( ITypeInfo *iface )
1204 return impl_from_ITypeInfo2((ITypeInfo2*)iface);
1207 static inline ITypeInfoImpl *info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2 *iface )
1209 return CONTAINING_RECORD(iface, ITypeInfoImpl, ICreateTypeInfo2_iface);
1212 static const ITypeInfo2Vtbl tinfvt;
1213 static const ITypeCompVtbl tcompvt;
1214 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl;
1216 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1217 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1219 typedef struct tagTLBContext
1221 unsigned int oStart; /* start of TLB in file */
1222 unsigned int pos; /* current pos */
1223 unsigned int length; /* total length */
1224 void *mapping; /* memory mapping */
1225 MSFT_SegDir * pTblDir;
1226 ITypeLibImpl* pLibInfo;
1227 } TLBContext;
1230 static inline BSTR TLB_get_bstr(const TLBString *str)
1232 return str != NULL ? str->str : NULL;
1235 static inline int TLB_str_memcmp(void *left, const TLBString *str, DWORD len)
1237 if(!str)
1238 return 1;
1239 return memcmp(left, str->str, len);
1242 static inline const GUID *TLB_get_guidref(const TLBGuid *guid)
1244 return guid != NULL ? &guid->guid : NULL;
1247 static inline const GUID *TLB_get_guid_null(const TLBGuid *guid)
1249 return guid != NULL ? &guid->guid : &GUID_NULL;
1252 static int get_ptr_size(SYSKIND syskind)
1254 switch(syskind){
1255 case SYS_WIN64:
1256 return 8;
1257 case SYS_WIN32:
1258 case SYS_MAC:
1259 case SYS_WIN16:
1260 return 4;
1262 WARN("Unhandled syskind: 0x%x\n", syskind);
1263 return 4;
1267 debug
1269 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1270 if (pTD->vt & VT_RESERVED)
1271 szVarType += strlen(strcpy(szVarType, "reserved | "));
1272 if (pTD->vt & VT_BYREF)
1273 szVarType += strlen(strcpy(szVarType, "ref to "));
1274 if (pTD->vt & VT_ARRAY)
1275 szVarType += strlen(strcpy(szVarType, "array of "));
1276 if (pTD->vt & VT_VECTOR)
1277 szVarType += strlen(strcpy(szVarType, "vector of "));
1278 switch(pTD->vt & VT_TYPEMASK) {
1279 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1280 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1281 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1282 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1283 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1284 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1285 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1286 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1287 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1288 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1289 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1290 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1291 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1292 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1293 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1294 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1295 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1296 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1297 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1298 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1299 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1300 pTD->u.hreftype); break;
1301 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1302 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1303 case VT_PTR: sprintf(szVarType, "ptr to ");
1304 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1305 break;
1306 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1307 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1308 break;
1309 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1310 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1311 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1312 break;
1314 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1318 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1319 char buf[200];
1320 USHORT flags = edesc->u.paramdesc.wParamFlags;
1321 dump_TypeDesc(&edesc->tdesc,buf);
1322 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1323 MESSAGE("\t\tu.paramdesc.wParamFlags");
1324 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1325 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1326 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1327 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1328 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1329 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1330 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1331 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1332 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1334 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1335 int i;
1336 MESSAGE("memid is %08x\n",funcdesc->memid);
1337 for (i=0;i<funcdesc->cParams;i++) {
1338 MESSAGE("Param %d:\n",i);
1339 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1341 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1342 switch (funcdesc->funckind) {
1343 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1344 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1345 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1346 case FUNC_STATIC: MESSAGE("static");break;
1347 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1348 default: MESSAGE("unknown");break;
1350 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1351 switch (funcdesc->invkind) {
1352 case INVOKE_FUNC: MESSAGE("func");break;
1353 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1354 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1355 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1357 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1358 switch (funcdesc->callconv) {
1359 case CC_CDECL: MESSAGE("cdecl");break;
1360 case CC_PASCAL: MESSAGE("pascal");break;
1361 case CC_STDCALL: MESSAGE("stdcall");break;
1362 case CC_SYSCALL: MESSAGE("syscall");break;
1363 default:break;
1365 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1366 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1367 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1369 MESSAGE("\telemdescFunc (return value type):\n");
1370 dump_ELEMDESC(&funcdesc->elemdescFunc);
1373 static const char * const typekind_desc[] =
1375 "TKIND_ENUM",
1376 "TKIND_RECORD",
1377 "TKIND_MODULE",
1378 "TKIND_INTERFACE",
1379 "TKIND_DISPATCH",
1380 "TKIND_COCLASS",
1381 "TKIND_ALIAS",
1382 "TKIND_UNION",
1383 "TKIND_MAX"
1386 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1388 int i;
1389 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd->Name)), pfd->funcdesc.cParams);
1390 for (i=0;i<pfd->funcdesc.cParams;i++)
1391 MESSAGE("\tparm%d: %s\n",i,debugstr_w(TLB_get_bstr(pfd->pParamDesc[i].Name)));
1394 dump_FUNCDESC(&(pfd->funcdesc));
1396 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd->HelpString)));
1397 if(pfd->Entry == NULL)
1398 MESSAGE("\tentry: (null)\n");
1399 else if(pfd->Entry == (void*)-1)
1400 MESSAGE("\tentry: invalid\n");
1401 else if(IS_INTRESOURCE(pfd->Entry))
1402 MESSAGE("\tentry: %p\n", pfd->Entry);
1403 else
1404 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd->Entry)));
1406 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1408 while (n)
1410 dump_TLBFuncDescOne(pfd);
1411 ++pfd;
1412 --n;
1415 static void dump_TLBVarDesc(const TLBVarDesc * pvd, UINT n)
1417 while (n)
1419 TRACE_(typelib)("%s\n", debugstr_w(TLB_get_bstr(pvd->Name)));
1420 ++pvd;
1421 --n;
1425 static void dump_TLBImpLib(const TLBImpLib *import)
1427 TRACE_(typelib)("%s %s\n", debugstr_guid(TLB_get_guidref(import->guid)),
1428 debugstr_w(import->name));
1429 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1430 import->wVersionMinor, import->lcid, import->offset);
1433 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1435 TLBRefType *ref;
1437 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1439 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1440 if(ref->index == -1)
1441 TRACE_(typelib)("%s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
1442 else
1443 TRACE_(typelib)("type no: %d\n", ref->index);
1445 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1447 TRACE_(typelib)("in lib\n");
1448 dump_TLBImpLib(ref->pImpTLInfo);
1453 static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1455 if(!impl)
1456 return;
1457 while (n) {
1458 TRACE_(typelib)("implementing/inheriting interface hRef = %x implflags %x\n",
1459 impl->hRef, impl->implflags);
1460 ++impl;
1461 --n;
1465 static void dump_Variant(const VARIANT * pvar)
1467 SYSTEMTIME st;
1469 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1471 if (pvar)
1473 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1474 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1476 TRACE(",%p", V_BYREF(pvar));
1478 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1480 TRACE(",%p", V_ARRAY(pvar));
1482 else switch (V_TYPE(pvar))
1484 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1485 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1486 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1487 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1488 case VT_INT:
1489 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1490 case VT_UINT:
1491 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1492 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1493 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1494 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1495 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1496 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1497 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1498 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1499 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1500 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1501 V_CY(pvar).s.Lo); break;
1502 case VT_DATE:
1503 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1504 TRACE(",<invalid>");
1505 else
1506 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1507 st.wHour, st.wMinute, st.wSecond);
1508 break;
1509 case VT_ERROR:
1510 case VT_VOID:
1511 case VT_USERDEFINED:
1512 case VT_EMPTY:
1513 case VT_NULL: break;
1514 default: TRACE(",?"); break;
1517 TRACE("}\n");
1520 static void dump_DispParms(const DISPPARAMS * pdp)
1522 unsigned int index;
1524 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1526 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1528 TRACE("named args:\n");
1529 for (index = 0; index < pdp->cNamedArgs; index++)
1530 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1533 if (pdp->cArgs && pdp->rgvarg)
1535 TRACE("args:\n");
1536 for (index = 0; index < pdp->cArgs; index++)
1537 dump_Variant( &pdp->rgvarg[index] );
1541 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1543 TRACE("%p ref=%u\n", pty, pty->ref);
1544 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty->Name)), debugstr_w(TLB_get_bstr(pty->DocString)));
1545 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty->guid)));
1546 TRACE("kind:%s\n", typekind_desc[pty->typekind]);
1547 TRACE("fct:%u var:%u impl:%u\n", pty->cFuncs, pty->cVars, pty->cImplTypes);
1548 TRACE("wTypeFlags: 0x%04x\n", pty->wTypeFlags);
1549 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1550 if (pty->typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty->DllName)));
1551 if (TRACE_ON(ole))
1552 dump_TLBFuncDesc(pty->funcdescs, pty->cFuncs);
1553 dump_TLBVarDesc(pty->vardescs, pty->cVars);
1554 dump_TLBImplType(pty->impltypes, pty->cImplTypes);
1557 static void dump_VARDESC(const VARDESC *v)
1559 MESSAGE("memid %d\n",v->memid);
1560 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1561 MESSAGE("oInst %d\n",v->u.oInst);
1562 dump_ELEMDESC(&(v->elemdescVar));
1563 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1564 MESSAGE("varkind %d\n",v->varkind);
1567 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1569 /* VT_LPWSTR is largest type that, may appear in type description */
1570 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1571 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1572 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1573 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1574 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1575 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1576 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1577 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1580 static void TLB_abort(void)
1582 DebugBreak();
1585 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size)
1587 void *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
1588 if (!ret) ERR("cannot allocate memory\n");
1589 return ret;
1592 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size)
1594 void *ret = HeapAlloc(GetProcessHeap(), 0, size);
1595 if (!ret) ERR("cannot allocate memory\n");
1596 return ret;
1599 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr, unsigned size)
1601 return HeapReAlloc(GetProcessHeap(), 0, ptr, size);
1604 void heap_free(void *ptr)
1606 HeapFree(GetProcessHeap(), 0, ptr);
1609 /* returns the size required for a deep copy of a typedesc into a
1610 * flat buffer */
1611 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1613 SIZE_T size = 0;
1615 if (alloc_initial_space)
1616 size += sizeof(TYPEDESC);
1618 switch (tdesc->vt)
1620 case VT_PTR:
1621 case VT_SAFEARRAY:
1622 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1623 break;
1624 case VT_CARRAY:
1625 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1626 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1627 break;
1629 return size;
1632 /* deep copy a typedesc into a flat buffer */
1633 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1635 if (!dest)
1637 dest = buffer;
1638 buffer = (char *)buffer + sizeof(TYPEDESC);
1641 *dest = *src;
1643 switch (src->vt)
1645 case VT_PTR:
1646 case VT_SAFEARRAY:
1647 dest->u.lptdesc = buffer;
1648 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1649 break;
1650 case VT_CARRAY:
1651 dest->u.lpadesc = buffer;
1652 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1653 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1654 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1655 break;
1657 return buffer;
1660 /* free custom data allocated by MSFT_CustData */
1661 static inline void TLB_FreeCustData(struct list *custdata_list)
1663 TLBCustData *cd, *cdn;
1664 LIST_FOR_EACH_ENTRY_SAFE(cd, cdn, custdata_list, TLBCustData, entry)
1666 list_remove(&cd->entry);
1667 VariantClear(&cd->data);
1668 heap_free(cd);
1672 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1674 DWORD len;
1675 BSTR ret;
1677 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1678 ret = SysAllocStringLen(NULL, len - 1);
1679 if (!ret) return ret;
1680 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1681 return ret;
1684 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(TLBFuncDesc *funcdescs,
1685 UINT n, MEMBERID memid)
1687 while(n){
1688 if(funcdescs->funcdesc.memid == memid)
1689 return funcdescs;
1690 ++funcdescs;
1691 --n;
1693 return NULL;
1696 static inline TLBFuncDesc *TLB_get_funcdesc_by_name(TLBFuncDesc *funcdescs,
1697 UINT n, const OLECHAR *name)
1699 while(n){
1700 if(!lstrcmpiW(TLB_get_bstr(funcdescs->Name), name))
1701 return funcdescs;
1702 ++funcdescs;
1703 --n;
1705 return NULL;
1708 static inline TLBVarDesc *TLB_get_vardesc_by_memberid(TLBVarDesc *vardescs,
1709 UINT n, MEMBERID memid)
1711 while(n){
1712 if(vardescs->vardesc.memid == memid)
1713 return vardescs;
1714 ++vardescs;
1715 --n;
1717 return NULL;
1720 static inline TLBVarDesc *TLB_get_vardesc_by_name(TLBVarDesc *vardescs,
1721 UINT n, const OLECHAR *name)
1723 while(n){
1724 if(!lstrcmpiW(TLB_get_bstr(vardescs->Name), name))
1725 return vardescs;
1726 ++vardescs;
1727 --n;
1729 return NULL;
1732 static inline TLBCustData *TLB_get_custdata_by_guid(struct list *custdata_list, REFGUID guid)
1734 TLBCustData *cust_data;
1735 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1736 if(IsEqualIID(TLB_get_guid_null(cust_data->guid), guid))
1737 return cust_data;
1738 return NULL;
1741 static inline ITypeInfoImpl *TLB_get_typeinfo_by_name(ITypeInfoImpl **typeinfos,
1742 UINT n, const OLECHAR *name)
1744 while(n){
1745 if(!lstrcmpiW(TLB_get_bstr((*typeinfos)->Name), name))
1746 return *typeinfos;
1747 ++typeinfos;
1748 --n;
1750 return NULL;
1753 static void TLBVarDesc_Constructor(TLBVarDesc *var_desc)
1755 list_init(&var_desc->custdata_list);
1758 static TLBVarDesc *TLBVarDesc_Alloc(UINT n)
1760 TLBVarDesc *ret;
1762 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1763 if(!ret)
1764 return NULL;
1766 while(n){
1767 TLBVarDesc_Constructor(&ret[n-1]);
1768 --n;
1771 return ret;
1774 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1776 TLBParDesc *ret;
1778 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1779 if(!ret)
1780 return NULL;
1782 while(n){
1783 list_init(&ret[n-1].custdata_list);
1784 --n;
1787 return ret;
1790 static void TLBFuncDesc_Constructor(TLBFuncDesc *func_desc)
1792 list_init(&func_desc->custdata_list);
1795 static TLBFuncDesc *TLBFuncDesc_Alloc(UINT n)
1797 TLBFuncDesc *ret;
1799 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1800 if(!ret)
1801 return NULL;
1803 while(n){
1804 TLBFuncDesc_Constructor(&ret[n-1]);
1805 --n;
1808 return ret;
1811 static void TLBImplType_Constructor(TLBImplType *impl)
1813 list_init(&impl->custdata_list);
1816 static TLBImplType *TLBImplType_Alloc(UINT n)
1818 TLBImplType *ret;
1820 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1821 if(!ret)
1822 return NULL;
1824 while(n){
1825 TLBImplType_Constructor(&ret[n-1]);
1826 --n;
1829 return ret;
1832 static TLBGuid *TLB_append_guid(struct list *guid_list,
1833 const GUID *new_guid, HREFTYPE hreftype)
1835 TLBGuid *guid;
1837 LIST_FOR_EACH_ENTRY(guid, guid_list, TLBGuid, entry) {
1838 if (IsEqualGUID(&guid->guid, new_guid))
1839 return guid;
1842 guid = heap_alloc(sizeof(TLBGuid));
1843 if (!guid)
1844 return NULL;
1846 memcpy(&guid->guid, new_guid, sizeof(GUID));
1847 guid->hreftype = hreftype;
1849 list_add_tail(guid_list, &guid->entry);
1851 return guid;
1854 static HRESULT TLB_set_custdata(struct list *custdata_list, TLBGuid *tlbguid, VARIANT *var)
1856 TLBCustData *cust_data;
1858 switch(V_VT(var)){
1859 case VT_I4:
1860 case VT_R4:
1861 case VT_UI4:
1862 case VT_INT:
1863 case VT_UINT:
1864 case VT_HRESULT:
1865 case VT_BSTR:
1866 break;
1867 default:
1868 return DISP_E_BADVARTYPE;
1871 cust_data = TLB_get_custdata_by_guid(custdata_list, TLB_get_guid_null(tlbguid));
1873 if (!cust_data) {
1874 cust_data = heap_alloc(sizeof(TLBCustData));
1875 if (!cust_data)
1876 return E_OUTOFMEMORY;
1878 cust_data->guid = tlbguid;
1879 VariantInit(&cust_data->data);
1881 list_add_tail(custdata_list, &cust_data->entry);
1882 }else
1883 VariantClear(&cust_data->data);
1885 return VariantCopy(&cust_data->data, var);
1888 static TLBString *TLB_append_str(struct list *string_list, BSTR new_str)
1890 TLBString *str;
1892 LIST_FOR_EACH_ENTRY(str, string_list, TLBString, entry) {
1893 if (strcmpW(str->str, new_str) == 0)
1894 return str;
1897 str = heap_alloc(sizeof(TLBString));
1898 if (!str)
1899 return NULL;
1901 str->str = SysAllocString(new_str);
1902 if (!str->str) {
1903 heap_free(str);
1904 return NULL;
1907 list_add_tail(string_list, &str->entry);
1909 return str;
1912 static HRESULT TLB_get_size_from_hreftype(ITypeInfoImpl *info, HREFTYPE href,
1913 ULONG *size, WORD *align)
1915 ITypeInfo *other;
1916 TYPEATTR *attr;
1917 HRESULT hr;
1919 hr = ITypeInfo2_GetRefTypeInfo(&info->ITypeInfo2_iface, href, &other);
1920 if(FAILED(hr))
1921 return hr;
1923 hr = ITypeInfo_GetTypeAttr(other, &attr);
1924 if(FAILED(hr)){
1925 ITypeInfo_Release(other);
1926 return hr;
1929 if(size)
1930 *size = attr->cbSizeInstance;
1931 if(align)
1932 *align = attr->cbAlignment;
1934 ITypeInfo_ReleaseTypeAttr(other, attr);
1935 ITypeInfo_Release(other);
1937 return S_OK;
1940 static HRESULT TLB_size_instance(ITypeInfoImpl *info, SYSKIND sys,
1941 TYPEDESC *tdesc, ULONG *size, WORD *align)
1943 ULONG i, sub, ptr_size;
1944 HRESULT hr;
1946 ptr_size = get_ptr_size(sys);
1948 switch(tdesc->vt){
1949 case VT_VOID:
1950 *size = 0;
1951 break;
1952 case VT_I1:
1953 case VT_UI1:
1954 *size = 1;
1955 break;
1956 case VT_I2:
1957 case VT_BOOL:
1958 case VT_UI2:
1959 *size = 2;
1960 break;
1961 case VT_I4:
1962 case VT_R4:
1963 case VT_ERROR:
1964 case VT_UI4:
1965 case VT_INT:
1966 case VT_UINT:
1967 case VT_HRESULT:
1968 *size = 4;
1969 break;
1970 case VT_R8:
1971 case VT_I8:
1972 case VT_UI8:
1973 *size = 8;
1974 break;
1975 case VT_BSTR:
1976 case VT_DISPATCH:
1977 case VT_UNKNOWN:
1978 case VT_PTR:
1979 case VT_SAFEARRAY:
1980 case VT_LPSTR:
1981 case VT_LPWSTR:
1982 *size = ptr_size;
1983 break;
1984 case VT_DATE:
1985 *size = sizeof(DATE);
1986 break;
1987 case VT_VARIANT:
1988 *size = sizeof(VARIANT);
1989 #ifdef _WIN64
1990 if(sys == SYS_WIN32)
1991 *size -= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
1992 #endif
1993 break;
1994 case VT_DECIMAL:
1995 *size = sizeof(DECIMAL);
1996 break;
1997 case VT_CY:
1998 *size = sizeof(CY);
1999 break;
2000 case VT_CARRAY:
2001 *size = 0;
2002 for(i = 0; i < tdesc->u.lpadesc->cDims; ++i)
2003 *size += tdesc->u.lpadesc->rgbounds[i].cElements;
2004 hr = TLB_size_instance(info, sys, &tdesc->u.lpadesc->tdescElem, &sub, align);
2005 if(FAILED(hr))
2006 return hr;
2007 *size *= sub;
2008 return S_OK;
2009 case VT_USERDEFINED:
2010 return TLB_get_size_from_hreftype(info, tdesc->u.hreftype, size, align);
2011 default:
2012 FIXME("Unsized VT: 0x%x\n", tdesc->vt);
2013 return E_FAIL;
2016 if(align){
2017 if(*size < 4)
2018 *align = *size;
2019 else
2020 *align = 4;
2023 return S_OK;
2026 /**********************************************************************
2028 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2030 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
2032 return pcx->pos;
2035 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
2037 if (where != DO_NOT_SEEK)
2039 where += pcx->oStart;
2040 if (where > pcx->length)
2042 /* FIXME */
2043 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
2044 TLB_abort();
2046 pcx->pos = where;
2050 /* read function */
2051 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
2053 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2054 pcx->pos, count, pcx->oStart, pcx->length, where);
2056 MSFT_Seek(pcx, where);
2057 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
2058 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
2059 pcx->pos += count;
2060 return count;
2063 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
2064 LONG where )
2066 DWORD ret;
2068 ret = MSFT_Read(buffer, count, pcx, where);
2069 FromLEDWords(buffer, ret);
2071 return ret;
2074 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
2075 LONG where )
2077 DWORD ret;
2079 ret = MSFT_Read(buffer, count, pcx, where);
2080 FromLEWords(buffer, ret);
2082 return ret;
2085 static HRESULT MSFT_ReadAllGuids(TLBContext *pcx)
2087 TLBGuid *guid;
2088 MSFT_GuidEntry entry;
2089 int offs = 0;
2091 MSFT_Seek(pcx, pcx->pTblDir->pGuidTab.offset);
2092 while (1) {
2093 if (offs >= pcx->pTblDir->pGuidTab.length)
2094 return S_OK;
2096 MSFT_ReadLEWords(&entry, sizeof(MSFT_GuidEntry), pcx, DO_NOT_SEEK);
2098 guid = heap_alloc(sizeof(TLBGuid));
2100 guid->offset = offs;
2101 guid->guid = entry.guid;
2102 guid->hreftype = entry.hreftype;
2104 list_add_tail(&pcx->pLibInfo->guid_list, &guid->entry);
2106 offs += sizeof(MSFT_GuidEntry);
2110 static TLBGuid *MSFT_ReadGuid( int offset, TLBContext *pcx)
2112 TLBGuid *ret;
2114 LIST_FOR_EACH_ENTRY(ret, &pcx->pLibInfo->guid_list, TLBGuid, entry){
2115 if(ret->offset == offset){
2116 TRACE_(typelib)("%s\n", debugstr_guid(&ret->guid));
2117 return ret;
2121 return NULL;
2124 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
2126 MSFT_NameIntro niName;
2128 if (offset < 0)
2130 ERR_(typelib)("bad offset %d\n", offset);
2131 return -1;
2134 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
2135 pcx->pTblDir->pNametab.offset+offset);
2137 return niName.hreftype;
2140 static HRESULT MSFT_ReadAllNames(TLBContext *pcx)
2142 char *string;
2143 MSFT_NameIntro intro;
2144 INT16 len_piece;
2145 int offs = 0, lengthInChars;
2147 MSFT_Seek(pcx, pcx->pTblDir->pNametab.offset);
2148 while (1) {
2149 TLBString *tlbstr;
2151 if (offs >= pcx->pTblDir->pNametab.length)
2152 return S_OK;
2154 MSFT_ReadLEWords(&intro, sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2155 intro.namelen &= 0xFF;
2156 len_piece = intro.namelen + sizeof(MSFT_NameIntro);
2157 if(len_piece % 4)
2158 len_piece = (len_piece + 4) & ~0x3;
2159 if(len_piece < 8)
2160 len_piece = 8;
2162 string = heap_alloc(len_piece + 1);
2163 MSFT_Read(string, len_piece - sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2164 string[intro.namelen] = '\0';
2166 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2167 string, -1, NULL, 0);
2168 if (!lengthInChars) {
2169 heap_free(string);
2170 return E_UNEXPECTED;
2173 tlbstr = heap_alloc(sizeof(TLBString));
2175 tlbstr->offset = offs;
2176 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2177 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2179 heap_free(string);
2181 list_add_tail(&pcx->pLibInfo->name_list, &tlbstr->entry);
2183 offs += len_piece;
2187 static TLBString *MSFT_ReadName( TLBContext *pcx, int offset)
2189 TLBString *tlbstr;
2191 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->name_list, TLBString, entry) {
2192 if (tlbstr->offset == offset) {
2193 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2194 return tlbstr;
2198 return NULL;
2201 static TLBString *MSFT_ReadString( TLBContext *pcx, int offset)
2203 TLBString *tlbstr;
2205 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->string_list, TLBString, entry) {
2206 if (tlbstr->offset == offset) {
2207 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2208 return tlbstr;
2212 return NULL;
2216 * read a value and fill a VARIANT structure
2218 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
2220 int size;
2222 TRACE_(typelib)("\n");
2224 if(offset <0) { /* data are packed in here */
2225 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
2226 V_I4(pVar) = offset & 0x3ffffff;
2227 return;
2229 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
2230 pcx->pTblDir->pCustData.offset + offset );
2231 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
2232 switch (V_VT(pVar)){
2233 case VT_EMPTY: /* FIXME: is this right? */
2234 case VT_NULL: /* FIXME: is this right? */
2235 case VT_I2 : /* this should not happen */
2236 case VT_I4 :
2237 case VT_R4 :
2238 case VT_ERROR :
2239 case VT_BOOL :
2240 case VT_I1 :
2241 case VT_UI1 :
2242 case VT_UI2 :
2243 case VT_UI4 :
2244 case VT_INT :
2245 case VT_UINT :
2246 case VT_VOID : /* FIXME: is this right? */
2247 case VT_HRESULT :
2248 size=4; break;
2249 case VT_R8 :
2250 case VT_CY :
2251 case VT_DATE :
2252 case VT_I8 :
2253 case VT_UI8 :
2254 case VT_DECIMAL : /* FIXME: is this right? */
2255 case VT_FILETIME :
2256 size=8;break;
2257 /* pointer types with known behaviour */
2258 case VT_BSTR :{
2259 char * ptr;
2260 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
2261 if(size < 0) {
2262 char next;
2263 DWORD origPos = MSFT_Tell(pcx), nullPos;
2265 do {
2266 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
2267 } while (next);
2268 nullPos = MSFT_Tell(pcx);
2269 size = nullPos - origPos;
2270 MSFT_Seek(pcx, origPos);
2272 ptr = heap_alloc_zero(size);/* allocate temp buffer */
2273 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
2274 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
2275 /* FIXME: do we need a AtoW conversion here? */
2276 V_UNION(pVar, bstrVal[size])='\0';
2277 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
2278 heap_free(ptr);
2280 size=-4; break;
2281 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2282 case VT_DISPATCH :
2283 case VT_VARIANT :
2284 case VT_UNKNOWN :
2285 case VT_PTR :
2286 case VT_SAFEARRAY :
2287 case VT_CARRAY :
2288 case VT_USERDEFINED :
2289 case VT_LPSTR :
2290 case VT_LPWSTR :
2291 case VT_BLOB :
2292 case VT_STREAM :
2293 case VT_STORAGE :
2294 case VT_STREAMED_OBJECT :
2295 case VT_STORED_OBJECT :
2296 case VT_BLOB_OBJECT :
2297 case VT_CF :
2298 case VT_CLSID :
2299 default:
2300 size=0;
2301 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2302 V_VT(pVar));
2305 if(size>0) /* (big|small) endian correct? */
2306 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
2307 return;
2310 * create a linked list with custom data
2312 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
2314 MSFT_CDGuid entry;
2315 TLBCustData* pNew;
2316 int count=0;
2318 TRACE_(typelib)("\n");
2320 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
2322 while(offset >=0){
2323 count++;
2324 pNew=heap_alloc_zero(sizeof(TLBCustData));
2325 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
2326 pNew->guid = MSFT_ReadGuid(entry.GuidOffset, pcx);
2327 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
2328 list_add_head(custdata_list, &pNew->entry);
2329 offset = entry.next;
2331 return count;
2334 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd)
2336 if(type <0)
2337 pTd->vt=type & VT_TYPEMASK;
2338 else
2339 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
2341 TRACE_(typelib)("vt type = %X\n", pTd->vt);
2344 static int TLB_is_propgetput(INVOKEKIND invkind)
2346 return (invkind == INVOKE_PROPERTYGET ||
2347 invkind == INVOKE_PROPERTYPUT ||
2348 invkind == INVOKE_PROPERTYPUTREF);
2351 static void
2352 MSFT_DoFuncs(TLBContext* pcx,
2353 ITypeInfoImpl* pTI,
2354 int cFuncs,
2355 int cVars,
2356 int offset,
2357 TLBFuncDesc** pptfd)
2360 * member information is stored in a data structure at offset
2361 * indicated by the memoffset field of the typeinfo structure
2362 * There are several distinctive parts.
2363 * The first part starts with a field that holds the total length
2364 * of this (first) part excluding this field. Then follow the records,
2365 * for each member there is one record.
2367 * The first entry is always the length of the record (including this
2368 * length word).
2369 * The rest of the record depends on the type of the member. If there is
2370 * a field indicating the member type (function, variable, interface, etc)
2371 * I have not found it yet. At this time we depend on the information
2372 * in the type info and the usual order how things are stored.
2374 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2375 * for each member;
2377 * Third is an equal sized array with file offsets to the name entry
2378 * of each member.
2380 * The fourth and last (?) part is an array with offsets to the records
2381 * in the first part of this file segment.
2384 int infolen, nameoffset, reclength, i;
2385 int recoffset = offset + sizeof(INT);
2387 char *recbuf = heap_alloc(0xffff);
2388 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2389 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2391 TRACE_(typelib)("\n");
2393 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2395 *pptfd = TLBFuncDesc_Alloc(cFuncs);
2396 ptfd = *pptfd;
2397 for ( i = 0; i < cFuncs ; i++ )
2399 int optional;
2401 /* name, eventually add to a hash table */
2402 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2403 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2405 /* read the function information record */
2406 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2408 reclength &= 0xffff;
2410 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2412 /* size without argument data */
2413 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2414 if (pFuncRec->FKCCIC & 0x1000)
2415 optional -= pFuncRec->nrargs * sizeof(INT);
2417 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2418 ptfd->helpcontext = pFuncRec->HelpContext;
2420 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2421 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2423 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2425 if (pFuncRec->FKCCIC & 0x2000 )
2427 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2428 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2429 ptfd->Entry = (TLBString*)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2431 else
2432 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2434 else
2435 ptfd->Entry = (TLBString*)-1;
2437 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2438 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2440 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2441 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2443 /* fill the FuncDesc Structure */
2444 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2445 offset + infolen + ( i + 1) * sizeof(INT));
2447 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2448 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2449 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2450 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2451 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2452 ptfd->funcdesc.oVft = pFuncRec->VtableOffset & ~1;
2453 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2455 /* nameoffset is sometimes -1 on the second half of a propget/propput
2456 * pair of functions */
2457 if ((nameoffset == -1) && (i > 0) &&
2458 TLB_is_propgetput(ptfd_prev->funcdesc.invkind) &&
2459 TLB_is_propgetput(ptfd->funcdesc.invkind))
2460 ptfd->Name = ptfd_prev->Name;
2461 else
2462 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2464 MSFT_GetTdesc(pcx,
2465 pFuncRec->DataType,
2466 &ptfd->funcdesc.elemdescFunc.tdesc);
2468 /* do the parameters/arguments */
2469 if(pFuncRec->nrargs)
2471 int j = 0;
2472 MSFT_ParameterInfo paraminfo;
2474 ptfd->funcdesc.lprgelemdescParam =
2475 heap_alloc_zero(pFuncRec->nrargs * (sizeof(ELEMDESC) + sizeof(PARAMDESCEX)));
2477 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2479 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2480 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2482 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2484 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2486 MSFT_GetTdesc(pcx,
2487 paraminfo.DataType,
2488 &elemdesc->tdesc);
2490 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2492 /* name */
2493 if (paraminfo.oName != -1)
2494 ptfd->pParamDesc[j].Name =
2495 MSFT_ReadName( pcx, paraminfo.oName );
2496 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(TLB_get_bstr(ptfd->pParamDesc[j].Name)));
2498 /* default value */
2499 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2500 (pFuncRec->FKCCIC & 0x1000) )
2502 INT* pInt = (INT *)((char *)pFuncRec +
2503 reclength -
2504 (pFuncRec->nrargs * 4) * sizeof(INT) );
2506 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2508 pParamDesc->pparamdescex = (PARAMDESCEX*)(ptfd->funcdesc.lprgelemdescParam+pFuncRec->nrargs)+j;
2509 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2511 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2512 pInt[j], pcx);
2514 else
2515 elemdesc->u.paramdesc.pparamdescex = NULL;
2517 /* custom info */
2518 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2519 j*sizeof(pFuncRec->oArgCustData[0])) &&
2520 pFuncRec->FKCCIC & 0x80 )
2522 MSFT_CustData(pcx,
2523 pFuncRec->oArgCustData[j],
2524 &ptfd->pParamDesc[j].custdata_list);
2527 /* SEEK value = jump to offset,
2528 * from there jump to the end of record,
2529 * go back by (j-1) arguments
2531 MSFT_ReadLEDWords( &paraminfo ,
2532 sizeof(MSFT_ParameterInfo), pcx,
2533 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2534 * sizeof(MSFT_ParameterInfo)));
2538 /* scode is not used: archaic win16 stuff FIXME: right? */
2539 ptfd->funcdesc.cScodes = 0 ;
2540 ptfd->funcdesc.lprgscode = NULL ;
2542 ptfd_prev = ptfd;
2543 ++ptfd;
2544 recoffset += reclength;
2546 heap_free(recbuf);
2549 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2550 int cVars, int offset, TLBVarDesc ** pptvd)
2552 int infolen, nameoffset, reclength;
2553 char recbuf[256];
2554 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2555 TLBVarDesc *ptvd;
2556 int i;
2557 int recoffset;
2559 TRACE_(typelib)("\n");
2561 ptvd = *pptvd = TLBVarDesc_Alloc(cVars);
2562 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2563 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2564 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2565 recoffset += offset+sizeof(INT);
2566 for(i=0;i<cVars;i++, ++ptvd){
2567 /* name, eventually add to a hash table */
2568 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2569 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2570 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2571 /* read the variable information record */
2572 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2573 reclength &= 0xff;
2574 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2576 /* optional data */
2577 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2578 ptvd->HelpContext = pVarRec->HelpContext;
2580 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2581 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2583 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2584 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2586 /* fill the VarDesc Structure */
2587 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2588 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2589 ptvd->vardesc.varkind = pVarRec->VarKind;
2590 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2591 MSFT_GetTdesc(pcx, pVarRec->DataType,
2592 &ptvd->vardesc.elemdescVar.tdesc);
2593 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2594 if(pVarRec->VarKind == VAR_CONST ){
2595 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2596 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2597 pVarRec->OffsValue, pcx);
2598 } else
2599 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2600 recoffset += reclength;
2604 /* process Implemented Interfaces of a com class */
2605 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2606 int offset)
2608 int i;
2609 MSFT_RefRecord refrec;
2610 TLBImplType *pImpl;
2612 TRACE_(typelib)("\n");
2614 pTI->impltypes = TLBImplType_Alloc(count);
2615 pImpl = pTI->impltypes;
2616 for(i=0;i<count;i++){
2617 if(offset<0) break; /* paranoia */
2618 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2619 pImpl->hRef = refrec.reftype;
2620 pImpl->implflags=refrec.flags;
2621 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2622 offset=refrec.onext;
2623 ++pImpl;
2627 #ifdef _WIN64
2628 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2629 * and some structures, and fix the alignment */
2630 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl *info)
2632 if(info->typekind == TKIND_ALIAS){
2633 switch(info->tdescAlias->vt){
2634 case VT_BSTR:
2635 case VT_DISPATCH:
2636 case VT_UNKNOWN:
2637 case VT_PTR:
2638 case VT_SAFEARRAY:
2639 case VT_LPSTR:
2640 case VT_LPWSTR:
2641 info->cbSizeInstance = sizeof(void*);
2642 info->cbAlignment = sizeof(void*);
2643 break;
2644 case VT_CARRAY:
2645 case VT_USERDEFINED:
2646 TLB_size_instance(info, SYS_WIN64, info->tdescAlias, &info->cbSizeInstance, &info->cbAlignment);
2647 break;
2648 case VT_VARIANT:
2649 info->cbSizeInstance = sizeof(VARIANT);
2650 info->cbAlignment = 8;
2651 default:
2652 if(info->cbSizeInstance < sizeof(void*))
2653 info->cbAlignment = info->cbSizeInstance;
2654 else
2655 info->cbAlignment = sizeof(void*);
2656 break;
2658 }else if(info->typekind == TKIND_INTERFACE ||
2659 info->typekind == TKIND_DISPATCH ||
2660 info->typekind == TKIND_COCLASS){
2661 info->cbSizeInstance = sizeof(void*);
2662 info->cbAlignment = sizeof(void*);
2665 #endif
2668 * process a typeinfo record
2670 static ITypeInfoImpl * MSFT_DoTypeInfo(
2671 TLBContext *pcx,
2672 int count,
2673 ITypeLibImpl * pLibInfo)
2675 MSFT_TypeInfoBase tiBase;
2676 ITypeInfoImpl *ptiRet;
2678 TRACE_(typelib)("count=%u\n", count);
2680 ptiRet = ITypeInfoImpl_Constructor();
2681 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2682 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2684 /* this is where we are coming from */
2685 ptiRet->pTypeLib = pLibInfo;
2686 ptiRet->index=count;
2688 ptiRet->guid = MSFT_ReadGuid(tiBase.posguid, pcx);
2689 ptiRet->lcid=pLibInfo->set_lcid; /* FIXME: correct? */
2690 ptiRet->lpstrSchema=NULL; /* reserved */
2691 ptiRet->cbSizeInstance=tiBase.size;
2692 ptiRet->typekind=tiBase.typekind & 0xF;
2693 ptiRet->cFuncs=LOWORD(tiBase.cElement);
2694 ptiRet->cVars=HIWORD(tiBase.cElement);
2695 ptiRet->cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2696 ptiRet->wTypeFlags=tiBase.flags;
2697 ptiRet->wMajorVerNum=LOWORD(tiBase.version);
2698 ptiRet->wMinorVerNum=HIWORD(tiBase.version);
2699 ptiRet->cImplTypes=tiBase.cImplTypes;
2700 ptiRet->cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2701 if(ptiRet->typekind == TKIND_ALIAS){
2702 TYPEDESC tmp;
2703 MSFT_GetTdesc(pcx, tiBase.datatype1, &tmp);
2704 ptiRet->tdescAlias = heap_alloc(TLB_SizeTypeDesc(&tmp, TRUE));
2705 TLB_CopyTypeDesc(NULL, &tmp, ptiRet->tdescAlias);
2708 /* FIXME: */
2709 /* IDLDESC idldescType; *//* never saw this one != zero */
2711 /* name, eventually add to a hash table */
2712 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2713 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2714 TRACE_(typelib)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet->Name)));
2715 /* help info */
2716 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2717 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2718 ptiRet->dwHelpContext=tiBase.helpcontext;
2720 if (ptiRet->typekind == TKIND_MODULE)
2721 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2723 /* note: InfoType's Help file and HelpStringDll come from the containing
2724 * library. Further HelpString and Docstring appear to be the same thing :(
2726 /* functions */
2727 if(ptiRet->cFuncs >0 )
2728 MSFT_DoFuncs(pcx, ptiRet, ptiRet->cFuncs,
2729 ptiRet->cVars,
2730 tiBase.memoffset, &ptiRet->funcdescs);
2731 /* variables */
2732 if(ptiRet->cVars >0 )
2733 MSFT_DoVars(pcx, ptiRet, ptiRet->cFuncs,
2734 ptiRet->cVars,
2735 tiBase.memoffset, &ptiRet->vardescs);
2736 if(ptiRet->cImplTypes >0 ) {
2737 switch(ptiRet->typekind)
2739 case TKIND_COCLASS:
2740 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->cImplTypes,
2741 tiBase.datatype1);
2742 break;
2743 case TKIND_DISPATCH:
2744 /* This is not -1 when the interface is a non-base dual interface or
2745 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2746 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2747 not this interface.
2750 if (tiBase.datatype1 != -1)
2752 ptiRet->impltypes = TLBImplType_Alloc(1);
2753 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2755 break;
2756 default:
2757 ptiRet->impltypes = TLBImplType_Alloc(1);
2758 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2759 break;
2762 MSFT_CustData(pcx, tiBase.oCustData, ptiRet->pcustdata_list);
2764 TRACE_(typelib)("%s guid: %s kind:%s\n",
2765 debugstr_w(TLB_get_bstr(ptiRet->Name)),
2766 debugstr_guid(TLB_get_guidref(ptiRet->guid)),
2767 typekind_desc[ptiRet->typekind]);
2768 if (TRACE_ON(typelib))
2769 dump_TypeInfo(ptiRet);
2771 return ptiRet;
2774 static HRESULT MSFT_ReadAllStrings(TLBContext *pcx)
2776 char *string;
2777 INT16 len_str, len_piece;
2778 int offs = 0, lengthInChars;
2780 MSFT_Seek(pcx, pcx->pTblDir->pStringtab.offset);
2781 while (1) {
2782 TLBString *tlbstr;
2784 if (offs >= pcx->pTblDir->pStringtab.length)
2785 return S_OK;
2787 MSFT_ReadLEWords(&len_str, sizeof(INT16), pcx, DO_NOT_SEEK);
2788 len_piece = len_str + sizeof(INT16);
2789 if(len_piece % 4)
2790 len_piece = (len_piece + 4) & ~0x3;
2791 if(len_piece < 8)
2792 len_piece = 8;
2794 string = heap_alloc(len_piece + 1);
2795 MSFT_Read(string, len_piece - sizeof(INT16), pcx, DO_NOT_SEEK);
2796 string[len_str] = '\0';
2798 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2799 string, -1, NULL, 0);
2800 if (!lengthInChars) {
2801 heap_free(string);
2802 return E_UNEXPECTED;
2805 tlbstr = heap_alloc(sizeof(TLBString));
2807 tlbstr->offset = offs;
2808 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2809 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2811 heap_free(string);
2813 list_add_tail(&pcx->pLibInfo->string_list, &tlbstr->entry);
2815 offs += len_piece;
2819 static HRESULT MSFT_ReadAllRefs(TLBContext *pcx)
2821 TLBRefType *ref;
2822 int offs = 0;
2824 MSFT_Seek(pcx, pcx->pTblDir->pImpInfo.offset);
2825 while (offs < pcx->pTblDir->pImpInfo.length) {
2826 MSFT_ImpInfo impinfo;
2827 TLBImpLib *pImpLib;
2829 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx, DO_NOT_SEEK);
2831 ref = heap_alloc_zero(sizeof(TLBRefType));
2832 list_add_tail(&pcx->pLibInfo->ref_list, &ref->entry);
2834 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2835 if(pImpLib->offset==impinfo.oImpFile)
2836 break;
2838 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2839 ref->reference = offs;
2840 ref->pImpTLInfo = pImpLib;
2841 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2842 ref->guid = MSFT_ReadGuid(impinfo.oGuid, pcx);
2843 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
2844 ref->index = TLB_REF_USE_GUID;
2845 } else
2846 ref->index = impinfo.oGuid;
2847 }else{
2848 ERR("Cannot find a reference\n");
2849 ref->reference = -1;
2850 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2853 offs += sizeof(impinfo);
2856 return S_OK;
2859 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2860 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2861 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2862 * tradeoff here.
2864 static struct list tlb_cache = LIST_INIT(tlb_cache);
2865 static CRITICAL_SECTION cache_section;
2866 static CRITICAL_SECTION_DEBUG cache_section_debug =
2868 0, 0, &cache_section,
2869 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2870 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2872 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2875 typedef struct TLB_PEFile
2877 IUnknown IUnknown_iface;
2878 LONG refs;
2879 HMODULE dll;
2880 HRSRC typelib_resource;
2881 HGLOBAL typelib_global;
2882 LPVOID typelib_base;
2883 } TLB_PEFile;
2885 static inline TLB_PEFile *pefile_impl_from_IUnknown(IUnknown *iface)
2887 return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2890 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2892 if (IsEqualIID(riid, &IID_IUnknown))
2894 *ppv = iface;
2895 IUnknown_AddRef(iface);
2896 return S_OK;
2898 *ppv = NULL;
2899 return E_NOINTERFACE;
2902 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2904 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2905 return InterlockedIncrement(&This->refs);
2908 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2910 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2911 ULONG refs = InterlockedDecrement(&This->refs);
2912 if (!refs)
2914 if (This->typelib_global)
2915 FreeResource(This->typelib_global);
2916 if (This->dll)
2917 FreeLibrary(This->dll);
2918 heap_free(This);
2920 return refs;
2923 static const IUnknownVtbl TLB_PEFile_Vtable =
2925 TLB_PEFile_QueryInterface,
2926 TLB_PEFile_AddRef,
2927 TLB_PEFile_Release
2930 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2932 TLB_PEFile *This;
2933 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2935 This = heap_alloc(sizeof(TLB_PEFile));
2936 if (!This)
2937 return E_OUTOFMEMORY;
2939 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
2940 This->refs = 1;
2941 This->dll = NULL;
2942 This->typelib_resource = NULL;
2943 This->typelib_global = NULL;
2944 This->typelib_base = NULL;
2946 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2947 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2949 if (This->dll)
2951 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2952 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2953 if (This->typelib_resource)
2955 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2956 if (This->typelib_global)
2958 This->typelib_base = LockResource(This->typelib_global);
2960 if (This->typelib_base)
2962 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2963 *ppBase = This->typelib_base;
2964 *ppFile = &This->IUnknown_iface;
2965 return S_OK;
2970 TRACE("No TYPELIB resource found\n");
2971 hr = E_FAIL;
2974 TLB_PEFile_Release(&This->IUnknown_iface);
2975 return hr;
2978 typedef struct TLB_NEFile
2980 IUnknown IUnknown_iface;
2981 LONG refs;
2982 LPVOID typelib_base;
2983 } TLB_NEFile;
2985 static inline TLB_NEFile *nefile_impl_from_IUnknown(IUnknown *iface)
2987 return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
2990 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2992 if (IsEqualIID(riid, &IID_IUnknown))
2994 *ppv = iface;
2995 IUnknown_AddRef(iface);
2996 return S_OK;
2998 *ppv = NULL;
2999 return E_NOINTERFACE;
3002 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
3004 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
3005 return InterlockedIncrement(&This->refs);
3008 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
3010 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
3011 ULONG refs = InterlockedDecrement(&This->refs);
3012 if (!refs)
3014 heap_free(This->typelib_base);
3015 heap_free(This);
3017 return refs;
3020 static const IUnknownVtbl TLB_NEFile_Vtable =
3022 TLB_NEFile_QueryInterface,
3023 TLB_NEFile_AddRef,
3024 TLB_NEFile_Release
3027 /***********************************************************************
3028 * read_xx_header [internal]
3030 static int read_xx_header( HFILE lzfd )
3032 IMAGE_DOS_HEADER mzh;
3033 char magic[3];
3035 LZSeek( lzfd, 0, SEEK_SET );
3036 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
3037 return 0;
3038 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
3039 return 0;
3041 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3042 if ( 2 != LZRead( lzfd, magic, 2 ) )
3043 return 0;
3045 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3047 if ( magic[0] == 'N' && magic[1] == 'E' )
3048 return IMAGE_OS2_SIGNATURE;
3049 if ( magic[0] == 'P' && magic[1] == 'E' )
3050 return IMAGE_NT_SIGNATURE;
3052 magic[2] = '\0';
3053 WARN("Can't handle %s files.\n", magic );
3054 return 0;
3058 /***********************************************************************
3059 * find_ne_resource [internal]
3061 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
3062 DWORD *resLen, DWORD *resOff )
3064 IMAGE_OS2_HEADER nehd;
3065 NE_TYPEINFO *typeInfo;
3066 NE_NAMEINFO *nameInfo;
3067 DWORD nehdoffset;
3068 LPBYTE resTab;
3069 DWORD resTabSize;
3070 int count;
3072 /* Read in NE header */
3073 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
3074 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
3076 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
3077 if ( !resTabSize )
3079 TRACE("No resources in NE dll\n" );
3080 return FALSE;
3083 /* Read in resource table */
3084 resTab = heap_alloc( resTabSize );
3085 if ( !resTab ) return FALSE;
3087 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
3088 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
3090 heap_free( resTab );
3091 return FALSE;
3094 /* Find resource */
3095 typeInfo = (NE_TYPEINFO *)(resTab + 2);
3097 if (!IS_INTRESOURCE(typeid)) /* named type */
3099 BYTE len = strlen( typeid );
3100 while (typeInfo->type_id)
3102 if (!(typeInfo->type_id & 0x8000))
3104 BYTE *p = resTab + typeInfo->type_id;
3105 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
3107 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3108 typeInfo->count * sizeof(NE_NAMEINFO));
3111 else /* numeric type id */
3113 WORD id = LOWORD(typeid) | 0x8000;
3114 while (typeInfo->type_id)
3116 if (typeInfo->type_id == id) goto found_type;
3117 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3118 typeInfo->count * sizeof(NE_NAMEINFO));
3121 TRACE("No typeid entry found for %p\n", typeid );
3122 heap_free( resTab );
3123 return FALSE;
3125 found_type:
3126 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
3128 if (!IS_INTRESOURCE(resid)) /* named resource */
3130 BYTE len = strlen( resid );
3131 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3133 BYTE *p = resTab + nameInfo->id;
3134 if (nameInfo->id & 0x8000) continue;
3135 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
3138 else /* numeric resource id */
3140 WORD id = LOWORD(resid) | 0x8000;
3141 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3142 if (nameInfo->id == id) goto found_name;
3144 TRACE("No resid entry found for %p\n", typeid );
3145 heap_free( resTab );
3146 return FALSE;
3148 found_name:
3149 /* Return resource data */
3150 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
3151 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
3153 heap_free( resTab );
3154 return TRUE;
3157 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
3159 HFILE lzfd = -1;
3160 OFSTRUCT ofs;
3161 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
3162 TLB_NEFile *This;
3164 This = heap_alloc(sizeof(TLB_NEFile));
3165 if (!This) return E_OUTOFMEMORY;
3167 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
3168 This->refs = 1;
3169 This->typelib_base = NULL;
3171 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
3172 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
3174 DWORD reslen, offset;
3175 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
3177 This->typelib_base = heap_alloc(reslen);
3178 if( !This->typelib_base )
3179 hr = E_OUTOFMEMORY;
3180 else
3182 LZSeek( lzfd, offset, SEEK_SET );
3183 reslen = LZRead( lzfd, This->typelib_base, reslen );
3184 LZClose( lzfd );
3185 *ppBase = This->typelib_base;
3186 *pdwTLBLength = reslen;
3187 *ppFile = &This->IUnknown_iface;
3188 return S_OK;
3193 if( lzfd >= 0) LZClose( lzfd );
3194 TLB_NEFile_Release(&This->IUnknown_iface);
3195 return hr;
3198 typedef struct TLB_Mapping
3200 IUnknown IUnknown_iface;
3201 LONG refs;
3202 HANDLE file;
3203 HANDLE mapping;
3204 LPVOID typelib_base;
3205 } TLB_Mapping;
3207 static inline TLB_Mapping *mapping_impl_from_IUnknown(IUnknown *iface)
3209 return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
3212 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3214 if (IsEqualIID(riid, &IID_IUnknown))
3216 *ppv = iface;
3217 IUnknown_AddRef(iface);
3218 return S_OK;
3220 *ppv = NULL;
3221 return E_NOINTERFACE;
3224 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
3226 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3227 return InterlockedIncrement(&This->refs);
3230 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
3232 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3233 ULONG refs = InterlockedDecrement(&This->refs);
3234 if (!refs)
3236 if (This->typelib_base)
3237 UnmapViewOfFile(This->typelib_base);
3238 if (This->mapping)
3239 CloseHandle(This->mapping);
3240 if (This->file != INVALID_HANDLE_VALUE)
3241 CloseHandle(This->file);
3242 heap_free(This);
3244 return refs;
3247 static const IUnknownVtbl TLB_Mapping_Vtable =
3249 TLB_Mapping_QueryInterface,
3250 TLB_Mapping_AddRef,
3251 TLB_Mapping_Release
3254 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
3256 TLB_Mapping *This;
3258 This = heap_alloc(sizeof(TLB_Mapping));
3259 if (!This)
3260 return E_OUTOFMEMORY;
3262 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
3263 This->refs = 1;
3264 This->file = INVALID_HANDLE_VALUE;
3265 This->mapping = NULL;
3266 This->typelib_base = NULL;
3268 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3269 if (INVALID_HANDLE_VALUE != This->file)
3271 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
3272 if (This->mapping)
3274 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
3275 if(This->typelib_base)
3277 /* retrieve file size */
3278 *pdwTLBLength = GetFileSize(This->file, NULL);
3279 *ppBase = This->typelib_base;
3280 *ppFile = &This->IUnknown_iface;
3281 return S_OK;
3286 IUnknown_Release(&This->IUnknown_iface);
3287 return TYPE_E_CANTLOADLIBRARY;
3290 /****************************************************************************
3291 * TLB_ReadTypeLib
3293 * find the type of the typelib file and map the typelib resource into
3294 * the memory
3297 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3298 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
3300 ITypeLibImpl *entry;
3301 HRESULT ret;
3302 INT index = 1;
3303 LPWSTR index_str, file = (LPWSTR)pszFileName;
3304 LPVOID pBase = NULL;
3305 DWORD dwTLBLength = 0;
3306 IUnknown *pFile = NULL;
3307 HANDLE h;
3309 *ppTypeLib = NULL;
3311 index_str = strrchrW(pszFileName, '\\');
3312 if(index_str && *++index_str != '\0')
3314 LPWSTR end_ptr;
3315 LONG idx = strtolW(index_str, &end_ptr, 10);
3316 if(*end_ptr == '\0')
3318 int str_len = index_str - pszFileName - 1;
3319 index = idx;
3320 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
3321 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
3322 file[str_len] = 0;
3326 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
3328 if(strchrW(file, '\\'))
3330 lstrcpyW(pszPath, file);
3332 else
3334 int len = GetSystemDirectoryW(pszPath, cchPath);
3335 pszPath[len] = '\\';
3336 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
3340 if(file != pszFileName) heap_free(file);
3342 h = CreateFileW(pszPath, GENERIC_READ, 0, NULL, OPEN_ALWAYS,
3343 FILE_ATTRIBUTE_NORMAL, NULL);
3344 if(h != INVALID_HANDLE_VALUE){
3345 FILE_NAME_INFORMATION *info;
3346 char data[MAX_PATH * sizeof(WCHAR) + sizeof(info->FileNameLength)];
3347 BOOL br;
3349 info = (FILE_NAME_INFORMATION*)data;
3350 /* GetFileInformationByHandleEx returns the path of the file without
3351 * WOW64 redirection */
3352 br = GetFileInformationByHandleEx(h, FileNameInfo, data, sizeof(data));
3353 if(br){
3354 info->FileName[info->FileNameLength / sizeof(WCHAR)] = 0;
3355 lstrcpynW(pszPath + 2, info->FileName, cchPath - 2);
3357 CloseHandle(h);
3360 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
3362 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3363 EnterCriticalSection(&cache_section);
3364 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
3366 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
3368 TRACE("cache hit\n");
3369 *ppTypeLib = &entry->ITypeLib2_iface;
3370 ITypeLib2_AddRef(*ppTypeLib);
3371 LeaveCriticalSection(&cache_section);
3372 return S_OK;
3375 LeaveCriticalSection(&cache_section);
3377 /* now actually load and parse the typelib */
3379 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3380 if (ret == TYPE_E_CANTLOADLIBRARY)
3381 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3382 if (ret == TYPE_E_CANTLOADLIBRARY)
3383 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
3384 if (SUCCEEDED(ret))
3386 if (dwTLBLength >= 4)
3388 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
3389 if (dwSignature == MSFT_SIGNATURE)
3390 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
3391 else if (dwSignature == SLTG_SIGNATURE)
3392 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
3393 else
3395 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
3396 ret = TYPE_E_CANTLOADLIBRARY;
3399 else
3400 ret = TYPE_E_CANTLOADLIBRARY;
3401 IUnknown_Release(pFile);
3404 if(*ppTypeLib) {
3405 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
3407 TRACE("adding to cache\n");
3408 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
3409 lstrcpyW(impl->path, pszPath);
3410 /* We should really canonicalise the path here. */
3411 impl->index = index;
3413 /* FIXME: check if it has added already in the meantime */
3414 EnterCriticalSection(&cache_section);
3415 list_add_head(&tlb_cache, &impl->entry);
3416 LeaveCriticalSection(&cache_section);
3417 ret = S_OK;
3419 else
3421 if(ret != E_FAIL)
3422 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
3424 ret = TYPE_E_CANTLOADLIBRARY;
3428 return ret;
3431 /*================== ITypeLib(2) Methods ===================================*/
3433 static ITypeLibImpl* TypeLibImpl_Constructor(void)
3435 ITypeLibImpl* pTypeLibImpl;
3437 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
3438 if (!pTypeLibImpl) return NULL;
3440 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3441 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3442 pTypeLibImpl->ICreateTypeLib2_iface.lpVtbl = &CreateTypeLib2Vtbl;
3443 pTypeLibImpl->ref = 1;
3445 list_init(&pTypeLibImpl->implib_list);
3446 list_init(&pTypeLibImpl->custdata_list);
3447 list_init(&pTypeLibImpl->name_list);
3448 list_init(&pTypeLibImpl->string_list);
3449 list_init(&pTypeLibImpl->guid_list);
3450 list_init(&pTypeLibImpl->ref_list);
3451 pTypeLibImpl->dispatch_href = -1;
3453 return pTypeLibImpl;
3456 /****************************************************************************
3457 * ITypeLib2_Constructor_MSFT
3459 * loading an MSFT typelib from an in-memory image
3461 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3463 TLBContext cx;
3464 LONG lPSegDir;
3465 MSFT_Header tlbHeader;
3466 MSFT_SegDir tlbSegDir;
3467 ITypeLibImpl * pTypeLibImpl;
3468 int i;
3470 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3472 pTypeLibImpl = TypeLibImpl_Constructor();
3473 if (!pTypeLibImpl) return NULL;
3475 /* get pointer to beginning of typelib data */
3476 cx.pos = 0;
3477 cx.oStart=0;
3478 cx.mapping = pLib;
3479 cx.pLibInfo = pTypeLibImpl;
3480 cx.length = dwTLBLength;
3482 /* read header */
3483 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
3484 TRACE_(typelib)("header:\n");
3485 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3486 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3487 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3488 return NULL;
3490 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3492 /* there is a small amount of information here until the next important
3493 * part:
3494 * the segment directory . Try to calculate the amount of data */
3495 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3497 /* now read the segment directory */
3498 TRACE("read segment directory (at %d)\n",lPSegDir);
3499 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3500 cx.pTblDir = &tlbSegDir;
3502 /* just check two entries */
3503 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3505 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3506 heap_free(pTypeLibImpl);
3507 return NULL;
3510 MSFT_ReadAllNames(&cx);
3511 MSFT_ReadAllStrings(&cx);
3512 MSFT_ReadAllGuids(&cx);
3514 /* now fill our internal data */
3515 /* TLIBATTR fields */
3516 pTypeLibImpl->guid = MSFT_ReadGuid(tlbHeader.posguid, &cx);
3518 pTypeLibImpl->syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3519 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3520 pTypeLibImpl->ver_major = LOWORD(tlbHeader.version);
3521 pTypeLibImpl->ver_minor = HIWORD(tlbHeader.version);
3522 pTypeLibImpl->libflags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
3524 pTypeLibImpl->set_lcid = tlbHeader.lcid2;
3525 pTypeLibImpl->lcid = tlbHeader.lcid;
3527 /* name, eventually add to a hash table */
3528 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3530 /* help info */
3531 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3532 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3534 if( tlbHeader.varflags & HELPDLLFLAG)
3536 int offset;
3537 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3538 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3541 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3543 /* custom data */
3544 if(tlbHeader.CustomDataOffset >= 0)
3546 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3549 /* fill in type descriptions */
3550 if(tlbSegDir.pTypdescTab.length > 0)
3552 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3553 INT16 td[4];
3554 pTypeLibImpl->ctTypeDesc = cTD;
3555 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3556 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3557 for(i=0; i<cTD; )
3559 /* FIXME: add several sanity checks here */
3560 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3561 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3563 /* FIXME: check safearray */
3564 if(td[3] < 0)
3565 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3566 else
3567 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3569 else if(td[0] == VT_CARRAY)
3571 /* array descr table here */
3572 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3574 else if(td[0] == VT_USERDEFINED)
3576 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3578 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3581 /* second time around to fill the array subscript info */
3582 for(i=0;i<cTD;i++)
3584 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3585 if(tlbSegDir.pArrayDescriptions.offset>0)
3587 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3588 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3590 if(td[1]<0)
3591 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3592 else
3593 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3595 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3597 for(j = 0; j<td[2]; j++)
3599 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3600 sizeof(INT), &cx, DO_NOT_SEEK);
3601 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3602 sizeof(INT), &cx, DO_NOT_SEEK);
3605 else
3607 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3608 ERR("didn't find array description data\n");
3613 /* imported type libs */
3614 if(tlbSegDir.pImpFiles.offset>0)
3616 TLBImpLib *pImpLib;
3617 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3618 UINT16 size;
3620 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3622 char *name;
3624 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3625 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3626 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3628 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3629 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3630 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3631 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3633 size >>= 2;
3634 name = heap_alloc_zero(size+1);
3635 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3636 pImpLib->name = TLB_MultiByteToBSTR(name);
3637 heap_free(name);
3639 pImpLib->guid = MSFT_ReadGuid(oGuid, &cx);
3640 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3642 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3646 MSFT_ReadAllRefs(&cx);
3648 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3650 /* type infos */
3651 if(tlbHeader.nrtypeinfos >= 0 )
3653 ITypeInfoImpl **ppTI;
3655 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3657 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3659 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3661 ++ppTI;
3662 (pTypeLibImpl->TypeInfoCount)++;
3666 #ifdef _WIN64
3667 if(pTypeLibImpl->syskind == SYS_WIN32){
3668 for(i = 0; i < pTypeLibImpl->TypeInfoCount; ++i)
3669 TLB_fix_32on64_typeinfo(pTypeLibImpl->typeinfos[i]);
3671 #endif
3673 TRACE("(%p)\n", pTypeLibImpl);
3674 return &pTypeLibImpl->ITypeLib2_iface;
3678 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3680 char b[3];
3681 int i;
3682 short s;
3684 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3685 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3686 return FALSE;
3689 guid->Data4[0] = s >> 8;
3690 guid->Data4[1] = s & 0xff;
3692 b[2] = '\0';
3693 for(i = 0; i < 6; i++) {
3694 memcpy(b, str + 24 + 2 * i, 2);
3695 guid->Data4[i + 2] = strtol(b, NULL, 16);
3697 return TRUE;
3700 static WORD SLTG_ReadString(const char *ptr, const TLBString **pStr, ITypeLibImpl *lib)
3702 WORD bytelen;
3703 DWORD len;
3704 BSTR tmp_str;
3706 *pStr = NULL;
3707 bytelen = *(const WORD*)ptr;
3708 if(bytelen == 0xffff) return 2;
3710 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3711 tmp_str = SysAllocStringLen(NULL, len);
3712 if (tmp_str) {
3713 MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, tmp_str, len);
3714 *pStr = TLB_append_str(&lib->string_list, tmp_str);
3715 SysFreeString(tmp_str);
3717 return bytelen + 2;
3720 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3722 WORD bytelen;
3724 *str = NULL;
3725 bytelen = *(const WORD*)ptr;
3726 if(bytelen == 0xffff) return 2;
3727 *str = heap_alloc(bytelen + 1);
3728 memcpy(*str, ptr + 2, bytelen);
3729 (*str)[bytelen] = '\0';
3730 return bytelen + 2;
3733 static TLBString *SLTG_ReadName(const char *pNameTable, int offset, ITypeLibImpl *lib)
3735 BSTR tmp_str;
3736 TLBString *tlbstr;
3738 LIST_FOR_EACH_ENTRY(tlbstr, &lib->name_list, TLBString, entry) {
3739 if (tlbstr->offset == offset)
3740 return tlbstr;
3743 tmp_str = TLB_MultiByteToBSTR(pNameTable + offset);
3744 tlbstr = TLB_append_str(&lib->name_list, tmp_str);
3745 SysFreeString(tmp_str);
3747 return tlbstr;
3750 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3752 char *ptr = pLibBlk;
3753 WORD w;
3755 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3756 FIXME("libblk magic = %04x\n", w);
3757 return 0;
3760 ptr += 6;
3761 if((w = *(WORD*)ptr) != 0xffff) {
3762 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3763 ptr += w;
3765 ptr += 2;
3767 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString, pTypeLibImpl);
3769 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile, pTypeLibImpl);
3771 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3772 ptr += 4;
3774 pTypeLibImpl->syskind = *(WORD*)ptr;
3775 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3776 ptr += 2;
3778 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3779 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3780 else
3781 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = 0;
3782 ptr += 2;
3784 ptr += 4; /* skip res12 */
3786 pTypeLibImpl->libflags = *(WORD*)ptr;
3787 ptr += 2;
3789 pTypeLibImpl->ver_major = *(WORD*)ptr;
3790 ptr += 2;
3792 pTypeLibImpl->ver_minor = *(WORD*)ptr;
3793 ptr += 2;
3795 pTypeLibImpl->guid = TLB_append_guid(&pTypeLibImpl->guid_list, (GUID*)ptr, -2);
3796 ptr += sizeof(GUID);
3798 return ptr - (char*)pLibBlk;
3801 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3802 typedef struct
3804 unsigned int num;
3805 HREFTYPE refs[1];
3806 } sltg_ref_lookup_t;
3808 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3809 HREFTYPE *typelib_ref)
3811 if(table && typeinfo_ref < table->num)
3813 *typelib_ref = table->refs[typeinfo_ref];
3814 return S_OK;
3817 ERR_(typelib)("Unable to find reference\n");
3818 *typelib_ref = -1;
3819 return E_FAIL;
3822 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3824 BOOL done = FALSE;
3826 while(!done) {
3827 if((*pType & 0xe00) == 0xe00) {
3828 pTD->vt = VT_PTR;
3829 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3830 pTD = pTD->u.lptdesc;
3832 switch(*pType & 0x3f) {
3833 case VT_PTR:
3834 pTD->vt = VT_PTR;
3835 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3836 pTD = pTD->u.lptdesc;
3837 break;
3839 case VT_USERDEFINED:
3840 pTD->vt = VT_USERDEFINED;
3841 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3842 done = TRUE;
3843 break;
3845 case VT_CARRAY:
3847 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3848 array */
3850 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3852 pTD->vt = VT_CARRAY;
3853 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3854 pTD->u.lpadesc->cDims = pSA->cDims;
3855 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3856 pSA->cDims * sizeof(SAFEARRAYBOUND));
3858 pTD = &pTD->u.lpadesc->tdescElem;
3859 break;
3862 case VT_SAFEARRAY:
3864 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3865 useful? */
3867 pType++;
3868 pTD->vt = VT_SAFEARRAY;
3869 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3870 pTD = pTD->u.lptdesc;
3871 break;
3873 default:
3874 pTD->vt = *pType & 0x3f;
3875 done = TRUE;
3876 break;
3878 pType++;
3880 return pType;
3883 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3884 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3886 /* Handle [in/out] first */
3887 if((*pType & 0xc000) == 0xc000)
3888 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3889 else if(*pType & 0x8000)
3890 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3891 else if(*pType & 0x4000)
3892 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3893 else
3894 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3896 if(*pType & 0x2000)
3897 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3899 if(*pType & 0x80)
3900 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3902 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3906 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3907 char *pNameTable)
3909 unsigned int ref;
3910 char *name;
3911 TLBRefType *ref_type;
3912 sltg_ref_lookup_t *table;
3913 HREFTYPE typelib_ref;
3915 if(pRef->magic != SLTG_REF_MAGIC) {
3916 FIXME("Ref magic = %x\n", pRef->magic);
3917 return NULL;
3919 name = ( (char*)pRef->names + pRef->number);
3921 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3922 table->num = pRef->number >> 3;
3924 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3926 /* We don't want the first href to be 0 */
3927 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3929 for(ref = 0; ref < pRef->number >> 3; ref++) {
3930 char *refname;
3931 unsigned int lib_offs, type_num;
3933 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3935 name += SLTG_ReadStringA(name, &refname);
3936 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3937 FIXME_(typelib)("Can't sscanf ref\n");
3938 if(lib_offs != 0xffff) {
3939 TLBImpLib *import;
3941 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
3942 if(import->offset == lib_offs)
3943 break;
3945 if(&import->entry == &pTL->implib_list) {
3946 char fname[MAX_PATH+1];
3947 int len;
3948 GUID tmpguid;
3950 import = heap_alloc_zero(sizeof(*import));
3951 import->offset = lib_offs;
3952 TLB_GUIDFromString( pNameTable + lib_offs + 4, &tmpguid);
3953 import->guid = TLB_append_guid(&pTL->guid_list, &tmpguid, 2);
3954 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3955 &import->wVersionMajor,
3956 &import->wVersionMinor,
3957 &import->lcid, fname) != 4) {
3958 FIXME_(typelib)("can't sscanf ref %s\n",
3959 pNameTable + lib_offs + 40);
3961 len = strlen(fname);
3962 if(fname[len-1] != '#')
3963 FIXME("fname = %s\n", fname);
3964 fname[len-1] = '\0';
3965 import->name = TLB_MultiByteToBSTR(fname);
3966 list_add_tail(&pTL->implib_list, &import->entry);
3968 ref_type->pImpTLInfo = import;
3970 /* Store a reference to IDispatch */
3971 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid->guid, &IID_StdOle) && type_num == 4)
3972 pTL->dispatch_href = typelib_ref;
3974 } else { /* internal ref */
3975 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3977 ref_type->reference = typelib_ref;
3978 ref_type->index = type_num;
3980 heap_free(refname);
3981 list_add_tail(&pTL->ref_list, &ref_type->entry);
3983 table->refs[ref] = typelib_ref;
3984 typelib_ref += 4;
3986 if((BYTE)*name != SLTG_REF_MAGIC)
3987 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3988 dump_TLBRefType(pTL);
3989 return table;
3992 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3993 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3995 SLTG_ImplInfo *info;
3996 TLBImplType *pImplType;
3997 /* I don't really get this structure, usually it's 0x16 bytes
3998 long, but iuser.tlb contains some that are 0x18 bytes long.
3999 That's ok because we can use the next ptr to jump to the next
4000 one. But how do we know the length of the last one? The WORD
4001 at offs 0x8 might be the clue. For now I'm just assuming that
4002 the last one is the regular 0x16 bytes. */
4004 info = (SLTG_ImplInfo*)pBlk;
4005 while(1){
4006 pTI->cImplTypes++;
4007 if(info->next == 0xffff)
4008 break;
4009 info = (SLTG_ImplInfo*)(pBlk + info->next);
4012 info = (SLTG_ImplInfo*)pBlk;
4013 pTI->impltypes = TLBImplType_Alloc(pTI->cImplTypes);
4014 pImplType = pTI->impltypes;
4015 while(1) {
4016 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
4017 pImplType->implflags = info->impltypeflags;
4018 ++pImplType;
4020 if(info->next == 0xffff)
4021 break;
4022 if(OneOnly)
4023 FIXME_(typelib)("Interface inheriting more than one interface\n");
4024 info = (SLTG_ImplInfo*)(pBlk + info->next);
4026 info++; /* see comment at top of function */
4027 return (char*)info;
4030 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
4031 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4033 TLBVarDesc *pVarDesc;
4034 const TLBString *prevName = NULL;
4035 SLTG_Variable *pItem;
4036 unsigned short i;
4037 WORD *pType;
4039 pVarDesc = pTI->vardescs = TLBVarDesc_Alloc(cVars);
4041 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
4042 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
4044 pVarDesc->vardesc.memid = pItem->memid;
4046 if (pItem->magic != SLTG_VAR_MAGIC &&
4047 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
4048 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
4049 return;
4052 if (pItem->name == 0xfffe)
4053 pVarDesc->Name = prevName;
4054 else
4055 pVarDesc->Name = SLTG_ReadName(pNameTable, pItem->name, pTI->pTypeLib);
4057 TRACE_(typelib)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc->Name)));
4058 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
4059 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
4061 if(pItem->flags & 0x02)
4062 pType = &pItem->type;
4063 else
4064 pType = (WORD*)(pBlk + pItem->type);
4066 if (pItem->flags & ~0xda)
4067 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
4069 SLTG_DoElem(pType, pBlk,
4070 &pVarDesc->vardesc.elemdescVar, ref_lookup);
4072 if (TRACE_ON(typelib)) {
4073 char buf[300];
4074 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
4075 TRACE_(typelib)("elemdescVar: %s\n", buf);
4078 if (pItem->flags & 0x40) {
4079 TRACE_(typelib)("VAR_DISPATCH\n");
4080 pVarDesc->vardesc.varkind = VAR_DISPATCH;
4082 else if (pItem->flags & 0x10) {
4083 TRACE_(typelib)("VAR_CONST\n");
4084 pVarDesc->vardesc.varkind = VAR_CONST;
4085 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
4086 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
4087 if (pItem->flags & 0x08)
4088 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
4089 else {
4090 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
4092 case VT_LPSTR:
4093 case VT_LPWSTR:
4094 case VT_BSTR:
4096 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
4097 BSTR str;
4098 TRACE_(typelib)("len = %u\n", len);
4099 if (len == 0xffff) {
4100 str = NULL;
4101 } else {
4102 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
4103 str = SysAllocStringLen(NULL, alloc_len);
4104 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
4106 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
4107 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
4108 break;
4110 case VT_I2:
4111 case VT_UI2:
4112 case VT_I4:
4113 case VT_UI4:
4114 case VT_INT:
4115 case VT_UINT:
4116 V_INT(pVarDesc->vardesc.u.lpvarValue) =
4117 *(INT*)(pBlk + pItem->byte_offs);
4118 break;
4119 default:
4120 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
4124 else {
4125 TRACE_(typelib)("VAR_PERINSTANCE\n");
4126 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
4127 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
4130 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
4131 pVarDesc->vardesc.wVarFlags = pItem->varflags;
4133 if (pItem->flags & 0x80)
4134 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
4136 prevName = pVarDesc->Name;
4138 pTI->cVars = cVars;
4141 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
4142 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4144 SLTG_Function *pFunc;
4145 unsigned short i;
4146 TLBFuncDesc *pFuncDesc;
4148 pTI->funcdescs = TLBFuncDesc_Alloc(cFuncs);
4150 pFuncDesc = pTI->funcdescs;
4151 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
4152 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
4154 int param;
4155 WORD *pType, *pArg;
4157 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
4158 case SLTG_FUNCTION_MAGIC:
4159 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
4160 break;
4161 case SLTG_DISPATCH_FUNCTION_MAGIC:
4162 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
4163 break;
4164 case SLTG_STATIC_FUNCTION_MAGIC:
4165 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
4166 break;
4167 default:
4168 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
4169 continue;
4171 pFuncDesc->Name = SLTG_ReadName(pNameTable, pFunc->name, pTI->pTypeLib);
4173 pFuncDesc->funcdesc.memid = pFunc->dispid;
4174 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
4175 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
4176 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
4177 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
4178 pFuncDesc->funcdesc.oVft = pFunc->vtblpos & ~1;
4180 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
4181 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
4183 if(pFunc->retnextopt & 0x80)
4184 pType = &pFunc->rettype;
4185 else
4186 pType = (WORD*)(pBlk + pFunc->rettype);
4188 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
4190 pFuncDesc->funcdesc.lprgelemdescParam =
4191 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
4192 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
4194 pArg = (WORD*)(pBlk + pFunc->arg_off);
4196 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
4197 char *paramName = pNameTable + *pArg;
4198 BOOL HaveOffs;
4199 /* If arg type follows then paramName points to the 2nd
4200 letter of the name, else the next WORD is an offset to
4201 the arg type and paramName points to the first letter.
4202 So let's take one char off paramName and see if we're
4203 pointing at an alpha-numeric char. However if *pArg is
4204 0xffff or 0xfffe then the param has no name, the former
4205 meaning that the next WORD is the type, the latter
4206 meaning that the next WORD is an offset to the type. */
4208 HaveOffs = FALSE;
4209 if(*pArg == 0xffff)
4210 paramName = NULL;
4211 else if(*pArg == 0xfffe) {
4212 paramName = NULL;
4213 HaveOffs = TRUE;
4215 else if(paramName[-1] && !isalnum(paramName[-1]))
4216 HaveOffs = TRUE;
4218 pArg++;
4220 if(HaveOffs) { /* the next word is an offset to type */
4221 pType = (WORD*)(pBlk + *pArg);
4222 SLTG_DoElem(pType, pBlk,
4223 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4224 pArg++;
4225 } else {
4226 if(paramName)
4227 paramName--;
4228 pArg = SLTG_DoElem(pArg, pBlk,
4229 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4232 /* Are we an optional param ? */
4233 if(pFuncDesc->funcdesc.cParams - param <=
4234 pFuncDesc->funcdesc.cParamsOpt)
4235 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
4237 if(paramName) {
4238 pFuncDesc->pParamDesc[param].Name = SLTG_ReadName(pNameTable,
4239 paramName - pNameTable, pTI->pTypeLib);
4240 } else {
4241 pFuncDesc->pParamDesc[param].Name = pFuncDesc->Name;
4245 pTI->cFuncs = cFuncs;
4248 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
4249 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4250 SLTG_TypeInfoTail *pTITail)
4252 char *pFirstItem;
4253 sltg_ref_lookup_t *ref_lookup = NULL;
4255 if(pTIHeader->href_table != 0xffffffff) {
4256 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4257 pNameTable);
4260 pFirstItem = pBlk;
4262 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4263 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
4265 heap_free(ref_lookup);
4269 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
4270 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4271 const SLTG_TypeInfoTail *pTITail)
4273 char *pFirstItem;
4274 sltg_ref_lookup_t *ref_lookup = NULL;
4276 if(pTIHeader->href_table != 0xffffffff) {
4277 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4278 pNameTable);
4281 pFirstItem = pBlk;
4283 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4284 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
4287 if (pTITail->funcs_off != 0xffff)
4288 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4290 heap_free(ref_lookup);
4292 if (TRACE_ON(typelib))
4293 dump_TLBFuncDesc(pTI->funcdescs, pTI->cFuncs);
4296 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
4297 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4298 const SLTG_TypeInfoTail *pTITail)
4300 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4303 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
4304 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4305 const SLTG_TypeInfoTail *pTITail)
4307 WORD *pType;
4308 sltg_ref_lookup_t *ref_lookup = NULL;
4310 if (pTITail->simple_alias) {
4311 /* if simple alias, no more processing required */
4312 pTI->tdescAlias = heap_alloc_zero(sizeof(TYPEDESC));
4313 pTI->tdescAlias->vt = pTITail->tdescalias_vt;
4314 return;
4317 if(pTIHeader->href_table != 0xffffffff) {
4318 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4319 pNameTable);
4322 /* otherwise it is an offset to a type */
4323 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
4325 pTI->tdescAlias = heap_alloc(sizeof(TYPEDESC));
4326 SLTG_DoType(pType, pBlk, pTI->tdescAlias, ref_lookup);
4328 heap_free(ref_lookup);
4331 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
4332 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4333 const SLTG_TypeInfoTail *pTITail)
4335 sltg_ref_lookup_t *ref_lookup = NULL;
4336 if (pTIHeader->href_table != 0xffffffff)
4337 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4338 pNameTable);
4340 if (pTITail->vars_off != 0xffff)
4341 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4343 if (pTITail->funcs_off != 0xffff)
4344 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4346 if (pTITail->impls_off != 0xffff)
4347 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
4349 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4350 * of dispinterface functions including the IDispatch ones, so
4351 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4352 pTI->cbSizeVft = pTI->cFuncs * pTI->pTypeLib->ptr_size;
4354 heap_free(ref_lookup);
4355 if (TRACE_ON(typelib))
4356 dump_TLBFuncDesc(pTI->funcdescs, pTI->cFuncs);
4359 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
4360 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4361 const SLTG_TypeInfoTail *pTITail)
4363 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4366 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
4367 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4368 const SLTG_TypeInfoTail *pTITail)
4370 sltg_ref_lookup_t *ref_lookup = NULL;
4371 if (pTIHeader->href_table != 0xffffffff)
4372 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4373 pNameTable);
4375 if (pTITail->vars_off != 0xffff)
4376 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4378 if (pTITail->funcs_off != 0xffff)
4379 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4380 heap_free(ref_lookup);
4381 if (TRACE_ON(typelib))
4382 dump_TypeInfo(pTI);
4385 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4386 manageable copy of it into this */
4387 typedef struct {
4388 WORD small_no;
4389 char *index_name;
4390 char *other_name;
4391 WORD res1a;
4392 WORD name_offs;
4393 WORD more_bytes;
4394 char *extra;
4395 WORD res20;
4396 DWORD helpcontext;
4397 WORD res26;
4398 GUID uuid;
4399 } SLTG_InternalOtherTypeInfo;
4401 /****************************************************************************
4402 * ITypeLib2_Constructor_SLTG
4404 * loading a SLTG typelib from an in-memory image
4406 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
4408 ITypeLibImpl *pTypeLibImpl;
4409 SLTG_Header *pHeader;
4410 SLTG_BlkEntry *pBlkEntry;
4411 SLTG_Magic *pMagic;
4412 SLTG_Index *pIndex;
4413 SLTG_Pad9 *pPad9;
4414 LPVOID pBlk, pFirstBlk;
4415 SLTG_LibBlk *pLibBlk;
4416 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
4417 char *pAfterOTIBlks = NULL;
4418 char *pNameTable, *ptr;
4419 int i;
4420 DWORD len, order;
4421 ITypeInfoImpl **ppTypeInfoImpl;
4423 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
4426 pTypeLibImpl = TypeLibImpl_Constructor();
4427 if (!pTypeLibImpl) return NULL;
4429 pHeader = pLib;
4431 TRACE_(typelib)("header:\n");
4432 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
4433 pHeader->nrOfFileBlks );
4434 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
4435 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
4436 pHeader->SLTG_magic);
4437 return NULL;
4440 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4441 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
4443 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4444 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
4446 /* Next we have a magic block */
4447 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
4449 /* Let's see if we're still in sync */
4450 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
4451 sizeof(SLTG_COMPOBJ_MAGIC))) {
4452 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
4453 return NULL;
4455 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
4456 sizeof(SLTG_DIR_MAGIC))) {
4457 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
4458 return NULL;
4461 pIndex = (SLTG_Index*)(pMagic+1);
4463 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
4465 pFirstBlk = pPad9 + 1;
4467 /* We'll set up a ptr to the main library block, which is the last one. */
4469 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4470 pBlkEntry[order].next != 0;
4471 order = pBlkEntry[order].next - 1, i++) {
4472 pBlk = (char*)pBlk + pBlkEntry[order].len;
4474 pLibBlk = pBlk;
4476 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
4478 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4479 interspersed */
4481 len += 0x40;
4483 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4485 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
4488 ptr = (char*)pLibBlk + len;
4490 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4491 WORD w, extra;
4492 len = 0;
4494 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
4496 w = *(WORD*)(ptr + 2);
4497 if(w != 0xffff) {
4498 len += w;
4499 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
4500 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4501 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4503 w = *(WORD*)(ptr + 4 + len);
4504 if(w != 0xffff) {
4505 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4506 len += w;
4507 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4508 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4509 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4511 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4512 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4513 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4514 if(extra) {
4515 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4516 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4517 len += extra;
4519 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4520 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4521 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4522 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4523 len += sizeof(SLTG_OtherTypeInfo);
4524 ptr += len;
4527 pAfterOTIBlks = ptr;
4529 /* Skip this WORD and get the next DWORD */
4530 len = *(DWORD*)(pAfterOTIBlks + 2);
4532 /* Now add this to pLibBLk look at what we're pointing at and
4533 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4534 dust and we should be pointing at the beginning of the name
4535 table */
4537 pNameTable = (char*)pLibBlk + len;
4539 switch(*(WORD*)pNameTable) {
4540 case 0xffff:
4541 break;
4542 case 0x0200:
4543 pNameTable += 0x20;
4544 break;
4545 default:
4546 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4547 break;
4550 pNameTable += 0x216;
4552 pNameTable += 2;
4554 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4556 pTypeLibImpl->Name = SLTG_ReadName(pNameTable, pLibBlk->name, pTypeLibImpl);
4559 /* Hopefully we now have enough ptrs set up to actually read in
4560 some TypeInfos. It's not clear which order to do them in, so
4561 I'll just follow the links along the BlkEntry chain and read
4562 them in the order in which they are in the file */
4564 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4565 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4567 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4568 pBlkEntry[order].next != 0;
4569 order = pBlkEntry[order].next - 1, i++) {
4571 SLTG_TypeInfoHeader *pTIHeader;
4572 SLTG_TypeInfoTail *pTITail;
4573 SLTG_MemberHeader *pMemHeader;
4575 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4576 FIXME_(typelib)("Index strings don't match\n");
4577 heap_free(pOtherTypeInfoBlks);
4578 return NULL;
4581 pTIHeader = pBlk;
4582 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4583 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4584 heap_free(pOtherTypeInfoBlks);
4585 return NULL;
4587 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4588 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4589 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4591 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4592 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4593 (*ppTypeInfoImpl)->index = i;
4594 (*ppTypeInfoImpl)->Name = SLTG_ReadName(pNameTable, pOtherTypeInfoBlks[i].name_offs, pTypeLibImpl);
4595 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4596 (*ppTypeInfoImpl)->guid = TLB_append_guid(&pTypeLibImpl->guid_list, &pOtherTypeInfoBlks[i].uuid, 2);
4597 (*ppTypeInfoImpl)->typekind = pTIHeader->typekind;
4598 (*ppTypeInfoImpl)->wMajorVerNum = pTIHeader->major_version;
4599 (*ppTypeInfoImpl)->wMinorVerNum = pTIHeader->minor_version;
4600 (*ppTypeInfoImpl)->wTypeFlags =
4601 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4603 if((*ppTypeInfoImpl)->wTypeFlags & TYPEFLAG_FDUAL)
4604 (*ppTypeInfoImpl)->typekind = TKIND_DISPATCH;
4606 if((pTIHeader->typeflags1 & 7) != 2)
4607 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4608 if(pTIHeader->typeflags3 != 2)
4609 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4611 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4612 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl)->Name)),
4613 typekind_desc[pTIHeader->typekind],
4614 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl)->guid)),
4615 (*ppTypeInfoImpl)->wTypeFlags);
4617 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4619 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4621 (*ppTypeInfoImpl)->cbAlignment = pTITail->cbAlignment;
4622 (*ppTypeInfoImpl)->cbSizeInstance = pTITail->cbSizeInstance;
4623 (*ppTypeInfoImpl)->cbSizeVft = pTITail->cbSizeVft;
4625 switch(pTIHeader->typekind) {
4626 case TKIND_ENUM:
4627 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4628 pTIHeader, pTITail);
4629 break;
4631 case TKIND_RECORD:
4632 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4633 pTIHeader, pTITail);
4634 break;
4636 case TKIND_INTERFACE:
4637 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4638 pTIHeader, pTITail);
4639 break;
4641 case TKIND_COCLASS:
4642 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4643 pTIHeader, pTITail);
4644 break;
4646 case TKIND_ALIAS:
4647 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4648 pTIHeader, pTITail);
4649 break;
4651 case TKIND_DISPATCH:
4652 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4653 pTIHeader, pTITail);
4654 break;
4656 case TKIND_MODULE:
4657 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4658 pTIHeader, pTITail);
4659 break;
4661 default:
4662 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4663 break;
4667 /* could get cFuncs, cVars and cImplTypes from here
4668 but we've already set those */
4669 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4670 X(06);
4671 X(16);
4672 X(18);
4673 X(1a);
4674 X(1e);
4675 X(24);
4676 X(26);
4677 X(2a);
4678 X(2c);
4679 X(2e);
4680 X(30);
4681 X(32);
4682 X(34);
4683 #undef X
4684 ++ppTypeInfoImpl;
4685 pBlk = (char*)pBlk + pBlkEntry[order].len;
4688 if(i != pTypeLibImpl->TypeInfoCount) {
4689 FIXME("Somehow processed %d TypeInfos\n", i);
4690 heap_free(pOtherTypeInfoBlks);
4691 return NULL;
4694 heap_free(pOtherTypeInfoBlks);
4695 return &pTypeLibImpl->ITypeLib2_iface;
4698 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4700 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4702 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4704 if(IsEqualIID(riid, &IID_IUnknown) ||
4705 IsEqualIID(riid,&IID_ITypeLib)||
4706 IsEqualIID(riid,&IID_ITypeLib2))
4708 *ppv = &This->ITypeLib2_iface;
4710 else if(IsEqualIID(riid, &IID_ICreateTypeLib) ||
4711 IsEqualIID(riid, &IID_ICreateTypeLib2))
4713 *ppv = &This->ICreateTypeLib2_iface;
4715 else
4717 *ppv = NULL;
4718 TRACE("-- Interface: E_NOINTERFACE\n");
4719 return E_NOINTERFACE;
4722 IUnknown_AddRef((IUnknown*)*ppv);
4723 return S_OK;
4726 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4728 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4729 ULONG ref = InterlockedIncrement(&This->ref);
4731 TRACE("(%p) ref=%u\n", This, ref);
4733 return ref;
4736 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4738 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4739 ULONG ref = InterlockedDecrement(&This->ref);
4741 TRACE("(%p) ref=%u\n",This, ref);
4743 if (!ref)
4745 TLBImpLib *pImpLib, *pImpLibNext;
4746 TLBRefType *ref_type;
4747 TLBString *tlbstr, *tlbstr_next;
4748 TLBGuid *tlbguid, *tlbguid_next;
4749 void *cursor2;
4750 int i;
4752 /* remove cache entry */
4753 if(This->path)
4755 TRACE("removing from cache list\n");
4756 EnterCriticalSection(&cache_section);
4757 if(This->entry.next)
4758 list_remove(&This->entry);
4759 LeaveCriticalSection(&cache_section);
4760 heap_free(This->path);
4762 TRACE(" destroying ITypeLib(%p)\n",This);
4764 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->string_list, TLBString, entry) {
4765 list_remove(&tlbstr->entry);
4766 SysFreeString(tlbstr->str);
4767 heap_free(tlbstr);
4770 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->name_list, TLBString, entry) {
4771 list_remove(&tlbstr->entry);
4772 SysFreeString(tlbstr->str);
4773 heap_free(tlbstr);
4776 LIST_FOR_EACH_ENTRY_SAFE(tlbguid, tlbguid_next, &This->guid_list, TLBGuid, entry) {
4777 list_remove(&tlbguid->entry);
4778 heap_free(tlbguid);
4781 TLB_FreeCustData(&This->custdata_list);
4783 for (i = 0; i < This->ctTypeDesc; i++)
4784 if (This->pTypeDesc[i].vt == VT_CARRAY)
4785 heap_free(This->pTypeDesc[i].u.lpadesc);
4787 heap_free(This->pTypeDesc);
4789 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4791 if (pImpLib->pImpTypeLib)
4792 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4793 SysFreeString(pImpLib->name);
4795 list_remove(&pImpLib->entry);
4796 heap_free(pImpLib);
4799 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4801 list_remove(&ref_type->entry);
4802 heap_free(ref_type);
4805 for (i = 0; i < This->TypeInfoCount; ++i){
4806 heap_free(This->typeinfos[i]->tdescAlias);
4807 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4809 heap_free(This->typeinfos);
4810 heap_free(This);
4811 return 0;
4814 return ref;
4817 /* ITypeLib::GetTypeInfoCount
4819 * Returns the number of type descriptions in the type library
4821 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4823 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4824 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4825 return This->TypeInfoCount;
4828 /* ITypeLib::GetTypeInfo
4830 * retrieves the specified type description in the library.
4832 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4833 ITypeLib2 *iface,
4834 UINT index,
4835 ITypeInfo **ppTInfo)
4837 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4839 TRACE("%p %u %p\n", This, index, ppTInfo);
4841 if(!ppTInfo)
4842 return E_INVALIDARG;
4844 if(index >= This->TypeInfoCount)
4845 return TYPE_E_ELEMENTNOTFOUND;
4847 *ppTInfo = (ITypeInfo *)&This->typeinfos[index]->ITypeInfo2_iface;
4848 ITypeInfo_AddRef(*ppTInfo);
4850 return S_OK;
4854 /* ITypeLibs::GetTypeInfoType
4856 * Retrieves the type of a type description.
4858 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4859 ITypeLib2 *iface,
4860 UINT index,
4861 TYPEKIND *pTKind)
4863 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4865 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4867 if(!pTKind)
4868 return E_INVALIDARG;
4870 if(index >= This->TypeInfoCount)
4871 return TYPE_E_ELEMENTNOTFOUND;
4873 *pTKind = This->typeinfos[index]->typekind;
4875 return S_OK;
4878 /* ITypeLib::GetTypeInfoOfGuid
4880 * Retrieves the type description that corresponds to the specified GUID.
4883 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4884 ITypeLib2 *iface,
4885 REFGUID guid,
4886 ITypeInfo **ppTInfo)
4888 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4889 int i;
4891 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4893 for(i = 0; i < This->TypeInfoCount; ++i){
4894 if(IsEqualIID(TLB_get_guid_null(This->typeinfos[i]->guid), guid)){
4895 *ppTInfo = (ITypeInfo *)&This->typeinfos[i]->ITypeInfo2_iface;
4896 ITypeInfo_AddRef(*ppTInfo);
4897 return S_OK;
4901 return TYPE_E_ELEMENTNOTFOUND;
4904 /* ITypeLib::GetLibAttr
4906 * Retrieves the structure that contains the library's attributes.
4909 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4910 ITypeLib2 *iface,
4911 LPTLIBATTR *attr)
4913 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4915 TRACE("(%p, %p)\n", This, attr);
4917 if (!attr) return E_INVALIDARG;
4919 *attr = heap_alloc(sizeof(**attr));
4920 if (!*attr) return E_OUTOFMEMORY;
4922 (*attr)->guid = *TLB_get_guid_null(This->guid);
4923 (*attr)->lcid = This->set_lcid;
4924 (*attr)->syskind = This->syskind;
4925 (*attr)->wMajorVerNum = This->ver_major;
4926 (*attr)->wMinorVerNum = This->ver_minor;
4927 (*attr)->wLibFlags = This->libflags;
4929 return S_OK;
4932 /* ITypeLib::GetTypeComp
4934 * Enables a client compiler to bind to a library's types, variables,
4935 * constants, and global functions.
4938 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4939 ITypeLib2 *iface,
4940 ITypeComp **ppTComp)
4942 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4944 TRACE("(%p)->(%p)\n",This,ppTComp);
4945 *ppTComp = &This->ITypeComp_iface;
4946 ITypeComp_AddRef(*ppTComp);
4948 return S_OK;
4951 /* ITypeLib::GetDocumentation
4953 * Retrieves the library's documentation string, the complete Help file name
4954 * and path, and the context identifier for the library Help topic in the Help
4955 * file.
4957 * On a successful return all non-null BSTR pointers will have been set,
4958 * possibly to NULL.
4960 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4961 ITypeLib2 *iface,
4962 INT index,
4963 BSTR *pBstrName,
4964 BSTR *pBstrDocString,
4965 DWORD *pdwHelpContext,
4966 BSTR *pBstrHelpFile)
4968 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4969 HRESULT result = E_INVALIDARG;
4970 ITypeInfo *pTInfo;
4972 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4973 This, index,
4974 pBstrName, pBstrDocString,
4975 pdwHelpContext, pBstrHelpFile);
4977 if(index<0)
4979 /* documentation for the typelib */
4980 if(pBstrName)
4982 if (This->Name)
4984 if(!(*pBstrName = SysAllocString(TLB_get_bstr(This->Name))))
4985 goto memerr1;
4987 else
4988 *pBstrName = NULL;
4990 if(pBstrDocString)
4992 if (This->DocString)
4994 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->DocString))))
4995 goto memerr2;
4997 else
4998 *pBstrDocString = NULL;
5000 if(pdwHelpContext)
5002 *pdwHelpContext = This->dwHelpContext;
5004 if(pBstrHelpFile)
5006 if (This->HelpFile)
5008 if(!(*pBstrHelpFile = SysAllocString(TLB_get_bstr(This->HelpFile))))
5009 goto memerr3;
5011 else
5012 *pBstrHelpFile = NULL;
5015 result = S_OK;
5017 else
5019 /* for a typeinfo */
5020 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
5022 if(SUCCEEDED(result))
5024 result = ITypeInfo_GetDocumentation(pTInfo,
5025 MEMBERID_NIL,
5026 pBstrName,
5027 pBstrDocString,
5028 pdwHelpContext, pBstrHelpFile);
5030 ITypeInfo_Release(pTInfo);
5033 return result;
5034 memerr3:
5035 if (pBstrDocString) SysFreeString (*pBstrDocString);
5036 memerr2:
5037 if (pBstrName) SysFreeString (*pBstrName);
5038 memerr1:
5039 return STG_E_INSUFFICIENTMEMORY;
5042 /* ITypeLib::IsName
5044 * Indicates whether a passed-in string contains the name of a type or member
5045 * described in the library.
5048 static HRESULT WINAPI ITypeLib2_fnIsName(
5049 ITypeLib2 *iface,
5050 LPOLESTR szNameBuf,
5051 ULONG lHashVal,
5052 BOOL *pfName)
5054 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5055 int tic;
5056 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
5058 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
5059 pfName);
5061 *pfName=TRUE;
5062 for(tic = 0; tic < This->TypeInfoCount; ++tic){
5063 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5064 if(!TLB_str_memcmp(szNameBuf, pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5065 for(fdc = 0; fdc < pTInfo->cFuncs; ++fdc) {
5066 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
5067 int pc;
5068 if(!TLB_str_memcmp(szNameBuf, pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5069 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++){
5070 if(!TLB_str_memcmp(szNameBuf, pFInfo->pParamDesc[pc].Name, nNameBufLen))
5071 goto ITypeLib2_fnIsName_exit;
5074 for(vrc = 0; vrc < pTInfo->cVars; ++vrc){
5075 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
5076 if(!TLB_str_memcmp(szNameBuf, pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5080 *pfName=FALSE;
5082 ITypeLib2_fnIsName_exit:
5083 TRACE("(%p)slow! search for %s: %sfound!\n", This,
5084 debugstr_w(szNameBuf), *pfName ? "" : "NOT ");
5086 return S_OK;
5089 /* ITypeLib::FindName
5091 * Finds occurrences of a type description in a type library. This may be used
5092 * to quickly verify that a name exists in a type library.
5095 static HRESULT WINAPI ITypeLib2_fnFindName(
5096 ITypeLib2 *iface,
5097 LPOLESTR name,
5098 ULONG hash,
5099 ITypeInfo **ppTInfo,
5100 MEMBERID *memid,
5101 UINT16 *found)
5103 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5104 int tic;
5105 UINT count = 0;
5106 UINT len;
5108 TRACE("(%p)->(%s %u %p %p %p)\n", This, debugstr_w(name), hash, ppTInfo, memid, found);
5110 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
5111 return E_INVALIDARG;
5113 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
5114 for(tic = 0; tic < This->TypeInfoCount; ++tic) {
5115 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5116 TLBVarDesc *var;
5117 UINT fdc;
5119 if(!TLB_str_memcmp(name, pTInfo->Name, len)) goto ITypeLib2_fnFindName_exit;
5120 for(fdc = 0; fdc < pTInfo->cFuncs; ++fdc) {
5121 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
5122 int pc;
5124 if(!TLB_str_memcmp(name, func->Name, len)) goto ITypeLib2_fnFindName_exit;
5125 for(pc = 0; pc < func->funcdesc.cParams; pc++) {
5126 if(!TLB_str_memcmp(name, func->pParamDesc[pc].Name, len))
5127 goto ITypeLib2_fnFindName_exit;
5131 var = TLB_get_vardesc_by_name(pTInfo->vardescs, pTInfo->cVars, name);
5132 if (var)
5133 goto ITypeLib2_fnFindName_exit;
5135 continue;
5136 ITypeLib2_fnFindName_exit:
5137 ITypeInfo2_AddRef(&pTInfo->ITypeInfo2_iface);
5138 ppTInfo[count] = (ITypeInfo *)&pTInfo->ITypeInfo2_iface;
5139 count++;
5141 TRACE("found %d typeinfos\n", count);
5143 *found = count;
5145 return S_OK;
5148 /* ITypeLib::ReleaseTLibAttr
5150 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5153 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
5154 ITypeLib2 *iface,
5155 TLIBATTR *pTLibAttr)
5157 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5158 TRACE("(%p)->(%p)\n", This, pTLibAttr);
5159 heap_free(pTLibAttr);
5162 /* ITypeLib2::GetCustData
5164 * gets the custom data
5166 static HRESULT WINAPI ITypeLib2_fnGetCustData(
5167 ITypeLib2 * iface,
5168 REFGUID guid,
5169 VARIANT *pVarVal)
5171 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5172 TLBCustData *pCData;
5174 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
5176 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
5177 if(!pCData)
5178 return TYPE_E_ELEMENTNOTFOUND;
5180 VariantInit(pVarVal);
5181 VariantCopy(pVarVal, &pCData->data);
5183 return S_OK;
5186 /* ITypeLib2::GetLibStatistics
5188 * Returns statistics about a type library that are required for efficient
5189 * sizing of hash tables.
5192 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
5193 ITypeLib2 * iface,
5194 ULONG *pcUniqueNames,
5195 ULONG *pcchUniqueNames)
5197 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5199 FIXME("(%p): stub!\n", This);
5201 if(pcUniqueNames) *pcUniqueNames=1;
5202 if(pcchUniqueNames) *pcchUniqueNames=1;
5203 return S_OK;
5206 /* ITypeLib2::GetDocumentation2
5208 * Retrieves the library's documentation string, the complete Help file name
5209 * and path, the localization context to use, and the context ID for the
5210 * library Help topic in the Help file.
5213 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
5214 ITypeLib2 * iface,
5215 INT index,
5216 LCID lcid,
5217 BSTR *pbstrHelpString,
5218 DWORD *pdwHelpStringContext,
5219 BSTR *pbstrHelpStringDll)
5221 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5222 HRESULT result;
5223 ITypeInfo *pTInfo;
5225 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
5227 /* the help string should be obtained from the helpstringdll,
5228 * using the _DLLGetDocumentation function, based on the supplied
5229 * lcid. Nice to do sometime...
5231 if(index<0)
5233 /* documentation for the typelib */
5234 if(pbstrHelpString)
5235 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->DocString));
5236 if(pdwHelpStringContext)
5237 *pdwHelpStringContext=This->dwHelpContext;
5238 if(pbstrHelpStringDll)
5239 *pbstrHelpStringDll=SysAllocString(TLB_get_bstr(This->HelpStringDll));
5241 result = S_OK;
5243 else
5245 /* for a typeinfo */
5246 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
5248 if(SUCCEEDED(result))
5250 ITypeInfo2 * pTInfo2;
5251 result = ITypeInfo_QueryInterface(pTInfo,
5252 &IID_ITypeInfo2,
5253 (LPVOID*) &pTInfo2);
5255 if(SUCCEEDED(result))
5257 result = ITypeInfo2_GetDocumentation2(pTInfo2,
5258 MEMBERID_NIL,
5259 lcid,
5260 pbstrHelpString,
5261 pdwHelpStringContext,
5262 pbstrHelpStringDll);
5264 ITypeInfo2_Release(pTInfo2);
5267 ITypeInfo_Release(pTInfo);
5270 return result;
5273 static HRESULT TLB_copy_all_custdata(struct list *custdata_list, CUSTDATA *pCustData)
5275 TLBCustData *pCData;
5276 unsigned int ct;
5277 CUSTDATAITEM *cdi;
5279 ct = list_count(custdata_list);
5281 pCustData->prgCustData = heap_alloc_zero(ct * sizeof(CUSTDATAITEM));
5282 if(!pCustData->prgCustData)
5283 return E_OUTOFMEMORY;
5285 pCustData->cCustData = ct;
5287 cdi = pCustData->prgCustData;
5288 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
5289 cdi->guid = *TLB_get_guid_null(pCData->guid);
5290 VariantCopy(&cdi->varValue, &pCData->data);
5291 ++cdi;
5294 return S_OK;
5298 /* ITypeLib2::GetAllCustData
5300 * Gets all custom data items for the library.
5303 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
5304 ITypeLib2 * iface,
5305 CUSTDATA *pCustData)
5307 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5308 TRACE("(%p)->(%p)\n", This, pCustData);
5309 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
5312 static const ITypeLib2Vtbl tlbvt = {
5313 ITypeLib2_fnQueryInterface,
5314 ITypeLib2_fnAddRef,
5315 ITypeLib2_fnRelease,
5316 ITypeLib2_fnGetTypeInfoCount,
5317 ITypeLib2_fnGetTypeInfo,
5318 ITypeLib2_fnGetTypeInfoType,
5319 ITypeLib2_fnGetTypeInfoOfGuid,
5320 ITypeLib2_fnGetLibAttr,
5321 ITypeLib2_fnGetTypeComp,
5322 ITypeLib2_fnGetDocumentation,
5323 ITypeLib2_fnIsName,
5324 ITypeLib2_fnFindName,
5325 ITypeLib2_fnReleaseTLibAttr,
5327 ITypeLib2_fnGetCustData,
5328 ITypeLib2_fnGetLibStatistics,
5329 ITypeLib2_fnGetDocumentation2,
5330 ITypeLib2_fnGetAllCustData
5334 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5336 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5338 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
5341 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
5343 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5345 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
5348 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
5350 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5352 return ITypeLib2_Release(&This->ITypeLib2_iface);
5355 static HRESULT WINAPI ITypeLibComp_fnBind(
5356 ITypeComp * iface,
5357 OLECHAR * szName,
5358 ULONG lHash,
5359 WORD wFlags,
5360 ITypeInfo ** ppTInfo,
5361 DESCKIND * pDescKind,
5362 BINDPTR * pBindPtr)
5364 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5365 int typemismatch=0, i;
5367 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5369 *pDescKind = DESCKIND_NONE;
5370 pBindPtr->lptcomp = NULL;
5371 *ppTInfo = NULL;
5373 for(i = 0; i < This->TypeInfoCount; ++i){
5374 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5375 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo->Name)));
5377 /* FIXME: check wFlags here? */
5378 /* FIXME: we should use a hash table to look this info up using lHash
5379 * instead of an O(n) search */
5380 if ((pTypeInfo->typekind == TKIND_ENUM) ||
5381 (pTypeInfo->typekind == TKIND_MODULE))
5383 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name->str, szName))
5385 *pDescKind = DESCKIND_TYPECOMP;
5386 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
5387 ITypeComp_AddRef(pBindPtr->lptcomp);
5388 TRACE("module or enum: %s\n", debugstr_w(szName));
5389 return S_OK;
5393 if ((pTypeInfo->typekind == TKIND_MODULE) ||
5394 (pTypeInfo->typekind == TKIND_ENUM))
5396 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5397 HRESULT hr;
5399 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5400 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
5402 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
5403 return S_OK;
5405 else if (hr == TYPE_E_TYPEMISMATCH)
5406 typemismatch = 1;
5409 if ((pTypeInfo->typekind == TKIND_COCLASS) &&
5410 (pTypeInfo->wTypeFlags & TYPEFLAG_FAPPOBJECT))
5412 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5413 HRESULT hr;
5414 ITypeInfo *subtypeinfo;
5415 BINDPTR subbindptr;
5416 DESCKIND subdesckind;
5418 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
5419 &subtypeinfo, &subdesckind, &subbindptr);
5420 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
5422 TYPEDESC tdesc_appobject;
5423 const VARDESC vardesc_appobject =
5425 -2, /* memid */
5426 NULL, /* lpstrSchema */
5428 0 /* oInst */
5431 /* ELEMDESC */
5433 /* TYPEDESC */
5435 &tdesc_appobject
5437 VT_PTR
5440 0, /* wVarFlags */
5441 VAR_STATIC /* varkind */
5444 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
5445 tdesc_appobject.vt = VT_USERDEFINED;
5447 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
5449 /* cleanup things filled in by Bind call so we can put our
5450 * application object data in there instead */
5451 switch (subdesckind)
5453 case DESCKIND_FUNCDESC:
5454 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
5455 break;
5456 case DESCKIND_VARDESC:
5457 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
5458 break;
5459 default:
5460 break;
5462 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
5464 if (pTypeInfo->hreftype == -1)
5465 FIXME("no hreftype for interface %p\n", pTypeInfo);
5467 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
5468 if (FAILED(hr))
5469 return hr;
5471 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5472 *ppTInfo = (ITypeInfo *)&pTypeInfo->ITypeInfo2_iface;
5473 ITypeInfo_AddRef(*ppTInfo);
5474 return S_OK;
5476 else if (hr == TYPE_E_TYPEMISMATCH)
5477 typemismatch = 1;
5481 if (typemismatch)
5483 TRACE("type mismatch %s\n", debugstr_w(szName));
5484 return TYPE_E_TYPEMISMATCH;
5486 else
5488 TRACE("name not found %s\n", debugstr_w(szName));
5489 return S_OK;
5493 static HRESULT WINAPI ITypeLibComp_fnBindType(
5494 ITypeComp * iface,
5495 OLECHAR * szName,
5496 ULONG lHash,
5497 ITypeInfo ** ppTInfo,
5498 ITypeComp ** ppTComp)
5500 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5501 ITypeInfoImpl *info;
5503 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5505 if(!szName || !ppTInfo || !ppTComp)
5506 return E_INVALIDARG;
5508 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, szName);
5509 if(!info){
5510 *ppTInfo = NULL;
5511 *ppTComp = NULL;
5512 return S_OK;
5515 *ppTInfo = (ITypeInfo *)&info->ITypeInfo2_iface;
5516 ITypeInfo_AddRef(*ppTInfo);
5517 *ppTComp = &info->ITypeComp_iface;
5518 ITypeComp_AddRef(*ppTComp);
5520 return S_OK;
5523 static const ITypeCompVtbl tlbtcvt =
5526 ITypeLibComp_fnQueryInterface,
5527 ITypeLibComp_fnAddRef,
5528 ITypeLibComp_fnRelease,
5530 ITypeLibComp_fnBind,
5531 ITypeLibComp_fnBindType
5534 /*================== ITypeInfo(2) Methods ===================================*/
5535 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5537 ITypeInfoImpl *pTypeInfoImpl;
5539 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5540 if (pTypeInfoImpl)
5542 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5543 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5544 pTypeInfoImpl->ICreateTypeInfo2_iface.lpVtbl = &CreateTypeInfo2Vtbl;
5545 pTypeInfoImpl->ref = 0;
5546 pTypeInfoImpl->hreftype = -1;
5547 pTypeInfoImpl->memidConstructor = MEMBERID_NIL;
5548 pTypeInfoImpl->memidDestructor = MEMBERID_NIL;
5549 pTypeInfoImpl->pcustdata_list = &pTypeInfoImpl->custdata_list;
5550 list_init(pTypeInfoImpl->pcustdata_list);
5552 TRACE("(%p)\n", pTypeInfoImpl);
5553 return pTypeInfoImpl;
5556 /* ITypeInfo::QueryInterface
5558 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5559 ITypeInfo2 *iface,
5560 REFIID riid,
5561 VOID **ppvObject)
5563 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5565 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5567 *ppvObject=NULL;
5568 if(IsEqualIID(riid, &IID_IUnknown) ||
5569 IsEqualIID(riid,&IID_ITypeInfo)||
5570 IsEqualIID(riid,&IID_ITypeInfo2))
5571 *ppvObject = This;
5572 else if(IsEqualIID(riid, &IID_ICreateTypeInfo) ||
5573 IsEqualIID(riid, &IID_ICreateTypeInfo2))
5574 *ppvObject = &This->ICreateTypeInfo2_iface;
5576 if(*ppvObject){
5577 ITypeInfo2_AddRef(iface);
5578 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5579 return S_OK;
5581 TRACE("-- Interface: E_NOINTERFACE\n");
5582 return E_NOINTERFACE;
5585 /* ITypeInfo::AddRef
5587 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5589 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5590 ULONG ref = InterlockedIncrement(&This->ref);
5592 TRACE("(%p)->ref is %u\n",This, ref);
5594 if (ref == 1 /* incremented from 0 */)
5595 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5597 return ref;
5600 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5602 UINT i;
5604 TRACE("destroying ITypeInfo(%p)\n",This);
5606 for (i = 0; i < This->cFuncs; ++i)
5608 int j;
5609 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5610 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5612 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5613 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5614 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5615 TLB_FreeCustData(&pFInfo->pParamDesc[j].custdata_list);
5617 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5618 heap_free(pFInfo->pParamDesc);
5619 TLB_FreeCustData(&pFInfo->custdata_list);
5621 heap_free(This->funcdescs);
5623 for(i = 0; i < This->cVars; ++i)
5625 TLBVarDesc *pVInfo = &This->vardescs[i];
5626 if (pVInfo->vardesc_create) {
5627 TLB_FreeVarDesc(pVInfo->vardesc_create);
5628 } else if (pVInfo->vardesc.varkind == VAR_CONST) {
5629 VariantClear(pVInfo->vardesc.u.lpvarValue);
5630 heap_free(pVInfo->vardesc.u.lpvarValue);
5632 TLB_FreeCustData(&pVInfo->custdata_list);
5634 heap_free(This->vardescs);
5636 if(This->impltypes){
5637 for (i = 0; i < This->cImplTypes; ++i){
5638 TLBImplType *pImpl = &This->impltypes[i];
5639 TLB_FreeCustData(&pImpl->custdata_list);
5641 heap_free(This->impltypes);
5644 TLB_FreeCustData(&This->custdata_list);
5646 heap_free(This);
5649 /* ITypeInfo::Release
5651 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5653 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5654 ULONG ref = InterlockedDecrement(&This->ref);
5656 TRACE("(%p)->(%u)\n",This, ref);
5658 if (!ref)
5660 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5661 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5662 if (not_attached_to_typelib)
5663 heap_free(This);
5664 /* otherwise This will be freed when typelib is freed */
5667 return ref;
5670 /* ITypeInfo::GetTypeAttr
5672 * Retrieves a TYPEATTR structure that contains the attributes of the type
5673 * description.
5676 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5677 LPTYPEATTR *ppTypeAttr)
5679 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5680 SIZE_T size;
5682 TRACE("(%p)\n",This);
5684 size = sizeof(**ppTypeAttr);
5685 if (This->typekind == TKIND_ALIAS && This->tdescAlias)
5686 size += TLB_SizeTypeDesc(This->tdescAlias, FALSE);
5688 *ppTypeAttr = heap_alloc(size);
5689 if (!*ppTypeAttr)
5690 return E_OUTOFMEMORY;
5692 (*ppTypeAttr)->guid = *TLB_get_guid_null(This->guid);
5693 (*ppTypeAttr)->lcid = This->lcid;
5694 (*ppTypeAttr)->memidConstructor = This->memidConstructor;
5695 (*ppTypeAttr)->memidDestructor = This->memidDestructor;
5696 (*ppTypeAttr)->lpstrSchema = This->lpstrSchema;
5697 (*ppTypeAttr)->cbSizeInstance = This->cbSizeInstance;
5698 (*ppTypeAttr)->typekind = This->typekind;
5699 (*ppTypeAttr)->cFuncs = This->cFuncs;
5700 (*ppTypeAttr)->cVars = This->cVars;
5701 (*ppTypeAttr)->cImplTypes = This->cImplTypes;
5702 (*ppTypeAttr)->cbSizeVft = This->cbSizeVft;
5703 (*ppTypeAttr)->cbAlignment = This->cbAlignment;
5704 (*ppTypeAttr)->wTypeFlags = This->wTypeFlags;
5705 (*ppTypeAttr)->wMajorVerNum = This->wMajorVerNum;
5706 (*ppTypeAttr)->wMinorVerNum = This->wMinorVerNum;
5707 (*ppTypeAttr)->idldescType = This->idldescType;
5709 if (This->tdescAlias)
5710 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5711 This->tdescAlias, *ppTypeAttr + 1);
5712 else{
5713 (*ppTypeAttr)->tdescAlias.vt = VT_EMPTY;
5714 (*ppTypeAttr)->tdescAlias.u.lptdesc = NULL;
5717 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5718 /* This should include all the inherited funcs */
5719 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / This->pTypeLib->ptr_size;
5720 /* This is always the size of IDispatch's vtbl */
5721 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5722 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5724 return S_OK;
5727 /* ITypeInfo::GetTypeComp
5729 * Retrieves the ITypeComp interface for the type description, which enables a
5730 * client compiler to bind to the type description's members.
5733 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5734 ITypeComp * *ppTComp)
5736 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5738 TRACE("(%p)->(%p)\n", This, ppTComp);
5740 *ppTComp = &This->ITypeComp_iface;
5741 ITypeComp_AddRef(*ppTComp);
5742 return S_OK;
5745 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5747 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5748 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5749 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5750 return size;
5753 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5755 *dest = *src;
5756 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5757 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5759 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5760 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5761 *buffer += sizeof(PARAMDESCEX);
5762 *pparamdescex_dest = *pparamdescex_src;
5763 pparamdescex_dest->cBytes = sizeof(PARAMDESCEX);
5764 VariantInit(&pparamdescex_dest->varDefaultValue);
5765 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5766 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5768 else
5769 dest->u.paramdesc.pparamdescex = NULL;
5770 return S_OK;
5773 static HRESULT TLB_SanitizeBSTR(BSTR str)
5775 UINT len = SysStringLen(str), i;
5776 for (i = 0; i < len; ++i)
5777 if (str[i] > 0x7f)
5778 str[i] = '?';
5779 return S_OK;
5782 static HRESULT TLB_SanitizeVariant(VARIANT *var)
5784 if (V_VT(var) == VT_INT)
5785 return VariantChangeType(var, var, 0, VT_I4);
5786 else if (V_VT(var) == VT_UINT)
5787 return VariantChangeType(var, var, 0, VT_UI4);
5788 else if (V_VT(var) == VT_BSTR)
5789 return TLB_SanitizeBSTR(V_BSTR(var));
5791 return S_OK;
5794 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5796 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5797 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5800 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5802 FUNCDESC *dest;
5803 char *buffer;
5804 SIZE_T size = sizeof(*src);
5805 SHORT i;
5806 HRESULT hr;
5808 size += sizeof(*src->lprgscode) * src->cScodes;
5809 size += TLB_SizeElemDesc(&src->elemdescFunc);
5810 for (i = 0; i < src->cParams; i++)
5812 size += sizeof(ELEMDESC);
5813 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5816 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5817 if (!dest) return E_OUTOFMEMORY;
5819 *dest = *src;
5820 if (dispinterface) /* overwrite funckind */
5821 dest->funckind = FUNC_DISPATCH;
5822 buffer = (char *)(dest + 1);
5824 dest->oVft = dest->oVft & 0xFFFC;
5826 if (dest->cScodes) {
5827 dest->lprgscode = (SCODE *)buffer;
5828 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5829 buffer += sizeof(*src->lprgscode) * src->cScodes;
5830 } else
5831 dest->lprgscode = NULL;
5833 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5834 if (FAILED(hr))
5836 SysFreeString((BSTR)dest);
5837 return hr;
5840 if (dest->cParams) {
5841 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5842 buffer += sizeof(ELEMDESC) * src->cParams;
5843 for (i = 0; i < src->cParams; i++)
5845 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5846 if (FAILED(hr))
5847 break;
5849 if (FAILED(hr))
5851 /* undo the above actions */
5852 for (i = i - 1; i >= 0; i--)
5853 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5854 TLB_FreeElemDesc(&dest->elemdescFunc);
5855 SysFreeString((BSTR)dest);
5856 return hr;
5858 } else
5859 dest->lprgelemdescParam = NULL;
5861 /* special treatment for dispinterfaces: this makes functions appear
5862 * to return their [retval] value when it is really returning an
5863 * HRESULT */
5864 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5866 if (dest->cParams &&
5867 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5869 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5870 if (elemdesc->tdesc.vt != VT_PTR)
5872 ERR("elemdesc should have started with VT_PTR instead of:\n");
5873 if (ERR_ON(ole))
5874 dump_ELEMDESC(elemdesc);
5875 return E_UNEXPECTED;
5878 /* copy last parameter to the return value. we are using a flat
5879 * buffer so there is no danger of leaking memory in
5880 * elemdescFunc */
5881 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5883 /* remove the last parameter */
5884 dest->cParams--;
5886 else
5887 /* otherwise this function is made to appear to have no return
5888 * value */
5889 dest->elemdescFunc.tdesc.vt = VT_VOID;
5893 *dest_ptr = dest;
5894 return S_OK;
5897 static void TLB_FreeVarDesc(VARDESC *var_desc)
5899 TLB_FreeElemDesc(&var_desc->elemdescVar);
5900 if (var_desc->varkind == VAR_CONST)
5901 VariantClear(var_desc->u.lpvarValue);
5902 SysFreeString((BSTR)var_desc);
5905 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5907 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5909 if (index >= This->cFuncs)
5910 return TYPE_E_ELEMENTNOTFOUND;
5912 *ppFuncDesc = &This->funcdescs[index].funcdesc;
5913 return S_OK;
5916 /* internal function to make the inherited interfaces' methods appear
5917 * part of the interface */
5918 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5919 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5921 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5922 HRESULT hr;
5923 UINT implemented_funcs = 0;
5925 if (funcs)
5926 *funcs = 0;
5927 else
5928 *hrefoffset = DISPATCH_HREF_OFFSET;
5930 if(This->impltypes)
5932 ITypeInfo *pSubTypeInfo;
5933 UINT sub_funcs;
5935 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5936 if (FAILED(hr))
5937 return hr;
5939 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5940 index,
5941 ppFuncDesc,
5942 &sub_funcs, hrefoffset);
5943 implemented_funcs += sub_funcs;
5944 ITypeInfo_Release(pSubTypeInfo);
5945 if (SUCCEEDED(hr))
5946 return hr;
5947 *hrefoffset += DISPATCH_HREF_OFFSET;
5950 if (funcs)
5951 *funcs = implemented_funcs + This->cFuncs;
5952 else
5953 *hrefoffset = 0;
5955 if (index < implemented_funcs)
5956 return E_INVALIDARG;
5957 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5958 ppFuncDesc);
5961 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5963 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5964 while (TRUE)
5966 switch (pTypeDesc->vt)
5968 case VT_USERDEFINED:
5969 pTypeDesc->u.hreftype += hrefoffset;
5970 return;
5971 case VT_PTR:
5972 case VT_SAFEARRAY:
5973 pTypeDesc = pTypeDesc->u.lptdesc;
5974 break;
5975 case VT_CARRAY:
5976 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5977 break;
5978 default:
5979 return;
5984 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5986 SHORT i;
5987 for (i = 0; i < pFuncDesc->cParams; i++)
5988 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5989 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5992 /* ITypeInfo::GetFuncDesc
5994 * Retrieves the FUNCDESC structure that contains information about a
5995 * specified function.
5998 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5999 LPFUNCDESC *ppFuncDesc)
6001 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6002 const FUNCDESC *internal_funcdesc;
6003 HRESULT hr;
6004 UINT hrefoffset = 0;
6006 TRACE("(%p) index %d\n", This, index);
6008 if (!ppFuncDesc)
6009 return E_INVALIDARG;
6011 if (This->needs_layout)
6012 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6014 if (This->typekind == TKIND_DISPATCH)
6015 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
6016 &internal_funcdesc, NULL,
6017 &hrefoffset);
6018 else
6019 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
6020 &internal_funcdesc);
6021 if (FAILED(hr))
6023 WARN("description for function %d not found\n", index);
6024 return hr;
6027 hr = TLB_AllocAndInitFuncDesc(
6028 internal_funcdesc,
6029 ppFuncDesc,
6030 This->typekind == TKIND_DISPATCH);
6032 if ((This->typekind == TKIND_DISPATCH) && hrefoffset)
6033 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
6035 TRACE("-- 0x%08x\n", hr);
6036 return hr;
6039 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
6041 VARDESC *dest;
6042 char *buffer;
6043 SIZE_T size = sizeof(*src);
6044 HRESULT hr;
6046 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
6047 if (src->varkind == VAR_CONST)
6048 size += sizeof(VARIANT);
6049 size += TLB_SizeElemDesc(&src->elemdescVar);
6051 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
6052 if (!dest) return E_OUTOFMEMORY;
6054 *dest = *src;
6055 buffer = (char *)(dest + 1);
6056 if (src->lpstrSchema)
6058 int len;
6059 dest->lpstrSchema = (LPOLESTR)buffer;
6060 len = strlenW(src->lpstrSchema);
6061 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
6062 buffer += (len + 1) * sizeof(WCHAR);
6065 if (src->varkind == VAR_CONST)
6067 HRESULT hr;
6069 dest->u.lpvarValue = (VARIANT *)buffer;
6070 *dest->u.lpvarValue = *src->u.lpvarValue;
6071 buffer += sizeof(VARIANT);
6072 VariantInit(dest->u.lpvarValue);
6073 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
6074 if (FAILED(hr))
6076 SysFreeString((BSTR)dest);
6077 return hr;
6080 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
6081 if (FAILED(hr))
6083 if (src->varkind == VAR_CONST)
6084 VariantClear(dest->u.lpvarValue);
6085 SysFreeString((BSTR)dest);
6086 return hr;
6088 *dest_ptr = dest;
6089 return S_OK;
6092 /* ITypeInfo::GetVarDesc
6094 * Retrieves a VARDESC structure that describes the specified variable.
6097 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
6098 LPVARDESC *ppVarDesc)
6100 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6101 const TLBVarDesc *pVDesc = &This->vardescs[index];
6103 TRACE("(%p) index %d\n", This, index);
6105 if(index >= This->cVars)
6106 return TYPE_E_ELEMENTNOTFOUND;
6108 if (This->needs_layout)
6109 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6111 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
6114 /* ITypeInfo_GetNames
6116 * Retrieves the variable with the specified member ID (or the name of the
6117 * property or method and its parameters) that correspond to the specified
6118 * function ID.
6120 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
6121 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
6123 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6124 const TLBFuncDesc *pFDesc;
6125 const TLBVarDesc *pVDesc;
6126 int i;
6127 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
6129 if(!rgBstrNames)
6130 return E_INVALIDARG;
6132 *pcNames = 0;
6134 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
6135 if(pFDesc)
6137 if(!cMaxNames || !pFDesc->Name)
6138 return S_OK;
6140 *rgBstrNames = SysAllocString(TLB_get_bstr(pFDesc->Name));
6141 ++(*pcNames);
6143 for(i = 0; i < pFDesc->funcdesc.cParams; ++i){
6144 if(*pcNames >= cMaxNames || !pFDesc->pParamDesc[i].Name)
6145 return S_OK;
6146 rgBstrNames[*pcNames] = SysAllocString(TLB_get_bstr(pFDesc->pParamDesc[i].Name));
6147 ++(*pcNames);
6149 return S_OK;
6152 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
6153 if(pVDesc)
6155 *rgBstrNames=SysAllocString(TLB_get_bstr(pVDesc->Name));
6156 *pcNames=1;
6158 else
6160 if(This->impltypes &&
6161 (This->typekind==TKIND_INTERFACE || This->typekind==TKIND_DISPATCH)) {
6162 /* recursive search */
6163 ITypeInfo *pTInfo;
6164 HRESULT result;
6165 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6166 if(SUCCEEDED(result))
6168 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
6169 ITypeInfo_Release(pTInfo);
6170 return result;
6172 WARN("Could not search inherited interface!\n");
6174 else
6176 WARN("no names found\n");
6178 *pcNames=0;
6179 return TYPE_E_ELEMENTNOTFOUND;
6181 return S_OK;
6185 /* ITypeInfo::GetRefTypeOfImplType
6187 * If a type description describes a COM class, it retrieves the type
6188 * description of the implemented interface types. For an interface,
6189 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6190 * if any exist.
6193 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
6194 ITypeInfo2 *iface,
6195 UINT index,
6196 HREFTYPE *pRefType)
6198 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6199 HRESULT hr = S_OK;
6201 TRACE("(%p) index %d\n", This, index);
6202 if (TRACE_ON(ole)) dump_TypeInfo(This);
6204 if(index==(UINT)-1)
6206 /* only valid on dual interfaces;
6207 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6210 if (This->wTypeFlags & TYPEFLAG_FDUAL)
6212 *pRefType = -2;
6214 else
6216 hr = TYPE_E_ELEMENTNOTFOUND;
6219 else if(index == 0 && This->typekind == TKIND_DISPATCH)
6221 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6222 *pRefType = This->pTypeLib->dispatch_href;
6224 else
6226 if(index >= This->cImplTypes)
6227 hr = TYPE_E_ELEMENTNOTFOUND;
6228 else{
6229 *pRefType = This->impltypes[index].hRef;
6230 if(This->typekind == TKIND_INTERFACE)
6231 *pRefType |= 0x2;
6235 if(TRACE_ON(ole))
6237 if(SUCCEEDED(hr))
6238 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
6239 else
6240 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
6243 return hr;
6246 /* ITypeInfo::GetImplTypeFlags
6248 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6249 * or base interface in a type description.
6251 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
6252 UINT index, INT *pImplTypeFlags)
6254 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6256 TRACE("(%p) index %d\n", This, index);
6258 if(!pImplTypeFlags)
6259 return E_INVALIDARG;
6261 if(This->typekind == TKIND_DISPATCH && index == 0){
6262 *pImplTypeFlags = 0;
6263 return S_OK;
6266 if(index >= This->cImplTypes)
6267 return TYPE_E_ELEMENTNOTFOUND;
6269 *pImplTypeFlags = This->impltypes[index].implflags;
6271 return S_OK;
6274 /* GetIDsOfNames
6275 * Maps between member names and member IDs, and parameter names and
6276 * parameter IDs.
6278 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
6279 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
6281 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6282 const TLBVarDesc *pVDesc;
6283 HRESULT ret=S_OK;
6284 UINT i, fdc;
6286 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
6287 cNames);
6289 /* init out parameters in case of failure */
6290 for (i = 0; i < cNames; i++)
6291 pMemId[i] = MEMBERID_NIL;
6293 for (fdc = 0; fdc < This->cFuncs; ++fdc) {
6294 int j;
6295 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
6296 if(!lstrcmpiW(*rgszNames, TLB_get_bstr(pFDesc->Name))) {
6297 if(cNames) *pMemId=pFDesc->funcdesc.memid;
6298 for(i=1; i < cNames; i++){
6299 for(j=0; j<pFDesc->funcdesc.cParams; j++)
6300 if(!lstrcmpiW(rgszNames[i],TLB_get_bstr(pFDesc->pParamDesc[j].Name)))
6301 break;
6302 if( j<pFDesc->funcdesc.cParams)
6303 pMemId[i]=j;
6304 else
6305 ret=DISP_E_UNKNOWNNAME;
6307 TRACE("-- 0x%08x\n", ret);
6308 return ret;
6311 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->cVars, *rgszNames);
6312 if(pVDesc){
6313 if(cNames)
6314 *pMemId = pVDesc->vardesc.memid;
6315 return ret;
6317 /* not found, see if it can be found in an inherited interface */
6318 if(This->impltypes) {
6319 /* recursive search */
6320 ITypeInfo *pTInfo;
6321 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6322 if(SUCCEEDED(ret)){
6323 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
6324 ITypeInfo_Release(pTInfo);
6325 return ret;
6327 WARN("Could not search inherited interface!\n");
6328 } else
6329 WARN("no names found\n");
6330 return DISP_E_UNKNOWNNAME;
6334 #ifdef __i386__
6336 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6337 __ASM_GLOBAL_FUNC( call_method,
6338 "pushl %ebp\n\t"
6339 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6340 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6341 "movl %esp,%ebp\n\t"
6342 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6343 "pushl %esi\n\t"
6344 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6345 "pushl %edi\n\t"
6346 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6347 "movl 12(%ebp),%edx\n\t"
6348 "movl %esp,%edi\n\t"
6349 "shll $2,%edx\n\t"
6350 "jz 1f\n\t"
6351 "subl %edx,%edi\n\t"
6352 "andl $~15,%edi\n\t"
6353 "movl %edi,%esp\n\t"
6354 "movl 12(%ebp),%ecx\n\t"
6355 "movl 16(%ebp),%esi\n\t"
6356 "cld\n\t"
6357 "rep; movsl\n"
6358 "1:\tcall *8(%ebp)\n\t"
6359 "subl %esp,%edi\n\t"
6360 "movl 20(%ebp),%ecx\n\t"
6361 "movl %edi,(%ecx)\n\t"
6362 "leal -8(%ebp),%esp\n\t"
6363 "popl %edi\n\t"
6364 __ASM_CFI(".cfi_same_value %edi\n\t")
6365 "popl %esi\n\t"
6366 __ASM_CFI(".cfi_same_value %esi\n\t")
6367 "popl %ebp\n\t"
6368 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6369 __ASM_CFI(".cfi_same_value %ebp\n\t")
6370 "ret" )
6372 /* same function but returning floating point */
6373 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
6375 /* ITypeInfo::Invoke
6377 * Invokes a method, or accesses a property of an object, that implements the
6378 * interface described by the type description.
6380 DWORD
6381 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
6382 DWORD res;
6383 int stack_offset;
6385 if (TRACE_ON(ole)) {
6386 int i;
6387 TRACE("Calling %p(",func);
6388 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
6389 if (nrargs > 30) TRACE("...");
6390 TRACE(")\n");
6393 switch (callconv) {
6394 case CC_STDCALL:
6395 case CC_CDECL:
6396 res = call_method( func, nrargs, args, &stack_offset );
6397 break;
6398 default:
6399 FIXME("unsupported calling convention %d\n",callconv);
6400 res = -1;
6401 break;
6403 TRACE("returns %08x\n",res);
6404 return res;
6407 #elif defined(__x86_64__)
6409 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
6410 __ASM_GLOBAL_FUNC( call_method,
6411 "pushq %rbp\n\t"
6412 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6413 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6414 "movq %rsp,%rbp\n\t"
6415 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6416 "pushq %rsi\n\t"
6417 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6418 "pushq %rdi\n\t"
6419 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6420 "movq %rcx,%rax\n\t"
6421 "movq $4,%rcx\n\t"
6422 "cmp %rcx,%rdx\n\t"
6423 "cmovgq %rdx,%rcx\n\t"
6424 "leaq 0(,%rcx,8),%rdx\n\t"
6425 "subq %rdx,%rsp\n\t"
6426 "andq $~15,%rsp\n\t"
6427 "movq %rsp,%rdi\n\t"
6428 "movq %r8,%rsi\n\t"
6429 "rep; movsq\n\t"
6430 "movq 0(%rsp),%rcx\n\t"
6431 "movq 8(%rsp),%rdx\n\t"
6432 "movq 16(%rsp),%r8\n\t"
6433 "movq 24(%rsp),%r9\n\t"
6434 "movq %rcx,%xmm0\n\t"
6435 "movq %rdx,%xmm1\n\t"
6436 "movq %r8,%xmm2\n\t"
6437 "movq %r9,%xmm3\n\t"
6438 "callq *%rax\n\t"
6439 "leaq -16(%rbp),%rsp\n\t"
6440 "popq %rdi\n\t"
6441 __ASM_CFI(".cfi_same_value %rdi\n\t")
6442 "popq %rsi\n\t"
6443 __ASM_CFI(".cfi_same_value %rsi\n\t")
6444 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6445 "popq %rbp\n\t"
6446 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6447 __ASM_CFI(".cfi_same_value %rbp\n\t")
6448 "ret")
6450 /* same function but returning floating point */
6451 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
6453 #endif /* __x86_64__ */
6455 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6457 HRESULT hr = S_OK;
6458 ITypeInfo *tinfo2 = NULL;
6459 TYPEATTR *tattr = NULL;
6461 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6462 if (hr)
6464 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6465 "hr = 0x%08x\n",
6466 tdesc->u.hreftype, hr);
6467 return hr;
6469 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6470 if (hr)
6472 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
6473 ITypeInfo_Release(tinfo2);
6474 return hr;
6477 switch (tattr->typekind)
6479 case TKIND_ENUM:
6480 *vt |= VT_I4;
6481 break;
6483 case TKIND_ALIAS:
6484 tdesc = &tattr->tdescAlias;
6485 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
6486 break;
6488 case TKIND_INTERFACE:
6489 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
6490 *vt |= VT_DISPATCH;
6491 else
6492 *vt |= VT_UNKNOWN;
6493 break;
6495 case TKIND_DISPATCH:
6496 *vt |= VT_DISPATCH;
6497 break;
6499 case TKIND_COCLASS:
6500 *vt |= VT_DISPATCH;
6501 break;
6503 case TKIND_RECORD:
6504 FIXME("TKIND_RECORD unhandled.\n");
6505 hr = E_NOTIMPL;
6506 break;
6508 case TKIND_UNION:
6509 FIXME("TKIND_UNION unhandled.\n");
6510 hr = E_NOTIMPL;
6511 break;
6513 default:
6514 FIXME("TKIND %d unhandled.\n",tattr->typekind);
6515 hr = E_NOTIMPL;
6516 break;
6518 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6519 ITypeInfo_Release(tinfo2);
6520 return hr;
6523 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6525 HRESULT hr = S_OK;
6527 /* enforce only one level of pointer indirection */
6528 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
6530 tdesc = tdesc->u.lptdesc;
6532 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6533 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6534 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6535 if ((tdesc->vt == VT_USERDEFINED) ||
6536 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
6538 VARTYPE vt_userdefined = 0;
6539 const TYPEDESC *tdesc_userdefined = tdesc;
6540 if (tdesc->vt == VT_PTR)
6542 vt_userdefined = VT_BYREF;
6543 tdesc_userdefined = tdesc->u.lptdesc;
6545 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
6546 if ((hr == S_OK) &&
6547 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
6548 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
6550 *vt |= vt_userdefined;
6551 return S_OK;
6554 *vt = VT_BYREF;
6557 switch (tdesc->vt)
6559 case VT_HRESULT:
6560 *vt |= VT_ERROR;
6561 break;
6562 case VT_USERDEFINED:
6563 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
6564 break;
6565 case VT_VOID:
6566 case VT_CARRAY:
6567 case VT_PTR:
6568 case VT_LPSTR:
6569 case VT_LPWSTR:
6570 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
6571 hr = DISP_E_BADVARTYPE;
6572 break;
6573 case VT_SAFEARRAY:
6574 *vt |= VT_ARRAY;
6575 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
6576 break;
6577 case VT_INT:
6578 *vt |= VT_I4;
6579 break;
6580 case VT_UINT:
6581 *vt |= VT_UI4;
6582 break;
6583 default:
6584 *vt |= tdesc->vt;
6585 break;
6587 return hr;
6590 static HRESULT get_iface_guid(ITypeInfo *tinfo, const TYPEDESC *tdesc, GUID *guid)
6592 ITypeInfo *tinfo2;
6593 TYPEATTR *tattr;
6594 HRESULT hres;
6596 hres = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6597 if(FAILED(hres))
6598 return hres;
6600 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6601 if(FAILED(hres)) {
6602 ITypeInfo_Release(tinfo2);
6603 return hres;
6606 switch(tattr->typekind) {
6607 case TKIND_ALIAS:
6608 hres = get_iface_guid(tinfo2, &tattr->tdescAlias, guid);
6609 break;
6611 case TKIND_INTERFACE:
6612 case TKIND_DISPATCH:
6613 *guid = tattr->guid;
6614 break;
6616 default:
6617 ERR("Unexpected typekind %d\n", tattr->typekind);
6618 hres = E_UNEXPECTED;
6621 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6622 ITypeInfo_Release(tinfo2);
6623 return hres;
6626 /***********************************************************************
6627 * DispCallFunc (OLEAUT32.@)
6629 * Invokes a function of the specified calling convention, passing the
6630 * specified arguments and returns the result.
6632 * PARAMS
6633 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6634 * oVft [I] The offset in the vtable. See notes.
6635 * cc [I] Calling convention of the function to call.
6636 * vtReturn [I] The return type of the function.
6637 * cActuals [I] Number of parameters.
6638 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6639 * prgpvarg [I] The arguments to pass.
6640 * pvargResult [O] The return value of the function. Can be NULL.
6642 * RETURNS
6643 * Success: S_OK.
6644 * Failure: HRESULT code.
6646 * NOTES
6647 * The HRESULT return value of this function is not affected by the return
6648 * value of the user supplied function, which is returned in pvargResult.
6650 * If pvInstance is NULL then a non-object function is to be called and oVft
6651 * is the address of the function to call.
6653 * The cc parameter can be one of the following values:
6654 *|CC_FASTCALL
6655 *|CC_CDECL
6656 *|CC_PASCAL
6657 *|CC_STDCALL
6658 *|CC_FPFASTCALL
6659 *|CC_SYSCALL
6660 *|CC_MPWCDECL
6661 *|CC_MPWPASCAL
6664 HRESULT WINAPI
6665 DispCallFunc(
6666 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
6667 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
6669 #ifdef __i386__
6670 int argspos, stack_offset;
6671 void *func;
6672 UINT i;
6673 DWORD *args;
6675 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6676 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6677 pvargResult, V_VT(pvargResult));
6679 if (cc != CC_STDCALL && cc != CC_CDECL)
6681 FIXME("unsupported calling convention %d\n",cc);
6682 return E_INVALIDARG;
6685 /* maximum size for an argument is sizeof(VARIANT) */
6686 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6688 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6689 argspos = 1;
6690 if (pvInstance)
6692 const FARPROC *vtable = *(FARPROC **)pvInstance;
6693 func = vtable[oVft/sizeof(void *)];
6694 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6696 else func = (void *)oVft;
6698 for (i = 0; i < cActuals; i++)
6700 VARIANT *arg = prgpvarg[i];
6702 switch (prgvt[i])
6704 case VT_EMPTY:
6705 break;
6706 case VT_I8:
6707 case VT_UI8:
6708 case VT_R8:
6709 case VT_DATE:
6710 case VT_CY:
6711 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6712 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6713 break;
6714 case VT_DECIMAL:
6715 case VT_VARIANT:
6716 memcpy( &args[argspos], arg, sizeof(*arg) );
6717 argspos += sizeof(*arg) / sizeof(DWORD);
6718 break;
6719 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6720 args[argspos++] = V_BOOL(arg);
6721 break;
6722 default:
6723 args[argspos++] = V_UI4(arg);
6724 break;
6726 TRACE("arg %u: type %d\n",i,prgvt[i]);
6727 dump_Variant(arg);
6730 switch (vtReturn)
6732 case VT_EMPTY:
6733 call_method( func, argspos - 1, args + 1, &stack_offset );
6734 break;
6735 case VT_R4:
6736 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6737 break;
6738 case VT_R8:
6739 case VT_DATE:
6740 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6741 break;
6742 case VT_DECIMAL:
6743 case VT_VARIANT:
6744 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6745 call_method( func, argspos, args, &stack_offset );
6746 break;
6747 case VT_I8:
6748 case VT_UI8:
6749 case VT_CY:
6750 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6751 break;
6752 case VT_HRESULT:
6753 WARN("invalid return type %u\n", vtReturn);
6754 heap_free( args );
6755 return E_INVALIDARG;
6756 default:
6757 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6758 break;
6760 heap_free( args );
6761 if (stack_offset && cc == CC_STDCALL)
6763 WARN( "stack pointer off by %d\n", stack_offset );
6764 return DISP_E_BADCALLEE;
6766 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6767 TRACE("retval: "); dump_Variant(pvargResult);
6768 return S_OK;
6770 #elif defined(__x86_64__)
6771 int argspos;
6772 UINT i;
6773 DWORD_PTR *args;
6774 void *func;
6776 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6777 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6778 pvargResult, V_VT(pvargResult));
6780 if (cc != CC_STDCALL && cc != CC_CDECL)
6782 FIXME("unsupported calling convention %d\n",cc);
6783 return E_INVALIDARG;
6786 /* maximum size for an argument is sizeof(DWORD_PTR) */
6787 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6789 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6790 argspos = 1;
6791 if (pvInstance)
6793 const FARPROC *vtable = *(FARPROC **)pvInstance;
6794 func = vtable[oVft/sizeof(void *)];
6795 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6797 else func = (void *)oVft;
6799 for (i = 0; i < cActuals; i++)
6801 VARIANT *arg = prgpvarg[i];
6803 switch (prgvt[i])
6805 case VT_DECIMAL:
6806 case VT_VARIANT:
6807 args[argspos++] = (ULONG_PTR)arg;
6808 break;
6809 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6810 args[argspos++] = V_BOOL(arg);
6811 break;
6812 default:
6813 args[argspos++] = V_UI8(arg);
6814 break;
6816 TRACE("arg %u: type %d\n",i,prgvt[i]);
6817 dump_Variant(arg);
6820 switch (vtReturn)
6822 case VT_R4:
6823 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6824 break;
6825 case VT_R8:
6826 case VT_DATE:
6827 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6828 break;
6829 case VT_DECIMAL:
6830 case VT_VARIANT:
6831 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6832 call_method( func, argspos, args );
6833 break;
6834 case VT_HRESULT:
6835 WARN("invalid return type %u\n", vtReturn);
6836 heap_free( args );
6837 return E_INVALIDARG;
6838 default:
6839 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6840 break;
6842 heap_free( args );
6843 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6844 TRACE("retval: "); dump_Variant(pvargResult);
6845 return S_OK;
6847 #else
6848 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6849 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6850 return E_NOTIMPL;
6851 #endif
6854 static inline BOOL func_restricted( const FUNCDESC *desc )
6856 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
6859 #define INVBUF_ELEMENT_SIZE \
6860 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6861 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6862 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6863 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6864 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6865 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6866 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6867 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6869 static HRESULT WINAPI ITypeInfo_fnInvoke(
6870 ITypeInfo2 *iface,
6871 VOID *pIUnk,
6872 MEMBERID memid,
6873 UINT16 wFlags,
6874 DISPPARAMS *pDispParams,
6875 VARIANT *pVarResult,
6876 EXCEPINFO *pExcepInfo,
6877 UINT *pArgErr)
6879 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6880 int i;
6881 unsigned int var_index;
6882 TYPEKIND type_kind;
6883 HRESULT hres;
6884 const TLBFuncDesc *pFuncInfo;
6885 UINT fdc;
6887 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6888 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6891 if( This->wTypeFlags & TYPEFLAG_FRESTRICTED )
6892 return DISP_E_MEMBERNOTFOUND;
6894 if (!pDispParams)
6896 ERR("NULL pDispParams not allowed\n");
6897 return E_INVALIDARG;
6900 dump_DispParms(pDispParams);
6902 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6904 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6905 pDispParams->cNamedArgs, pDispParams->cArgs);
6906 return E_INVALIDARG;
6909 /* we do this instead of using GetFuncDesc since it will return a fake
6910 * FUNCDESC for dispinterfaces and we want the real function description */
6911 for (fdc = 0; fdc < This->cFuncs; ++fdc){
6912 pFuncInfo = &This->funcdescs[fdc];
6913 if ((memid == pFuncInfo->funcdesc.memid) &&
6914 (wFlags & pFuncInfo->funcdesc.invkind) &&
6915 !func_restricted( &pFuncInfo->funcdesc ))
6916 break;
6919 if (fdc < This->cFuncs) {
6920 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6922 if (TRACE_ON(ole))
6924 TRACE("invoking:\n");
6925 dump_TLBFuncDescOne(pFuncInfo);
6928 switch (func_desc->funckind) {
6929 case FUNC_PUREVIRTUAL:
6930 case FUNC_VIRTUAL: {
6931 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
6932 VARIANT varresult;
6933 VARIANT retval; /* pointer for storing byref retvals in */
6934 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6935 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6936 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6937 UINT cNamedArgs = pDispParams->cNamedArgs;
6938 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6939 UINT vargs_converted=0;
6941 hres = S_OK;
6943 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6945 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6947 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6948 hres = DISP_E_PARAMNOTFOUND;
6949 goto func_fail;
6953 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6955 ERR("functions with the vararg attribute do not support named arguments\n");
6956 hres = DISP_E_NONAMEDARGS;
6957 goto func_fail;
6960 for (i = 0; i < func_desc->cParams; i++)
6962 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6963 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6964 if (FAILED(hres))
6965 goto func_fail;
6968 TRACE("changing args\n");
6969 for (i = 0; i < func_desc->cParams; i++)
6971 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6972 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6973 VARIANTARG *src_arg;
6975 if (wParamFlags & PARAMFLAG_FLCID)
6977 VARIANTARG *arg;
6978 arg = prgpvarg[i] = &rgvarg[i];
6979 V_VT(arg) = VT_I4;
6980 V_I4(arg) = This->pTypeLib->lcid;
6981 continue;
6984 src_arg = NULL;
6986 if (cNamedArgs)
6988 USHORT j;
6989 for (j = 0; j < cNamedArgs; j++)
6990 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
6992 src_arg = &pDispParams->rgvarg[j];
6993 break;
6997 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
6999 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7000 vargs_converted++;
7003 if (wParamFlags & PARAMFLAG_FRETVAL)
7005 /* under most conditions the caller is not allowed to
7006 * pass in a dispparam arg in the index of what would be
7007 * the retval parameter. however, there is an exception
7008 * where the extra parameter is used in an extra
7009 * IDispatch::Invoke below */
7010 if ((i < pDispParams->cArgs) &&
7011 ((func_desc->cParams != 1) || !pVarResult ||
7012 !(func_desc->invkind & INVOKE_PROPERTYGET)))
7014 hres = DISP_E_BADPARAMCOUNT;
7015 break;
7018 /* note: this check is placed so that if the caller passes
7019 * in a VARIANTARG for the retval we just ignore it, like
7020 * native does */
7021 if (i == func_desc->cParams - 1)
7023 VARIANTARG *arg;
7024 arg = prgpvarg[i] = &rgvarg[i];
7025 memset(arg, 0, sizeof(*arg));
7026 V_VT(arg) = rgvt[i];
7027 memset(&retval, 0, sizeof(retval));
7028 V_BYREF(arg) = &retval;
7030 else
7032 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
7033 hres = E_UNEXPECTED;
7034 break;
7037 else if (src_arg)
7039 dump_Variant(src_arg);
7041 if(rgvt[i]!=V_VT(src_arg))
7043 if (rgvt[i] == VT_VARIANT)
7044 hres = VariantCopy(&rgvarg[i], src_arg);
7045 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
7047 if (rgvt[i] == V_VT(src_arg))
7048 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
7049 else
7051 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7052 if (wParamFlags & PARAMFLAG_FIN)
7053 hres = VariantCopy(&missing_arg[i], src_arg);
7054 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
7056 V_VT(&rgvarg[i]) = rgvt[i];
7058 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
7060 SAFEARRAY *a;
7061 SAFEARRAYBOUND bound;
7062 VARIANT *v;
7063 LONG j;
7064 bound.lLbound = 0;
7065 bound.cElements = pDispParams->cArgs-i;
7066 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
7068 ERR("SafeArrayCreate failed\n");
7069 break;
7071 hres = SafeArrayAccessData(a, (LPVOID)&v);
7072 if (hres != S_OK)
7074 ERR("SafeArrayAccessData failed with %x\n", hres);
7075 SafeArrayDestroy(a);
7076 break;
7078 for (j = 0; j < bound.cElements; j++)
7079 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
7080 hres = SafeArrayUnaccessData(a);
7081 if (hres != S_OK)
7083 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7084 SafeArrayDestroy(a);
7085 break;
7087 V_ARRAY(&rgvarg[i]) = a;
7088 V_VT(&rgvarg[i]) = rgvt[i];
7090 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
7092 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7093 if (wParamFlags & PARAMFLAG_FIN)
7094 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
7095 else
7096 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
7097 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
7098 V_VT(&rgvarg[i]) = rgvt[i];
7100 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
7102 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
7103 V_VT(&rgvarg[i]) = rgvt[i];
7105 else
7107 /* FIXME: this doesn't work for VT_BYREF arguments if
7108 * they are not the same type as in the paramdesc */
7109 V_VT(&rgvarg[i]) = V_VT(src_arg);
7110 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
7111 V_VT(&rgvarg[i]) = rgvt[i];
7114 if (FAILED(hres))
7116 ERR("failed to convert param %d to %s%s from %s%s\n", i,
7117 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
7118 debugstr_VT(src_arg), debugstr_VF(src_arg));
7119 break;
7121 prgpvarg[i] = &rgvarg[i];
7123 else
7125 prgpvarg[i] = src_arg;
7128 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
7129 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
7130 && V_UNKNOWN(prgpvarg[i])) {
7131 IUnknown *userdefined_iface;
7132 GUID guid;
7134 hres = get_iface_guid((ITypeInfo*)iface, tdesc->vt == VT_PTR ? tdesc->u.lptdesc : tdesc, &guid);
7135 if(FAILED(hres))
7136 break;
7138 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
7139 if(FAILED(hres)) {
7140 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
7141 break;
7144 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
7145 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
7148 else if (wParamFlags & PARAMFLAG_FOPT)
7150 VARIANTARG *arg;
7151 arg = prgpvarg[i] = &rgvarg[i];
7152 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7154 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
7155 if (FAILED(hres))
7156 break;
7158 else
7160 VARIANTARG *missing_arg;
7161 /* if the function wants a pointer to a variant then
7162 * set that up, otherwise just pass the VT_ERROR in
7163 * the argument by value */
7164 if (rgvt[i] & VT_BYREF)
7166 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
7167 V_VT(arg) = VT_VARIANT | VT_BYREF;
7168 V_VARIANTREF(arg) = missing_arg;
7170 else
7171 missing_arg = arg;
7172 V_VT(missing_arg) = VT_ERROR;
7173 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
7176 else
7178 hres = DISP_E_BADPARAMCOUNT;
7179 break;
7182 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7184 /* VT_VOID is a special case for return types, so it is not
7185 * handled in the general function */
7186 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
7187 V_VT(&varresult) = VT_EMPTY;
7188 else
7190 V_VT(&varresult) = 0;
7191 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
7192 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7195 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv,
7196 V_VT(&varresult), func_desc->cParams, rgvt,
7197 prgpvarg, &varresult);
7199 vargs_converted = 0;
7201 for (i = 0; i < func_desc->cParams; i++)
7203 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7204 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7206 if (wParamFlags & PARAMFLAG_FLCID)
7207 continue;
7208 else if (wParamFlags & PARAMFLAG_FRETVAL)
7210 if (TRACE_ON(ole))
7212 TRACE("[retval] value: ");
7213 dump_Variant(prgpvarg[i]);
7216 if (pVarResult)
7218 VariantInit(pVarResult);
7219 /* deref return value */
7220 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
7223 VARIANT_ClearInd(prgpvarg[i]);
7225 else if (vargs_converted < pDispParams->cArgs)
7227 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7228 if (wParamFlags & PARAMFLAG_FOUT)
7230 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
7232 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
7234 if (FAILED(hres))
7236 ERR("failed to convert param %d to vt %d\n", i,
7237 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
7238 break;
7242 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
7243 func_desc->cParamsOpt < 0 &&
7244 i == func_desc->cParams-1)
7246 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
7247 LONG j, ubound;
7248 VARIANT *v;
7249 hres = SafeArrayGetUBound(a, 1, &ubound);
7250 if (hres != S_OK)
7252 ERR("SafeArrayGetUBound failed with %x\n", hres);
7253 break;
7255 hres = SafeArrayAccessData(a, (LPVOID)&v);
7256 if (hres != S_OK)
7258 ERR("SafeArrayAccessData failed with %x\n", hres);
7259 break;
7261 for (j = 0; j <= ubound; j++)
7262 VariantClear(&v[j]);
7263 hres = SafeArrayUnaccessData(a);
7264 if (hres != S_OK)
7266 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7267 break;
7270 VariantClear(&rgvarg[i]);
7271 vargs_converted++;
7273 else if (wParamFlags & PARAMFLAG_FOPT)
7275 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7276 VariantClear(&rgvarg[i]);
7279 VariantClear(&missing_arg[i]);
7282 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
7284 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
7285 hres = DISP_E_EXCEPTION;
7286 if (pExcepInfo)
7288 IErrorInfo *pErrorInfo;
7289 pExcepInfo->scode = V_ERROR(&varresult);
7290 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
7292 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
7293 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
7294 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
7295 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
7297 IErrorInfo_Release(pErrorInfo);
7301 if (V_VT(&varresult) != VT_ERROR)
7303 TRACE("varresult value: ");
7304 dump_Variant(&varresult);
7306 if (pVarResult)
7308 VariantClear(pVarResult);
7309 *pVarResult = varresult;
7311 else
7312 VariantClear(&varresult);
7315 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
7316 (func_desc->invkind & INVOKE_PROPERTYGET) &&
7317 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
7318 (pDispParams->cArgs != 0))
7320 if (V_VT(pVarResult) == VT_DISPATCH)
7322 IDispatch *pDispatch = V_DISPATCH(pVarResult);
7323 /* Note: not VariantClear; we still need the dispatch
7324 * pointer to be valid */
7325 VariantInit(pVarResult);
7326 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
7327 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
7328 pDispParams, pVarResult, pExcepInfo, pArgErr);
7329 IDispatch_Release(pDispatch);
7331 else
7333 VariantClear(pVarResult);
7334 hres = DISP_E_NOTACOLLECTION;
7338 func_fail:
7339 heap_free(buffer);
7340 break;
7342 case FUNC_DISPATCH: {
7343 IDispatch *disp;
7345 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
7346 if (SUCCEEDED(hres)) {
7347 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7348 hres = IDispatch_Invoke(
7349 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
7350 pVarResult,pExcepInfo,pArgErr
7352 if (FAILED(hres))
7353 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
7354 IDispatch_Release(disp);
7355 } else
7356 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7357 break;
7359 default:
7360 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
7361 hres = E_FAIL;
7362 break;
7365 TRACE("-- 0x%08x\n", hres);
7366 return hres;
7368 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
7369 VARDESC *var_desc;
7371 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
7372 if(FAILED(hres)) return hres;
7374 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7375 dump_VARDESC(var_desc);
7376 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
7377 return E_NOTIMPL;
7380 /* not found, look for it in inherited interfaces */
7381 ITypeInfo2_GetTypeKind(iface, &type_kind);
7382 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
7383 if(This->impltypes) {
7384 /* recursive search */
7385 ITypeInfo *pTInfo;
7386 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7387 if(SUCCEEDED(hres)){
7388 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
7389 ITypeInfo_Release(pTInfo);
7390 return hres;
7392 WARN("Could not search inherited interface!\n");
7395 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
7396 return DISP_E_MEMBERNOTFOUND;
7399 /* ITypeInfo::GetDocumentation
7401 * Retrieves the documentation string, the complete Help file name and path,
7402 * and the context ID for the Help topic for a specified type description.
7404 * (Can be tested by the Visual Basic Editor in Word for instance.)
7406 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
7407 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
7408 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
7410 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7411 const TLBFuncDesc *pFDesc;
7412 const TLBVarDesc *pVDesc;
7413 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7414 " HelpContext(%p) HelpFile(%p)\n",
7415 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
7416 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7417 if(pBstrName)
7418 *pBstrName=SysAllocString(TLB_get_bstr(This->Name));
7419 if(pBstrDocString)
7420 *pBstrDocString=SysAllocString(TLB_get_bstr(This->DocString));
7421 if(pdwHelpContext)
7422 *pdwHelpContext=This->dwHelpContext;
7423 if(pBstrHelpFile)
7424 *pBstrHelpFile=SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7425 return S_OK;
7426 }else {/* for a member */
7427 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7428 if(pFDesc){
7429 if(pBstrName)
7430 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Name));
7431 if(pBstrDocString)
7432 *pBstrDocString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7433 if(pdwHelpContext)
7434 *pdwHelpContext=pFDesc->helpcontext;
7435 if(pBstrHelpFile)
7436 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7437 return S_OK;
7439 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
7440 if(pVDesc){
7441 if(pBstrName)
7442 *pBstrName = SysAllocString(TLB_get_bstr(pVDesc->Name));
7443 if(pBstrDocString)
7444 *pBstrDocString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7445 if(pdwHelpContext)
7446 *pdwHelpContext=pVDesc->HelpContext;
7447 if(pBstrHelpFile)
7448 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7449 return S_OK;
7453 if(This->impltypes &&
7454 (This->typekind==TKIND_INTERFACE || This->typekind==TKIND_DISPATCH)) {
7455 /* recursive search */
7456 ITypeInfo *pTInfo;
7457 HRESULT result;
7458 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7459 if(SUCCEEDED(result)) {
7460 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
7461 pBstrDocString, pdwHelpContext, pBstrHelpFile);
7462 ITypeInfo_Release(pTInfo);
7463 return result;
7465 WARN("Could not search inherited interface!\n");
7468 WARN("member %d not found\n", memid);
7469 return TYPE_E_ELEMENTNOTFOUND;
7472 /* ITypeInfo::GetDllEntry
7474 * Retrieves a description or specification of an entry point for a function
7475 * in a DLL.
7477 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
7478 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
7479 WORD *pwOrdinal)
7481 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7482 const TLBFuncDesc *pFDesc;
7484 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
7486 if (pBstrDllName) *pBstrDllName = NULL;
7487 if (pBstrName) *pBstrName = NULL;
7488 if (pwOrdinal) *pwOrdinal = 0;
7490 if (This->typekind != TKIND_MODULE)
7491 return TYPE_E_BADMODULEKIND;
7493 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7494 if(pFDesc){
7495 dump_TypeInfo(This);
7496 if (TRACE_ON(ole))
7497 dump_TLBFuncDescOne(pFDesc);
7499 if (pBstrDllName)
7500 *pBstrDllName = SysAllocString(TLB_get_bstr(This->DllName));
7502 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
7503 if (pBstrName)
7504 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Entry));
7505 if (pwOrdinal)
7506 *pwOrdinal = -1;
7507 return S_OK;
7509 if (pBstrName)
7510 *pBstrName = NULL;
7511 if (pwOrdinal)
7512 *pwOrdinal = LOWORD(pFDesc->Entry);
7513 return S_OK;
7515 return TYPE_E_ELEMENTNOTFOUND;
7518 /* internal function to make the inherited interfaces' methods appear
7519 * part of the interface */
7520 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7521 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7523 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7524 HRESULT hr;
7526 TRACE("%p, 0x%x\n", iface, *hRefType);
7528 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7530 ITypeInfo *pSubTypeInfo;
7532 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7533 if (FAILED(hr))
7534 return hr;
7536 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7537 hRefType, ppTInfo);
7538 ITypeInfo_Release(pSubTypeInfo);
7539 if (SUCCEEDED(hr))
7540 return hr;
7542 *hRefType -= DISPATCH_HREF_OFFSET;
7544 if (!(*hRefType & DISPATCH_HREF_MASK))
7545 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7546 else
7547 return E_FAIL;
7550 /* ITypeInfo::GetRefTypeInfo
7552 * If a type description references other type descriptions, it retrieves
7553 * the referenced type descriptions.
7555 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7556 ITypeInfo2 *iface,
7557 HREFTYPE hRefType,
7558 ITypeInfo **ppTInfo)
7560 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7561 HRESULT result = E_FAIL;
7563 if(!ppTInfo)
7564 return E_INVALIDARG;
7566 if ((INT)hRefType < 0) {
7567 ITypeInfoImpl *pTypeInfoImpl;
7569 if (!(This->wTypeFlags & TYPEFLAG_FDUAL) ||
7570 !(This->typekind == TKIND_INTERFACE ||
7571 This->typekind == TKIND_DISPATCH))
7572 return TYPE_E_ELEMENTNOTFOUND;
7574 /* when we meet a DUAL typeinfo, we must create the alternate
7575 * version of it.
7577 pTypeInfoImpl = ITypeInfoImpl_Constructor();
7579 *pTypeInfoImpl = *This;
7580 pTypeInfoImpl->ref = 0;
7581 list_init(&pTypeInfoImpl->custdata_list);
7583 if (This->typekind == TKIND_INTERFACE)
7584 pTypeInfoImpl->typekind = TKIND_DISPATCH;
7585 else
7586 pTypeInfoImpl->typekind = TKIND_INTERFACE;
7588 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface;
7589 /* the AddRef implicitly adds a reference to the parent typelib, which
7590 * stops the copied data from being destroyed until the new typeinfo's
7591 * refcount goes to zero, but we need to signal to the new instance to
7592 * not free its data structures when it is destroyed */
7593 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7595 ITypeInfo_AddRef(*ppTInfo);
7597 result = S_OK;
7598 } else if ((hRefType & DISPATCH_HREF_MASK) &&
7599 (This->typekind == TKIND_DISPATCH))
7601 HREFTYPE href_dispatch = hRefType;
7602 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
7603 } else {
7604 TLBRefType *ref_type;
7605 ITypeLib *pTLib = NULL;
7606 UINT i;
7608 if(!(hRefType & 0x1)){
7609 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
7611 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
7613 result = S_OK;
7614 *ppTInfo = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
7615 ITypeInfo_AddRef(*ppTInfo);
7616 goto end;
7621 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7623 if(ref_type->reference == (hRefType & (~0x3)))
7624 break;
7626 if(&ref_type->entry == &This->pTypeLib->ref_list)
7628 FIXME("Can't find pRefType for ref %x\n", hRefType);
7629 goto end;
7632 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7633 UINT Index;
7634 TRACE("internal reference\n");
7635 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7636 } else {
7637 if(ref_type->pImpTLInfo->pImpTypeLib) {
7638 TRACE("typeinfo in imported typelib that is already loaded\n");
7639 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
7640 ITypeLib_AddRef(pTLib);
7641 result = S_OK;
7642 } else {
7643 BSTR libnam;
7645 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7647 result = query_typelib_path(TLB_get_guid_null(ref_type->pImpTLInfo->guid),
7648 ref_type->pImpTLInfo->wVersionMajor,
7649 ref_type->pImpTLInfo->wVersionMinor,
7650 This->pTypeLib->syskind,
7651 ref_type->pImpTLInfo->lcid, &libnam);
7652 if(FAILED(result))
7653 libnam = SysAllocString(ref_type->pImpTLInfo->name);
7655 result = LoadTypeLib(libnam, &pTLib);
7656 SysFreeString(libnam);
7658 if(SUCCEEDED(result)) {
7659 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
7660 ITypeLib_AddRef(pTLib);
7664 if(SUCCEEDED(result)) {
7665 if(ref_type->index == TLB_REF_USE_GUID)
7666 result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), ppTInfo);
7667 else
7668 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, ppTInfo);
7670 if (pTLib != NULL)
7671 ITypeLib_Release(pTLib);
7674 end:
7675 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
7676 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
7677 return result;
7680 /* ITypeInfo::AddressOfMember
7682 * Retrieves the addresses of static functions or variables, such as those
7683 * defined in a DLL.
7685 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
7686 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
7688 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7689 HRESULT hr;
7690 BSTR dll, entry;
7691 WORD ordinal;
7692 HMODULE module;
7694 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
7696 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
7697 if (FAILED(hr))
7698 return hr;
7700 module = LoadLibraryW(dll);
7701 if (!module)
7703 ERR("couldn't load %s\n", debugstr_w(dll));
7704 SysFreeString(dll);
7705 SysFreeString(entry);
7706 return STG_E_FILENOTFOUND;
7708 /* FIXME: store library somewhere where we can free it */
7710 if (entry)
7712 LPSTR entryA;
7713 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
7714 entryA = heap_alloc(len);
7715 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
7717 *ppv = GetProcAddress(module, entryA);
7718 if (!*ppv)
7719 ERR("function not found %s\n", debugstr_a(entryA));
7721 heap_free(entryA);
7723 else
7725 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7726 if (!*ppv)
7727 ERR("function not found %d\n", ordinal);
7730 SysFreeString(dll);
7731 SysFreeString(entry);
7733 if (!*ppv)
7734 return TYPE_E_DLLFUNCTIONNOTFOUND;
7736 return S_OK;
7739 /* ITypeInfo::CreateInstance
7741 * Creates a new instance of a type that describes a component object class
7742 * (coclass).
7744 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7745 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7747 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7748 HRESULT hr;
7749 TYPEATTR *pTA;
7751 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7753 *ppvObj = NULL;
7755 if(pOuterUnk)
7757 WARN("Not able to aggregate\n");
7758 return CLASS_E_NOAGGREGATION;
7761 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
7762 if(FAILED(hr)) return hr;
7764 if(pTA->typekind != TKIND_COCLASS)
7766 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7767 hr = E_INVALIDARG;
7768 goto end;
7771 hr = S_FALSE;
7772 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7774 IUnknown *pUnk;
7775 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7776 TRACE("GetActiveObject rets %08x\n", hr);
7777 if(hr == S_OK)
7779 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7780 IUnknown_Release(pUnk);
7784 if(hr != S_OK)
7785 hr = CoCreateInstance(&pTA->guid, NULL,
7786 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7787 riid, ppvObj);
7789 end:
7790 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
7791 return hr;
7794 /* ITypeInfo::GetMops
7796 * Retrieves marshalling information.
7798 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7799 BSTR *pBstrMops)
7801 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7802 FIXME("(%p %d) stub!\n", This, memid);
7803 *pBstrMops = NULL;
7804 return S_OK;
7807 /* ITypeInfo::GetContainingTypeLib
7809 * Retrieves the containing type library and the index of the type description
7810 * within that type library.
7812 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7813 ITypeLib * *ppTLib, UINT *pIndex)
7815 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7817 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7818 if (pIndex) {
7819 *pIndex=This->index;
7820 TRACE("returning pIndex=%d\n", *pIndex);
7823 if (ppTLib) {
7824 *ppTLib=(LPTYPELIB )(This->pTypeLib);
7825 ITypeLib_AddRef(*ppTLib);
7826 TRACE("returning ppTLib=%p\n", *ppTLib);
7829 return S_OK;
7832 /* ITypeInfo::ReleaseTypeAttr
7834 * Releases a TYPEATTR previously returned by Get
7837 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7838 TYPEATTR* pTypeAttr)
7840 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7841 TRACE("(%p)->(%p)\n", This, pTypeAttr);
7842 heap_free(pTypeAttr);
7845 /* ITypeInfo::ReleaseFuncDesc
7847 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7849 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7850 ITypeInfo2 *iface,
7851 FUNCDESC *pFuncDesc)
7853 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7854 SHORT i;
7856 TRACE("(%p)->(%p)\n", This, pFuncDesc);
7858 for (i = 0; i < pFuncDesc->cParams; i++)
7859 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7860 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7862 SysFreeString((BSTR)pFuncDesc);
7865 /* ITypeInfo::ReleaseVarDesc
7867 * Releases a VARDESC previously returned by GetVarDesc.
7869 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7870 VARDESC *pVarDesc)
7872 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7873 TRACE("(%p)->(%p)\n", This, pVarDesc);
7875 TLB_FreeVarDesc(pVarDesc);
7878 /* ITypeInfo2::GetTypeKind
7880 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7883 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7884 TYPEKIND *pTypeKind)
7886 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7887 *pTypeKind=This->typekind;
7888 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7889 return S_OK;
7892 /* ITypeInfo2::GetTypeFlags
7894 * Returns the type flags without any allocations. This returns a DWORD type
7895 * flag, which expands the type flags without growing the TYPEATTR (type
7896 * attribute).
7899 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7901 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7902 *pTypeFlags=This->wTypeFlags;
7903 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7904 return S_OK;
7907 /* ITypeInfo2::GetFuncIndexOfMemId
7908 * Binds to a specific member based on a known DISPID, where the member name
7909 * is not known (for example, when binding to a default member).
7912 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7913 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7915 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7916 UINT fdc;
7917 HRESULT result;
7919 for (fdc = 0; fdc < This->cFuncs; ++fdc){
7920 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
7921 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7922 break;
7924 if(fdc < This->cFuncs) {
7925 *pFuncIndex = fdc;
7926 result = S_OK;
7927 } else
7928 result = TYPE_E_ELEMENTNOTFOUND;
7930 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7931 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7932 return result;
7935 /* TypeInfo2::GetVarIndexOfMemId
7937 * Binds to a specific member based on a known DISPID, where the member name
7938 * is not known (for example, when binding to a default member).
7941 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7942 MEMBERID memid, UINT *pVarIndex)
7944 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7945 TLBVarDesc *pVarInfo;
7947 TRACE("%p %d %p\n", iface, memid, pVarIndex);
7949 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
7950 if(!pVarInfo)
7951 return TYPE_E_ELEMENTNOTFOUND;
7953 *pVarIndex = (pVarInfo - This->vardescs);
7955 return S_OK;
7958 /* ITypeInfo2::GetCustData
7960 * Gets the custom data
7962 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7963 ITypeInfo2 * iface,
7964 REFGUID guid,
7965 VARIANT *pVarVal)
7967 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7968 TLBCustData *pCData;
7970 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7972 if(!guid || !pVarVal)
7973 return E_INVALIDARG;
7975 pCData = TLB_get_custdata_by_guid(This->pcustdata_list, guid);
7977 VariantInit( pVarVal);
7978 if (pCData)
7979 VariantCopy( pVarVal, &pCData->data);
7980 else
7981 VariantClear( pVarVal );
7982 return S_OK;
7985 /* ITypeInfo2::GetFuncCustData
7987 * Gets the custom data
7989 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7990 ITypeInfo2 * iface,
7991 UINT index,
7992 REFGUID guid,
7993 VARIANT *pVarVal)
7995 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7996 TLBCustData *pCData;
7997 TLBFuncDesc *pFDesc = &This->funcdescs[index];
7999 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8001 if(index >= This->cFuncs)
8002 return TYPE_E_ELEMENTNOTFOUND;
8004 pCData = TLB_get_custdata_by_guid(&pFDesc->custdata_list, guid);
8005 if(!pCData)
8006 return TYPE_E_ELEMENTNOTFOUND;
8008 VariantInit(pVarVal);
8009 VariantCopy(pVarVal, &pCData->data);
8011 return S_OK;
8014 /* ITypeInfo2::GetParamCustData
8016 * Gets the custom data
8018 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
8019 ITypeInfo2 * iface,
8020 UINT indexFunc,
8021 UINT indexParam,
8022 REFGUID guid,
8023 VARIANT *pVarVal)
8025 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8026 TLBCustData *pCData;
8027 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8029 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
8030 debugstr_guid(guid), pVarVal);
8032 if(indexFunc >= This->cFuncs)
8033 return TYPE_E_ELEMENTNOTFOUND;
8035 if(indexParam >= pFDesc->funcdesc.cParams)
8036 return TYPE_E_ELEMENTNOTFOUND;
8038 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
8039 if(!pCData)
8040 return TYPE_E_ELEMENTNOTFOUND;
8042 VariantInit(pVarVal);
8043 VariantCopy(pVarVal, &pCData->data);
8045 return S_OK;
8048 /* ITypeInfo2::GetVarCustData
8050 * Gets the custom data
8052 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
8053 ITypeInfo2 * iface,
8054 UINT index,
8055 REFGUID guid,
8056 VARIANT *pVarVal)
8058 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8059 TLBCustData *pCData;
8060 TLBVarDesc *pVDesc = &This->vardescs[index];
8062 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8064 if(index >= This->cVars)
8065 return TYPE_E_ELEMENTNOTFOUND;
8067 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
8068 if(!pCData)
8069 return TYPE_E_ELEMENTNOTFOUND;
8071 VariantInit(pVarVal);
8072 VariantCopy(pVarVal, &pCData->data);
8074 return S_OK;
8077 /* ITypeInfo2::GetImplCustData
8079 * Gets the custom data
8081 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
8082 ITypeInfo2 * iface,
8083 UINT index,
8084 REFGUID guid,
8085 VARIANT *pVarVal)
8087 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8088 TLBCustData *pCData;
8089 TLBImplType *pRDesc = &This->impltypes[index];
8091 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8093 if(index >= This->cImplTypes)
8094 return TYPE_E_ELEMENTNOTFOUND;
8096 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
8097 if(!pCData)
8098 return TYPE_E_ELEMENTNOTFOUND;
8100 VariantInit(pVarVal);
8101 VariantCopy(pVarVal, &pCData->data);
8103 return S_OK;
8106 /* ITypeInfo2::GetDocumentation2
8108 * Retrieves the documentation string, the complete Help file name and path,
8109 * the localization context to use, and the context ID for the library Help
8110 * topic in the Help file.
8113 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
8114 ITypeInfo2 * iface,
8115 MEMBERID memid,
8116 LCID lcid,
8117 BSTR *pbstrHelpString,
8118 DWORD *pdwHelpStringContext,
8119 BSTR *pbstrHelpStringDll)
8121 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8122 const TLBFuncDesc *pFDesc;
8123 const TLBVarDesc *pVDesc;
8124 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8125 "HelpStringContext(%p) HelpStringDll(%p)\n",
8126 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
8127 pbstrHelpStringDll );
8128 /* the help string should be obtained from the helpstringdll,
8129 * using the _DLLGetDocumentation function, based on the supplied
8130 * lcid. Nice to do sometime...
8132 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
8133 if(pbstrHelpString)
8134 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->Name));
8135 if(pdwHelpStringContext)
8136 *pdwHelpStringContext=This->dwHelpStringContext;
8137 if(pbstrHelpStringDll)
8138 *pbstrHelpStringDll=
8139 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8140 return S_OK;
8141 }else {/* for a member */
8142 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
8143 if(pFDesc){
8144 if(pbstrHelpString)
8145 *pbstrHelpString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
8146 if(pdwHelpStringContext)
8147 *pdwHelpStringContext=pFDesc->HelpStringContext;
8148 if(pbstrHelpStringDll)
8149 *pbstrHelpStringDll=
8150 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8151 return S_OK;
8153 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
8154 if(pVDesc){
8155 if(pbstrHelpString)
8156 *pbstrHelpString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
8157 if(pdwHelpStringContext)
8158 *pdwHelpStringContext=pVDesc->HelpStringContext;
8159 if(pbstrHelpStringDll)
8160 *pbstrHelpStringDll=
8161 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8162 return S_OK;
8165 return TYPE_E_ELEMENTNOTFOUND;
8168 /* ITypeInfo2::GetAllCustData
8170 * Gets all custom data items for the Type info.
8173 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
8174 ITypeInfo2 * iface,
8175 CUSTDATA *pCustData)
8177 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8179 TRACE("%p %p\n", This, pCustData);
8181 return TLB_copy_all_custdata(This->pcustdata_list, pCustData);
8184 /* ITypeInfo2::GetAllFuncCustData
8186 * Gets all custom data items for the specified Function
8189 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
8190 ITypeInfo2 * iface,
8191 UINT index,
8192 CUSTDATA *pCustData)
8194 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8195 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8197 TRACE("%p %u %p\n", This, index, pCustData);
8199 if(index >= This->cFuncs)
8200 return TYPE_E_ELEMENTNOTFOUND;
8202 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
8205 /* ITypeInfo2::GetAllParamCustData
8207 * Gets all custom data items for the Functions
8210 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
8211 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
8213 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8214 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8216 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
8218 if(indexFunc >= This->cFuncs)
8219 return TYPE_E_ELEMENTNOTFOUND;
8221 if(indexParam >= pFDesc->funcdesc.cParams)
8222 return TYPE_E_ELEMENTNOTFOUND;
8224 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
8227 /* ITypeInfo2::GetAllVarCustData
8229 * Gets all custom data items for the specified Variable
8232 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
8233 UINT index, CUSTDATA *pCustData)
8235 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8236 TLBVarDesc * pVDesc = &This->vardescs[index];
8238 TRACE("%p %u %p\n", This, index, pCustData);
8240 if(index >= This->cVars)
8241 return TYPE_E_ELEMENTNOTFOUND;
8243 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
8246 /* ITypeInfo2::GetAllImplCustData
8248 * Gets all custom data items for the specified implementation type
8251 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
8252 ITypeInfo2 * iface,
8253 UINT index,
8254 CUSTDATA *pCustData)
8256 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8257 TLBImplType *pRDesc = &This->impltypes[index];
8259 TRACE("%p %u %p\n", This, index, pCustData);
8261 if(index >= This->cImplTypes)
8262 return TYPE_E_ELEMENTNOTFOUND;
8264 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
8267 static const ITypeInfo2Vtbl tinfvt =
8270 ITypeInfo_fnQueryInterface,
8271 ITypeInfo_fnAddRef,
8272 ITypeInfo_fnRelease,
8274 ITypeInfo_fnGetTypeAttr,
8275 ITypeInfo_fnGetTypeComp,
8276 ITypeInfo_fnGetFuncDesc,
8277 ITypeInfo_fnGetVarDesc,
8278 ITypeInfo_fnGetNames,
8279 ITypeInfo_fnGetRefTypeOfImplType,
8280 ITypeInfo_fnGetImplTypeFlags,
8281 ITypeInfo_fnGetIDsOfNames,
8282 ITypeInfo_fnInvoke,
8283 ITypeInfo_fnGetDocumentation,
8284 ITypeInfo_fnGetDllEntry,
8285 ITypeInfo_fnGetRefTypeInfo,
8286 ITypeInfo_fnAddressOfMember,
8287 ITypeInfo_fnCreateInstance,
8288 ITypeInfo_fnGetMops,
8289 ITypeInfo_fnGetContainingTypeLib,
8290 ITypeInfo_fnReleaseTypeAttr,
8291 ITypeInfo_fnReleaseFuncDesc,
8292 ITypeInfo_fnReleaseVarDesc,
8294 ITypeInfo2_fnGetTypeKind,
8295 ITypeInfo2_fnGetTypeFlags,
8296 ITypeInfo2_fnGetFuncIndexOfMemId,
8297 ITypeInfo2_fnGetVarIndexOfMemId,
8298 ITypeInfo2_fnGetCustData,
8299 ITypeInfo2_fnGetFuncCustData,
8300 ITypeInfo2_fnGetParamCustData,
8301 ITypeInfo2_fnGetVarCustData,
8302 ITypeInfo2_fnGetImplTypeCustData,
8303 ITypeInfo2_fnGetDocumentation2,
8304 ITypeInfo2_fnGetAllCustData,
8305 ITypeInfo2_fnGetAllFuncCustData,
8306 ITypeInfo2_fnGetAllParamCustData,
8307 ITypeInfo2_fnGetAllVarCustData,
8308 ITypeInfo2_fnGetAllImplTypeCustData,
8311 /******************************************************************************
8312 * CreateDispTypeInfo [OLEAUT32.31]
8314 * Build type information for an object so it can be called through an
8315 * IDispatch interface.
8317 * RETURNS
8318 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8319 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8321 * NOTES
8322 * This call allows an objects methods to be accessed through IDispatch, by
8323 * building an ITypeInfo object that IDispatch can use to call through.
8325 HRESULT WINAPI CreateDispTypeInfo(
8326 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
8327 LCID lcid, /* [I] Locale Id */
8328 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
8330 ITypeInfoImpl *pTIClass, *pTIIface;
8331 ITypeLibImpl *pTypeLibImpl;
8332 unsigned int param, func;
8333 TLBFuncDesc *pFuncDesc;
8334 TLBRefType *ref;
8336 TRACE("\n");
8337 pTypeLibImpl = TypeLibImpl_Constructor();
8338 if (!pTypeLibImpl) return E_FAIL;
8340 pTypeLibImpl->TypeInfoCount = 2;
8341 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
8343 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
8344 pTIIface->pTypeLib = pTypeLibImpl;
8345 pTIIface->index = 0;
8346 pTIIface->Name = NULL;
8347 pTIIface->dwHelpContext = -1;
8348 pTIIface->guid = NULL;
8349 pTIIface->lcid = lcid;
8350 pTIIface->typekind = TKIND_INTERFACE;
8351 pTIIface->wMajorVerNum = 0;
8352 pTIIface->wMinorVerNum = 0;
8353 pTIIface->cbAlignment = 2;
8354 pTIIface->cbSizeInstance = -1;
8355 pTIIface->cbSizeVft = -1;
8356 pTIIface->cFuncs = 0;
8357 pTIIface->cImplTypes = 0;
8358 pTIIface->cVars = 0;
8359 pTIIface->wTypeFlags = 0;
8360 pTIIface->hreftype = 0;
8362 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers);
8363 pFuncDesc = pTIIface->funcdescs;
8364 for(func = 0; func < pidata->cMembers; func++) {
8365 METHODDATA *md = pidata->pmethdata + func;
8366 pFuncDesc->Name = TLB_append_str(&pTypeLibImpl->name_list, md->szName);
8367 pFuncDesc->funcdesc.memid = md->dispid;
8368 pFuncDesc->funcdesc.lprgscode = NULL;
8369 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
8370 pFuncDesc->funcdesc.invkind = md->wFlags;
8371 pFuncDesc->funcdesc.callconv = md->cc;
8372 pFuncDesc->funcdesc.cParams = md->cArgs;
8373 pFuncDesc->funcdesc.cParamsOpt = 0;
8374 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
8375 pFuncDesc->funcdesc.cScodes = 0;
8376 pFuncDesc->funcdesc.wFuncFlags = 0;
8377 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
8378 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
8379 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
8380 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8381 md->cArgs * sizeof(ELEMDESC));
8382 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
8383 for(param = 0; param < md->cArgs; param++) {
8384 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
8385 pFuncDesc->pParamDesc[param].Name = TLB_append_str(&pTypeLibImpl->name_list, md->ppdata[param].szName);
8387 pFuncDesc->helpcontext = 0;
8388 pFuncDesc->HelpStringContext = 0;
8389 pFuncDesc->HelpString = NULL;
8390 pFuncDesc->Entry = NULL;
8391 list_init(&pFuncDesc->custdata_list);
8392 pTIIface->cFuncs++;
8393 ++pFuncDesc;
8396 dump_TypeInfo(pTIIface);
8398 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
8399 pTIClass->pTypeLib = pTypeLibImpl;
8400 pTIClass->index = 1;
8401 pTIClass->Name = NULL;
8402 pTIClass->dwHelpContext = -1;
8403 pTIClass->guid = NULL;
8404 pTIClass->lcid = lcid;
8405 pTIClass->typekind = TKIND_COCLASS;
8406 pTIClass->wMajorVerNum = 0;
8407 pTIClass->wMinorVerNum = 0;
8408 pTIClass->cbAlignment = 2;
8409 pTIClass->cbSizeInstance = -1;
8410 pTIClass->cbSizeVft = -1;
8411 pTIClass->cFuncs = 0;
8412 pTIClass->cImplTypes = 1;
8413 pTIClass->cVars = 0;
8414 pTIClass->wTypeFlags = 0;
8415 pTIClass->hreftype = sizeof(MSFT_TypeInfoBase);
8417 pTIClass->impltypes = TLBImplType_Alloc(1);
8419 ref = heap_alloc_zero(sizeof(*ref));
8420 ref->pImpTLInfo = TLB_REF_INTERNAL;
8421 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
8423 dump_TypeInfo(pTIClass);
8425 *pptinfo = (ITypeInfo *)&pTIClass->ITypeInfo2_iface;
8427 ITypeInfo_AddRef(*pptinfo);
8428 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
8430 return S_OK;
8434 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
8436 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8438 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, ppv);
8441 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
8443 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8445 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
8448 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
8450 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8452 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
8455 static HRESULT WINAPI ITypeComp_fnBind(
8456 ITypeComp * iface,
8457 OLECHAR * szName,
8458 ULONG lHash,
8459 WORD wFlags,
8460 ITypeInfo ** ppTInfo,
8461 DESCKIND * pDescKind,
8462 BINDPTR * pBindPtr)
8464 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8465 const TLBFuncDesc *pFDesc;
8466 const TLBVarDesc *pVDesc;
8467 HRESULT hr = DISP_E_MEMBERNOTFOUND;
8468 UINT fdc;
8470 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8472 *pDescKind = DESCKIND_NONE;
8473 pBindPtr->lpfuncdesc = NULL;
8474 *ppTInfo = NULL;
8476 for(fdc = 0; fdc < This->cFuncs; ++fdc){
8477 pFDesc = &This->funcdescs[fdc];
8478 if (!lstrcmpiW(TLB_get_bstr(pFDesc->Name), szName)) {
8479 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
8480 break;
8481 else
8482 /* name found, but wrong flags */
8483 hr = TYPE_E_TYPEMISMATCH;
8487 if (fdc < This->cFuncs)
8489 HRESULT hr = TLB_AllocAndInitFuncDesc(
8490 &pFDesc->funcdesc,
8491 &pBindPtr->lpfuncdesc,
8492 This->typekind == TKIND_DISPATCH);
8493 if (FAILED(hr))
8494 return hr;
8495 *pDescKind = DESCKIND_FUNCDESC;
8496 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8497 ITypeInfo_AddRef(*ppTInfo);
8498 return S_OK;
8499 } else {
8500 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->cVars, szName);
8501 if(pVDesc){
8502 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
8503 if (FAILED(hr))
8504 return hr;
8505 *pDescKind = DESCKIND_VARDESC;
8506 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8507 ITypeInfo_AddRef(*ppTInfo);
8508 return S_OK;
8512 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
8513 /* recursive search */
8514 ITypeInfo *pTInfo;
8515 ITypeComp *pTComp;
8516 HRESULT hr;
8517 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
8518 if (SUCCEEDED(hr))
8520 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
8521 ITypeInfo_Release(pTInfo);
8523 if (SUCCEEDED(hr))
8525 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8526 ITypeComp_Release(pTComp);
8527 if (SUCCEEDED(hr) && *pDescKind == DESCKIND_FUNCDESC &&
8528 This->typekind == TKIND_DISPATCH)
8530 FUNCDESC *tmp = pBindPtr->lpfuncdesc;
8531 hr = TLB_AllocAndInitFuncDesc(tmp, &pBindPtr->lpfuncdesc, TRUE);
8532 SysFreeString((BSTR)tmp);
8534 return hr;
8536 WARN("Could not search inherited interface!\n");
8538 if (hr == DISP_E_MEMBERNOTFOUND)
8539 hr = S_OK;
8540 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
8541 return hr;
8544 static HRESULT WINAPI ITypeComp_fnBindType(
8545 ITypeComp * iface,
8546 OLECHAR * szName,
8547 ULONG lHash,
8548 ITypeInfo ** ppTInfo,
8549 ITypeComp ** ppTComp)
8551 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
8553 /* strange behaviour (does nothing) but like the
8554 * original */
8556 if (!ppTInfo || !ppTComp)
8557 return E_POINTER;
8559 *ppTInfo = NULL;
8560 *ppTComp = NULL;
8562 return S_OK;
8565 static const ITypeCompVtbl tcompvt =
8568 ITypeComp_fnQueryInterface,
8569 ITypeComp_fnAddRef,
8570 ITypeComp_fnRelease,
8572 ITypeComp_fnBind,
8573 ITypeComp_fnBindType
8576 HRESULT WINAPI CreateTypeLib2(SYSKIND syskind, LPCOLESTR szFile,
8577 ICreateTypeLib2** ppctlib)
8579 ITypeLibImpl *This;
8580 HRESULT hres;
8582 TRACE("(%d,%s,%p)\n", syskind, debugstr_w(szFile), ppctlib);
8584 if (!szFile) return E_INVALIDARG;
8586 This = TypeLibImpl_Constructor();
8587 if (!This)
8588 return E_OUTOFMEMORY;
8590 This->lcid = GetSystemDefaultLCID();
8591 This->syskind = syskind;
8592 This->ptr_size = get_ptr_size(syskind);
8594 This->path = heap_alloc((lstrlenW(szFile) + 1) * sizeof(WCHAR));
8595 if (!This->path) {
8596 ITypeLib2_Release(&This->ITypeLib2_iface);
8597 return E_OUTOFMEMORY;
8599 lstrcpyW(This->path, szFile);
8601 hres = ITypeLib2_QueryInterface(&This->ITypeLib2_iface, &IID_ICreateTypeLib2, (LPVOID*)ppctlib);
8602 ITypeLib2_Release(&This->ITypeLib2_iface);
8603 return hres;
8606 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
8607 REFIID riid, void **object)
8609 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8611 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, object);
8614 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
8616 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8618 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
8621 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
8623 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8625 return ITypeLib2_Release(&This->ITypeLib2_iface);
8628 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
8629 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
8631 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8632 ITypeInfoImpl *info;
8633 HRESULT hres;
8635 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo);
8637 if (!ctinfo || !name)
8638 return E_INVALIDARG;
8640 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, name);
8641 if (info)
8642 return TYPE_E_NAMECONFLICT;
8644 if (This->typeinfos)
8645 This->typeinfos = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->typeinfos,
8646 sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1));
8647 else
8648 This->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*));
8650 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor();
8652 info->pTypeLib = This;
8653 info->Name = TLB_append_str(&This->name_list, name);
8654 info->index = This->TypeInfoCount;
8655 info->typekind = kind;
8656 info->cbAlignment = 4;
8658 switch(info->typekind) {
8659 case TKIND_ENUM:
8660 case TKIND_INTERFACE:
8661 case TKIND_DISPATCH:
8662 case TKIND_COCLASS:
8663 info->cbSizeInstance = This->ptr_size;
8664 break;
8665 case TKIND_RECORD:
8666 case TKIND_UNION:
8667 info->cbSizeInstance = 0;
8668 break;
8669 case TKIND_MODULE:
8670 info->cbSizeInstance = 2;
8671 break;
8672 case TKIND_ALIAS:
8673 info->cbSizeInstance = -0x75;
8674 break;
8675 default:
8676 FIXME("unrecognized typekind %d\n", info->typekind);
8677 info->cbSizeInstance = 0xdeadbeef;
8678 break;
8681 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface,
8682 &IID_ICreateTypeInfo, (void **)ctinfo);
8683 if (FAILED(hres)) {
8684 ITypeInfo2_Release(&info->ITypeInfo2_iface);
8685 return hres;
8688 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase);
8690 ++This->TypeInfoCount;
8692 return S_OK;
8695 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
8696 LPOLESTR name)
8698 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8700 TRACE("%p %s\n", This, wine_dbgstr_w(name));
8702 if (!name)
8703 return E_INVALIDARG;
8705 This->Name = TLB_append_str(&This->name_list, name);
8707 return S_OK;
8710 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
8711 WORD majorVerNum, WORD minorVerNum)
8713 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8715 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
8717 This->ver_major = majorVerNum;
8718 This->ver_minor = minorVerNum;
8720 return S_OK;
8723 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
8724 REFGUID guid)
8726 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8728 TRACE("%p %s\n", This, debugstr_guid(guid));
8730 This->guid = TLB_append_guid(&This->guid_list, guid, -2);
8732 return S_OK;
8735 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
8736 LPOLESTR doc)
8738 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8740 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
8742 if (!doc)
8743 return E_INVALIDARG;
8745 This->DocString = TLB_append_str(&This->string_list, doc);
8747 return S_OK;
8750 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
8751 LPOLESTR helpFileName)
8753 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8755 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
8757 if (!helpFileName)
8758 return E_INVALIDARG;
8760 This->HelpFile = TLB_append_str(&This->string_list, helpFileName);
8762 return S_OK;
8765 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
8766 DWORD helpContext)
8768 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8770 TRACE("%p %d\n", This, helpContext);
8772 This->dwHelpContext = helpContext;
8774 return S_OK;
8777 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
8778 LCID lcid)
8780 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8782 TRACE("%p %x\n", This, lcid);
8784 This->set_lcid = lcid;
8786 return S_OK;
8789 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
8790 UINT libFlags)
8792 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8794 TRACE("%p %x\n", This, libFlags);
8796 This->libflags = libFlags;
8798 return S_OK;
8801 typedef struct tagWMSFT_SegContents {
8802 DWORD len;
8803 void *data;
8804 } WMSFT_SegContents;
8806 typedef struct tagWMSFT_TLBFile {
8807 MSFT_Header header;
8808 WMSFT_SegContents typeinfo_seg;
8809 WMSFT_SegContents impfile_seg;
8810 WMSFT_SegContents impinfo_seg;
8811 WMSFT_SegContents ref_seg;
8812 WMSFT_SegContents guidhash_seg;
8813 WMSFT_SegContents guid_seg;
8814 WMSFT_SegContents namehash_seg;
8815 WMSFT_SegContents name_seg;
8816 WMSFT_SegContents string_seg;
8817 WMSFT_SegContents typdesc_seg;
8818 WMSFT_SegContents arraydesc_seg;
8819 WMSFT_SegContents custdata_seg;
8820 WMSFT_SegContents cdguids_seg;
8821 MSFT_SegDir segdir;
8822 WMSFT_SegContents aux_seg;
8823 } WMSFT_TLBFile;
8825 static HRESULT WMSFT_compile_strings(ITypeLibImpl *This,
8826 WMSFT_TLBFile *file)
8828 TLBString *str;
8829 UINT last_offs;
8830 char *data;
8832 file->string_seg.len = 0;
8833 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8834 int size;
8836 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str), NULL, 0, NULL, NULL);
8837 if (size == 0)
8838 return E_UNEXPECTED;
8840 size += sizeof(INT16);
8841 if (size % 4)
8842 size = (size + 4) & ~0x3;
8843 if (size < 8)
8844 size = 8;
8846 file->string_seg.len += size;
8848 /* temporarily use str->offset to store the length of the aligned,
8849 * converted string */
8850 str->offset = size;
8853 file->string_seg.data = data = heap_alloc(file->string_seg.len);
8855 last_offs = 0;
8856 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8857 int size;
8859 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8860 data + sizeof(INT16), file->string_seg.len - last_offs - sizeof(INT16), NULL, NULL);
8861 if (size == 0) {
8862 heap_free(file->string_seg.data);
8863 return E_UNEXPECTED;
8866 *((INT16*)data) = size;
8868 memset(data + sizeof(INT16) + size, 0x57, str->offset - size - sizeof(INT16));
8870 size = str->offset;
8871 data += size;
8872 str->offset = last_offs;
8873 last_offs += size;
8876 return S_OK;
8879 static HRESULT WMSFT_compile_names(ITypeLibImpl *This,
8880 WMSFT_TLBFile *file)
8882 TLBString *str;
8883 UINT last_offs;
8884 char *data;
8885 MSFT_NameIntro *last_intro = NULL;
8887 file->header.nametablecount = 0;
8888 file->header.nametablechars = 0;
8890 file->name_seg.len = 0;
8891 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8892 int size;
8894 size = strlenW(str->str);
8895 file->header.nametablechars += size;
8896 file->header.nametablecount++;
8898 size = WideCharToMultiByte(CP_ACP, 0, str->str, size, NULL, 0, NULL, NULL);
8899 if (size == 0)
8900 return E_UNEXPECTED;
8902 size += sizeof(MSFT_NameIntro);
8903 if (size % 4)
8904 size = (size + 4) & ~0x3;
8905 if (size < 8)
8906 size = 8;
8908 file->name_seg.len += size;
8910 /* temporarily use str->offset to store the length of the aligned,
8911 * converted string */
8912 str->offset = size;
8915 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
8916 file->name_seg.data = data = heap_alloc(file->name_seg.len+1);
8918 last_offs = 0;
8919 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8920 int size, hash;
8921 MSFT_NameIntro *intro = (MSFT_NameIntro*)data;
8923 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8924 data + sizeof(MSFT_NameIntro),
8925 file->name_seg.len - last_offs - sizeof(MSFT_NameIntro), NULL, NULL);
8926 if (size == 0) {
8927 heap_free(file->name_seg.data);
8928 return E_UNEXPECTED;
8930 data[sizeof(MSFT_NameIntro) + size] = '\0';
8932 intro->hreftype = -1; /* TODO? */
8933 intro->namelen = size & 0xFF;
8934 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
8935 hash = LHashValOfNameSysA(This->syskind, This->lcid, data + sizeof(MSFT_NameIntro));
8936 intro->namelen |= hash << 16;
8937 intro->next_hash = ((DWORD*)file->namehash_seg.data)[hash & 0x7f];
8938 ((DWORD*)file->namehash_seg.data)[hash & 0x7f] = last_offs;
8940 memset(data + sizeof(MSFT_NameIntro) + size, 0x57,
8941 str->offset - size - sizeof(MSFT_NameIntro));
8943 /* update str->offset to actual value to use in other
8944 * compilation functions that require positions within
8945 * the string table */
8946 last_intro = intro;
8947 size = str->offset;
8948 data += size;
8949 str->offset = last_offs;
8950 last_offs += size;
8953 if(last_intro)
8954 last_intro->hreftype = 0; /* last one is 0? */
8956 return S_OK;
8959 static inline int hash_guid(GUID *guid)
8961 int i, hash = 0;
8963 for (i = 0; i < 8; i ++)
8964 hash ^= ((const short *)guid)[i];
8966 return hash & 0x1f;
8969 static HRESULT WMSFT_compile_guids(ITypeLibImpl *This, WMSFT_TLBFile *file)
8971 TLBGuid *guid;
8972 MSFT_GuidEntry *entry;
8973 DWORD offs;
8974 int hash_key, *guidhashtab;
8976 file->guid_seg.len = sizeof(MSFT_GuidEntry) * list_count(&This->guid_list);
8977 file->guid_seg.data = heap_alloc(file->guid_seg.len);
8979 entry = file->guid_seg.data;
8980 offs = 0;
8981 guidhashtab = file->guidhash_seg.data;
8982 LIST_FOR_EACH_ENTRY(guid, &This->guid_list, TLBGuid, entry){
8983 memcpy(&entry->guid, &guid->guid, sizeof(GUID));
8984 entry->hreftype = guid->hreftype;
8986 hash_key = hash_guid(&guid->guid);
8987 entry->next_hash = guidhashtab[hash_key];
8988 guidhashtab[hash_key] = offs;
8990 guid->offset = offs;
8991 offs += sizeof(MSFT_GuidEntry);
8992 ++entry;
8995 return S_OK;
8998 static DWORD WMSFT_encode_variant(VARIANT *value, WMSFT_TLBFile *file)
9000 VARIANT v = *value;
9001 VARTYPE arg_type = V_VT(value);
9002 int mask = 0;
9003 HRESULT hres;
9004 DWORD ret = file->custdata_seg.len;
9006 if(arg_type == VT_INT)
9007 arg_type = VT_I4;
9008 if(arg_type == VT_UINT)
9009 arg_type = VT_UI4;
9011 v = *value;
9012 if(V_VT(value) != arg_type) {
9013 hres = VariantChangeType(&v, value, 0, arg_type);
9014 if(FAILED(hres)){
9015 ERR("VariantChangeType failed: %08x\n", hres);
9016 return -1;
9020 /* Check if default value can be stored in-place */
9021 switch(arg_type){
9022 case VT_I4:
9023 case VT_UI4:
9024 mask = 0x3ffffff;
9025 if(V_UI4(&v) > 0x3ffffff)
9026 break;
9027 /* fall through */
9028 case VT_I1:
9029 case VT_UI1:
9030 case VT_BOOL:
9031 if(!mask)
9032 mask = 0xff;
9033 /* fall through */
9034 case VT_I2:
9035 case VT_UI2:
9036 if(!mask)
9037 mask = 0xffff;
9038 return ((0x80 + 0x4 * V_VT(value)) << 24) | (V_UI4(&v) & mask);
9041 /* have to allocate space in custdata_seg */
9042 switch(arg_type) {
9043 case VT_I4:
9044 case VT_R4:
9045 case VT_UI4:
9046 case VT_INT:
9047 case VT_UINT:
9048 case VT_HRESULT:
9049 case VT_PTR: {
9050 /* Construct the data to be allocated */
9051 int *data;
9053 if(file->custdata_seg.data){
9054 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + sizeof(int) * 2);
9055 data = (int *)(((char *)file->custdata_seg.data) + file->custdata_seg.len);
9056 file->custdata_seg.len += sizeof(int) * 2;
9057 }else{
9058 file->custdata_seg.len = sizeof(int) * 2;
9059 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9062 data[0] = V_VT(value) + (V_UI4(&v) << 16);
9063 data[1] = (V_UI4(&v) >> 16) + 0x57570000;
9065 /* TODO: Check if the encoded data is already present in custdata_seg */
9067 return ret;
9070 case VT_BSTR: {
9071 int i, len = (6+SysStringLen(V_BSTR(&v))+3) & ~0x3;
9072 char *data;
9074 if(file->custdata_seg.data){
9075 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + len);
9076 data = ((char *)file->custdata_seg.data) + file->custdata_seg.len;
9077 file->custdata_seg.len += len;
9078 }else{
9079 file->custdata_seg.len = len;
9080 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9083 *((unsigned short *)data) = V_VT(value);
9084 *((unsigned int *)(data+2)) = SysStringLen(V_BSTR(&v));
9085 for(i=0; i<SysStringLen(V_BSTR(&v)); i++) {
9086 if(V_BSTR(&v)[i] <= 0x7f)
9087 data[i+6] = V_BSTR(&v)[i];
9088 else
9089 data[i+6] = '?';
9091 WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], len-6, NULL, NULL);
9092 for(i=6+SysStringLen(V_BSTR(&v)); i<len; i++)
9093 data[i] = 0x57;
9095 /* TODO: Check if the encoded data is already present in custdata_seg */
9097 return ret;
9099 default:
9100 FIXME("Argument type not yet handled\n");
9101 return -1;
9105 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size);
9107 static DWORD WMSFT_append_arraydesc(ARRAYDESC *desc, WMSFT_TLBFile *file)
9109 DWORD offs = file->arraydesc_seg.len;
9110 DWORD *encoded;
9111 USHORT i;
9113 /* TODO: we should check for duplicates, but that's harder because each
9114 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9115 * at the library-level) */
9117 file->arraydesc_seg.len += (2 + desc->cDims * 2) * sizeof(DWORD);
9118 if(!file->arraydesc_seg.data)
9119 file->arraydesc_seg.data = heap_alloc(file->arraydesc_seg.len);
9120 else
9121 file->arraydesc_seg.data = heap_realloc(file->arraydesc_seg.data, file->arraydesc_seg.len);
9122 encoded = (DWORD*)((char *)file->arraydesc_seg.data) + offs;
9124 encoded[0] = WMSFT_append_typedesc(&desc->tdescElem, file, NULL, NULL);
9125 encoded[1] = desc->cDims | ((desc->cDims * 2 * sizeof(DWORD)) << 16);
9126 for(i = 0; i < desc->cDims; ++i){
9127 encoded[2 + i * 2] = desc->rgbounds[i].cElements;
9128 encoded[2 + i * 2 + 1] = desc->rgbounds[i].lLbound;
9131 return offs;
9134 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size)
9136 DWORD junk;
9137 INT16 junk2;
9138 DWORD offs = 0;
9139 DWORD encoded[2];
9140 VARTYPE vt, subtype;
9141 char *data;
9143 if(!desc)
9144 return -1;
9146 if(!out_mix)
9147 out_mix = &junk;
9148 if(!out_size)
9149 out_size = &junk2;
9151 vt = desc->vt & VT_TYPEMASK;
9153 if(vt == VT_PTR || vt == VT_SAFEARRAY){
9154 DWORD mix;
9155 encoded[1] = WMSFT_append_typedesc(desc->u.lptdesc, file, &mix, out_size);
9156 encoded[0] = desc->vt | ((mix | VT_BYREF) << 16);
9157 *out_mix = 0x7FFF;
9158 *out_size += 2 * sizeof(DWORD);
9159 }else if(vt == VT_CARRAY){
9160 encoded[0] = desc->vt | (0x7FFE << 16);
9161 encoded[1] = WMSFT_append_arraydesc(desc->u.lpadesc, file);
9162 *out_mix = 0x7FFE;
9163 }else if(vt == VT_USERDEFINED){
9164 encoded[0] = desc->vt | (0x7FFF << 16);
9165 encoded[1] = desc->u.hreftype;
9166 *out_mix = 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9167 }else{
9168 TRACE("Mixing in-place, VT: 0x%x\n", desc->vt);
9170 switch(vt){
9171 case VT_INT:
9172 subtype = VT_I4;
9173 break;
9174 case VT_UINT:
9175 subtype = VT_UI4;
9176 break;
9177 case VT_VOID:
9178 subtype = VT_EMPTY;
9179 break;
9180 default:
9181 subtype = vt;
9182 break;
9185 *out_mix = subtype;
9186 return 0x80000000 | (subtype << 16) | desc->vt;
9189 data = file->typdesc_seg.data;
9190 while(offs < file->typdesc_seg.len){
9191 if(!memcmp(&data[offs], encoded, sizeof(encoded)))
9192 return offs;
9193 offs += sizeof(encoded);
9196 file->typdesc_seg.len += sizeof(encoded);
9197 if(!file->typdesc_seg.data)
9198 data = file->typdesc_seg.data = heap_alloc(file->typdesc_seg.len);
9199 else
9200 data = file->typdesc_seg.data = heap_realloc(file->typdesc_seg.data, file->typdesc_seg.len);
9202 memcpy(&data[offs], encoded, sizeof(encoded));
9204 return offs;
9207 static DWORD WMSFT_compile_custdata(struct list *custdata_list, WMSFT_TLBFile *file)
9209 WMSFT_SegContents *cdguids_seg = &file->cdguids_seg;
9210 DWORD ret = cdguids_seg->len, offs;
9211 MSFT_CDGuid *cdguid = cdguids_seg->data;
9212 TLBCustData *cd;
9214 if(list_empty(custdata_list))
9215 return -1;
9217 cdguids_seg->len += sizeof(MSFT_CDGuid) * list_count(custdata_list);
9218 if(!cdguids_seg->data){
9219 cdguid = cdguids_seg->data = heap_alloc(cdguids_seg->len);
9220 }else
9221 cdguids_seg->data = heap_realloc(cdguids_seg->data, cdguids_seg->len);
9223 offs = ret + sizeof(MSFT_CDGuid);
9224 LIST_FOR_EACH_ENTRY(cd, custdata_list, TLBCustData, entry){
9225 cdguid->GuidOffset = cd->guid->offset;
9226 cdguid->DataOffset = WMSFT_encode_variant(&cd->data, file);
9227 cdguid->next = offs;
9228 offs += sizeof(MSFT_CDGuid);
9229 ++cdguid;
9232 --cdguid;
9233 cdguid->next = -1;
9235 return ret;
9238 static DWORD WMSFT_compile_typeinfo_aux(ITypeInfoImpl *info,
9239 WMSFT_TLBFile *file)
9241 WMSFT_SegContents *aux_seg = &file->aux_seg;
9242 DWORD ret = aux_seg->len, i, j, recorded_size = 0, extra_size = 0;
9243 MSFT_VarRecord *varrecord;
9244 MSFT_FuncRecord *funcrecord;
9245 MEMBERID *memid;
9246 DWORD *name, *offsets, offs;
9248 for(i = 0; i < info->cFuncs; ++i){
9249 TLBFuncDesc *desc = &info->funcdescs[i];
9251 recorded_size += 6 * sizeof(INT); /* mandatory fields */
9253 /* optional fields */
9254 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9255 if(!list_empty(&desc->custdata_list))
9256 recorded_size += 7 * sizeof(INT);
9257 else if(desc->HelpStringContext != 0)
9258 recorded_size += 6 * sizeof(INT);
9259 /* res9? resA? */
9260 else if(desc->Entry)
9261 recorded_size += 3 * sizeof(INT);
9262 else if(desc->HelpString)
9263 recorded_size += 2 * sizeof(INT);
9264 else if(desc->helpcontext)
9265 recorded_size += sizeof(INT);
9267 recorded_size += desc->funcdesc.cParams * sizeof(MSFT_ParameterInfo);
9269 for(j = 0; j < desc->funcdesc.cParams; ++j){
9270 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9271 recorded_size += desc->funcdesc.cParams * sizeof(INT);
9272 break;
9276 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9279 for(i = 0; i < info->cVars; ++i){
9280 TLBVarDesc *desc = &info->vardescs[i];
9282 recorded_size += 5 * sizeof(INT); /* mandatory fields */
9284 /* optional fields */
9285 if(desc->HelpStringContext != 0)
9286 recorded_size += 5 * sizeof(INT);
9287 else if(!list_empty(&desc->custdata_list))
9288 recorded_size += 4 * sizeof(INT);
9289 /* res9? */
9290 else if(desc->HelpString)
9291 recorded_size += 2 * sizeof(INT);
9292 else if(desc->HelpContext != 0)
9293 recorded_size += sizeof(INT);
9295 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9298 if(!recorded_size && !extra_size)
9299 return ret;
9301 extra_size += sizeof(INT); /* total aux size for this typeinfo */
9303 aux_seg->len += recorded_size + extra_size;
9305 aux_seg->len += sizeof(INT) * (info->cVars + info->cFuncs); /* offsets at the end */
9307 if(aux_seg->data)
9308 aux_seg->data = heap_realloc(aux_seg->data, aux_seg->len);
9309 else
9310 aux_seg->data = heap_alloc(aux_seg->len);
9312 *((DWORD*)((char *)aux_seg->data + ret)) = recorded_size;
9314 offsets = (DWORD*)((char *)aux_seg->data + ret + recorded_size + extra_size);
9315 offs = 0;
9317 funcrecord = (MSFT_FuncRecord*)(((char *)aux_seg->data) + ret + sizeof(INT));
9318 for(i = 0; i < info->cFuncs; ++i){
9319 TLBFuncDesc *desc = &info->funcdescs[i];
9320 DWORD size = 6 * sizeof(INT), paramdefault_size = 0, *paramdefault;
9322 funcrecord->funcdescsize = sizeof(desc->funcdesc) + desc->funcdesc.cParams * sizeof(ELEMDESC);
9323 funcrecord->DataType = WMSFT_append_typedesc(&desc->funcdesc.elemdescFunc.tdesc, file, NULL, &funcrecord->funcdescsize);
9324 funcrecord->Flags = desc->funcdesc.wFuncFlags;
9325 funcrecord->VtableOffset = desc->funcdesc.oVft;
9327 /* FKCCIC:
9328 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9329 * ^^^funckind
9330 * ^^^ ^invkind
9331 * ^has_cust_data
9332 * ^^^^callconv
9333 * ^has_param_defaults
9334 * ^oEntry_is_intresource
9336 funcrecord->FKCCIC =
9337 desc->funcdesc.funckind |
9338 (desc->funcdesc.invkind << 3) |
9339 (list_empty(&desc->custdata_list) ? 0 : 0x80) |
9340 (desc->funcdesc.callconv << 8);
9342 if(desc->Entry && desc->Entry != (TLBString*)-1 && IS_INTRESOURCE(desc->Entry))
9343 funcrecord->FKCCIC |= 0x2000;
9345 for(j = 0; j < desc->funcdesc.cParams; ++j){
9346 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9347 paramdefault_size = sizeof(INT) * desc->funcdesc.cParams;
9348 funcrecord->funcdescsize += sizeof(PARAMDESCEX);
9351 if(paramdefault_size > 0)
9352 funcrecord->FKCCIC |= 0x1000;
9354 funcrecord->nrargs = desc->funcdesc.cParams;
9355 funcrecord->nroargs = desc->funcdesc.cParamsOpt;
9357 /* optional fields */
9358 /* res9? resA? */
9359 if(!list_empty(&desc->custdata_list)){
9360 size += 7 * sizeof(INT);
9361 funcrecord->HelpContext = desc->helpcontext;
9362 if(desc->HelpString)
9363 funcrecord->oHelpString = desc->HelpString->offset;
9364 else
9365 funcrecord->oHelpString = -1;
9366 if(!desc->Entry)
9367 funcrecord->oEntry = -1;
9368 else if(IS_INTRESOURCE(desc->Entry))
9369 funcrecord->oEntry = LOWORD(desc->Entry);
9370 else
9371 funcrecord->oEntry = desc->Entry->offset;
9372 funcrecord->res9 = -1;
9373 funcrecord->resA = -1;
9374 funcrecord->HelpStringContext = desc->HelpStringContext;
9375 funcrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9376 }else if(desc->HelpStringContext != 0){
9377 size += 6 * sizeof(INT);
9378 funcrecord->HelpContext = desc->helpcontext;
9379 if(desc->HelpString)
9380 funcrecord->oHelpString = desc->HelpString->offset;
9381 else
9382 funcrecord->oHelpString = -1;
9383 if(!desc->Entry)
9384 funcrecord->oEntry = -1;
9385 else if(IS_INTRESOURCE(desc->Entry))
9386 funcrecord->oEntry = LOWORD(desc->Entry);
9387 else
9388 funcrecord->oEntry = desc->Entry->offset;
9389 funcrecord->res9 = -1;
9390 funcrecord->resA = -1;
9391 funcrecord->HelpStringContext = desc->HelpStringContext;
9392 }else if(desc->Entry){
9393 size += 3 * sizeof(INT);
9394 funcrecord->HelpContext = desc->helpcontext;
9395 if(desc->HelpString)
9396 funcrecord->oHelpString = desc->HelpString->offset;
9397 else
9398 funcrecord->oHelpString = -1;
9399 if(!desc->Entry)
9400 funcrecord->oEntry = -1;
9401 else if(IS_INTRESOURCE(desc->Entry))
9402 funcrecord->oEntry = LOWORD(desc->Entry);
9403 else
9404 funcrecord->oEntry = desc->Entry->offset;
9405 }else if(desc->HelpString){
9406 size += 2 * sizeof(INT);
9407 funcrecord->HelpContext = desc->helpcontext;
9408 funcrecord->oHelpString = desc->HelpString->offset;
9409 }else if(desc->helpcontext){
9410 size += sizeof(INT);
9411 funcrecord->HelpContext = desc->helpcontext;
9414 paramdefault = (DWORD*)((char *)funcrecord + size);
9415 size += paramdefault_size;
9417 for(j = 0; j < desc->funcdesc.cParams; ++j){
9418 MSFT_ParameterInfo *info = (MSFT_ParameterInfo*)(((char *)funcrecord) + size);
9420 info->DataType = WMSFT_append_typedesc(&desc->funcdesc.lprgelemdescParam[j].tdesc, file, NULL, &funcrecord->funcdescsize);
9421 if(desc->pParamDesc[j].Name)
9422 info->oName = desc->pParamDesc[j].Name->offset;
9423 else
9424 info->oName = -1;
9425 info->Flags = desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags;
9427 if(paramdefault_size){
9428 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
9429 *paramdefault = WMSFT_encode_variant(&desc->funcdesc.lprgelemdescParam[j].u.paramdesc.pparamdescex->varDefaultValue, file);
9430 else if(paramdefault_size)
9431 *paramdefault = -1;
9432 ++paramdefault;
9435 size += sizeof(MSFT_ParameterInfo);
9438 funcrecord->Info = size | (i << 16); /* is it just the index? */
9440 *offsets = offs;
9441 offs += size;
9442 ++offsets;
9444 funcrecord = (MSFT_FuncRecord*)(((char*)funcrecord) + size);
9447 varrecord = (MSFT_VarRecord*)funcrecord;
9448 for(i = 0; i < info->cVars; ++i){
9449 TLBVarDesc *desc = &info->vardescs[i];
9450 DWORD size = 5 * sizeof(INT);
9452 varrecord->vardescsize = sizeof(desc->vardesc);
9453 varrecord->DataType = WMSFT_append_typedesc(&desc->vardesc.elemdescVar.tdesc, file, NULL, &varrecord->vardescsize);
9454 varrecord->Flags = desc->vardesc.wVarFlags;
9455 varrecord->VarKind = desc->vardesc.varkind;
9457 if(desc->vardesc.varkind == VAR_CONST){
9458 varrecord->vardescsize += sizeof(VARIANT);
9459 varrecord->OffsValue = WMSFT_encode_variant(desc->vardesc.u.lpvarValue, file);
9460 }else
9461 varrecord->OffsValue = desc->vardesc.u.oInst;
9463 /* res9? */
9464 if(desc->HelpStringContext != 0){
9465 size += 5 * sizeof(INT);
9466 varrecord->HelpContext = desc->HelpContext;
9467 if(desc->HelpString)
9468 varrecord->HelpString = desc->HelpString->offset;
9469 else
9470 varrecord->HelpString = -1;
9471 varrecord->res9 = -1;
9472 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9473 varrecord->HelpStringContext = desc->HelpStringContext;
9474 }else if(!list_empty(&desc->custdata_list)){
9475 size += 4 * sizeof(INT);
9476 varrecord->HelpContext = desc->HelpContext;
9477 if(desc->HelpString)
9478 varrecord->HelpString = desc->HelpString->offset;
9479 else
9480 varrecord->HelpString = -1;
9481 varrecord->res9 = -1;
9482 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9483 }else if(desc->HelpString){
9484 size += 2 * sizeof(INT);
9485 varrecord->HelpContext = desc->HelpContext;
9486 if(desc->HelpString)
9487 varrecord->HelpString = desc->HelpString->offset;
9488 else
9489 varrecord->HelpString = -1;
9490 }else if(desc->HelpContext != 0){
9491 size += sizeof(INT);
9492 varrecord->HelpContext = desc->HelpContext;
9495 varrecord->Info = size | (i << 16);
9497 *offsets = offs;
9498 offs += size;
9499 ++offsets;
9501 varrecord = (MSFT_VarRecord*)(((char*)varrecord) + size);
9504 memid = (MEMBERID*)varrecord;
9505 for(i = 0; i < info->cFuncs; ++i){
9506 TLBFuncDesc *desc = &info->funcdescs[i];
9507 *memid = desc->funcdesc.memid;
9508 ++memid;
9510 for(i = 0; i < info->cVars; ++i){
9511 TLBVarDesc *desc = &info->vardescs[i];
9512 *memid = desc->vardesc.memid;
9513 ++memid;
9516 name = (UINT*)memid;
9517 for(i = 0; i < info->cFuncs; ++i){
9518 TLBFuncDesc *desc = &info->funcdescs[i];
9519 if(desc->Name)
9520 *name = desc->Name->offset;
9521 else
9522 *name = -1;
9523 ++name;
9525 for(i = 0; i < info->cVars; ++i){
9526 TLBVarDesc *desc = &info->vardescs[i];
9527 if(desc->Name)
9528 *name = desc->Name->offset;
9529 else
9530 *name = -1;
9531 ++name;
9534 return ret;
9537 typedef struct tagWMSFT_RefChunk {
9538 DWORD href;
9539 DWORD res04;
9540 DWORD res08;
9541 DWORD next;
9542 } WMSFT_RefChunk;
9544 static DWORD WMSFT_compile_typeinfo_ref(ITypeInfoImpl *info, WMSFT_TLBFile *file)
9546 DWORD offs = file->ref_seg.len, i;
9547 WMSFT_RefChunk *chunk;
9549 file->ref_seg.len += info->cImplTypes * sizeof(WMSFT_RefChunk);
9550 if(!file->ref_seg.data)
9551 file->ref_seg.data = heap_alloc(file->ref_seg.len);
9552 else
9553 file->ref_seg.data = heap_realloc(file->ref_seg.data, file->ref_seg.len);
9555 chunk = (WMSFT_RefChunk*)((char*)file->ref_seg.data + offs);
9557 for(i = 0; i < info->cImplTypes; ++i){
9558 chunk->href = info->impltypes[i].hRef;
9559 chunk->res04 = info->impltypes[i].implflags;
9560 chunk->res08 = -1;
9561 if(i < info->cImplTypes - 1)
9562 chunk->next = offs + sizeof(WMSFT_RefChunk) * (i + 1);
9563 else
9564 chunk->next = -1;
9565 ++chunk;
9568 return offs;
9571 static DWORD WMSFT_compile_typeinfo(ITypeInfoImpl *info, INT16 index, WMSFT_TLBFile *file, char *data)
9573 DWORD size;
9575 size = sizeof(MSFT_TypeInfoBase);
9577 if(data){
9578 MSFT_TypeInfoBase *base = (void*)data;
9579 if(info->wTypeFlags & TYPEFLAG_FDUAL)
9580 base->typekind = TKIND_DISPATCH;
9581 else
9582 base->typekind = info->typekind;
9583 base->typekind |= index << 16; /* TODO: There are some other flags here */
9584 base->typekind |= (info->cbAlignment << 11) | (info->cbAlignment << 6);
9585 base->memoffset = WMSFT_compile_typeinfo_aux(info, file);
9586 base->res2 = 0;
9587 base->res3 = 0;
9588 base->res4 = 3;
9589 base->res5 = 0;
9590 base->cElement = (info->cVars << 16) | info->cFuncs;
9591 base->res7 = 0;
9592 base->res8 = 0;
9593 base->res9 = 0;
9594 base->resA = 0;
9595 if(info->guid)
9596 base->posguid = info->guid->offset;
9597 else
9598 base->posguid = -1;
9599 base->flags = info->wTypeFlags;
9600 if(info->Name) {
9601 base->NameOffset = info->Name->offset;
9603 ((unsigned char*)file->name_seg.data)[info->Name->offset+9] = 0x38;
9604 *(HREFTYPE*)((unsigned char*)file->name_seg.data+info->Name->offset) = info->hreftype;
9605 }else {
9606 base->NameOffset = -1;
9608 base->version = (info->wMinorVerNum << 16) | info->wMajorVerNum;
9609 if(info->DocString)
9610 base->docstringoffs = info->DocString->offset;
9611 else
9612 base->docstringoffs = -1;
9613 base->helpstringcontext = info->dwHelpStringContext;
9614 base->helpcontext = info->dwHelpContext;
9615 base->oCustData = WMSFT_compile_custdata(info->pcustdata_list, file);
9616 base->cImplTypes = info->cImplTypes;
9617 base->cbSizeVft = info->cbSizeVft;
9618 base->size = info->cbSizeInstance;
9619 if(info->typekind == TKIND_COCLASS){
9620 base->datatype1 = WMSFT_compile_typeinfo_ref(info, file);
9621 }else if(info->typekind == TKIND_ALIAS){
9622 base->datatype1 = WMSFT_append_typedesc(info->tdescAlias, file, NULL, NULL);
9623 }else if(info->typekind == TKIND_MODULE){
9624 if(info->DllName)
9625 base->datatype1 = info->DllName->offset;
9626 else
9627 base->datatype1 = -1;
9628 }else{
9629 if(info->cImplTypes > 0)
9630 base->datatype1 = info->impltypes[0].hRef;
9631 else
9632 base->datatype1 = -1;
9634 base->datatype2 = index; /* FIXME: i think there's more here */
9635 base->res18 = 0;
9636 base->res19 = -1;
9639 return size;
9642 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl *This, WMSFT_TLBFile *file, DWORD *junk)
9644 UINT i;
9646 file->typeinfo_seg.len = 0;
9647 for(i = 0; i < This->TypeInfoCount; ++i){
9648 ITypeInfoImpl *info = This->typeinfos[i];
9649 *junk = file->typeinfo_seg.len;
9650 ++junk;
9651 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, NULL, NULL);
9654 file->typeinfo_seg.data = heap_alloc(file->typeinfo_seg.len);
9655 memset(file->typeinfo_seg.data, 0x96, file->typeinfo_seg.len);
9657 file->aux_seg.len = 0;
9658 file->aux_seg.data = NULL;
9660 file->typeinfo_seg.len = 0;
9661 for(i = 0; i < This->TypeInfoCount; ++i){
9662 ITypeInfoImpl *info = This->typeinfos[i];
9663 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, file,
9664 ((char *)file->typeinfo_seg.data) + file->typeinfo_seg.len);
9668 typedef struct tagWMSFT_ImpFile {
9669 INT guid_offs;
9670 LCID lcid;
9671 DWORD version;
9672 } WMSFT_ImpFile;
9674 static void WMSFT_compile_impfile(ITypeLibImpl *This, WMSFT_TLBFile *file)
9676 TLBImpLib *implib;
9677 WMSFT_ImpFile *impfile;
9678 char *data;
9679 DWORD last_offs = 0;
9681 file->impfile_seg.len = 0;
9682 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9683 int size = 0;
9685 if(implib->name){
9686 WCHAR *path = strrchrW(implib->name, '\\');
9687 if(path)
9688 ++path;
9689 else
9690 path = implib->name;
9691 size = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path), NULL, 0, NULL, NULL);
9692 if (size == 0)
9693 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9696 size += sizeof(INT16);
9697 if (size % 4)
9698 size = (size + 4) & ~0x3;
9699 if (size < 8)
9700 size = 8;
9702 file->impfile_seg.len += sizeof(WMSFT_ImpFile) + size;
9705 data = file->impfile_seg.data = heap_alloc(file->impfile_seg.len);
9707 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9708 int strlen = 0, size;
9710 impfile = (WMSFT_ImpFile*)data;
9711 impfile->guid_offs = implib->guid->offset;
9712 impfile->lcid = implib->lcid;
9713 impfile->version = (implib->wVersionMinor << 16) | implib->wVersionMajor;
9715 data += sizeof(WMSFT_ImpFile);
9717 if(implib->name){
9718 WCHAR *path= strrchrW(implib->name, '\\');
9719 if(path)
9720 ++path;
9721 else
9722 path = implib->name;
9723 strlen = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path),
9724 data + sizeof(INT16), file->impfile_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9725 if (strlen == 0)
9726 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9729 *((INT16*)data) = (strlen << 2) | 1; /* FIXME: is that a flag, or what? */
9731 size = strlen + sizeof(INT16);
9732 if (size % 4)
9733 size = (size + 4) & ~0x3;
9734 if (size < 8)
9735 size = 8;
9736 memset(data + sizeof(INT16) + strlen, 0x57, size - strlen - sizeof(INT16));
9738 data += size;
9739 implib->offset = last_offs;
9740 last_offs += size + sizeof(WMSFT_ImpFile);
9744 static void WMSFT_compile_impinfo(ITypeLibImpl *This, WMSFT_TLBFile *file)
9746 MSFT_ImpInfo *info;
9747 TLBRefType *ref_type;
9748 UINT i = 0;
9750 WMSFT_compile_impfile(This, file);
9752 file->impinfo_seg.len = sizeof(MSFT_ImpInfo) * list_count(&This->ref_list);
9753 info = file->impinfo_seg.data = heap_alloc(file->impinfo_seg.len);
9755 LIST_FOR_EACH_ENTRY(ref_type, &This->ref_list, TLBRefType, entry){
9756 info->flags = i | ((ref_type->tkind & 0xFF) << 24);
9757 if(ref_type->index == TLB_REF_USE_GUID){
9758 info->flags |= MSFT_IMPINFO_OFFSET_IS_GUID;
9759 info->oGuid = ref_type->guid->offset;
9760 }else
9761 info->oGuid = ref_type->index;
9762 info->oImpFile = ref_type->pImpTLInfo->offset;
9763 ++i;
9764 ++info;
9768 static void WMSFT_compile_guidhash(ITypeLibImpl *This, WMSFT_TLBFile *file)
9770 file->guidhash_seg.len = 0x80;
9771 file->guidhash_seg.data = heap_alloc(file->guidhash_seg.len);
9772 memset(file->guidhash_seg.data, 0xFF, file->guidhash_seg.len);
9775 static void WMSFT_compile_namehash(ITypeLibImpl *This, WMSFT_TLBFile *file)
9777 file->namehash_seg.len = 0x200;
9778 file->namehash_seg.data = heap_alloc(file->namehash_seg.len);
9779 memset(file->namehash_seg.data, 0xFF, file->namehash_seg.len);
9782 static void tmp_fill_segdir_seg(MSFT_pSeg *segdir, WMSFT_SegContents *contents, DWORD *running_offset)
9784 if(contents && contents->len){
9785 segdir->offset = *running_offset;
9786 segdir->length = contents->len;
9787 *running_offset += segdir->length;
9788 }else{
9789 segdir->offset = -1;
9790 segdir->length = 0;
9793 /* TODO: do these ever change? */
9794 segdir->res08 = -1;
9795 segdir->res0c = 0xf;
9798 static void WMSFT_write_segment(HANDLE outfile, WMSFT_SegContents *segment)
9800 DWORD written;
9801 if(segment)
9802 WriteFile(outfile, segment->data, segment->len, &written, NULL);
9805 static HRESULT WMSFT_fixup_typeinfos(ITypeLibImpl *This, WMSFT_TLBFile *file,
9806 DWORD file_len)
9808 DWORD i;
9809 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase *)file->typeinfo_seg.data;
9811 for(i = 0; i < This->TypeInfoCount; ++i){
9812 base->memoffset += file_len;
9813 ++base;
9816 return S_OK;
9819 static void WMSFT_free_file(WMSFT_TLBFile *file)
9821 HeapFree(GetProcessHeap(), 0, file->typeinfo_seg.data);
9822 HeapFree(GetProcessHeap(), 0, file->guidhash_seg.data);
9823 HeapFree(GetProcessHeap(), 0, file->guid_seg.data);
9824 HeapFree(GetProcessHeap(), 0, file->ref_seg.data);
9825 HeapFree(GetProcessHeap(), 0, file->impinfo_seg.data);
9826 HeapFree(GetProcessHeap(), 0, file->impfile_seg.data);
9827 HeapFree(GetProcessHeap(), 0, file->namehash_seg.data);
9828 HeapFree(GetProcessHeap(), 0, file->name_seg.data);
9829 HeapFree(GetProcessHeap(), 0, file->string_seg.data);
9830 HeapFree(GetProcessHeap(), 0, file->typdesc_seg.data);
9831 HeapFree(GetProcessHeap(), 0, file->arraydesc_seg.data);
9832 HeapFree(GetProcessHeap(), 0, file->custdata_seg.data);
9833 HeapFree(GetProcessHeap(), 0, file->cdguids_seg.data);
9834 HeapFree(GetProcessHeap(), 0, file->aux_seg.data);
9837 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
9839 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9840 WMSFT_TLBFile file;
9841 DWORD written, junk_size, junk_offs, running_offset;
9842 BOOL br;
9843 HANDLE outfile;
9844 HRESULT hres;
9845 DWORD *junk;
9846 UINT i;
9848 TRACE("%p\n", This);
9850 for(i = 0; i < This->TypeInfoCount; ++i)
9851 if(This->typeinfos[i]->needs_layout)
9852 ICreateTypeInfo2_LayOut(&This->typeinfos[i]->ICreateTypeInfo2_iface);
9854 memset(&file, 0, sizeof(file));
9856 file.header.magic1 = 0x5446534D;
9857 file.header.magic2 = 0x00010002;
9858 file.header.lcid = This->set_lcid ? This->set_lcid : MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
9859 file.header.lcid2 = This->set_lcid;
9860 file.header.varflags = 0x40 | This->syskind;
9861 if (This->HelpFile)
9862 file.header.varflags |= 0x10;
9863 if (This->HelpStringDll)
9864 file.header.varflags |= HELPDLLFLAG;
9865 file.header.version = (This->ver_minor << 16) | This->ver_major;
9866 file.header.flags = This->libflags;
9867 file.header.helpstringcontext = 0; /* TODO - SetHelpStringContext not implemented yet */
9868 file.header.helpcontext = This->dwHelpContext;
9869 file.header.res44 = 0x20;
9870 file.header.res48 = 0x80;
9871 file.header.dispatchpos = This->dispatch_href;
9873 WMSFT_compile_namehash(This, &file);
9874 /* do name and string compilation to get offsets for other compilations */
9875 hres = WMSFT_compile_names(This, &file);
9876 if (FAILED(hres)){
9877 WMSFT_free_file(&file);
9878 return hres;
9881 hres = WMSFT_compile_strings(This, &file);
9882 if (FAILED(hres)){
9883 WMSFT_free_file(&file);
9884 return hres;
9887 WMSFT_compile_guidhash(This, &file);
9888 hres = WMSFT_compile_guids(This, &file);
9889 if (FAILED(hres)){
9890 WMSFT_free_file(&file);
9891 return hres;
9894 if(This->HelpFile)
9895 file.header.helpfile = This->HelpFile->offset;
9896 else
9897 file.header.helpfile = -1;
9899 if(This->DocString)
9900 file.header.helpstring = This->DocString->offset;
9901 else
9902 file.header.helpstring = -1;
9904 /* do some more segment compilation */
9905 file.header.nimpinfos = list_count(&This->ref_list);
9906 file.header.nrtypeinfos = This->TypeInfoCount;
9908 if(This->Name)
9909 file.header.NameOffset = This->Name->offset;
9910 else
9911 file.header.NameOffset = -1;
9913 file.header.CustomDataOffset = -1; /* TODO SetCustData not impl yet */
9915 if(This->guid)
9916 file.header.posguid = This->guid->offset;
9917 else
9918 file.header.posguid = -1;
9920 junk_size = file.header.nrtypeinfos * sizeof(DWORD);
9921 if(file.header.varflags & HELPDLLFLAG)
9922 junk_size += sizeof(DWORD);
9923 if(junk_size){
9924 junk = heap_alloc_zero(junk_size);
9925 if(file.header.varflags & HELPDLLFLAG){
9926 *junk = This->HelpStringDll->offset;
9927 junk_offs = 1;
9928 }else
9929 junk_offs = 0;
9930 }else{
9931 junk = NULL;
9932 junk_offs = 0;
9935 WMSFT_compile_typeinfo_seg(This, &file, junk + junk_offs);
9936 WMSFT_compile_impinfo(This, &file);
9938 running_offset = 0;
9940 TRACE("header at: 0x%x\n", running_offset);
9941 running_offset += sizeof(file.header);
9943 TRACE("junk at: 0x%x\n", running_offset);
9944 running_offset += junk_size;
9946 TRACE("segdir at: 0x%x\n", running_offset);
9947 running_offset += sizeof(file.segdir);
9949 TRACE("typeinfo at: 0x%x\n", running_offset);
9950 tmp_fill_segdir_seg(&file.segdir.pTypeInfoTab, &file.typeinfo_seg, &running_offset);
9952 TRACE("guidhashtab at: 0x%x\n", running_offset);
9953 tmp_fill_segdir_seg(&file.segdir.pGuidHashTab, &file.guidhash_seg, &running_offset);
9955 TRACE("guidtab at: 0x%x\n", running_offset);
9956 tmp_fill_segdir_seg(&file.segdir.pGuidTab, &file.guid_seg, &running_offset);
9958 TRACE("reftab at: 0x%x\n", running_offset);
9959 tmp_fill_segdir_seg(&file.segdir.pRefTab, &file.ref_seg, &running_offset);
9961 TRACE("impinfo at: 0x%x\n", running_offset);
9962 tmp_fill_segdir_seg(&file.segdir.pImpInfo, &file.impinfo_seg, &running_offset);
9964 TRACE("impfiles at: 0x%x\n", running_offset);
9965 tmp_fill_segdir_seg(&file.segdir.pImpFiles, &file.impfile_seg, &running_offset);
9967 TRACE("namehashtab at: 0x%x\n", running_offset);
9968 tmp_fill_segdir_seg(&file.segdir.pNameHashTab, &file.namehash_seg, &running_offset);
9970 TRACE("nametab at: 0x%x\n", running_offset);
9971 tmp_fill_segdir_seg(&file.segdir.pNametab, &file.name_seg, &running_offset);
9973 TRACE("stringtab at: 0x%x\n", running_offset);
9974 tmp_fill_segdir_seg(&file.segdir.pStringtab, &file.string_seg, &running_offset);
9976 TRACE("typdesc at: 0x%x\n", running_offset);
9977 tmp_fill_segdir_seg(&file.segdir.pTypdescTab, &file.typdesc_seg, &running_offset);
9979 TRACE("arraydescriptions at: 0x%x\n", running_offset);
9980 tmp_fill_segdir_seg(&file.segdir.pArrayDescriptions, &file.arraydesc_seg, &running_offset);
9982 TRACE("custdata at: 0x%x\n", running_offset);
9983 tmp_fill_segdir_seg(&file.segdir.pCustData, &file.custdata_seg, &running_offset);
9985 TRACE("cdguids at: 0x%x\n", running_offset);
9986 tmp_fill_segdir_seg(&file.segdir.pCDGuids, &file.cdguids_seg, &running_offset);
9988 TRACE("res0e at: 0x%x\n", running_offset);
9989 tmp_fill_segdir_seg(&file.segdir.res0e, NULL, &running_offset);
9991 TRACE("res0f at: 0x%x\n", running_offset);
9992 tmp_fill_segdir_seg(&file.segdir.res0f, NULL, &running_offset);
9994 TRACE("aux_seg at: 0x%x\n", running_offset);
9996 WMSFT_fixup_typeinfos(This, &file, running_offset);
9998 outfile = CreateFileW(This->path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
9999 FILE_ATTRIBUTE_NORMAL, 0);
10000 if (outfile == INVALID_HANDLE_VALUE){
10001 WMSFT_free_file(&file);
10002 heap_free(junk);
10003 return TYPE_E_IOERROR;
10006 br = WriteFile(outfile, &file.header, sizeof(file.header), &written, NULL);
10007 if (!br) {
10008 WMSFT_free_file(&file);
10009 CloseHandle(outfile);
10010 heap_free(junk);
10011 return TYPE_E_IOERROR;
10014 br = WriteFile(outfile, junk, junk_size, &written, NULL);
10015 heap_free(junk);
10016 if (!br) {
10017 WMSFT_free_file(&file);
10018 CloseHandle(outfile);
10019 return TYPE_E_IOERROR;
10022 br = WriteFile(outfile, &file.segdir, sizeof(file.segdir), &written, NULL);
10023 if (!br) {
10024 WMSFT_free_file(&file);
10025 CloseHandle(outfile);
10026 return TYPE_E_IOERROR;
10029 WMSFT_write_segment(outfile, &file.typeinfo_seg);
10030 WMSFT_write_segment(outfile, &file.guidhash_seg);
10031 WMSFT_write_segment(outfile, &file.guid_seg);
10032 WMSFT_write_segment(outfile, &file.ref_seg);
10033 WMSFT_write_segment(outfile, &file.impinfo_seg);
10034 WMSFT_write_segment(outfile, &file.impfile_seg);
10035 WMSFT_write_segment(outfile, &file.namehash_seg);
10036 WMSFT_write_segment(outfile, &file.name_seg);
10037 WMSFT_write_segment(outfile, &file.string_seg);
10038 WMSFT_write_segment(outfile, &file.typdesc_seg);
10039 WMSFT_write_segment(outfile, &file.arraydesc_seg);
10040 WMSFT_write_segment(outfile, &file.custdata_seg);
10041 WMSFT_write_segment(outfile, &file.cdguids_seg);
10042 WMSFT_write_segment(outfile, &file.aux_seg);
10044 WMSFT_free_file(&file);
10046 CloseHandle(outfile);
10048 return S_OK;
10051 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
10052 LPOLESTR name)
10054 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10055 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
10056 return E_NOTIMPL;
10059 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
10060 REFGUID guid, VARIANT *varVal)
10062 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10063 FIXME("%p %s %p - stub\n", This, debugstr_guid(guid), varVal);
10064 return E_NOTIMPL;
10067 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
10068 ULONG helpStringContext)
10070 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10071 FIXME("%p %u - stub\n", This, helpStringContext);
10072 return E_NOTIMPL;
10075 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
10076 LPOLESTR filename)
10078 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10079 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
10081 if (!filename)
10082 return E_INVALIDARG;
10084 This->HelpStringDll = TLB_append_str(&This->string_list, filename);
10086 return S_OK;
10089 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
10090 ICreateTypeLib2_fnQueryInterface,
10091 ICreateTypeLib2_fnAddRef,
10092 ICreateTypeLib2_fnRelease,
10093 ICreateTypeLib2_fnCreateTypeInfo,
10094 ICreateTypeLib2_fnSetName,
10095 ICreateTypeLib2_fnSetVersion,
10096 ICreateTypeLib2_fnSetGuid,
10097 ICreateTypeLib2_fnSetDocString,
10098 ICreateTypeLib2_fnSetHelpFileName,
10099 ICreateTypeLib2_fnSetHelpContext,
10100 ICreateTypeLib2_fnSetLcid,
10101 ICreateTypeLib2_fnSetLibFlags,
10102 ICreateTypeLib2_fnSaveAllChanges,
10103 ICreateTypeLib2_fnDeleteTypeInfo,
10104 ICreateTypeLib2_fnSetCustData,
10105 ICreateTypeLib2_fnSetHelpStringContext,
10106 ICreateTypeLib2_fnSetHelpStringDll
10109 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
10110 REFIID riid, void **object)
10112 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10114 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, object);
10117 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
10119 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10121 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
10124 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
10126 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10128 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
10131 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
10132 REFGUID guid)
10134 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10136 TRACE("%p %s\n", This, debugstr_guid(guid));
10138 This->guid = TLB_append_guid(&This->pTypeLib->guid_list, guid, This->hreftype);
10140 return S_OK;
10143 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
10144 UINT typeFlags)
10146 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10147 WORD old_flags;
10148 HRESULT hres;
10150 TRACE("%p %x\n", This, typeFlags);
10152 if (typeFlags & TYPEFLAG_FDUAL) {
10153 static const WCHAR stdole2tlb[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10154 ITypeLib *stdole;
10155 ITypeInfo *dispatch;
10156 HREFTYPE hreftype;
10157 HRESULT hres;
10159 hres = LoadTypeLib(stdole2tlb, &stdole);
10160 if(FAILED(hres))
10161 return hres;
10163 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
10164 ITypeLib_Release(stdole);
10165 if(FAILED(hres))
10166 return hres;
10168 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
10169 ITypeInfo_Release(dispatch);
10170 if(FAILED(hres))
10171 return hres;
10174 old_flags = This->wTypeFlags;
10175 This->wTypeFlags = typeFlags;
10177 hres = ICreateTypeInfo2_LayOut(iface);
10178 if (FAILED(hres)) {
10179 This->wTypeFlags = old_flags;
10180 return hres;
10183 return S_OK;
10186 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
10187 LPOLESTR doc)
10189 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10191 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
10193 if (!doc)
10194 return E_INVALIDARG;
10196 This->DocString = TLB_append_str(&This->pTypeLib->string_list, doc);
10198 return S_OK;
10201 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
10202 DWORD helpContext)
10204 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10206 TRACE("%p %d\n", This, helpContext);
10208 This->dwHelpContext = helpContext;
10210 return S_OK;
10213 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
10214 WORD majorVerNum, WORD minorVerNum)
10216 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10218 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
10220 This->wMajorVerNum = majorVerNum;
10221 This->wMinorVerNum = minorVerNum;
10223 return S_OK;
10226 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
10227 ITypeInfo *typeInfo, HREFTYPE *refType)
10229 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10230 UINT index;
10231 ITypeLib *container;
10232 TLBRefType *ref_type;
10233 TLBImpLib *implib;
10234 TYPEATTR *typeattr;
10235 TLIBATTR *libattr;
10236 HRESULT hres;
10238 TRACE("%p %p %p\n", This, typeInfo, refType);
10240 if (!typeInfo || !refType)
10241 return E_INVALIDARG;
10243 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
10244 if (FAILED(hres))
10245 return hres;
10247 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
10248 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
10250 ITypeLib_Release(container);
10252 *refType = target->hreftype;
10254 return S_OK;
10257 hres = ITypeLib_GetLibAttr(container, &libattr);
10258 if (FAILED(hres)) {
10259 ITypeLib_Release(container);
10260 return hres;
10263 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
10264 if(IsEqualGUID(&implib->guid->guid, &libattr->guid) &&
10265 implib->lcid == libattr->lcid &&
10266 implib->wVersionMajor == libattr->wMajorVerNum &&
10267 implib->wVersionMinor == libattr->wMinorVerNum)
10268 break;
10271 if(&implib->entry == &This->pTypeLib->implib_list){
10272 implib = heap_alloc_zero(sizeof(TLBImpLib));
10274 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
10275 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
10276 implib->name = SysAllocString(our_container->path);
10277 }else{
10278 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
10279 libattr->wMinorVerNum, libattr->lcid, &implib->name);
10280 if(FAILED(hres)){
10281 implib->name = NULL;
10282 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres);
10286 implib->guid = TLB_append_guid(&This->pTypeLib->guid_list, &libattr->guid, 2);
10287 implib->lcid = libattr->lcid;
10288 implib->wVersionMajor = libattr->wMajorVerNum;
10289 implib->wVersionMinor = libattr->wMinorVerNum;
10291 list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
10294 ITypeLib_ReleaseTLibAttr(container, libattr);
10295 ITypeLib_Release(container);
10297 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
10298 if (FAILED(hres))
10299 return hres;
10301 index = 0;
10302 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
10303 if(ref_type->index == TLB_REF_USE_GUID &&
10304 IsEqualGUID(&ref_type->guid->guid, &typeattr->guid) &&
10305 ref_type->tkind == typeattr->typekind)
10306 break;
10307 ++index;
10310 if(&ref_type->entry == &This->pTypeLib->ref_list){
10311 ref_type = heap_alloc_zero(sizeof(TLBRefType));
10313 ref_type->tkind = typeattr->typekind;
10314 ref_type->pImpTLInfo = implib;
10315 ref_type->reference = index * sizeof(MSFT_ImpInfo);
10317 ref_type->index = TLB_REF_USE_GUID;
10319 ref_type->guid = TLB_append_guid(&This->pTypeLib->guid_list, &typeattr->guid, ref_type->reference+1);
10321 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
10324 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
10326 *refType = ref_type->reference | 0x1;
10328 if(IsEqualGUID(&ref_type->guid->guid, &IID_IDispatch))
10329 This->pTypeLib->dispatch_href = *refType;
10331 return S_OK;
10334 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
10335 UINT index, FUNCDESC *funcDesc)
10337 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10338 TLBFuncDesc tmp_func_desc, *func_desc;
10339 int buf_size, i;
10340 char *buffer;
10341 HRESULT hres;
10343 TRACE("%p %u %p\n", This, index, funcDesc);
10345 if (!funcDesc || funcDesc->oVft & 3)
10346 return E_INVALIDARG;
10348 switch (This->typekind) {
10349 case TKIND_MODULE:
10350 if (funcDesc->funckind != FUNC_STATIC)
10351 return TYPE_E_BADMODULEKIND;
10352 break;
10353 case TKIND_DISPATCH:
10354 if (funcDesc->funckind != FUNC_DISPATCH)
10355 return TYPE_E_BADMODULEKIND;
10356 break;
10357 default:
10358 if (funcDesc->funckind != FUNC_PUREVIRTUAL)
10359 return TYPE_E_BADMODULEKIND;
10362 if (index > This->cFuncs)
10363 return TYPE_E_ELEMENTNOTFOUND;
10365 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) &&
10366 !funcDesc->cParams)
10367 return TYPE_E_INCONSISTENTPROPFUNCS;
10369 #ifdef _WIN64
10370 if(This->pTypeLib->syskind == SYS_WIN64 &&
10371 funcDesc->oVft % 8 != 0)
10372 return E_INVALIDARG;
10373 #endif
10375 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc));
10376 TLBFuncDesc_Constructor(&tmp_func_desc);
10378 tmp_func_desc.funcdesc = *funcDesc;
10380 if (tmp_func_desc.funcdesc.oVft != 0)
10381 tmp_func_desc.funcdesc.oVft |= 1;
10383 if (funcDesc->cScodes) {
10384 tmp_func_desc.funcdesc.lprgscode = heap_alloc(sizeof(SCODE) * funcDesc->cScodes);
10385 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes);
10386 } else
10387 tmp_func_desc.funcdesc.lprgscode = NULL;
10389 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc);
10390 for (i = 0; i < funcDesc->cParams; ++i) {
10391 buf_size += sizeof(ELEMDESC);
10392 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i);
10394 tmp_func_desc.funcdesc.lprgelemdescParam = heap_alloc(buf_size);
10395 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams);
10397 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer);
10398 if (FAILED(hres)) {
10399 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10400 heap_free(tmp_func_desc.funcdesc.lprgscode);
10401 return hres;
10404 for (i = 0; i < funcDesc->cParams; ++i) {
10405 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i,
10406 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer);
10407 if (FAILED(hres)) {
10408 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10409 heap_free(tmp_func_desc.funcdesc.lprgscode);
10410 return hres;
10412 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT &&
10413 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT &&
10414 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){
10415 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
10416 if (FAILED(hres)) {
10417 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10418 heap_free(tmp_func_desc.funcdesc.lprgscode);
10419 return hres;
10424 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams);
10426 if (This->funcdescs) {
10427 This->funcdescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->funcdescs,
10428 sizeof(TLBFuncDesc) * (This->cFuncs + 1));
10430 if (index < This->cFuncs) {
10431 memmove(This->funcdescs + index + 1, This->funcdescs + index,
10432 (This->cFuncs - index) * sizeof(TLBFuncDesc));
10433 func_desc = This->funcdescs + index;
10434 } else
10435 func_desc = This->funcdescs + This->cFuncs;
10437 /* move custdata lists to the new memory location */
10438 for(i = 0; i < This->cFuncs + 1; ++i){
10439 if(index != i){
10440 TLBFuncDesc *fd = &This->funcdescs[i];
10441 if(fd->custdata_list.prev == fd->custdata_list.next)
10442 list_init(&fd->custdata_list);
10443 else{
10444 fd->custdata_list.prev->next = &fd->custdata_list;
10445 fd->custdata_list.next->prev = &fd->custdata_list;
10449 } else
10450 func_desc = This->funcdescs = heap_alloc(sizeof(TLBFuncDesc));
10452 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc));
10453 list_init(&func_desc->custdata_list);
10455 ++This->cFuncs;
10457 This->needs_layout = TRUE;
10459 return S_OK;
10462 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
10463 UINT index, HREFTYPE refType)
10465 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10466 TLBImplType *impl_type;
10467 HRESULT hres;
10469 TRACE("%p %u %d\n", This, index, refType);
10471 switch(This->typekind){
10472 case TKIND_COCLASS: {
10473 if (index == -1) {
10474 FIXME("Unhandled index: -1\n");
10475 return E_NOTIMPL;
10478 if(index != This->cImplTypes)
10479 return TYPE_E_ELEMENTNOTFOUND;
10481 break;
10483 case TKIND_INTERFACE:
10484 case TKIND_DISPATCH:
10485 if (index != 0 || This->cImplTypes)
10486 return TYPE_E_ELEMENTNOTFOUND;
10487 break;
10488 default:
10489 FIXME("Unimplemented typekind: %d\n", This->typekind);
10490 return E_NOTIMPL;
10493 if (This->impltypes){
10494 UINT i;
10496 This->impltypes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->impltypes,
10497 sizeof(TLBImplType) * (This->cImplTypes + 1));
10499 if (index < This->cImplTypes) {
10500 memmove(This->impltypes + index + 1, This->impltypes + index,
10501 (This->cImplTypes - index) * sizeof(TLBImplType));
10502 impl_type = This->impltypes + index;
10503 } else
10504 impl_type = This->impltypes + This->cImplTypes;
10506 /* move custdata lists to the new memory location */
10507 for(i = 0; i < This->cImplTypes + 1; ++i){
10508 if(index != i){
10509 TLBImplType *it = &This->impltypes[i];
10510 if(it->custdata_list.prev == it->custdata_list.next)
10511 list_init(&it->custdata_list);
10512 else{
10513 it->custdata_list.prev->next = &it->custdata_list;
10514 it->custdata_list.next->prev = &it->custdata_list;
10518 } else
10519 impl_type = This->impltypes = heap_alloc(sizeof(TLBImplType));
10521 memset(impl_type, 0, sizeof(TLBImplType));
10522 TLBImplType_Constructor(impl_type);
10523 impl_type->hRef = refType;
10525 ++This->cImplTypes;
10527 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
10528 This->wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
10530 hres = ICreateTypeInfo2_LayOut(iface);
10531 if (FAILED(hres))
10532 return hres;
10534 return S_OK;
10537 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
10538 UINT index, INT implTypeFlags)
10540 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10541 TLBImplType *impl_type = &This->impltypes[index];
10543 TRACE("%p %u %x\n", This, index, implTypeFlags);
10545 if (This->typekind != TKIND_COCLASS)
10546 return TYPE_E_BADMODULEKIND;
10548 if (index >= This->cImplTypes)
10549 return TYPE_E_ELEMENTNOTFOUND;
10551 impl_type->implflags = implTypeFlags;
10553 return S_OK;
10556 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
10557 WORD alignment)
10559 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10561 TRACE("%p %d\n", This, alignment);
10563 This->cbAlignment = alignment;
10565 return S_OK;
10568 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
10569 LPOLESTR schema)
10571 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10573 TRACE("%p %s\n", This, wine_dbgstr_w(schema));
10575 if (!schema)
10576 return E_INVALIDARG;
10578 This->Schema = TLB_append_str(&This->pTypeLib->string_list, schema);
10580 This->lpstrSchema = This->Schema->str;
10582 return S_OK;
10585 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
10586 UINT index, VARDESC *varDesc)
10588 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10589 TLBVarDesc *var_desc;
10591 TRACE("%p %u %p\n", This, index, varDesc);
10593 if (This->vardescs){
10594 UINT i;
10596 This->vardescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->vardescs,
10597 sizeof(TLBVarDesc) * (This->cVars + 1));
10599 if (index < This->cVars) {
10600 memmove(This->vardescs + index + 1, This->vardescs + index,
10601 (This->cVars - index) * sizeof(TLBVarDesc));
10602 var_desc = This->vardescs + index;
10603 } else
10604 var_desc = This->vardescs + This->cVars;
10606 /* move custdata lists to the new memory location */
10607 for(i = 0; i < This->cVars + 1; ++i){
10608 if(index != i){
10609 TLBVarDesc *var = &This->vardescs[i];
10610 if(var->custdata_list.prev == var->custdata_list.next)
10611 list_init(&var->custdata_list);
10612 else{
10613 var->custdata_list.prev->next = &var->custdata_list;
10614 var->custdata_list.next->prev = &var->custdata_list;
10618 } else
10619 var_desc = This->vardescs = heap_alloc_zero(sizeof(TLBVarDesc));
10621 TLBVarDesc_Constructor(var_desc);
10622 TLB_AllocAndInitVarDesc(varDesc, &var_desc->vardesc_create);
10623 var_desc->vardesc = *var_desc->vardesc_create;
10625 ++This->cVars;
10627 This->needs_layout = TRUE;
10629 return S_OK;
10632 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
10633 UINT index, LPOLESTR *names, UINT numNames)
10635 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10636 TLBFuncDesc *func_desc = &This->funcdescs[index];
10637 int i;
10639 TRACE("%p %u %p %u\n", This, index, names, numNames);
10641 if (!names)
10642 return E_INVALIDARG;
10644 if (index >= This->cFuncs || numNames == 0)
10645 return TYPE_E_ELEMENTNOTFOUND;
10647 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){
10648 if(numNames > func_desc->funcdesc.cParams)
10649 return TYPE_E_ELEMENTNOTFOUND;
10650 } else
10651 if(numNames > func_desc->funcdesc.cParams + 1)
10652 return TYPE_E_ELEMENTNOTFOUND;
10654 for(i = 0; i < This->cFuncs; ++i) {
10655 TLBFuncDesc *iter = &This->funcdescs[i];
10656 if (iter->Name && !strcmpW(TLB_get_bstr(iter->Name), *names)) {
10657 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10658 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10659 func_desc->funcdesc.invkind != iter->funcdesc.invkind)
10660 continue;
10661 return TYPE_E_AMBIGUOUSNAME;
10665 func_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *names);
10667 for (i = 1; i < numNames; ++i) {
10668 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1;
10669 par_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *(names + i));
10672 return S_OK;
10675 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
10676 UINT index, LPOLESTR name)
10678 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10680 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(name));
10682 if(!name)
10683 return E_INVALIDARG;
10685 if(index >= This->cVars)
10686 return TYPE_E_ELEMENTNOTFOUND;
10688 This->vardescs[index].Name = TLB_append_str(&This->pTypeLib->name_list, name);
10689 return S_OK;
10692 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
10693 TYPEDESC *tdescAlias)
10695 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10696 HRESULT hr;
10698 TRACE("%p %p\n", This, tdescAlias);
10700 if(!tdescAlias)
10701 return E_INVALIDARG;
10703 if(This->typekind != TKIND_ALIAS)
10704 return TYPE_E_BADMODULEKIND;
10706 hr = TLB_size_instance(This, This->pTypeLib->syskind, tdescAlias, &This->cbSizeInstance, &This->cbAlignment);
10707 if(FAILED(hr))
10708 return hr;
10710 heap_free(This->tdescAlias);
10711 This->tdescAlias = heap_alloc(TLB_SizeTypeDesc(tdescAlias, TRUE));
10712 TLB_CopyTypeDesc(NULL, tdescAlias, This->tdescAlias);
10714 return S_OK;
10717 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
10718 UINT index, LPOLESTR dllName, LPOLESTR procName)
10720 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10721 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
10722 return E_NOTIMPL;
10725 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
10726 UINT index, LPOLESTR docString)
10728 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10729 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(docString));
10730 return E_NOTIMPL;
10733 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
10734 UINT index, LPOLESTR docString)
10736 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10737 TLBVarDesc *var_desc = &This->vardescs[index];
10739 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10741 if(!docString)
10742 return E_INVALIDARG;
10744 if(index >= This->cVars)
10745 return TYPE_E_ELEMENTNOTFOUND;
10747 var_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10749 return S_OK;
10752 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
10753 UINT index, DWORD helpContext)
10755 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10756 TLBFuncDesc *func_desc = &This->funcdescs[index];
10758 TRACE("%p %u %d\n", This, index, helpContext);
10760 if(index >= This->cFuncs)
10761 return TYPE_E_ELEMENTNOTFOUND;
10763 func_desc->helpcontext = helpContext;
10765 return S_OK;
10768 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
10769 UINT index, DWORD helpContext)
10771 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10772 TLBVarDesc *var_desc = &This->vardescs[index];
10774 TRACE("%p %u %d\n", This, index, helpContext);
10776 if(index >= This->cVars)
10777 return TYPE_E_ELEMENTNOTFOUND;
10779 var_desc->HelpContext = helpContext;
10781 return S_OK;
10784 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
10785 UINT index, BSTR bstrMops)
10787 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10788 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
10789 return E_NOTIMPL;
10792 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
10793 IDLDESC *idlDesc)
10795 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10797 TRACE("%p %p\n", This, idlDesc);
10799 if (!idlDesc)
10800 return E_INVALIDARG;
10802 This->idldescType.dwReserved = idlDesc->dwReserved;
10803 This->idldescType.wIDLFlags = idlDesc->wIDLFlags;
10805 return S_OK;
10808 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
10810 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10811 ITypeInfo *tinfo;
10812 TLBFuncDesc *func_desc;
10813 UINT user_vft = 0, i, depth = 0;
10814 HRESULT hres = S_OK;
10816 TRACE("%p\n", This);
10818 This->needs_layout = FALSE;
10820 hres = ICreateTypeInfo2_QueryInterface(iface, &IID_ITypeInfo, (LPVOID*)&tinfo);
10821 if (FAILED(hres))
10822 return hres;
10824 if (This->typekind == TKIND_INTERFACE) {
10825 ITypeInfo *inh;
10826 TYPEATTR *attr;
10827 HREFTYPE inh_href;
10829 hres = ITypeInfo_GetRefTypeOfImplType(tinfo, 0, &inh_href);
10831 if (SUCCEEDED(hres)) {
10832 hres = ITypeInfo_GetRefTypeInfo(tinfo, inh_href, &inh);
10834 if (SUCCEEDED(hres)) {
10835 hres = ITypeInfo_GetTypeAttr(inh, &attr);
10836 if (FAILED(hres)) {
10837 ITypeInfo_Release(inh);
10838 ITypeInfo_Release(tinfo);
10839 return hres;
10841 This->cbSizeVft = attr->cbSizeVft;
10842 ITypeInfo_ReleaseTypeAttr(inh, attr);
10845 ++depth;
10846 hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href);
10847 if(SUCCEEDED(hres)){
10848 ITypeInfo *next;
10849 hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next);
10850 if(SUCCEEDED(hres)){
10851 ITypeInfo_Release(inh);
10852 inh = next;
10855 }while(SUCCEEDED(hres));
10856 hres = S_OK;
10858 ITypeInfo_Release(inh);
10859 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10860 This->cbSizeVft = 0;
10861 hres = S_OK;
10862 } else {
10863 ITypeInfo_Release(tinfo);
10864 return hres;
10866 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10867 This->cbSizeVft = 0;
10868 hres = S_OK;
10869 } else {
10870 ITypeInfo_Release(tinfo);
10871 return hres;
10873 } else if (This->typekind == TKIND_DISPATCH)
10874 This->cbSizeVft = 7 * This->pTypeLib->ptr_size;
10875 else
10876 This->cbSizeVft = 0;
10878 func_desc = This->funcdescs;
10879 i = 0;
10880 while (i < This->cFuncs) {
10881 if (!(func_desc->funcdesc.oVft & 0x1))
10882 func_desc->funcdesc.oVft = This->cbSizeVft;
10884 if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft)
10885 user_vft = func_desc->funcdesc.oVft & 0xFFFC;
10887 This->cbSizeVft += This->pTypeLib->ptr_size;
10889 if (func_desc->funcdesc.memid == MEMBERID_NIL) {
10890 TLBFuncDesc *iter;
10891 UINT j = 0;
10892 BOOL reset = FALSE;
10894 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i;
10896 iter = This->funcdescs;
10897 while (j < This->cFuncs) {
10898 if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) {
10899 if (!reset) {
10900 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->cFuncs;
10901 reset = TRUE;
10902 } else
10903 ++func_desc->funcdesc.memid;
10904 iter = This->funcdescs;
10905 j = 0;
10906 } else {
10907 ++iter;
10908 ++j;
10913 ++func_desc;
10914 ++i;
10917 if (user_vft > This->cbSizeVft)
10918 This->cbSizeVft = user_vft + This->pTypeLib->ptr_size;
10920 for(i = 0; i < This->cVars; ++i){
10921 TLBVarDesc *var_desc = &This->vardescs[i];
10922 if(var_desc->vardesc.memid == MEMBERID_NIL){
10923 UINT j = 0;
10924 BOOL reset = FALSE;
10925 TLBVarDesc *iter;
10927 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + i;
10929 iter = This->vardescs;
10930 while (j < This->cVars) {
10931 if (iter != var_desc && iter->vardesc.memid == var_desc->vardesc.memid) {
10932 if (!reset) {
10933 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + This->cVars;
10934 reset = TRUE;
10935 } else
10936 ++var_desc->vardesc.memid;
10937 iter = This->vardescs;
10938 j = 0;
10939 } else {
10940 ++iter;
10941 ++j;
10947 ITypeInfo_Release(tinfo);
10948 return hres;
10951 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
10952 UINT index)
10954 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10955 FIXME("%p %u - stub\n", This, index);
10956 return E_NOTIMPL;
10959 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
10960 MEMBERID memid, INVOKEKIND invKind)
10962 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10963 FIXME("%p %x %d - stub\n", This, memid, invKind);
10964 return E_NOTIMPL;
10967 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
10968 UINT index)
10970 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10971 FIXME("%p %u - stub\n", This, index);
10972 return E_NOTIMPL;
10975 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
10976 MEMBERID memid)
10978 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10979 FIXME("%p %x - stub\n", This, memid);
10980 return E_NOTIMPL;
10983 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
10984 UINT index)
10986 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10987 FIXME("%p %u - stub\n", This, index);
10988 return E_NOTIMPL;
10991 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
10992 REFGUID guid, VARIANT *varVal)
10994 TLBGuid *tlbguid;
10996 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10998 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
11000 if (!guid || !varVal)
11001 return E_INVALIDARG;
11003 tlbguid = TLB_append_guid(&This->pTypeLib->guid_list, guid, -1);
11005 return TLB_set_custdata(This->pcustdata_list, tlbguid, varVal);
11008 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
11009 UINT index, REFGUID guid, VARIANT *varVal)
11011 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11012 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11013 return E_NOTIMPL;
11016 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
11017 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
11019 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11020 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
11021 return E_NOTIMPL;
11024 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
11025 UINT index, REFGUID guid, VARIANT *varVal)
11027 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11028 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11029 return E_NOTIMPL;
11032 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
11033 UINT index, REFGUID guid, VARIANT *varVal)
11035 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11036 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11037 return E_NOTIMPL;
11040 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
11041 ULONG helpStringContext)
11043 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11045 TRACE("%p %u\n", This, helpStringContext);
11047 This->dwHelpStringContext = helpStringContext;
11049 return S_OK;
11052 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
11053 UINT index, ULONG helpStringContext)
11055 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11056 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11057 return E_NOTIMPL;
11060 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
11061 UINT index, ULONG helpStringContext)
11063 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11064 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11065 return E_NOTIMPL;
11068 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
11070 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11071 FIXME("%p - stub\n", This);
11072 return E_NOTIMPL;
11075 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
11076 LPOLESTR name)
11078 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11080 TRACE("%p %s\n", This, wine_dbgstr_w(name));
11082 if (!name)
11083 return E_INVALIDARG;
11085 This->Name = TLB_append_str(&This->pTypeLib->name_list, name);
11087 return S_OK;
11090 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
11091 ICreateTypeInfo2_fnQueryInterface,
11092 ICreateTypeInfo2_fnAddRef,
11093 ICreateTypeInfo2_fnRelease,
11094 ICreateTypeInfo2_fnSetGuid,
11095 ICreateTypeInfo2_fnSetTypeFlags,
11096 ICreateTypeInfo2_fnSetDocString,
11097 ICreateTypeInfo2_fnSetHelpContext,
11098 ICreateTypeInfo2_fnSetVersion,
11099 ICreateTypeInfo2_fnAddRefTypeInfo,
11100 ICreateTypeInfo2_fnAddFuncDesc,
11101 ICreateTypeInfo2_fnAddImplType,
11102 ICreateTypeInfo2_fnSetImplTypeFlags,
11103 ICreateTypeInfo2_fnSetAlignment,
11104 ICreateTypeInfo2_fnSetSchema,
11105 ICreateTypeInfo2_fnAddVarDesc,
11106 ICreateTypeInfo2_fnSetFuncAndParamNames,
11107 ICreateTypeInfo2_fnSetVarName,
11108 ICreateTypeInfo2_fnSetTypeDescAlias,
11109 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
11110 ICreateTypeInfo2_fnSetFuncDocString,
11111 ICreateTypeInfo2_fnSetVarDocString,
11112 ICreateTypeInfo2_fnSetFuncHelpContext,
11113 ICreateTypeInfo2_fnSetVarHelpContext,
11114 ICreateTypeInfo2_fnSetMops,
11115 ICreateTypeInfo2_fnSetTypeIdldesc,
11116 ICreateTypeInfo2_fnLayOut,
11117 ICreateTypeInfo2_fnDeleteFuncDesc,
11118 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
11119 ICreateTypeInfo2_fnDeleteVarDesc,
11120 ICreateTypeInfo2_fnDeleteVarDescByMemId,
11121 ICreateTypeInfo2_fnDeleteImplType,
11122 ICreateTypeInfo2_fnSetCustData,
11123 ICreateTypeInfo2_fnSetFuncCustData,
11124 ICreateTypeInfo2_fnSetParamCustData,
11125 ICreateTypeInfo2_fnSetVarCustData,
11126 ICreateTypeInfo2_fnSetImplTypeCustData,
11127 ICreateTypeInfo2_fnSetHelpStringContext,
11128 ICreateTypeInfo2_fnSetFuncHelpStringContext,
11129 ICreateTypeInfo2_fnSetVarHelpStringContext,
11130 ICreateTypeInfo2_fnInvalidate,
11131 ICreateTypeInfo2_fnSetName
11134 /******************************************************************************
11135 * ClearCustData (OLEAUT32.171)
11137 * Clear a custom data type's data.
11139 * PARAMS
11140 * lpCust [I] The custom data type instance
11142 * RETURNS
11143 * Nothing.
11145 void WINAPI ClearCustData(CUSTDATA *lpCust)
11147 if (lpCust && lpCust->cCustData)
11149 if (lpCust->prgCustData)
11151 DWORD i;
11153 for (i = 0; i < lpCust->cCustData; i++)
11154 VariantClear(&lpCust->prgCustData[i].varValue);
11156 /* FIXME - Should be using a per-thread IMalloc */
11157 heap_free(lpCust->prgCustData);
11158 lpCust->prgCustData = NULL;
11160 lpCust->cCustData = 0;