oleaut32: Don't crash on NULL string arguments.
[wine.git] / dlls / oleaut32 / typelib.c
blobafcdc5c9017e8ee2d693f34d4412bb62c72d399d
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 if(!new_str)
1893 return NULL;
1895 LIST_FOR_EACH_ENTRY(str, string_list, TLBString, entry) {
1896 if (strcmpW(str->str, new_str) == 0)
1897 return str;
1900 str = heap_alloc(sizeof(TLBString));
1901 if (!str)
1902 return NULL;
1904 str->str = SysAllocString(new_str);
1905 if (!str->str) {
1906 heap_free(str);
1907 return NULL;
1910 list_add_tail(string_list, &str->entry);
1912 return str;
1915 static HRESULT TLB_get_size_from_hreftype(ITypeInfoImpl *info, HREFTYPE href,
1916 ULONG *size, WORD *align)
1918 ITypeInfo *other;
1919 TYPEATTR *attr;
1920 HRESULT hr;
1922 hr = ITypeInfo2_GetRefTypeInfo(&info->ITypeInfo2_iface, href, &other);
1923 if(FAILED(hr))
1924 return hr;
1926 hr = ITypeInfo_GetTypeAttr(other, &attr);
1927 if(FAILED(hr)){
1928 ITypeInfo_Release(other);
1929 return hr;
1932 if(size)
1933 *size = attr->cbSizeInstance;
1934 if(align)
1935 *align = attr->cbAlignment;
1937 ITypeInfo_ReleaseTypeAttr(other, attr);
1938 ITypeInfo_Release(other);
1940 return S_OK;
1943 static HRESULT TLB_size_instance(ITypeInfoImpl *info, SYSKIND sys,
1944 TYPEDESC *tdesc, ULONG *size, WORD *align)
1946 ULONG i, sub, ptr_size;
1947 HRESULT hr;
1949 ptr_size = get_ptr_size(sys);
1951 switch(tdesc->vt){
1952 case VT_VOID:
1953 *size = 0;
1954 break;
1955 case VT_I1:
1956 case VT_UI1:
1957 *size = 1;
1958 break;
1959 case VT_I2:
1960 case VT_BOOL:
1961 case VT_UI2:
1962 *size = 2;
1963 break;
1964 case VT_I4:
1965 case VT_R4:
1966 case VT_ERROR:
1967 case VT_UI4:
1968 case VT_INT:
1969 case VT_UINT:
1970 case VT_HRESULT:
1971 *size = 4;
1972 break;
1973 case VT_R8:
1974 case VT_I8:
1975 case VT_UI8:
1976 *size = 8;
1977 break;
1978 case VT_BSTR:
1979 case VT_DISPATCH:
1980 case VT_UNKNOWN:
1981 case VT_PTR:
1982 case VT_SAFEARRAY:
1983 case VT_LPSTR:
1984 case VT_LPWSTR:
1985 *size = ptr_size;
1986 break;
1987 case VT_DATE:
1988 *size = sizeof(DATE);
1989 break;
1990 case VT_VARIANT:
1991 *size = sizeof(VARIANT);
1992 #ifdef _WIN64
1993 if(sys == SYS_WIN32)
1994 *size -= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
1995 #endif
1996 break;
1997 case VT_DECIMAL:
1998 *size = sizeof(DECIMAL);
1999 break;
2000 case VT_CY:
2001 *size = sizeof(CY);
2002 break;
2003 case VT_CARRAY:
2004 *size = 0;
2005 for(i = 0; i < tdesc->u.lpadesc->cDims; ++i)
2006 *size += tdesc->u.lpadesc->rgbounds[i].cElements;
2007 hr = TLB_size_instance(info, sys, &tdesc->u.lpadesc->tdescElem, &sub, align);
2008 if(FAILED(hr))
2009 return hr;
2010 *size *= sub;
2011 return S_OK;
2012 case VT_USERDEFINED:
2013 return TLB_get_size_from_hreftype(info, tdesc->u.hreftype, size, align);
2014 default:
2015 FIXME("Unsized VT: 0x%x\n", tdesc->vt);
2016 return E_FAIL;
2019 if(align){
2020 if(*size < 4)
2021 *align = *size;
2022 else
2023 *align = 4;
2026 return S_OK;
2029 /**********************************************************************
2031 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2033 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
2035 return pcx->pos;
2038 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
2040 if (where != DO_NOT_SEEK)
2042 where += pcx->oStart;
2043 if (where > pcx->length)
2045 /* FIXME */
2046 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
2047 TLB_abort();
2049 pcx->pos = where;
2053 /* read function */
2054 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
2056 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2057 pcx->pos, count, pcx->oStart, pcx->length, where);
2059 MSFT_Seek(pcx, where);
2060 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
2061 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
2062 pcx->pos += count;
2063 return count;
2066 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
2067 LONG where )
2069 DWORD ret;
2071 ret = MSFT_Read(buffer, count, pcx, where);
2072 FromLEDWords(buffer, ret);
2074 return ret;
2077 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
2078 LONG where )
2080 DWORD ret;
2082 ret = MSFT_Read(buffer, count, pcx, where);
2083 FromLEWords(buffer, ret);
2085 return ret;
2088 static HRESULT MSFT_ReadAllGuids(TLBContext *pcx)
2090 TLBGuid *guid;
2091 MSFT_GuidEntry entry;
2092 int offs = 0;
2094 MSFT_Seek(pcx, pcx->pTblDir->pGuidTab.offset);
2095 while (1) {
2096 if (offs >= pcx->pTblDir->pGuidTab.length)
2097 return S_OK;
2099 MSFT_ReadLEWords(&entry, sizeof(MSFT_GuidEntry), pcx, DO_NOT_SEEK);
2101 guid = heap_alloc(sizeof(TLBGuid));
2103 guid->offset = offs;
2104 guid->guid = entry.guid;
2105 guid->hreftype = entry.hreftype;
2107 list_add_tail(&pcx->pLibInfo->guid_list, &guid->entry);
2109 offs += sizeof(MSFT_GuidEntry);
2113 static TLBGuid *MSFT_ReadGuid( int offset, TLBContext *pcx)
2115 TLBGuid *ret;
2117 LIST_FOR_EACH_ENTRY(ret, &pcx->pLibInfo->guid_list, TLBGuid, entry){
2118 if(ret->offset == offset){
2119 TRACE_(typelib)("%s\n", debugstr_guid(&ret->guid));
2120 return ret;
2124 return NULL;
2127 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
2129 MSFT_NameIntro niName;
2131 if (offset < 0)
2133 ERR_(typelib)("bad offset %d\n", offset);
2134 return -1;
2137 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
2138 pcx->pTblDir->pNametab.offset+offset);
2140 return niName.hreftype;
2143 static HRESULT MSFT_ReadAllNames(TLBContext *pcx)
2145 char *string;
2146 MSFT_NameIntro intro;
2147 INT16 len_piece;
2148 int offs = 0, lengthInChars;
2150 MSFT_Seek(pcx, pcx->pTblDir->pNametab.offset);
2151 while (1) {
2152 TLBString *tlbstr;
2154 if (offs >= pcx->pTblDir->pNametab.length)
2155 return S_OK;
2157 MSFT_ReadLEWords(&intro, sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2158 intro.namelen &= 0xFF;
2159 len_piece = intro.namelen + sizeof(MSFT_NameIntro);
2160 if(len_piece % 4)
2161 len_piece = (len_piece + 4) & ~0x3;
2162 if(len_piece < 8)
2163 len_piece = 8;
2165 string = heap_alloc(len_piece + 1);
2166 MSFT_Read(string, len_piece - sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2167 string[intro.namelen] = '\0';
2169 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2170 string, -1, NULL, 0);
2171 if (!lengthInChars) {
2172 heap_free(string);
2173 return E_UNEXPECTED;
2176 tlbstr = heap_alloc(sizeof(TLBString));
2178 tlbstr->offset = offs;
2179 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2180 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2182 heap_free(string);
2184 list_add_tail(&pcx->pLibInfo->name_list, &tlbstr->entry);
2186 offs += len_piece;
2190 static TLBString *MSFT_ReadName( TLBContext *pcx, int offset)
2192 TLBString *tlbstr;
2194 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->name_list, TLBString, entry) {
2195 if (tlbstr->offset == offset) {
2196 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2197 return tlbstr;
2201 return NULL;
2204 static TLBString *MSFT_ReadString( TLBContext *pcx, int offset)
2206 TLBString *tlbstr;
2208 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->string_list, TLBString, entry) {
2209 if (tlbstr->offset == offset) {
2210 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2211 return tlbstr;
2215 return NULL;
2219 * read a value and fill a VARIANT structure
2221 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
2223 int size;
2225 TRACE_(typelib)("\n");
2227 if(offset <0) { /* data are packed in here */
2228 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
2229 V_I4(pVar) = offset & 0x3ffffff;
2230 return;
2232 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
2233 pcx->pTblDir->pCustData.offset + offset );
2234 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
2235 switch (V_VT(pVar)){
2236 case VT_EMPTY: /* FIXME: is this right? */
2237 case VT_NULL: /* FIXME: is this right? */
2238 case VT_I2 : /* this should not happen */
2239 case VT_I4 :
2240 case VT_R4 :
2241 case VT_ERROR :
2242 case VT_BOOL :
2243 case VT_I1 :
2244 case VT_UI1 :
2245 case VT_UI2 :
2246 case VT_UI4 :
2247 case VT_INT :
2248 case VT_UINT :
2249 case VT_VOID : /* FIXME: is this right? */
2250 case VT_HRESULT :
2251 size=4; break;
2252 case VT_R8 :
2253 case VT_CY :
2254 case VT_DATE :
2255 case VT_I8 :
2256 case VT_UI8 :
2257 case VT_DECIMAL : /* FIXME: is this right? */
2258 case VT_FILETIME :
2259 size=8;break;
2260 /* pointer types with known behaviour */
2261 case VT_BSTR :{
2262 char * ptr;
2263 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
2264 if(size == -1){
2265 V_BSTR(pVar) = NULL;
2266 }else{
2267 ptr = heap_alloc_zero(size);
2268 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);
2269 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
2270 /* FIXME: do we need a AtoW conversion here? */
2271 V_UNION(pVar, bstrVal[size])='\0';
2272 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
2273 heap_free(ptr);
2276 size=-4; break;
2277 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2278 case VT_DISPATCH :
2279 case VT_VARIANT :
2280 case VT_UNKNOWN :
2281 case VT_PTR :
2282 case VT_SAFEARRAY :
2283 case VT_CARRAY :
2284 case VT_USERDEFINED :
2285 case VT_LPSTR :
2286 case VT_LPWSTR :
2287 case VT_BLOB :
2288 case VT_STREAM :
2289 case VT_STORAGE :
2290 case VT_STREAMED_OBJECT :
2291 case VT_STORED_OBJECT :
2292 case VT_BLOB_OBJECT :
2293 case VT_CF :
2294 case VT_CLSID :
2295 default:
2296 size=0;
2297 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2298 V_VT(pVar));
2301 if(size>0) /* (big|small) endian correct? */
2302 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
2303 return;
2306 * create a linked list with custom data
2308 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
2310 MSFT_CDGuid entry;
2311 TLBCustData* pNew;
2312 int count=0;
2314 TRACE_(typelib)("\n");
2316 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
2318 while(offset >=0){
2319 count++;
2320 pNew=heap_alloc_zero(sizeof(TLBCustData));
2321 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
2322 pNew->guid = MSFT_ReadGuid(entry.GuidOffset, pcx);
2323 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
2324 list_add_head(custdata_list, &pNew->entry);
2325 offset = entry.next;
2327 return count;
2330 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd)
2332 if(type <0)
2333 pTd->vt=type & VT_TYPEMASK;
2334 else
2335 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
2337 TRACE_(typelib)("vt type = %X\n", pTd->vt);
2340 static int TLB_is_propgetput(INVOKEKIND invkind)
2342 return (invkind == INVOKE_PROPERTYGET ||
2343 invkind == INVOKE_PROPERTYPUT ||
2344 invkind == INVOKE_PROPERTYPUTREF);
2347 static void
2348 MSFT_DoFuncs(TLBContext* pcx,
2349 ITypeInfoImpl* pTI,
2350 int cFuncs,
2351 int cVars,
2352 int offset,
2353 TLBFuncDesc** pptfd)
2356 * member information is stored in a data structure at offset
2357 * indicated by the memoffset field of the typeinfo structure
2358 * There are several distinctive parts.
2359 * The first part starts with a field that holds the total length
2360 * of this (first) part excluding this field. Then follow the records,
2361 * for each member there is one record.
2363 * The first entry is always the length of the record (including this
2364 * length word).
2365 * The rest of the record depends on the type of the member. If there is
2366 * a field indicating the member type (function, variable, interface, etc)
2367 * I have not found it yet. At this time we depend on the information
2368 * in the type info and the usual order how things are stored.
2370 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2371 * for each member;
2373 * Third is an equal sized array with file offsets to the name entry
2374 * of each member.
2376 * The fourth and last (?) part is an array with offsets to the records
2377 * in the first part of this file segment.
2380 int infolen, nameoffset, reclength, i;
2381 int recoffset = offset + sizeof(INT);
2383 char *recbuf = heap_alloc(0xffff);
2384 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2385 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2387 TRACE_(typelib)("\n");
2389 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2391 *pptfd = TLBFuncDesc_Alloc(cFuncs);
2392 ptfd = *pptfd;
2393 for ( i = 0; i < cFuncs ; i++ )
2395 int optional;
2397 /* name, eventually add to a hash table */
2398 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2399 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2401 /* read the function information record */
2402 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2404 reclength &= 0xffff;
2406 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2408 /* size without argument data */
2409 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2410 if (pFuncRec->FKCCIC & 0x1000)
2411 optional -= pFuncRec->nrargs * sizeof(INT);
2413 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2414 ptfd->helpcontext = pFuncRec->HelpContext;
2416 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2417 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2419 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2421 if (pFuncRec->FKCCIC & 0x2000 )
2423 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2424 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2425 ptfd->Entry = (TLBString*)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2427 else
2428 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2430 else
2431 ptfd->Entry = (TLBString*)-1;
2433 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2434 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2436 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2437 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2439 /* fill the FuncDesc Structure */
2440 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2441 offset + infolen + ( i + 1) * sizeof(INT));
2443 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2444 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2445 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2446 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2447 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2448 ptfd->funcdesc.oVft = pFuncRec->VtableOffset & ~1;
2449 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2451 /* nameoffset is sometimes -1 on the second half of a propget/propput
2452 * pair of functions */
2453 if ((nameoffset == -1) && (i > 0) &&
2454 TLB_is_propgetput(ptfd_prev->funcdesc.invkind) &&
2455 TLB_is_propgetput(ptfd->funcdesc.invkind))
2456 ptfd->Name = ptfd_prev->Name;
2457 else
2458 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2460 MSFT_GetTdesc(pcx,
2461 pFuncRec->DataType,
2462 &ptfd->funcdesc.elemdescFunc.tdesc);
2464 /* do the parameters/arguments */
2465 if(pFuncRec->nrargs)
2467 int j = 0;
2468 MSFT_ParameterInfo paraminfo;
2470 ptfd->funcdesc.lprgelemdescParam =
2471 heap_alloc_zero(pFuncRec->nrargs * (sizeof(ELEMDESC) + sizeof(PARAMDESCEX)));
2473 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2475 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2476 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2478 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2480 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2482 MSFT_GetTdesc(pcx,
2483 paraminfo.DataType,
2484 &elemdesc->tdesc);
2486 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2488 /* name */
2489 if (paraminfo.oName != -1)
2490 ptfd->pParamDesc[j].Name =
2491 MSFT_ReadName( pcx, paraminfo.oName );
2492 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(TLB_get_bstr(ptfd->pParamDesc[j].Name)));
2494 /* default value */
2495 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2496 (pFuncRec->FKCCIC & 0x1000) )
2498 INT* pInt = (INT *)((char *)pFuncRec +
2499 reclength -
2500 (pFuncRec->nrargs * 4) * sizeof(INT) );
2502 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2504 pParamDesc->pparamdescex = (PARAMDESCEX*)(ptfd->funcdesc.lprgelemdescParam+pFuncRec->nrargs)+j;
2505 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2507 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2508 pInt[j], pcx);
2510 else
2511 elemdesc->u.paramdesc.pparamdescex = NULL;
2513 /* custom info */
2514 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2515 j*sizeof(pFuncRec->oArgCustData[0])) &&
2516 pFuncRec->FKCCIC & 0x80 )
2518 MSFT_CustData(pcx,
2519 pFuncRec->oArgCustData[j],
2520 &ptfd->pParamDesc[j].custdata_list);
2523 /* SEEK value = jump to offset,
2524 * from there jump to the end of record,
2525 * go back by (j-1) arguments
2527 MSFT_ReadLEDWords( &paraminfo ,
2528 sizeof(MSFT_ParameterInfo), pcx,
2529 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2530 * sizeof(MSFT_ParameterInfo)));
2534 /* scode is not used: archaic win16 stuff FIXME: right? */
2535 ptfd->funcdesc.cScodes = 0 ;
2536 ptfd->funcdesc.lprgscode = NULL ;
2538 ptfd_prev = ptfd;
2539 ++ptfd;
2540 recoffset += reclength;
2542 heap_free(recbuf);
2545 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2546 int cVars, int offset, TLBVarDesc ** pptvd)
2548 int infolen, nameoffset, reclength;
2549 char recbuf[256];
2550 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2551 TLBVarDesc *ptvd;
2552 int i;
2553 int recoffset;
2555 TRACE_(typelib)("\n");
2557 ptvd = *pptvd = TLBVarDesc_Alloc(cVars);
2558 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2559 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2560 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2561 recoffset += offset+sizeof(INT);
2562 for(i=0;i<cVars;i++, ++ptvd){
2563 /* name, eventually add to a hash table */
2564 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2565 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2566 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2567 /* read the variable information record */
2568 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2569 reclength &= 0xff;
2570 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2572 /* optional data */
2573 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2574 ptvd->HelpContext = pVarRec->HelpContext;
2576 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2577 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2579 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2580 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2582 /* fill the VarDesc Structure */
2583 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2584 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2585 ptvd->vardesc.varkind = pVarRec->VarKind;
2586 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2587 MSFT_GetTdesc(pcx, pVarRec->DataType,
2588 &ptvd->vardesc.elemdescVar.tdesc);
2589 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2590 if(pVarRec->VarKind == VAR_CONST ){
2591 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2592 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2593 pVarRec->OffsValue, pcx);
2594 } else
2595 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2596 recoffset += reclength;
2600 /* process Implemented Interfaces of a com class */
2601 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2602 int offset)
2604 int i;
2605 MSFT_RefRecord refrec;
2606 TLBImplType *pImpl;
2608 TRACE_(typelib)("\n");
2610 pTI->impltypes = TLBImplType_Alloc(count);
2611 pImpl = pTI->impltypes;
2612 for(i=0;i<count;i++){
2613 if(offset<0) break; /* paranoia */
2614 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2615 pImpl->hRef = refrec.reftype;
2616 pImpl->implflags=refrec.flags;
2617 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2618 offset=refrec.onext;
2619 ++pImpl;
2623 #ifdef _WIN64
2624 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2625 * and some structures, and fix the alignment */
2626 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl *info)
2628 if(info->typekind == TKIND_ALIAS){
2629 switch(info->tdescAlias->vt){
2630 case VT_BSTR:
2631 case VT_DISPATCH:
2632 case VT_UNKNOWN:
2633 case VT_PTR:
2634 case VT_SAFEARRAY:
2635 case VT_LPSTR:
2636 case VT_LPWSTR:
2637 info->cbSizeInstance = sizeof(void*);
2638 info->cbAlignment = sizeof(void*);
2639 break;
2640 case VT_CARRAY:
2641 case VT_USERDEFINED:
2642 TLB_size_instance(info, SYS_WIN64, info->tdescAlias, &info->cbSizeInstance, &info->cbAlignment);
2643 break;
2644 case VT_VARIANT:
2645 info->cbSizeInstance = sizeof(VARIANT);
2646 info->cbAlignment = 8;
2647 default:
2648 if(info->cbSizeInstance < sizeof(void*))
2649 info->cbAlignment = info->cbSizeInstance;
2650 else
2651 info->cbAlignment = sizeof(void*);
2652 break;
2654 }else if(info->typekind == TKIND_INTERFACE ||
2655 info->typekind == TKIND_DISPATCH ||
2656 info->typekind == TKIND_COCLASS){
2657 info->cbSizeInstance = sizeof(void*);
2658 info->cbAlignment = sizeof(void*);
2661 #endif
2664 * process a typeinfo record
2666 static ITypeInfoImpl * MSFT_DoTypeInfo(
2667 TLBContext *pcx,
2668 int count,
2669 ITypeLibImpl * pLibInfo)
2671 MSFT_TypeInfoBase tiBase;
2672 ITypeInfoImpl *ptiRet;
2674 TRACE_(typelib)("count=%u\n", count);
2676 ptiRet = ITypeInfoImpl_Constructor();
2677 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2678 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2680 /* this is where we are coming from */
2681 ptiRet->pTypeLib = pLibInfo;
2682 ptiRet->index=count;
2684 ptiRet->guid = MSFT_ReadGuid(tiBase.posguid, pcx);
2685 ptiRet->lcid=pLibInfo->set_lcid; /* FIXME: correct? */
2686 ptiRet->lpstrSchema=NULL; /* reserved */
2687 ptiRet->cbSizeInstance=tiBase.size;
2688 ptiRet->typekind=tiBase.typekind & 0xF;
2689 ptiRet->cFuncs=LOWORD(tiBase.cElement);
2690 ptiRet->cVars=HIWORD(tiBase.cElement);
2691 ptiRet->cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2692 ptiRet->wTypeFlags=tiBase.flags;
2693 ptiRet->wMajorVerNum=LOWORD(tiBase.version);
2694 ptiRet->wMinorVerNum=HIWORD(tiBase.version);
2695 ptiRet->cImplTypes=tiBase.cImplTypes;
2696 ptiRet->cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2697 if(ptiRet->typekind == TKIND_ALIAS){
2698 TYPEDESC tmp;
2699 MSFT_GetTdesc(pcx, tiBase.datatype1, &tmp);
2700 ptiRet->tdescAlias = heap_alloc(TLB_SizeTypeDesc(&tmp, TRUE));
2701 TLB_CopyTypeDesc(NULL, &tmp, ptiRet->tdescAlias);
2704 /* FIXME: */
2705 /* IDLDESC idldescType; *//* never saw this one != zero */
2707 /* name, eventually add to a hash table */
2708 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2709 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2710 TRACE_(typelib)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet->Name)));
2711 /* help info */
2712 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2713 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2714 ptiRet->dwHelpContext=tiBase.helpcontext;
2716 if (ptiRet->typekind == TKIND_MODULE)
2717 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2719 /* note: InfoType's Help file and HelpStringDll come from the containing
2720 * library. Further HelpString and Docstring appear to be the same thing :(
2722 /* functions */
2723 if(ptiRet->cFuncs >0 )
2724 MSFT_DoFuncs(pcx, ptiRet, ptiRet->cFuncs,
2725 ptiRet->cVars,
2726 tiBase.memoffset, &ptiRet->funcdescs);
2727 /* variables */
2728 if(ptiRet->cVars >0 )
2729 MSFT_DoVars(pcx, ptiRet, ptiRet->cFuncs,
2730 ptiRet->cVars,
2731 tiBase.memoffset, &ptiRet->vardescs);
2732 if(ptiRet->cImplTypes >0 ) {
2733 switch(ptiRet->typekind)
2735 case TKIND_COCLASS:
2736 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->cImplTypes,
2737 tiBase.datatype1);
2738 break;
2739 case TKIND_DISPATCH:
2740 /* This is not -1 when the interface is a non-base dual interface or
2741 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2742 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2743 not this interface.
2746 if (tiBase.datatype1 != -1)
2748 ptiRet->impltypes = TLBImplType_Alloc(1);
2749 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2751 break;
2752 default:
2753 ptiRet->impltypes = TLBImplType_Alloc(1);
2754 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2755 break;
2758 MSFT_CustData(pcx, tiBase.oCustData, ptiRet->pcustdata_list);
2760 TRACE_(typelib)("%s guid: %s kind:%s\n",
2761 debugstr_w(TLB_get_bstr(ptiRet->Name)),
2762 debugstr_guid(TLB_get_guidref(ptiRet->guid)),
2763 typekind_desc[ptiRet->typekind]);
2764 if (TRACE_ON(typelib))
2765 dump_TypeInfo(ptiRet);
2767 return ptiRet;
2770 static HRESULT MSFT_ReadAllStrings(TLBContext *pcx)
2772 char *string;
2773 INT16 len_str, len_piece;
2774 int offs = 0, lengthInChars;
2776 MSFT_Seek(pcx, pcx->pTblDir->pStringtab.offset);
2777 while (1) {
2778 TLBString *tlbstr;
2780 if (offs >= pcx->pTblDir->pStringtab.length)
2781 return S_OK;
2783 MSFT_ReadLEWords(&len_str, sizeof(INT16), pcx, DO_NOT_SEEK);
2784 len_piece = len_str + sizeof(INT16);
2785 if(len_piece % 4)
2786 len_piece = (len_piece + 4) & ~0x3;
2787 if(len_piece < 8)
2788 len_piece = 8;
2790 string = heap_alloc(len_piece + 1);
2791 MSFT_Read(string, len_piece - sizeof(INT16), pcx, DO_NOT_SEEK);
2792 string[len_str] = '\0';
2794 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2795 string, -1, NULL, 0);
2796 if (!lengthInChars) {
2797 heap_free(string);
2798 return E_UNEXPECTED;
2801 tlbstr = heap_alloc(sizeof(TLBString));
2803 tlbstr->offset = offs;
2804 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2805 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2807 heap_free(string);
2809 list_add_tail(&pcx->pLibInfo->string_list, &tlbstr->entry);
2811 offs += len_piece;
2815 static HRESULT MSFT_ReadAllRefs(TLBContext *pcx)
2817 TLBRefType *ref;
2818 int offs = 0;
2820 MSFT_Seek(pcx, pcx->pTblDir->pImpInfo.offset);
2821 while (offs < pcx->pTblDir->pImpInfo.length) {
2822 MSFT_ImpInfo impinfo;
2823 TLBImpLib *pImpLib;
2825 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx, DO_NOT_SEEK);
2827 ref = heap_alloc_zero(sizeof(TLBRefType));
2828 list_add_tail(&pcx->pLibInfo->ref_list, &ref->entry);
2830 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2831 if(pImpLib->offset==impinfo.oImpFile)
2832 break;
2834 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2835 ref->reference = offs;
2836 ref->pImpTLInfo = pImpLib;
2837 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2838 ref->guid = MSFT_ReadGuid(impinfo.oGuid, pcx);
2839 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
2840 ref->index = TLB_REF_USE_GUID;
2841 } else
2842 ref->index = impinfo.oGuid;
2843 }else{
2844 ERR("Cannot find a reference\n");
2845 ref->reference = -1;
2846 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2849 offs += sizeof(impinfo);
2852 return S_OK;
2855 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2856 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2857 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2858 * tradeoff here.
2860 static struct list tlb_cache = LIST_INIT(tlb_cache);
2861 static CRITICAL_SECTION cache_section;
2862 static CRITICAL_SECTION_DEBUG cache_section_debug =
2864 0, 0, &cache_section,
2865 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2866 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2868 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2871 typedef struct TLB_PEFile
2873 IUnknown IUnknown_iface;
2874 LONG refs;
2875 HMODULE dll;
2876 HRSRC typelib_resource;
2877 HGLOBAL typelib_global;
2878 LPVOID typelib_base;
2879 } TLB_PEFile;
2881 static inline TLB_PEFile *pefile_impl_from_IUnknown(IUnknown *iface)
2883 return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2886 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2888 if (IsEqualIID(riid, &IID_IUnknown))
2890 *ppv = iface;
2891 IUnknown_AddRef(iface);
2892 return S_OK;
2894 *ppv = NULL;
2895 return E_NOINTERFACE;
2898 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2900 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2901 return InterlockedIncrement(&This->refs);
2904 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2906 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2907 ULONG refs = InterlockedDecrement(&This->refs);
2908 if (!refs)
2910 if (This->typelib_global)
2911 FreeResource(This->typelib_global);
2912 if (This->dll)
2913 FreeLibrary(This->dll);
2914 heap_free(This);
2916 return refs;
2919 static const IUnknownVtbl TLB_PEFile_Vtable =
2921 TLB_PEFile_QueryInterface,
2922 TLB_PEFile_AddRef,
2923 TLB_PEFile_Release
2926 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2928 TLB_PEFile *This;
2929 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2931 This = heap_alloc(sizeof(TLB_PEFile));
2932 if (!This)
2933 return E_OUTOFMEMORY;
2935 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
2936 This->refs = 1;
2937 This->dll = NULL;
2938 This->typelib_resource = NULL;
2939 This->typelib_global = NULL;
2940 This->typelib_base = NULL;
2942 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2943 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2945 if (This->dll)
2947 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2948 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2949 if (This->typelib_resource)
2951 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2952 if (This->typelib_global)
2954 This->typelib_base = LockResource(This->typelib_global);
2956 if (This->typelib_base)
2958 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2959 *ppBase = This->typelib_base;
2960 *ppFile = &This->IUnknown_iface;
2961 return S_OK;
2966 TRACE("No TYPELIB resource found\n");
2967 hr = E_FAIL;
2970 TLB_PEFile_Release(&This->IUnknown_iface);
2971 return hr;
2974 typedef struct TLB_NEFile
2976 IUnknown IUnknown_iface;
2977 LONG refs;
2978 LPVOID typelib_base;
2979 } TLB_NEFile;
2981 static inline TLB_NEFile *nefile_impl_from_IUnknown(IUnknown *iface)
2983 return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
2986 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2988 if (IsEqualIID(riid, &IID_IUnknown))
2990 *ppv = iface;
2991 IUnknown_AddRef(iface);
2992 return S_OK;
2994 *ppv = NULL;
2995 return E_NOINTERFACE;
2998 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
3000 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
3001 return InterlockedIncrement(&This->refs);
3004 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
3006 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
3007 ULONG refs = InterlockedDecrement(&This->refs);
3008 if (!refs)
3010 heap_free(This->typelib_base);
3011 heap_free(This);
3013 return refs;
3016 static const IUnknownVtbl TLB_NEFile_Vtable =
3018 TLB_NEFile_QueryInterface,
3019 TLB_NEFile_AddRef,
3020 TLB_NEFile_Release
3023 /***********************************************************************
3024 * read_xx_header [internal]
3026 static int read_xx_header( HFILE lzfd )
3028 IMAGE_DOS_HEADER mzh;
3029 char magic[3];
3031 LZSeek( lzfd, 0, SEEK_SET );
3032 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
3033 return 0;
3034 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
3035 return 0;
3037 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3038 if ( 2 != LZRead( lzfd, magic, 2 ) )
3039 return 0;
3041 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3043 if ( magic[0] == 'N' && magic[1] == 'E' )
3044 return IMAGE_OS2_SIGNATURE;
3045 if ( magic[0] == 'P' && magic[1] == 'E' )
3046 return IMAGE_NT_SIGNATURE;
3048 magic[2] = '\0';
3049 WARN("Can't handle %s files.\n", magic );
3050 return 0;
3054 /***********************************************************************
3055 * find_ne_resource [internal]
3057 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
3058 DWORD *resLen, DWORD *resOff )
3060 IMAGE_OS2_HEADER nehd;
3061 NE_TYPEINFO *typeInfo;
3062 NE_NAMEINFO *nameInfo;
3063 DWORD nehdoffset;
3064 LPBYTE resTab;
3065 DWORD resTabSize;
3066 int count;
3068 /* Read in NE header */
3069 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
3070 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
3072 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
3073 if ( !resTabSize )
3075 TRACE("No resources in NE dll\n" );
3076 return FALSE;
3079 /* Read in resource table */
3080 resTab = heap_alloc( resTabSize );
3081 if ( !resTab ) return FALSE;
3083 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
3084 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
3086 heap_free( resTab );
3087 return FALSE;
3090 /* Find resource */
3091 typeInfo = (NE_TYPEINFO *)(resTab + 2);
3093 if (!IS_INTRESOURCE(typeid)) /* named type */
3095 BYTE len = strlen( typeid );
3096 while (typeInfo->type_id)
3098 if (!(typeInfo->type_id & 0x8000))
3100 BYTE *p = resTab + typeInfo->type_id;
3101 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
3103 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3104 typeInfo->count * sizeof(NE_NAMEINFO));
3107 else /* numeric type id */
3109 WORD id = LOWORD(typeid) | 0x8000;
3110 while (typeInfo->type_id)
3112 if (typeInfo->type_id == id) goto found_type;
3113 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3114 typeInfo->count * sizeof(NE_NAMEINFO));
3117 TRACE("No typeid entry found for %p\n", typeid );
3118 heap_free( resTab );
3119 return FALSE;
3121 found_type:
3122 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
3124 if (!IS_INTRESOURCE(resid)) /* named resource */
3126 BYTE len = strlen( resid );
3127 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3129 BYTE *p = resTab + nameInfo->id;
3130 if (nameInfo->id & 0x8000) continue;
3131 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
3134 else /* numeric resource id */
3136 WORD id = LOWORD(resid) | 0x8000;
3137 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3138 if (nameInfo->id == id) goto found_name;
3140 TRACE("No resid entry found for %p\n", typeid );
3141 heap_free( resTab );
3142 return FALSE;
3144 found_name:
3145 /* Return resource data */
3146 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
3147 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
3149 heap_free( resTab );
3150 return TRUE;
3153 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
3155 HFILE lzfd = -1;
3156 OFSTRUCT ofs;
3157 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
3158 TLB_NEFile *This;
3160 This = heap_alloc(sizeof(TLB_NEFile));
3161 if (!This) return E_OUTOFMEMORY;
3163 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
3164 This->refs = 1;
3165 This->typelib_base = NULL;
3167 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
3168 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
3170 DWORD reslen, offset;
3171 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
3173 This->typelib_base = heap_alloc(reslen);
3174 if( !This->typelib_base )
3175 hr = E_OUTOFMEMORY;
3176 else
3178 LZSeek( lzfd, offset, SEEK_SET );
3179 reslen = LZRead( lzfd, This->typelib_base, reslen );
3180 LZClose( lzfd );
3181 *ppBase = This->typelib_base;
3182 *pdwTLBLength = reslen;
3183 *ppFile = &This->IUnknown_iface;
3184 return S_OK;
3189 if( lzfd >= 0) LZClose( lzfd );
3190 TLB_NEFile_Release(&This->IUnknown_iface);
3191 return hr;
3194 typedef struct TLB_Mapping
3196 IUnknown IUnknown_iface;
3197 LONG refs;
3198 HANDLE file;
3199 HANDLE mapping;
3200 LPVOID typelib_base;
3201 } TLB_Mapping;
3203 static inline TLB_Mapping *mapping_impl_from_IUnknown(IUnknown *iface)
3205 return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
3208 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3210 if (IsEqualIID(riid, &IID_IUnknown))
3212 *ppv = iface;
3213 IUnknown_AddRef(iface);
3214 return S_OK;
3216 *ppv = NULL;
3217 return E_NOINTERFACE;
3220 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
3222 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3223 return InterlockedIncrement(&This->refs);
3226 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
3228 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3229 ULONG refs = InterlockedDecrement(&This->refs);
3230 if (!refs)
3232 if (This->typelib_base)
3233 UnmapViewOfFile(This->typelib_base);
3234 if (This->mapping)
3235 CloseHandle(This->mapping);
3236 if (This->file != INVALID_HANDLE_VALUE)
3237 CloseHandle(This->file);
3238 heap_free(This);
3240 return refs;
3243 static const IUnknownVtbl TLB_Mapping_Vtable =
3245 TLB_Mapping_QueryInterface,
3246 TLB_Mapping_AddRef,
3247 TLB_Mapping_Release
3250 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
3252 TLB_Mapping *This;
3254 This = heap_alloc(sizeof(TLB_Mapping));
3255 if (!This)
3256 return E_OUTOFMEMORY;
3258 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
3259 This->refs = 1;
3260 This->file = INVALID_HANDLE_VALUE;
3261 This->mapping = NULL;
3262 This->typelib_base = NULL;
3264 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3265 if (INVALID_HANDLE_VALUE != This->file)
3267 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
3268 if (This->mapping)
3270 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
3271 if(This->typelib_base)
3273 /* retrieve file size */
3274 *pdwTLBLength = GetFileSize(This->file, NULL);
3275 *ppBase = This->typelib_base;
3276 *ppFile = &This->IUnknown_iface;
3277 return S_OK;
3282 IUnknown_Release(&This->IUnknown_iface);
3283 return TYPE_E_CANTLOADLIBRARY;
3286 /****************************************************************************
3287 * TLB_ReadTypeLib
3289 * find the type of the typelib file and map the typelib resource into
3290 * the memory
3293 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3294 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
3296 ITypeLibImpl *entry;
3297 HRESULT ret;
3298 INT index = 1;
3299 LPWSTR index_str, file = (LPWSTR)pszFileName;
3300 LPVOID pBase = NULL;
3301 DWORD dwTLBLength = 0;
3302 IUnknown *pFile = NULL;
3303 HANDLE h;
3305 *ppTypeLib = NULL;
3307 index_str = strrchrW(pszFileName, '\\');
3308 if(index_str && *++index_str != '\0')
3310 LPWSTR end_ptr;
3311 LONG idx = strtolW(index_str, &end_ptr, 10);
3312 if(*end_ptr == '\0')
3314 int str_len = index_str - pszFileName - 1;
3315 index = idx;
3316 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
3317 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
3318 file[str_len] = 0;
3322 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
3324 if(strchrW(file, '\\'))
3326 lstrcpyW(pszPath, file);
3328 else
3330 int len = GetSystemDirectoryW(pszPath, cchPath);
3331 pszPath[len] = '\\';
3332 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
3336 if(file != pszFileName) heap_free(file);
3338 h = CreateFileW(pszPath, GENERIC_READ, 0, NULL, OPEN_ALWAYS,
3339 FILE_ATTRIBUTE_NORMAL, NULL);
3340 if(h != INVALID_HANDLE_VALUE){
3341 FILE_NAME_INFORMATION *info;
3342 char data[MAX_PATH * sizeof(WCHAR) + sizeof(info->FileNameLength)];
3343 BOOL br;
3345 info = (FILE_NAME_INFORMATION*)data;
3346 /* GetFileInformationByHandleEx returns the path of the file without
3347 * WOW64 redirection */
3348 br = GetFileInformationByHandleEx(h, FileNameInfo, data, sizeof(data));
3349 if(br){
3350 info->FileName[info->FileNameLength / sizeof(WCHAR)] = 0;
3351 lstrcpynW(pszPath + 2, info->FileName, cchPath - 2);
3353 CloseHandle(h);
3356 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
3358 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3359 EnterCriticalSection(&cache_section);
3360 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
3362 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
3364 TRACE("cache hit\n");
3365 *ppTypeLib = &entry->ITypeLib2_iface;
3366 ITypeLib2_AddRef(*ppTypeLib);
3367 LeaveCriticalSection(&cache_section);
3368 return S_OK;
3371 LeaveCriticalSection(&cache_section);
3373 /* now actually load and parse the typelib */
3375 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3376 if (ret == TYPE_E_CANTLOADLIBRARY)
3377 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3378 if (ret == TYPE_E_CANTLOADLIBRARY)
3379 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
3380 if (SUCCEEDED(ret))
3382 if (dwTLBLength >= 4)
3384 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
3385 if (dwSignature == MSFT_SIGNATURE)
3386 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
3387 else if (dwSignature == SLTG_SIGNATURE)
3388 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
3389 else
3391 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
3392 ret = TYPE_E_CANTLOADLIBRARY;
3395 else
3396 ret = TYPE_E_CANTLOADLIBRARY;
3397 IUnknown_Release(pFile);
3400 if(*ppTypeLib) {
3401 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
3403 TRACE("adding to cache\n");
3404 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
3405 lstrcpyW(impl->path, pszPath);
3406 /* We should really canonicalise the path here. */
3407 impl->index = index;
3409 /* FIXME: check if it has added already in the meantime */
3410 EnterCriticalSection(&cache_section);
3411 list_add_head(&tlb_cache, &impl->entry);
3412 LeaveCriticalSection(&cache_section);
3413 ret = S_OK;
3415 else
3417 if(ret != E_FAIL)
3418 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
3420 ret = TYPE_E_CANTLOADLIBRARY;
3424 return ret;
3427 /*================== ITypeLib(2) Methods ===================================*/
3429 static ITypeLibImpl* TypeLibImpl_Constructor(void)
3431 ITypeLibImpl* pTypeLibImpl;
3433 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
3434 if (!pTypeLibImpl) return NULL;
3436 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3437 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3438 pTypeLibImpl->ICreateTypeLib2_iface.lpVtbl = &CreateTypeLib2Vtbl;
3439 pTypeLibImpl->ref = 1;
3441 list_init(&pTypeLibImpl->implib_list);
3442 list_init(&pTypeLibImpl->custdata_list);
3443 list_init(&pTypeLibImpl->name_list);
3444 list_init(&pTypeLibImpl->string_list);
3445 list_init(&pTypeLibImpl->guid_list);
3446 list_init(&pTypeLibImpl->ref_list);
3447 pTypeLibImpl->dispatch_href = -1;
3449 return pTypeLibImpl;
3452 /****************************************************************************
3453 * ITypeLib2_Constructor_MSFT
3455 * loading an MSFT typelib from an in-memory image
3457 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3459 TLBContext cx;
3460 LONG lPSegDir;
3461 MSFT_Header tlbHeader;
3462 MSFT_SegDir tlbSegDir;
3463 ITypeLibImpl * pTypeLibImpl;
3464 int i;
3466 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3468 pTypeLibImpl = TypeLibImpl_Constructor();
3469 if (!pTypeLibImpl) return NULL;
3471 /* get pointer to beginning of typelib data */
3472 cx.pos = 0;
3473 cx.oStart=0;
3474 cx.mapping = pLib;
3475 cx.pLibInfo = pTypeLibImpl;
3476 cx.length = dwTLBLength;
3478 /* read header */
3479 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
3480 TRACE_(typelib)("header:\n");
3481 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3482 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3483 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3484 return NULL;
3486 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3488 /* there is a small amount of information here until the next important
3489 * part:
3490 * the segment directory . Try to calculate the amount of data */
3491 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3493 /* now read the segment directory */
3494 TRACE("read segment directory (at %d)\n",lPSegDir);
3495 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3496 cx.pTblDir = &tlbSegDir;
3498 /* just check two entries */
3499 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3501 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3502 heap_free(pTypeLibImpl);
3503 return NULL;
3506 MSFT_ReadAllNames(&cx);
3507 MSFT_ReadAllStrings(&cx);
3508 MSFT_ReadAllGuids(&cx);
3510 /* now fill our internal data */
3511 /* TLIBATTR fields */
3512 pTypeLibImpl->guid = MSFT_ReadGuid(tlbHeader.posguid, &cx);
3514 pTypeLibImpl->syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3515 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3516 pTypeLibImpl->ver_major = LOWORD(tlbHeader.version);
3517 pTypeLibImpl->ver_minor = HIWORD(tlbHeader.version);
3518 pTypeLibImpl->libflags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
3520 pTypeLibImpl->set_lcid = tlbHeader.lcid2;
3521 pTypeLibImpl->lcid = tlbHeader.lcid;
3523 /* name, eventually add to a hash table */
3524 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3526 /* help info */
3527 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3528 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3530 if( tlbHeader.varflags & HELPDLLFLAG)
3532 int offset;
3533 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3534 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3537 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3539 /* custom data */
3540 if(tlbHeader.CustomDataOffset >= 0)
3542 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3545 /* fill in type descriptions */
3546 if(tlbSegDir.pTypdescTab.length > 0)
3548 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3549 INT16 td[4];
3550 pTypeLibImpl->ctTypeDesc = cTD;
3551 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3552 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3553 for(i=0; i<cTD; )
3555 /* FIXME: add several sanity checks here */
3556 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3557 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3559 /* FIXME: check safearray */
3560 if(td[3] < 0)
3561 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3562 else
3563 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3565 else if(td[0] == VT_CARRAY)
3567 /* array descr table here */
3568 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3570 else if(td[0] == VT_USERDEFINED)
3572 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3574 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3577 /* second time around to fill the array subscript info */
3578 for(i=0;i<cTD;i++)
3580 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3581 if(tlbSegDir.pArrayDescriptions.offset>0)
3583 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3584 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3586 if(td[1]<0)
3587 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3588 else
3589 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3591 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3593 for(j = 0; j<td[2]; j++)
3595 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3596 sizeof(INT), &cx, DO_NOT_SEEK);
3597 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3598 sizeof(INT), &cx, DO_NOT_SEEK);
3601 else
3603 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3604 ERR("didn't find array description data\n");
3609 /* imported type libs */
3610 if(tlbSegDir.pImpFiles.offset>0)
3612 TLBImpLib *pImpLib;
3613 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3614 UINT16 size;
3616 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3618 char *name;
3620 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3621 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3622 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3624 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3625 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3626 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3627 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3629 size >>= 2;
3630 name = heap_alloc_zero(size+1);
3631 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3632 pImpLib->name = TLB_MultiByteToBSTR(name);
3633 heap_free(name);
3635 pImpLib->guid = MSFT_ReadGuid(oGuid, &cx);
3636 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3638 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3642 MSFT_ReadAllRefs(&cx);
3644 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3646 /* type infos */
3647 if(tlbHeader.nrtypeinfos >= 0 )
3649 ITypeInfoImpl **ppTI;
3651 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3653 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3655 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3657 ++ppTI;
3658 (pTypeLibImpl->TypeInfoCount)++;
3662 #ifdef _WIN64
3663 if(pTypeLibImpl->syskind == SYS_WIN32){
3664 for(i = 0; i < pTypeLibImpl->TypeInfoCount; ++i)
3665 TLB_fix_32on64_typeinfo(pTypeLibImpl->typeinfos[i]);
3667 #endif
3669 TRACE("(%p)\n", pTypeLibImpl);
3670 return &pTypeLibImpl->ITypeLib2_iface;
3674 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3676 char b[3];
3677 int i;
3678 short s;
3680 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3681 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3682 return FALSE;
3685 guid->Data4[0] = s >> 8;
3686 guid->Data4[1] = s & 0xff;
3688 b[2] = '\0';
3689 for(i = 0; i < 6; i++) {
3690 memcpy(b, str + 24 + 2 * i, 2);
3691 guid->Data4[i + 2] = strtol(b, NULL, 16);
3693 return TRUE;
3696 static WORD SLTG_ReadString(const char *ptr, const TLBString **pStr, ITypeLibImpl *lib)
3698 WORD bytelen;
3699 DWORD len;
3700 BSTR tmp_str;
3702 *pStr = NULL;
3703 bytelen = *(const WORD*)ptr;
3704 if(bytelen == 0xffff) return 2;
3706 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3707 tmp_str = SysAllocStringLen(NULL, len);
3708 if (tmp_str) {
3709 MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, tmp_str, len);
3710 *pStr = TLB_append_str(&lib->string_list, tmp_str);
3711 SysFreeString(tmp_str);
3713 return bytelen + 2;
3716 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3718 WORD bytelen;
3720 *str = NULL;
3721 bytelen = *(const WORD*)ptr;
3722 if(bytelen == 0xffff) return 2;
3723 *str = heap_alloc(bytelen + 1);
3724 memcpy(*str, ptr + 2, bytelen);
3725 (*str)[bytelen] = '\0';
3726 return bytelen + 2;
3729 static TLBString *SLTG_ReadName(const char *pNameTable, int offset, ITypeLibImpl *lib)
3731 BSTR tmp_str;
3732 TLBString *tlbstr;
3734 LIST_FOR_EACH_ENTRY(tlbstr, &lib->name_list, TLBString, entry) {
3735 if (tlbstr->offset == offset)
3736 return tlbstr;
3739 tmp_str = TLB_MultiByteToBSTR(pNameTable + offset);
3740 tlbstr = TLB_append_str(&lib->name_list, tmp_str);
3741 SysFreeString(tmp_str);
3743 return tlbstr;
3746 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3748 char *ptr = pLibBlk;
3749 WORD w;
3751 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3752 FIXME("libblk magic = %04x\n", w);
3753 return 0;
3756 ptr += 6;
3757 if((w = *(WORD*)ptr) != 0xffff) {
3758 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3759 ptr += w;
3761 ptr += 2;
3763 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString, pTypeLibImpl);
3765 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile, pTypeLibImpl);
3767 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3768 ptr += 4;
3770 pTypeLibImpl->syskind = *(WORD*)ptr;
3771 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3772 ptr += 2;
3774 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3775 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3776 else
3777 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = 0;
3778 ptr += 2;
3780 ptr += 4; /* skip res12 */
3782 pTypeLibImpl->libflags = *(WORD*)ptr;
3783 ptr += 2;
3785 pTypeLibImpl->ver_major = *(WORD*)ptr;
3786 ptr += 2;
3788 pTypeLibImpl->ver_minor = *(WORD*)ptr;
3789 ptr += 2;
3791 pTypeLibImpl->guid = TLB_append_guid(&pTypeLibImpl->guid_list, (GUID*)ptr, -2);
3792 ptr += sizeof(GUID);
3794 return ptr - (char*)pLibBlk;
3797 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3798 typedef struct
3800 unsigned int num;
3801 HREFTYPE refs[1];
3802 } sltg_ref_lookup_t;
3804 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3805 HREFTYPE *typelib_ref)
3807 if(table && typeinfo_ref < table->num)
3809 *typelib_ref = table->refs[typeinfo_ref];
3810 return S_OK;
3813 ERR_(typelib)("Unable to find reference\n");
3814 *typelib_ref = -1;
3815 return E_FAIL;
3818 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3820 BOOL done = FALSE;
3822 while(!done) {
3823 if((*pType & 0xe00) == 0xe00) {
3824 pTD->vt = VT_PTR;
3825 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3826 pTD = pTD->u.lptdesc;
3828 switch(*pType & 0x3f) {
3829 case VT_PTR:
3830 pTD->vt = VT_PTR;
3831 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3832 pTD = pTD->u.lptdesc;
3833 break;
3835 case VT_USERDEFINED:
3836 pTD->vt = VT_USERDEFINED;
3837 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3838 done = TRUE;
3839 break;
3841 case VT_CARRAY:
3843 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3844 array */
3846 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3848 pTD->vt = VT_CARRAY;
3849 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3850 pTD->u.lpadesc->cDims = pSA->cDims;
3851 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3852 pSA->cDims * sizeof(SAFEARRAYBOUND));
3854 pTD = &pTD->u.lpadesc->tdescElem;
3855 break;
3858 case VT_SAFEARRAY:
3860 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3861 useful? */
3863 pType++;
3864 pTD->vt = VT_SAFEARRAY;
3865 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3866 pTD = pTD->u.lptdesc;
3867 break;
3869 default:
3870 pTD->vt = *pType & 0x3f;
3871 done = TRUE;
3872 break;
3874 pType++;
3876 return pType;
3879 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3880 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3882 /* Handle [in/out] first */
3883 if((*pType & 0xc000) == 0xc000)
3884 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3885 else if(*pType & 0x8000)
3886 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3887 else if(*pType & 0x4000)
3888 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3889 else
3890 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3892 if(*pType & 0x2000)
3893 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3895 if(*pType & 0x80)
3896 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3898 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3902 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3903 char *pNameTable)
3905 unsigned int ref;
3906 char *name;
3907 TLBRefType *ref_type;
3908 sltg_ref_lookup_t *table;
3909 HREFTYPE typelib_ref;
3911 if(pRef->magic != SLTG_REF_MAGIC) {
3912 FIXME("Ref magic = %x\n", pRef->magic);
3913 return NULL;
3915 name = ( (char*)pRef->names + pRef->number);
3917 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3918 table->num = pRef->number >> 3;
3920 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3922 /* We don't want the first href to be 0 */
3923 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3925 for(ref = 0; ref < pRef->number >> 3; ref++) {
3926 char *refname;
3927 unsigned int lib_offs, type_num;
3929 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3931 name += SLTG_ReadStringA(name, &refname);
3932 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3933 FIXME_(typelib)("Can't sscanf ref\n");
3934 if(lib_offs != 0xffff) {
3935 TLBImpLib *import;
3937 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
3938 if(import->offset == lib_offs)
3939 break;
3941 if(&import->entry == &pTL->implib_list) {
3942 char fname[MAX_PATH+1];
3943 int len;
3944 GUID tmpguid;
3946 import = heap_alloc_zero(sizeof(*import));
3947 import->offset = lib_offs;
3948 TLB_GUIDFromString( pNameTable + lib_offs + 4, &tmpguid);
3949 import->guid = TLB_append_guid(&pTL->guid_list, &tmpguid, 2);
3950 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3951 &import->wVersionMajor,
3952 &import->wVersionMinor,
3953 &import->lcid, fname) != 4) {
3954 FIXME_(typelib)("can't sscanf ref %s\n",
3955 pNameTable + lib_offs + 40);
3957 len = strlen(fname);
3958 if(fname[len-1] != '#')
3959 FIXME("fname = %s\n", fname);
3960 fname[len-1] = '\0';
3961 import->name = TLB_MultiByteToBSTR(fname);
3962 list_add_tail(&pTL->implib_list, &import->entry);
3964 ref_type->pImpTLInfo = import;
3966 /* Store a reference to IDispatch */
3967 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid->guid, &IID_StdOle) && type_num == 4)
3968 pTL->dispatch_href = typelib_ref;
3970 } else { /* internal ref */
3971 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3973 ref_type->reference = typelib_ref;
3974 ref_type->index = type_num;
3976 heap_free(refname);
3977 list_add_tail(&pTL->ref_list, &ref_type->entry);
3979 table->refs[ref] = typelib_ref;
3980 typelib_ref += 4;
3982 if((BYTE)*name != SLTG_REF_MAGIC)
3983 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3984 dump_TLBRefType(pTL);
3985 return table;
3988 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3989 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3991 SLTG_ImplInfo *info;
3992 TLBImplType *pImplType;
3993 /* I don't really get this structure, usually it's 0x16 bytes
3994 long, but iuser.tlb contains some that are 0x18 bytes long.
3995 That's ok because we can use the next ptr to jump to the next
3996 one. But how do we know the length of the last one? The WORD
3997 at offs 0x8 might be the clue. For now I'm just assuming that
3998 the last one is the regular 0x16 bytes. */
4000 info = (SLTG_ImplInfo*)pBlk;
4001 while(1){
4002 pTI->cImplTypes++;
4003 if(info->next == 0xffff)
4004 break;
4005 info = (SLTG_ImplInfo*)(pBlk + info->next);
4008 info = (SLTG_ImplInfo*)pBlk;
4009 pTI->impltypes = TLBImplType_Alloc(pTI->cImplTypes);
4010 pImplType = pTI->impltypes;
4011 while(1) {
4012 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
4013 pImplType->implflags = info->impltypeflags;
4014 ++pImplType;
4016 if(info->next == 0xffff)
4017 break;
4018 if(OneOnly)
4019 FIXME_(typelib)("Interface inheriting more than one interface\n");
4020 info = (SLTG_ImplInfo*)(pBlk + info->next);
4022 info++; /* see comment at top of function */
4023 return (char*)info;
4026 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
4027 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4029 TLBVarDesc *pVarDesc;
4030 const TLBString *prevName = NULL;
4031 SLTG_Variable *pItem;
4032 unsigned short i;
4033 WORD *pType;
4035 pVarDesc = pTI->vardescs = TLBVarDesc_Alloc(cVars);
4037 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
4038 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
4040 pVarDesc->vardesc.memid = pItem->memid;
4042 if (pItem->magic != SLTG_VAR_MAGIC &&
4043 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
4044 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
4045 return;
4048 if (pItem->name == 0xfffe)
4049 pVarDesc->Name = prevName;
4050 else
4051 pVarDesc->Name = SLTG_ReadName(pNameTable, pItem->name, pTI->pTypeLib);
4053 TRACE_(typelib)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc->Name)));
4054 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
4055 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
4057 if(pItem->flags & 0x02)
4058 pType = &pItem->type;
4059 else
4060 pType = (WORD*)(pBlk + pItem->type);
4062 if (pItem->flags & ~0xda)
4063 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
4065 SLTG_DoElem(pType, pBlk,
4066 &pVarDesc->vardesc.elemdescVar, ref_lookup);
4068 if (TRACE_ON(typelib)) {
4069 char buf[300];
4070 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
4071 TRACE_(typelib)("elemdescVar: %s\n", buf);
4074 if (pItem->flags & 0x40) {
4075 TRACE_(typelib)("VAR_DISPATCH\n");
4076 pVarDesc->vardesc.varkind = VAR_DISPATCH;
4078 else if (pItem->flags & 0x10) {
4079 TRACE_(typelib)("VAR_CONST\n");
4080 pVarDesc->vardesc.varkind = VAR_CONST;
4081 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
4082 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
4083 if (pItem->flags & 0x08)
4084 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
4085 else {
4086 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
4088 case VT_LPSTR:
4089 case VT_LPWSTR:
4090 case VT_BSTR:
4092 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
4093 BSTR str;
4094 TRACE_(typelib)("len = %u\n", len);
4095 if (len == 0xffff) {
4096 str = NULL;
4097 } else {
4098 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
4099 str = SysAllocStringLen(NULL, alloc_len);
4100 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
4102 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
4103 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
4104 break;
4106 case VT_I2:
4107 case VT_UI2:
4108 case VT_I4:
4109 case VT_UI4:
4110 case VT_INT:
4111 case VT_UINT:
4112 V_INT(pVarDesc->vardesc.u.lpvarValue) =
4113 *(INT*)(pBlk + pItem->byte_offs);
4114 break;
4115 default:
4116 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
4120 else {
4121 TRACE_(typelib)("VAR_PERINSTANCE\n");
4122 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
4123 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
4126 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
4127 pVarDesc->vardesc.wVarFlags = pItem->varflags;
4129 if (pItem->flags & 0x80)
4130 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
4132 prevName = pVarDesc->Name;
4134 pTI->cVars = cVars;
4137 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
4138 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4140 SLTG_Function *pFunc;
4141 unsigned short i;
4142 TLBFuncDesc *pFuncDesc;
4144 pTI->funcdescs = TLBFuncDesc_Alloc(cFuncs);
4146 pFuncDesc = pTI->funcdescs;
4147 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
4148 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
4150 int param;
4151 WORD *pType, *pArg;
4153 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
4154 case SLTG_FUNCTION_MAGIC:
4155 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
4156 break;
4157 case SLTG_DISPATCH_FUNCTION_MAGIC:
4158 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
4159 break;
4160 case SLTG_STATIC_FUNCTION_MAGIC:
4161 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
4162 break;
4163 default:
4164 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
4165 continue;
4167 pFuncDesc->Name = SLTG_ReadName(pNameTable, pFunc->name, pTI->pTypeLib);
4169 pFuncDesc->funcdesc.memid = pFunc->dispid;
4170 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
4171 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
4172 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
4173 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
4174 pFuncDesc->funcdesc.oVft = pFunc->vtblpos & ~1;
4176 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
4177 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
4179 if(pFunc->retnextopt & 0x80)
4180 pType = &pFunc->rettype;
4181 else
4182 pType = (WORD*)(pBlk + pFunc->rettype);
4184 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
4186 pFuncDesc->funcdesc.lprgelemdescParam =
4187 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
4188 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
4190 pArg = (WORD*)(pBlk + pFunc->arg_off);
4192 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
4193 char *paramName = pNameTable + *pArg;
4194 BOOL HaveOffs;
4195 /* If arg type follows then paramName points to the 2nd
4196 letter of the name, else the next WORD is an offset to
4197 the arg type and paramName points to the first letter.
4198 So let's take one char off paramName and see if we're
4199 pointing at an alpha-numeric char. However if *pArg is
4200 0xffff or 0xfffe then the param has no name, the former
4201 meaning that the next WORD is the type, the latter
4202 meaning that the next WORD is an offset to the type. */
4204 HaveOffs = FALSE;
4205 if(*pArg == 0xffff)
4206 paramName = NULL;
4207 else if(*pArg == 0xfffe) {
4208 paramName = NULL;
4209 HaveOffs = TRUE;
4211 else if(paramName[-1] && !isalnum(paramName[-1]))
4212 HaveOffs = TRUE;
4214 pArg++;
4216 if(HaveOffs) { /* the next word is an offset to type */
4217 pType = (WORD*)(pBlk + *pArg);
4218 SLTG_DoElem(pType, pBlk,
4219 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4220 pArg++;
4221 } else {
4222 if(paramName)
4223 paramName--;
4224 pArg = SLTG_DoElem(pArg, pBlk,
4225 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4228 /* Are we an optional param ? */
4229 if(pFuncDesc->funcdesc.cParams - param <=
4230 pFuncDesc->funcdesc.cParamsOpt)
4231 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
4233 if(paramName) {
4234 pFuncDesc->pParamDesc[param].Name = SLTG_ReadName(pNameTable,
4235 paramName - pNameTable, pTI->pTypeLib);
4236 } else {
4237 pFuncDesc->pParamDesc[param].Name = pFuncDesc->Name;
4241 pTI->cFuncs = cFuncs;
4244 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
4245 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4246 SLTG_TypeInfoTail *pTITail)
4248 char *pFirstItem;
4249 sltg_ref_lookup_t *ref_lookup = NULL;
4251 if(pTIHeader->href_table != 0xffffffff) {
4252 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4253 pNameTable);
4256 pFirstItem = pBlk;
4258 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4259 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
4261 heap_free(ref_lookup);
4265 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
4266 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4267 const SLTG_TypeInfoTail *pTITail)
4269 char *pFirstItem;
4270 sltg_ref_lookup_t *ref_lookup = NULL;
4272 if(pTIHeader->href_table != 0xffffffff) {
4273 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4274 pNameTable);
4277 pFirstItem = pBlk;
4279 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4280 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
4283 if (pTITail->funcs_off != 0xffff)
4284 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4286 heap_free(ref_lookup);
4288 if (TRACE_ON(typelib))
4289 dump_TLBFuncDesc(pTI->funcdescs, pTI->cFuncs);
4292 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
4293 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4294 const SLTG_TypeInfoTail *pTITail)
4296 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4299 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
4300 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4301 const SLTG_TypeInfoTail *pTITail)
4303 WORD *pType;
4304 sltg_ref_lookup_t *ref_lookup = NULL;
4306 if (pTITail->simple_alias) {
4307 /* if simple alias, no more processing required */
4308 pTI->tdescAlias = heap_alloc_zero(sizeof(TYPEDESC));
4309 pTI->tdescAlias->vt = pTITail->tdescalias_vt;
4310 return;
4313 if(pTIHeader->href_table != 0xffffffff) {
4314 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4315 pNameTable);
4318 /* otherwise it is an offset to a type */
4319 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
4321 pTI->tdescAlias = heap_alloc(sizeof(TYPEDESC));
4322 SLTG_DoType(pType, pBlk, pTI->tdescAlias, ref_lookup);
4324 heap_free(ref_lookup);
4327 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
4328 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4329 const SLTG_TypeInfoTail *pTITail)
4331 sltg_ref_lookup_t *ref_lookup = NULL;
4332 if (pTIHeader->href_table != 0xffffffff)
4333 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4334 pNameTable);
4336 if (pTITail->vars_off != 0xffff)
4337 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4339 if (pTITail->funcs_off != 0xffff)
4340 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4342 if (pTITail->impls_off != 0xffff)
4343 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
4345 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4346 * of dispinterface functions including the IDispatch ones, so
4347 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4348 pTI->cbSizeVft = pTI->cFuncs * pTI->pTypeLib->ptr_size;
4350 heap_free(ref_lookup);
4351 if (TRACE_ON(typelib))
4352 dump_TLBFuncDesc(pTI->funcdescs, pTI->cFuncs);
4355 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
4356 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4357 const SLTG_TypeInfoTail *pTITail)
4359 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4362 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
4363 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4364 const SLTG_TypeInfoTail *pTITail)
4366 sltg_ref_lookup_t *ref_lookup = NULL;
4367 if (pTIHeader->href_table != 0xffffffff)
4368 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4369 pNameTable);
4371 if (pTITail->vars_off != 0xffff)
4372 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4374 if (pTITail->funcs_off != 0xffff)
4375 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4376 heap_free(ref_lookup);
4377 if (TRACE_ON(typelib))
4378 dump_TypeInfo(pTI);
4381 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4382 manageable copy of it into this */
4383 typedef struct {
4384 WORD small_no;
4385 char *index_name;
4386 char *other_name;
4387 WORD res1a;
4388 WORD name_offs;
4389 WORD more_bytes;
4390 char *extra;
4391 WORD res20;
4392 DWORD helpcontext;
4393 WORD res26;
4394 GUID uuid;
4395 } SLTG_InternalOtherTypeInfo;
4397 /****************************************************************************
4398 * ITypeLib2_Constructor_SLTG
4400 * loading a SLTG typelib from an in-memory image
4402 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
4404 ITypeLibImpl *pTypeLibImpl;
4405 SLTG_Header *pHeader;
4406 SLTG_BlkEntry *pBlkEntry;
4407 SLTG_Magic *pMagic;
4408 SLTG_Index *pIndex;
4409 SLTG_Pad9 *pPad9;
4410 LPVOID pBlk, pFirstBlk;
4411 SLTG_LibBlk *pLibBlk;
4412 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
4413 char *pAfterOTIBlks = NULL;
4414 char *pNameTable, *ptr;
4415 int i;
4416 DWORD len, order;
4417 ITypeInfoImpl **ppTypeInfoImpl;
4419 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
4422 pTypeLibImpl = TypeLibImpl_Constructor();
4423 if (!pTypeLibImpl) return NULL;
4425 pHeader = pLib;
4427 TRACE_(typelib)("header:\n");
4428 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
4429 pHeader->nrOfFileBlks );
4430 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
4431 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
4432 pHeader->SLTG_magic);
4433 return NULL;
4436 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4437 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
4439 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4440 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
4442 /* Next we have a magic block */
4443 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
4445 /* Let's see if we're still in sync */
4446 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
4447 sizeof(SLTG_COMPOBJ_MAGIC))) {
4448 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
4449 return NULL;
4451 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
4452 sizeof(SLTG_DIR_MAGIC))) {
4453 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
4454 return NULL;
4457 pIndex = (SLTG_Index*)(pMagic+1);
4459 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
4461 pFirstBlk = pPad9 + 1;
4463 /* We'll set up a ptr to the main library block, which is the last one. */
4465 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4466 pBlkEntry[order].next != 0;
4467 order = pBlkEntry[order].next - 1, i++) {
4468 pBlk = (char*)pBlk + pBlkEntry[order].len;
4470 pLibBlk = pBlk;
4472 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
4474 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4475 interspersed */
4477 len += 0x40;
4479 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4481 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
4484 ptr = (char*)pLibBlk + len;
4486 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4487 WORD w, extra;
4488 len = 0;
4490 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
4492 w = *(WORD*)(ptr + 2);
4493 if(w != 0xffff) {
4494 len += w;
4495 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
4496 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4497 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4499 w = *(WORD*)(ptr + 4 + len);
4500 if(w != 0xffff) {
4501 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4502 len += w;
4503 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4504 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4505 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4507 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4508 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4509 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4510 if(extra) {
4511 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4512 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4513 len += extra;
4515 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4516 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4517 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4518 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4519 len += sizeof(SLTG_OtherTypeInfo);
4520 ptr += len;
4523 pAfterOTIBlks = ptr;
4525 /* Skip this WORD and get the next DWORD */
4526 len = *(DWORD*)(pAfterOTIBlks + 2);
4528 /* Now add this to pLibBLk look at what we're pointing at and
4529 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4530 dust and we should be pointing at the beginning of the name
4531 table */
4533 pNameTable = (char*)pLibBlk + len;
4535 switch(*(WORD*)pNameTable) {
4536 case 0xffff:
4537 break;
4538 case 0x0200:
4539 pNameTable += 0x20;
4540 break;
4541 default:
4542 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4543 break;
4546 pNameTable += 0x216;
4548 pNameTable += 2;
4550 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4552 pTypeLibImpl->Name = SLTG_ReadName(pNameTable, pLibBlk->name, pTypeLibImpl);
4555 /* Hopefully we now have enough ptrs set up to actually read in
4556 some TypeInfos. It's not clear which order to do them in, so
4557 I'll just follow the links along the BlkEntry chain and read
4558 them in the order in which they are in the file */
4560 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4561 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4563 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4564 pBlkEntry[order].next != 0;
4565 order = pBlkEntry[order].next - 1, i++) {
4567 SLTG_TypeInfoHeader *pTIHeader;
4568 SLTG_TypeInfoTail *pTITail;
4569 SLTG_MemberHeader *pMemHeader;
4571 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4572 FIXME_(typelib)("Index strings don't match\n");
4573 heap_free(pOtherTypeInfoBlks);
4574 return NULL;
4577 pTIHeader = pBlk;
4578 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4579 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4580 heap_free(pOtherTypeInfoBlks);
4581 return NULL;
4583 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4584 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4585 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4587 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4588 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4589 (*ppTypeInfoImpl)->index = i;
4590 (*ppTypeInfoImpl)->Name = SLTG_ReadName(pNameTable, pOtherTypeInfoBlks[i].name_offs, pTypeLibImpl);
4591 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4592 (*ppTypeInfoImpl)->guid = TLB_append_guid(&pTypeLibImpl->guid_list, &pOtherTypeInfoBlks[i].uuid, 2);
4593 (*ppTypeInfoImpl)->typekind = pTIHeader->typekind;
4594 (*ppTypeInfoImpl)->wMajorVerNum = pTIHeader->major_version;
4595 (*ppTypeInfoImpl)->wMinorVerNum = pTIHeader->minor_version;
4596 (*ppTypeInfoImpl)->wTypeFlags =
4597 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4599 if((*ppTypeInfoImpl)->wTypeFlags & TYPEFLAG_FDUAL)
4600 (*ppTypeInfoImpl)->typekind = TKIND_DISPATCH;
4602 if((pTIHeader->typeflags1 & 7) != 2)
4603 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4604 if(pTIHeader->typeflags3 != 2)
4605 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4607 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4608 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl)->Name)),
4609 typekind_desc[pTIHeader->typekind],
4610 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl)->guid)),
4611 (*ppTypeInfoImpl)->wTypeFlags);
4613 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4615 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4617 (*ppTypeInfoImpl)->cbAlignment = pTITail->cbAlignment;
4618 (*ppTypeInfoImpl)->cbSizeInstance = pTITail->cbSizeInstance;
4619 (*ppTypeInfoImpl)->cbSizeVft = pTITail->cbSizeVft;
4621 switch(pTIHeader->typekind) {
4622 case TKIND_ENUM:
4623 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4624 pTIHeader, pTITail);
4625 break;
4627 case TKIND_RECORD:
4628 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4629 pTIHeader, pTITail);
4630 break;
4632 case TKIND_INTERFACE:
4633 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4634 pTIHeader, pTITail);
4635 break;
4637 case TKIND_COCLASS:
4638 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4639 pTIHeader, pTITail);
4640 break;
4642 case TKIND_ALIAS:
4643 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4644 pTIHeader, pTITail);
4645 break;
4647 case TKIND_DISPATCH:
4648 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4649 pTIHeader, pTITail);
4650 break;
4652 case TKIND_MODULE:
4653 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4654 pTIHeader, pTITail);
4655 break;
4657 default:
4658 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4659 break;
4663 /* could get cFuncs, cVars and cImplTypes from here
4664 but we've already set those */
4665 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4666 X(06);
4667 X(16);
4668 X(18);
4669 X(1a);
4670 X(1e);
4671 X(24);
4672 X(26);
4673 X(2a);
4674 X(2c);
4675 X(2e);
4676 X(30);
4677 X(32);
4678 X(34);
4679 #undef X
4680 ++ppTypeInfoImpl;
4681 pBlk = (char*)pBlk + pBlkEntry[order].len;
4684 if(i != pTypeLibImpl->TypeInfoCount) {
4685 FIXME("Somehow processed %d TypeInfos\n", i);
4686 heap_free(pOtherTypeInfoBlks);
4687 return NULL;
4690 heap_free(pOtherTypeInfoBlks);
4691 return &pTypeLibImpl->ITypeLib2_iface;
4694 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4696 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4698 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4700 if(IsEqualIID(riid, &IID_IUnknown) ||
4701 IsEqualIID(riid,&IID_ITypeLib)||
4702 IsEqualIID(riid,&IID_ITypeLib2))
4704 *ppv = &This->ITypeLib2_iface;
4706 else if(IsEqualIID(riid, &IID_ICreateTypeLib) ||
4707 IsEqualIID(riid, &IID_ICreateTypeLib2))
4709 *ppv = &This->ICreateTypeLib2_iface;
4711 else
4713 *ppv = NULL;
4714 TRACE("-- Interface: E_NOINTERFACE\n");
4715 return E_NOINTERFACE;
4718 IUnknown_AddRef((IUnknown*)*ppv);
4719 return S_OK;
4722 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4724 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4725 ULONG ref = InterlockedIncrement(&This->ref);
4727 TRACE("(%p) ref=%u\n", This, ref);
4729 return ref;
4732 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4734 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4735 ULONG ref = InterlockedDecrement(&This->ref);
4737 TRACE("(%p) ref=%u\n",This, ref);
4739 if (!ref)
4741 TLBImpLib *pImpLib, *pImpLibNext;
4742 TLBRefType *ref_type;
4743 TLBString *tlbstr, *tlbstr_next;
4744 TLBGuid *tlbguid, *tlbguid_next;
4745 void *cursor2;
4746 int i;
4748 /* remove cache entry */
4749 if(This->path)
4751 TRACE("removing from cache list\n");
4752 EnterCriticalSection(&cache_section);
4753 if(This->entry.next)
4754 list_remove(&This->entry);
4755 LeaveCriticalSection(&cache_section);
4756 heap_free(This->path);
4758 TRACE(" destroying ITypeLib(%p)\n",This);
4760 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->string_list, TLBString, entry) {
4761 list_remove(&tlbstr->entry);
4762 SysFreeString(tlbstr->str);
4763 heap_free(tlbstr);
4766 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->name_list, TLBString, entry) {
4767 list_remove(&tlbstr->entry);
4768 SysFreeString(tlbstr->str);
4769 heap_free(tlbstr);
4772 LIST_FOR_EACH_ENTRY_SAFE(tlbguid, tlbguid_next, &This->guid_list, TLBGuid, entry) {
4773 list_remove(&tlbguid->entry);
4774 heap_free(tlbguid);
4777 TLB_FreeCustData(&This->custdata_list);
4779 for (i = 0; i < This->ctTypeDesc; i++)
4780 if (This->pTypeDesc[i].vt == VT_CARRAY)
4781 heap_free(This->pTypeDesc[i].u.lpadesc);
4783 heap_free(This->pTypeDesc);
4785 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4787 if (pImpLib->pImpTypeLib)
4788 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4789 SysFreeString(pImpLib->name);
4791 list_remove(&pImpLib->entry);
4792 heap_free(pImpLib);
4795 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4797 list_remove(&ref_type->entry);
4798 heap_free(ref_type);
4801 for (i = 0; i < This->TypeInfoCount; ++i){
4802 heap_free(This->typeinfos[i]->tdescAlias);
4803 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4805 heap_free(This->typeinfos);
4806 heap_free(This);
4807 return 0;
4810 return ref;
4813 /* ITypeLib::GetTypeInfoCount
4815 * Returns the number of type descriptions in the type library
4817 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4819 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4820 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4821 return This->TypeInfoCount;
4824 /* ITypeLib::GetTypeInfo
4826 * retrieves the specified type description in the library.
4828 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4829 ITypeLib2 *iface,
4830 UINT index,
4831 ITypeInfo **ppTInfo)
4833 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4835 TRACE("%p %u %p\n", This, index, ppTInfo);
4837 if(!ppTInfo)
4838 return E_INVALIDARG;
4840 if(index >= This->TypeInfoCount)
4841 return TYPE_E_ELEMENTNOTFOUND;
4843 *ppTInfo = (ITypeInfo *)&This->typeinfos[index]->ITypeInfo2_iface;
4844 ITypeInfo_AddRef(*ppTInfo);
4846 return S_OK;
4850 /* ITypeLibs::GetTypeInfoType
4852 * Retrieves the type of a type description.
4854 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4855 ITypeLib2 *iface,
4856 UINT index,
4857 TYPEKIND *pTKind)
4859 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4861 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4863 if(!pTKind)
4864 return E_INVALIDARG;
4866 if(index >= This->TypeInfoCount)
4867 return TYPE_E_ELEMENTNOTFOUND;
4869 *pTKind = This->typeinfos[index]->typekind;
4871 return S_OK;
4874 /* ITypeLib::GetTypeInfoOfGuid
4876 * Retrieves the type description that corresponds to the specified GUID.
4879 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4880 ITypeLib2 *iface,
4881 REFGUID guid,
4882 ITypeInfo **ppTInfo)
4884 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4885 int i;
4887 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4889 for(i = 0; i < This->TypeInfoCount; ++i){
4890 if(IsEqualIID(TLB_get_guid_null(This->typeinfos[i]->guid), guid)){
4891 *ppTInfo = (ITypeInfo *)&This->typeinfos[i]->ITypeInfo2_iface;
4892 ITypeInfo_AddRef(*ppTInfo);
4893 return S_OK;
4897 return TYPE_E_ELEMENTNOTFOUND;
4900 /* ITypeLib::GetLibAttr
4902 * Retrieves the structure that contains the library's attributes.
4905 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4906 ITypeLib2 *iface,
4907 LPTLIBATTR *attr)
4909 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4911 TRACE("(%p, %p)\n", This, attr);
4913 if (!attr) return E_INVALIDARG;
4915 *attr = heap_alloc(sizeof(**attr));
4916 if (!*attr) return E_OUTOFMEMORY;
4918 (*attr)->guid = *TLB_get_guid_null(This->guid);
4919 (*attr)->lcid = This->set_lcid;
4920 (*attr)->syskind = This->syskind;
4921 (*attr)->wMajorVerNum = This->ver_major;
4922 (*attr)->wMinorVerNum = This->ver_minor;
4923 (*attr)->wLibFlags = This->libflags;
4925 return S_OK;
4928 /* ITypeLib::GetTypeComp
4930 * Enables a client compiler to bind to a library's types, variables,
4931 * constants, and global functions.
4934 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4935 ITypeLib2 *iface,
4936 ITypeComp **ppTComp)
4938 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4940 TRACE("(%p)->(%p)\n",This,ppTComp);
4941 *ppTComp = &This->ITypeComp_iface;
4942 ITypeComp_AddRef(*ppTComp);
4944 return S_OK;
4947 /* ITypeLib::GetDocumentation
4949 * Retrieves the library's documentation string, the complete Help file name
4950 * and path, and the context identifier for the library Help topic in the Help
4951 * file.
4953 * On a successful return all non-null BSTR pointers will have been set,
4954 * possibly to NULL.
4956 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4957 ITypeLib2 *iface,
4958 INT index,
4959 BSTR *pBstrName,
4960 BSTR *pBstrDocString,
4961 DWORD *pdwHelpContext,
4962 BSTR *pBstrHelpFile)
4964 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4965 HRESULT result = E_INVALIDARG;
4966 ITypeInfo *pTInfo;
4968 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4969 This, index,
4970 pBstrName, pBstrDocString,
4971 pdwHelpContext, pBstrHelpFile);
4973 if(index<0)
4975 /* documentation for the typelib */
4976 if(pBstrName)
4978 if (This->Name)
4980 if(!(*pBstrName = SysAllocString(TLB_get_bstr(This->Name))))
4981 goto memerr1;
4983 else
4984 *pBstrName = NULL;
4986 if(pBstrDocString)
4988 if (This->DocString)
4990 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->DocString))))
4991 goto memerr2;
4993 else
4994 *pBstrDocString = NULL;
4996 if(pdwHelpContext)
4998 *pdwHelpContext = This->dwHelpContext;
5000 if(pBstrHelpFile)
5002 if (This->HelpFile)
5004 if(!(*pBstrHelpFile = SysAllocString(TLB_get_bstr(This->HelpFile))))
5005 goto memerr3;
5007 else
5008 *pBstrHelpFile = NULL;
5011 result = S_OK;
5013 else
5015 /* for a typeinfo */
5016 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
5018 if(SUCCEEDED(result))
5020 result = ITypeInfo_GetDocumentation(pTInfo,
5021 MEMBERID_NIL,
5022 pBstrName,
5023 pBstrDocString,
5024 pdwHelpContext, pBstrHelpFile);
5026 ITypeInfo_Release(pTInfo);
5029 return result;
5030 memerr3:
5031 if (pBstrDocString) SysFreeString (*pBstrDocString);
5032 memerr2:
5033 if (pBstrName) SysFreeString (*pBstrName);
5034 memerr1:
5035 return STG_E_INSUFFICIENTMEMORY;
5038 /* ITypeLib::IsName
5040 * Indicates whether a passed-in string contains the name of a type or member
5041 * described in the library.
5044 static HRESULT WINAPI ITypeLib2_fnIsName(
5045 ITypeLib2 *iface,
5046 LPOLESTR szNameBuf,
5047 ULONG lHashVal,
5048 BOOL *pfName)
5050 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5051 int tic;
5052 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
5054 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
5055 pfName);
5057 *pfName=TRUE;
5058 for(tic = 0; tic < This->TypeInfoCount; ++tic){
5059 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5060 if(!TLB_str_memcmp(szNameBuf, pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5061 for(fdc = 0; fdc < pTInfo->cFuncs; ++fdc) {
5062 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
5063 int pc;
5064 if(!TLB_str_memcmp(szNameBuf, pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5065 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++){
5066 if(!TLB_str_memcmp(szNameBuf, pFInfo->pParamDesc[pc].Name, nNameBufLen))
5067 goto ITypeLib2_fnIsName_exit;
5070 for(vrc = 0; vrc < pTInfo->cVars; ++vrc){
5071 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
5072 if(!TLB_str_memcmp(szNameBuf, pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5076 *pfName=FALSE;
5078 ITypeLib2_fnIsName_exit:
5079 TRACE("(%p)slow! search for %s: %sfound!\n", This,
5080 debugstr_w(szNameBuf), *pfName ? "" : "NOT ");
5082 return S_OK;
5085 /* ITypeLib::FindName
5087 * Finds occurrences of a type description in a type library. This may be used
5088 * to quickly verify that a name exists in a type library.
5091 static HRESULT WINAPI ITypeLib2_fnFindName(
5092 ITypeLib2 *iface,
5093 LPOLESTR name,
5094 ULONG hash,
5095 ITypeInfo **ppTInfo,
5096 MEMBERID *memid,
5097 UINT16 *found)
5099 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5100 int tic;
5101 UINT count = 0;
5102 UINT len;
5104 TRACE("(%p)->(%s %u %p %p %p)\n", This, debugstr_w(name), hash, ppTInfo, memid, found);
5106 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
5107 return E_INVALIDARG;
5109 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
5110 for(tic = 0; tic < This->TypeInfoCount; ++tic) {
5111 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5112 TLBVarDesc *var;
5113 UINT fdc;
5115 if(!TLB_str_memcmp(name, pTInfo->Name, len)) goto ITypeLib2_fnFindName_exit;
5116 for(fdc = 0; fdc < pTInfo->cFuncs; ++fdc) {
5117 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
5118 int pc;
5120 if(!TLB_str_memcmp(name, func->Name, len)) goto ITypeLib2_fnFindName_exit;
5121 for(pc = 0; pc < func->funcdesc.cParams; pc++) {
5122 if(!TLB_str_memcmp(name, func->pParamDesc[pc].Name, len))
5123 goto ITypeLib2_fnFindName_exit;
5127 var = TLB_get_vardesc_by_name(pTInfo->vardescs, pTInfo->cVars, name);
5128 if (var)
5129 goto ITypeLib2_fnFindName_exit;
5131 continue;
5132 ITypeLib2_fnFindName_exit:
5133 ITypeInfo2_AddRef(&pTInfo->ITypeInfo2_iface);
5134 ppTInfo[count] = (ITypeInfo *)&pTInfo->ITypeInfo2_iface;
5135 count++;
5137 TRACE("found %d typeinfos\n", count);
5139 *found = count;
5141 return S_OK;
5144 /* ITypeLib::ReleaseTLibAttr
5146 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5149 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
5150 ITypeLib2 *iface,
5151 TLIBATTR *pTLibAttr)
5153 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5154 TRACE("(%p)->(%p)\n", This, pTLibAttr);
5155 heap_free(pTLibAttr);
5158 /* ITypeLib2::GetCustData
5160 * gets the custom data
5162 static HRESULT WINAPI ITypeLib2_fnGetCustData(
5163 ITypeLib2 * iface,
5164 REFGUID guid,
5165 VARIANT *pVarVal)
5167 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5168 TLBCustData *pCData;
5170 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
5172 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
5173 if(!pCData)
5174 return TYPE_E_ELEMENTNOTFOUND;
5176 VariantInit(pVarVal);
5177 VariantCopy(pVarVal, &pCData->data);
5179 return S_OK;
5182 /* ITypeLib2::GetLibStatistics
5184 * Returns statistics about a type library that are required for efficient
5185 * sizing of hash tables.
5188 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
5189 ITypeLib2 * iface,
5190 ULONG *pcUniqueNames,
5191 ULONG *pcchUniqueNames)
5193 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5195 FIXME("(%p): stub!\n", This);
5197 if(pcUniqueNames) *pcUniqueNames=1;
5198 if(pcchUniqueNames) *pcchUniqueNames=1;
5199 return S_OK;
5202 /* ITypeLib2::GetDocumentation2
5204 * Retrieves the library's documentation string, the complete Help file name
5205 * and path, the localization context to use, and the context ID for the
5206 * library Help topic in the Help file.
5209 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
5210 ITypeLib2 * iface,
5211 INT index,
5212 LCID lcid,
5213 BSTR *pbstrHelpString,
5214 DWORD *pdwHelpStringContext,
5215 BSTR *pbstrHelpStringDll)
5217 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5218 HRESULT result;
5219 ITypeInfo *pTInfo;
5221 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
5223 /* the help string should be obtained from the helpstringdll,
5224 * using the _DLLGetDocumentation function, based on the supplied
5225 * lcid. Nice to do sometime...
5227 if(index<0)
5229 /* documentation for the typelib */
5230 if(pbstrHelpString)
5231 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->DocString));
5232 if(pdwHelpStringContext)
5233 *pdwHelpStringContext=This->dwHelpContext;
5234 if(pbstrHelpStringDll)
5235 *pbstrHelpStringDll=SysAllocString(TLB_get_bstr(This->HelpStringDll));
5237 result = S_OK;
5239 else
5241 /* for a typeinfo */
5242 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
5244 if(SUCCEEDED(result))
5246 ITypeInfo2 * pTInfo2;
5247 result = ITypeInfo_QueryInterface(pTInfo,
5248 &IID_ITypeInfo2,
5249 (LPVOID*) &pTInfo2);
5251 if(SUCCEEDED(result))
5253 result = ITypeInfo2_GetDocumentation2(pTInfo2,
5254 MEMBERID_NIL,
5255 lcid,
5256 pbstrHelpString,
5257 pdwHelpStringContext,
5258 pbstrHelpStringDll);
5260 ITypeInfo2_Release(pTInfo2);
5263 ITypeInfo_Release(pTInfo);
5266 return result;
5269 static HRESULT TLB_copy_all_custdata(struct list *custdata_list, CUSTDATA *pCustData)
5271 TLBCustData *pCData;
5272 unsigned int ct;
5273 CUSTDATAITEM *cdi;
5275 ct = list_count(custdata_list);
5277 pCustData->prgCustData = heap_alloc_zero(ct * sizeof(CUSTDATAITEM));
5278 if(!pCustData->prgCustData)
5279 return E_OUTOFMEMORY;
5281 pCustData->cCustData = ct;
5283 cdi = pCustData->prgCustData;
5284 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
5285 cdi->guid = *TLB_get_guid_null(pCData->guid);
5286 VariantCopy(&cdi->varValue, &pCData->data);
5287 ++cdi;
5290 return S_OK;
5294 /* ITypeLib2::GetAllCustData
5296 * Gets all custom data items for the library.
5299 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
5300 ITypeLib2 * iface,
5301 CUSTDATA *pCustData)
5303 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5304 TRACE("(%p)->(%p)\n", This, pCustData);
5305 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
5308 static const ITypeLib2Vtbl tlbvt = {
5309 ITypeLib2_fnQueryInterface,
5310 ITypeLib2_fnAddRef,
5311 ITypeLib2_fnRelease,
5312 ITypeLib2_fnGetTypeInfoCount,
5313 ITypeLib2_fnGetTypeInfo,
5314 ITypeLib2_fnGetTypeInfoType,
5315 ITypeLib2_fnGetTypeInfoOfGuid,
5316 ITypeLib2_fnGetLibAttr,
5317 ITypeLib2_fnGetTypeComp,
5318 ITypeLib2_fnGetDocumentation,
5319 ITypeLib2_fnIsName,
5320 ITypeLib2_fnFindName,
5321 ITypeLib2_fnReleaseTLibAttr,
5323 ITypeLib2_fnGetCustData,
5324 ITypeLib2_fnGetLibStatistics,
5325 ITypeLib2_fnGetDocumentation2,
5326 ITypeLib2_fnGetAllCustData
5330 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5332 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5334 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
5337 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
5339 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5341 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
5344 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
5346 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5348 return ITypeLib2_Release(&This->ITypeLib2_iface);
5351 static HRESULT WINAPI ITypeLibComp_fnBind(
5352 ITypeComp * iface,
5353 OLECHAR * szName,
5354 ULONG lHash,
5355 WORD wFlags,
5356 ITypeInfo ** ppTInfo,
5357 DESCKIND * pDescKind,
5358 BINDPTR * pBindPtr)
5360 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5361 int typemismatch=0, i;
5363 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5365 *pDescKind = DESCKIND_NONE;
5366 pBindPtr->lptcomp = NULL;
5367 *ppTInfo = NULL;
5369 for(i = 0; i < This->TypeInfoCount; ++i){
5370 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5371 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo->Name)));
5373 /* FIXME: check wFlags here? */
5374 /* FIXME: we should use a hash table to look this info up using lHash
5375 * instead of an O(n) search */
5376 if ((pTypeInfo->typekind == TKIND_ENUM) ||
5377 (pTypeInfo->typekind == TKIND_MODULE))
5379 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name->str, szName))
5381 *pDescKind = DESCKIND_TYPECOMP;
5382 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
5383 ITypeComp_AddRef(pBindPtr->lptcomp);
5384 TRACE("module or enum: %s\n", debugstr_w(szName));
5385 return S_OK;
5389 if ((pTypeInfo->typekind == TKIND_MODULE) ||
5390 (pTypeInfo->typekind == TKIND_ENUM))
5392 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5393 HRESULT hr;
5395 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5396 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
5398 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
5399 return S_OK;
5401 else if (hr == TYPE_E_TYPEMISMATCH)
5402 typemismatch = 1;
5405 if ((pTypeInfo->typekind == TKIND_COCLASS) &&
5406 (pTypeInfo->wTypeFlags & TYPEFLAG_FAPPOBJECT))
5408 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5409 HRESULT hr;
5410 ITypeInfo *subtypeinfo;
5411 BINDPTR subbindptr;
5412 DESCKIND subdesckind;
5414 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
5415 &subtypeinfo, &subdesckind, &subbindptr);
5416 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
5418 TYPEDESC tdesc_appobject;
5419 const VARDESC vardesc_appobject =
5421 -2, /* memid */
5422 NULL, /* lpstrSchema */
5424 0 /* oInst */
5427 /* ELEMDESC */
5429 /* TYPEDESC */
5431 &tdesc_appobject
5433 VT_PTR
5436 0, /* wVarFlags */
5437 VAR_STATIC /* varkind */
5440 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
5441 tdesc_appobject.vt = VT_USERDEFINED;
5443 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
5445 /* cleanup things filled in by Bind call so we can put our
5446 * application object data in there instead */
5447 switch (subdesckind)
5449 case DESCKIND_FUNCDESC:
5450 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
5451 break;
5452 case DESCKIND_VARDESC:
5453 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
5454 break;
5455 default:
5456 break;
5458 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
5460 if (pTypeInfo->hreftype == -1)
5461 FIXME("no hreftype for interface %p\n", pTypeInfo);
5463 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
5464 if (FAILED(hr))
5465 return hr;
5467 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5468 *ppTInfo = (ITypeInfo *)&pTypeInfo->ITypeInfo2_iface;
5469 ITypeInfo_AddRef(*ppTInfo);
5470 return S_OK;
5472 else if (hr == TYPE_E_TYPEMISMATCH)
5473 typemismatch = 1;
5477 if (typemismatch)
5479 TRACE("type mismatch %s\n", debugstr_w(szName));
5480 return TYPE_E_TYPEMISMATCH;
5482 else
5484 TRACE("name not found %s\n", debugstr_w(szName));
5485 return S_OK;
5489 static HRESULT WINAPI ITypeLibComp_fnBindType(
5490 ITypeComp * iface,
5491 OLECHAR * szName,
5492 ULONG lHash,
5493 ITypeInfo ** ppTInfo,
5494 ITypeComp ** ppTComp)
5496 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5497 ITypeInfoImpl *info;
5499 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5501 if(!szName || !ppTInfo || !ppTComp)
5502 return E_INVALIDARG;
5504 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, szName);
5505 if(!info){
5506 *ppTInfo = NULL;
5507 *ppTComp = NULL;
5508 return S_OK;
5511 *ppTInfo = (ITypeInfo *)&info->ITypeInfo2_iface;
5512 ITypeInfo_AddRef(*ppTInfo);
5513 *ppTComp = &info->ITypeComp_iface;
5514 ITypeComp_AddRef(*ppTComp);
5516 return S_OK;
5519 static const ITypeCompVtbl tlbtcvt =
5522 ITypeLibComp_fnQueryInterface,
5523 ITypeLibComp_fnAddRef,
5524 ITypeLibComp_fnRelease,
5526 ITypeLibComp_fnBind,
5527 ITypeLibComp_fnBindType
5530 /*================== ITypeInfo(2) Methods ===================================*/
5531 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5533 ITypeInfoImpl *pTypeInfoImpl;
5535 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5536 if (pTypeInfoImpl)
5538 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5539 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5540 pTypeInfoImpl->ICreateTypeInfo2_iface.lpVtbl = &CreateTypeInfo2Vtbl;
5541 pTypeInfoImpl->ref = 0;
5542 pTypeInfoImpl->hreftype = -1;
5543 pTypeInfoImpl->memidConstructor = MEMBERID_NIL;
5544 pTypeInfoImpl->memidDestructor = MEMBERID_NIL;
5545 pTypeInfoImpl->pcustdata_list = &pTypeInfoImpl->custdata_list;
5546 list_init(pTypeInfoImpl->pcustdata_list);
5548 TRACE("(%p)\n", pTypeInfoImpl);
5549 return pTypeInfoImpl;
5552 /* ITypeInfo::QueryInterface
5554 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5555 ITypeInfo2 *iface,
5556 REFIID riid,
5557 VOID **ppvObject)
5559 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5561 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5563 *ppvObject=NULL;
5564 if(IsEqualIID(riid, &IID_IUnknown) ||
5565 IsEqualIID(riid,&IID_ITypeInfo)||
5566 IsEqualIID(riid,&IID_ITypeInfo2))
5567 *ppvObject = This;
5568 else if(IsEqualIID(riid, &IID_ICreateTypeInfo) ||
5569 IsEqualIID(riid, &IID_ICreateTypeInfo2))
5570 *ppvObject = &This->ICreateTypeInfo2_iface;
5572 if(*ppvObject){
5573 ITypeInfo2_AddRef(iface);
5574 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5575 return S_OK;
5577 TRACE("-- Interface: E_NOINTERFACE\n");
5578 return E_NOINTERFACE;
5581 /* ITypeInfo::AddRef
5583 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5585 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5586 ULONG ref = InterlockedIncrement(&This->ref);
5588 TRACE("(%p)->ref is %u\n",This, ref);
5590 if (ref == 1 /* incremented from 0 */)
5591 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5593 return ref;
5596 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5598 UINT i;
5600 TRACE("destroying ITypeInfo(%p)\n",This);
5602 for (i = 0; i < This->cFuncs; ++i)
5604 int j;
5605 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5606 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5608 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5609 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5610 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5611 TLB_FreeCustData(&pFInfo->pParamDesc[j].custdata_list);
5613 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5614 heap_free(pFInfo->pParamDesc);
5615 TLB_FreeCustData(&pFInfo->custdata_list);
5617 heap_free(This->funcdescs);
5619 for(i = 0; i < This->cVars; ++i)
5621 TLBVarDesc *pVInfo = &This->vardescs[i];
5622 if (pVInfo->vardesc_create) {
5623 TLB_FreeVarDesc(pVInfo->vardesc_create);
5624 } else if (pVInfo->vardesc.varkind == VAR_CONST) {
5625 VariantClear(pVInfo->vardesc.u.lpvarValue);
5626 heap_free(pVInfo->vardesc.u.lpvarValue);
5628 TLB_FreeCustData(&pVInfo->custdata_list);
5630 heap_free(This->vardescs);
5632 if(This->impltypes){
5633 for (i = 0; i < This->cImplTypes; ++i){
5634 TLBImplType *pImpl = &This->impltypes[i];
5635 TLB_FreeCustData(&pImpl->custdata_list);
5637 heap_free(This->impltypes);
5640 TLB_FreeCustData(&This->custdata_list);
5642 heap_free(This);
5645 /* ITypeInfo::Release
5647 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5649 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5650 ULONG ref = InterlockedDecrement(&This->ref);
5652 TRACE("(%p)->(%u)\n",This, ref);
5654 if (!ref)
5656 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5657 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5658 if (not_attached_to_typelib)
5659 heap_free(This);
5660 /* otherwise This will be freed when typelib is freed */
5663 return ref;
5666 /* ITypeInfo::GetTypeAttr
5668 * Retrieves a TYPEATTR structure that contains the attributes of the type
5669 * description.
5672 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5673 LPTYPEATTR *ppTypeAttr)
5675 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5676 SIZE_T size;
5678 TRACE("(%p)\n",This);
5680 size = sizeof(**ppTypeAttr);
5681 if (This->typekind == TKIND_ALIAS && This->tdescAlias)
5682 size += TLB_SizeTypeDesc(This->tdescAlias, FALSE);
5684 *ppTypeAttr = heap_alloc(size);
5685 if (!*ppTypeAttr)
5686 return E_OUTOFMEMORY;
5688 (*ppTypeAttr)->guid = *TLB_get_guid_null(This->guid);
5689 (*ppTypeAttr)->lcid = This->lcid;
5690 (*ppTypeAttr)->memidConstructor = This->memidConstructor;
5691 (*ppTypeAttr)->memidDestructor = This->memidDestructor;
5692 (*ppTypeAttr)->lpstrSchema = This->lpstrSchema;
5693 (*ppTypeAttr)->cbSizeInstance = This->cbSizeInstance;
5694 (*ppTypeAttr)->typekind = This->typekind;
5695 (*ppTypeAttr)->cFuncs = This->cFuncs;
5696 (*ppTypeAttr)->cVars = This->cVars;
5697 (*ppTypeAttr)->cImplTypes = This->cImplTypes;
5698 (*ppTypeAttr)->cbSizeVft = This->cbSizeVft;
5699 (*ppTypeAttr)->cbAlignment = This->cbAlignment;
5700 (*ppTypeAttr)->wTypeFlags = This->wTypeFlags;
5701 (*ppTypeAttr)->wMajorVerNum = This->wMajorVerNum;
5702 (*ppTypeAttr)->wMinorVerNum = This->wMinorVerNum;
5703 (*ppTypeAttr)->idldescType = This->idldescType;
5705 if (This->tdescAlias)
5706 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5707 This->tdescAlias, *ppTypeAttr + 1);
5708 else{
5709 (*ppTypeAttr)->tdescAlias.vt = VT_EMPTY;
5710 (*ppTypeAttr)->tdescAlias.u.lptdesc = NULL;
5713 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5714 /* This should include all the inherited funcs */
5715 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / This->pTypeLib->ptr_size;
5716 /* This is always the size of IDispatch's vtbl */
5717 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5718 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5720 return S_OK;
5723 /* ITypeInfo::GetTypeComp
5725 * Retrieves the ITypeComp interface for the type description, which enables a
5726 * client compiler to bind to the type description's members.
5729 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5730 ITypeComp * *ppTComp)
5732 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5734 TRACE("(%p)->(%p)\n", This, ppTComp);
5736 *ppTComp = &This->ITypeComp_iface;
5737 ITypeComp_AddRef(*ppTComp);
5738 return S_OK;
5741 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5743 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5744 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5745 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5746 return size;
5749 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5751 *dest = *src;
5752 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5753 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5755 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5756 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5757 *buffer += sizeof(PARAMDESCEX);
5758 *pparamdescex_dest = *pparamdescex_src;
5759 pparamdescex_dest->cBytes = sizeof(PARAMDESCEX);
5760 VariantInit(&pparamdescex_dest->varDefaultValue);
5761 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5762 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5764 else
5765 dest->u.paramdesc.pparamdescex = NULL;
5766 return S_OK;
5769 static HRESULT TLB_SanitizeBSTR(BSTR str)
5771 UINT len = SysStringLen(str), i;
5772 for (i = 0; i < len; ++i)
5773 if (str[i] > 0x7f)
5774 str[i] = '?';
5775 return S_OK;
5778 static HRESULT TLB_SanitizeVariant(VARIANT *var)
5780 if (V_VT(var) == VT_INT)
5781 return VariantChangeType(var, var, 0, VT_I4);
5782 else if (V_VT(var) == VT_UINT)
5783 return VariantChangeType(var, var, 0, VT_UI4);
5784 else if (V_VT(var) == VT_BSTR)
5785 return TLB_SanitizeBSTR(V_BSTR(var));
5787 return S_OK;
5790 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5792 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5793 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5796 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5798 FUNCDESC *dest;
5799 char *buffer;
5800 SIZE_T size = sizeof(*src);
5801 SHORT i;
5802 HRESULT hr;
5804 size += sizeof(*src->lprgscode) * src->cScodes;
5805 size += TLB_SizeElemDesc(&src->elemdescFunc);
5806 for (i = 0; i < src->cParams; i++)
5808 size += sizeof(ELEMDESC);
5809 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5812 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5813 if (!dest) return E_OUTOFMEMORY;
5815 *dest = *src;
5816 if (dispinterface) /* overwrite funckind */
5817 dest->funckind = FUNC_DISPATCH;
5818 buffer = (char *)(dest + 1);
5820 dest->oVft = dest->oVft & 0xFFFC;
5822 if (dest->cScodes) {
5823 dest->lprgscode = (SCODE *)buffer;
5824 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5825 buffer += sizeof(*src->lprgscode) * src->cScodes;
5826 } else
5827 dest->lprgscode = NULL;
5829 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5830 if (FAILED(hr))
5832 SysFreeString((BSTR)dest);
5833 return hr;
5836 if (dest->cParams) {
5837 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5838 buffer += sizeof(ELEMDESC) * src->cParams;
5839 for (i = 0; i < src->cParams; i++)
5841 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5842 if (FAILED(hr))
5843 break;
5845 if (FAILED(hr))
5847 /* undo the above actions */
5848 for (i = i - 1; i >= 0; i--)
5849 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5850 TLB_FreeElemDesc(&dest->elemdescFunc);
5851 SysFreeString((BSTR)dest);
5852 return hr;
5854 } else
5855 dest->lprgelemdescParam = NULL;
5857 /* special treatment for dispinterfaces: this makes functions appear
5858 * to return their [retval] value when it is really returning an
5859 * HRESULT */
5860 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5862 if (dest->cParams &&
5863 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5865 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5866 if (elemdesc->tdesc.vt != VT_PTR)
5868 ERR("elemdesc should have started with VT_PTR instead of:\n");
5869 if (ERR_ON(ole))
5870 dump_ELEMDESC(elemdesc);
5871 return E_UNEXPECTED;
5874 /* copy last parameter to the return value. we are using a flat
5875 * buffer so there is no danger of leaking memory in
5876 * elemdescFunc */
5877 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5879 /* remove the last parameter */
5880 dest->cParams--;
5882 else
5883 /* otherwise this function is made to appear to have no return
5884 * value */
5885 dest->elemdescFunc.tdesc.vt = VT_VOID;
5889 *dest_ptr = dest;
5890 return S_OK;
5893 static void TLB_FreeVarDesc(VARDESC *var_desc)
5895 TLB_FreeElemDesc(&var_desc->elemdescVar);
5896 if (var_desc->varkind == VAR_CONST)
5897 VariantClear(var_desc->u.lpvarValue);
5898 SysFreeString((BSTR)var_desc);
5901 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5903 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5905 if (index >= This->cFuncs)
5906 return TYPE_E_ELEMENTNOTFOUND;
5908 *ppFuncDesc = &This->funcdescs[index].funcdesc;
5909 return S_OK;
5912 /* internal function to make the inherited interfaces' methods appear
5913 * part of the interface */
5914 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5915 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5917 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5918 HRESULT hr;
5919 UINT implemented_funcs = 0;
5921 if (funcs)
5922 *funcs = 0;
5923 else
5924 *hrefoffset = DISPATCH_HREF_OFFSET;
5926 if(This->impltypes)
5928 ITypeInfo *pSubTypeInfo;
5929 UINT sub_funcs;
5931 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5932 if (FAILED(hr))
5933 return hr;
5935 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5936 index,
5937 ppFuncDesc,
5938 &sub_funcs, hrefoffset);
5939 implemented_funcs += sub_funcs;
5940 ITypeInfo_Release(pSubTypeInfo);
5941 if (SUCCEEDED(hr))
5942 return hr;
5943 *hrefoffset += DISPATCH_HREF_OFFSET;
5946 if (funcs)
5947 *funcs = implemented_funcs + This->cFuncs;
5948 else
5949 *hrefoffset = 0;
5951 if (index < implemented_funcs)
5952 return E_INVALIDARG;
5953 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5954 ppFuncDesc);
5957 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5959 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5960 while (TRUE)
5962 switch (pTypeDesc->vt)
5964 case VT_USERDEFINED:
5965 pTypeDesc->u.hreftype += hrefoffset;
5966 return;
5967 case VT_PTR:
5968 case VT_SAFEARRAY:
5969 pTypeDesc = pTypeDesc->u.lptdesc;
5970 break;
5971 case VT_CARRAY:
5972 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5973 break;
5974 default:
5975 return;
5980 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5982 SHORT i;
5983 for (i = 0; i < pFuncDesc->cParams; i++)
5984 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5985 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5988 /* ITypeInfo::GetFuncDesc
5990 * Retrieves the FUNCDESC structure that contains information about a
5991 * specified function.
5994 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5995 LPFUNCDESC *ppFuncDesc)
5997 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5998 const FUNCDESC *internal_funcdesc;
5999 HRESULT hr;
6000 UINT hrefoffset = 0;
6002 TRACE("(%p) index %d\n", This, index);
6004 if (!ppFuncDesc)
6005 return E_INVALIDARG;
6007 if (This->needs_layout)
6008 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6010 if (This->typekind == TKIND_DISPATCH)
6011 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
6012 &internal_funcdesc, NULL,
6013 &hrefoffset);
6014 else
6015 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
6016 &internal_funcdesc);
6017 if (FAILED(hr))
6019 WARN("description for function %d not found\n", index);
6020 return hr;
6023 hr = TLB_AllocAndInitFuncDesc(
6024 internal_funcdesc,
6025 ppFuncDesc,
6026 This->typekind == TKIND_DISPATCH);
6028 if ((This->typekind == TKIND_DISPATCH) && hrefoffset)
6029 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
6031 TRACE("-- 0x%08x\n", hr);
6032 return hr;
6035 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
6037 VARDESC *dest;
6038 char *buffer;
6039 SIZE_T size = sizeof(*src);
6040 HRESULT hr;
6042 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
6043 if (src->varkind == VAR_CONST)
6044 size += sizeof(VARIANT);
6045 size += TLB_SizeElemDesc(&src->elemdescVar);
6047 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
6048 if (!dest) return E_OUTOFMEMORY;
6050 *dest = *src;
6051 buffer = (char *)(dest + 1);
6052 if (src->lpstrSchema)
6054 int len;
6055 dest->lpstrSchema = (LPOLESTR)buffer;
6056 len = strlenW(src->lpstrSchema);
6057 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
6058 buffer += (len + 1) * sizeof(WCHAR);
6061 if (src->varkind == VAR_CONST)
6063 HRESULT hr;
6065 dest->u.lpvarValue = (VARIANT *)buffer;
6066 *dest->u.lpvarValue = *src->u.lpvarValue;
6067 buffer += sizeof(VARIANT);
6068 VariantInit(dest->u.lpvarValue);
6069 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
6070 if (FAILED(hr))
6072 SysFreeString((BSTR)dest);
6073 return hr;
6076 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
6077 if (FAILED(hr))
6079 if (src->varkind == VAR_CONST)
6080 VariantClear(dest->u.lpvarValue);
6081 SysFreeString((BSTR)dest);
6082 return hr;
6084 *dest_ptr = dest;
6085 return S_OK;
6088 /* ITypeInfo::GetVarDesc
6090 * Retrieves a VARDESC structure that describes the specified variable.
6093 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
6094 LPVARDESC *ppVarDesc)
6096 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6097 const TLBVarDesc *pVDesc = &This->vardescs[index];
6099 TRACE("(%p) index %d\n", This, index);
6101 if(index >= This->cVars)
6102 return TYPE_E_ELEMENTNOTFOUND;
6104 if (This->needs_layout)
6105 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6107 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
6110 /* ITypeInfo_GetNames
6112 * Retrieves the variable with the specified member ID (or the name of the
6113 * property or method and its parameters) that correspond to the specified
6114 * function ID.
6116 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
6117 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
6119 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6120 const TLBFuncDesc *pFDesc;
6121 const TLBVarDesc *pVDesc;
6122 int i;
6123 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
6125 if(!rgBstrNames)
6126 return E_INVALIDARG;
6128 *pcNames = 0;
6130 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
6131 if(pFDesc)
6133 if(!cMaxNames || !pFDesc->Name)
6134 return S_OK;
6136 *rgBstrNames = SysAllocString(TLB_get_bstr(pFDesc->Name));
6137 ++(*pcNames);
6139 for(i = 0; i < pFDesc->funcdesc.cParams; ++i){
6140 if(*pcNames >= cMaxNames || !pFDesc->pParamDesc[i].Name)
6141 return S_OK;
6142 rgBstrNames[*pcNames] = SysAllocString(TLB_get_bstr(pFDesc->pParamDesc[i].Name));
6143 ++(*pcNames);
6145 return S_OK;
6148 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
6149 if(pVDesc)
6151 *rgBstrNames=SysAllocString(TLB_get_bstr(pVDesc->Name));
6152 *pcNames=1;
6154 else
6156 if(This->impltypes &&
6157 (This->typekind==TKIND_INTERFACE || This->typekind==TKIND_DISPATCH)) {
6158 /* recursive search */
6159 ITypeInfo *pTInfo;
6160 HRESULT result;
6161 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6162 if(SUCCEEDED(result))
6164 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
6165 ITypeInfo_Release(pTInfo);
6166 return result;
6168 WARN("Could not search inherited interface!\n");
6170 else
6172 WARN("no names found\n");
6174 *pcNames=0;
6175 return TYPE_E_ELEMENTNOTFOUND;
6177 return S_OK;
6181 /* ITypeInfo::GetRefTypeOfImplType
6183 * If a type description describes a COM class, it retrieves the type
6184 * description of the implemented interface types. For an interface,
6185 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6186 * if any exist.
6189 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
6190 ITypeInfo2 *iface,
6191 UINT index,
6192 HREFTYPE *pRefType)
6194 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6195 HRESULT hr = S_OK;
6197 TRACE("(%p) index %d\n", This, index);
6198 if (TRACE_ON(ole)) dump_TypeInfo(This);
6200 if(index==(UINT)-1)
6202 /* only valid on dual interfaces;
6203 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6206 if (This->wTypeFlags & TYPEFLAG_FDUAL)
6208 *pRefType = -2;
6210 else
6212 hr = TYPE_E_ELEMENTNOTFOUND;
6215 else if(index == 0 && This->typekind == TKIND_DISPATCH)
6217 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6218 *pRefType = This->pTypeLib->dispatch_href;
6220 else
6222 if(index >= This->cImplTypes)
6223 hr = TYPE_E_ELEMENTNOTFOUND;
6224 else{
6225 *pRefType = This->impltypes[index].hRef;
6226 if(This->typekind == TKIND_INTERFACE)
6227 *pRefType |= 0x2;
6231 if(TRACE_ON(ole))
6233 if(SUCCEEDED(hr))
6234 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
6235 else
6236 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
6239 return hr;
6242 /* ITypeInfo::GetImplTypeFlags
6244 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6245 * or base interface in a type description.
6247 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
6248 UINT index, INT *pImplTypeFlags)
6250 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6252 TRACE("(%p) index %d\n", This, index);
6254 if(!pImplTypeFlags)
6255 return E_INVALIDARG;
6257 if(This->typekind == TKIND_DISPATCH && index == 0){
6258 *pImplTypeFlags = 0;
6259 return S_OK;
6262 if(index >= This->cImplTypes)
6263 return TYPE_E_ELEMENTNOTFOUND;
6265 *pImplTypeFlags = This->impltypes[index].implflags;
6267 return S_OK;
6270 /* GetIDsOfNames
6271 * Maps between member names and member IDs, and parameter names and
6272 * parameter IDs.
6274 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
6275 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
6277 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6278 const TLBVarDesc *pVDesc;
6279 HRESULT ret=S_OK;
6280 UINT i, fdc;
6282 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
6283 cNames);
6285 /* init out parameters in case of failure */
6286 for (i = 0; i < cNames; i++)
6287 pMemId[i] = MEMBERID_NIL;
6289 for (fdc = 0; fdc < This->cFuncs; ++fdc) {
6290 int j;
6291 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
6292 if(!lstrcmpiW(*rgszNames, TLB_get_bstr(pFDesc->Name))) {
6293 if(cNames) *pMemId=pFDesc->funcdesc.memid;
6294 for(i=1; i < cNames; i++){
6295 for(j=0; j<pFDesc->funcdesc.cParams; j++)
6296 if(!lstrcmpiW(rgszNames[i],TLB_get_bstr(pFDesc->pParamDesc[j].Name)))
6297 break;
6298 if( j<pFDesc->funcdesc.cParams)
6299 pMemId[i]=j;
6300 else
6301 ret=DISP_E_UNKNOWNNAME;
6303 TRACE("-- 0x%08x\n", ret);
6304 return ret;
6307 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->cVars, *rgszNames);
6308 if(pVDesc){
6309 if(cNames)
6310 *pMemId = pVDesc->vardesc.memid;
6311 return ret;
6313 /* not found, see if it can be found in an inherited interface */
6314 if(This->impltypes) {
6315 /* recursive search */
6316 ITypeInfo *pTInfo;
6317 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6318 if(SUCCEEDED(ret)){
6319 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
6320 ITypeInfo_Release(pTInfo);
6321 return ret;
6323 WARN("Could not search inherited interface!\n");
6324 } else
6325 WARN("no names found\n");
6326 return DISP_E_UNKNOWNNAME;
6330 #ifdef __i386__
6332 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6333 __ASM_GLOBAL_FUNC( call_method,
6334 "pushl %ebp\n\t"
6335 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6336 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6337 "movl %esp,%ebp\n\t"
6338 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6339 "pushl %esi\n\t"
6340 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6341 "pushl %edi\n\t"
6342 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6343 "movl 12(%ebp),%edx\n\t"
6344 "movl %esp,%edi\n\t"
6345 "shll $2,%edx\n\t"
6346 "jz 1f\n\t"
6347 "subl %edx,%edi\n\t"
6348 "andl $~15,%edi\n\t"
6349 "movl %edi,%esp\n\t"
6350 "movl 12(%ebp),%ecx\n\t"
6351 "movl 16(%ebp),%esi\n\t"
6352 "cld\n\t"
6353 "rep; movsl\n"
6354 "1:\tcall *8(%ebp)\n\t"
6355 "subl %esp,%edi\n\t"
6356 "movl 20(%ebp),%ecx\n\t"
6357 "movl %edi,(%ecx)\n\t"
6358 "leal -8(%ebp),%esp\n\t"
6359 "popl %edi\n\t"
6360 __ASM_CFI(".cfi_same_value %edi\n\t")
6361 "popl %esi\n\t"
6362 __ASM_CFI(".cfi_same_value %esi\n\t")
6363 "popl %ebp\n\t"
6364 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6365 __ASM_CFI(".cfi_same_value %ebp\n\t")
6366 "ret" )
6368 /* same function but returning floating point */
6369 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
6371 /* ITypeInfo::Invoke
6373 * Invokes a method, or accesses a property of an object, that implements the
6374 * interface described by the type description.
6376 DWORD
6377 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
6378 DWORD res;
6379 int stack_offset;
6381 if (TRACE_ON(ole)) {
6382 int i;
6383 TRACE("Calling %p(",func);
6384 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
6385 if (nrargs > 30) TRACE("...");
6386 TRACE(")\n");
6389 switch (callconv) {
6390 case CC_STDCALL:
6391 case CC_CDECL:
6392 res = call_method( func, nrargs, args, &stack_offset );
6393 break;
6394 default:
6395 FIXME("unsupported calling convention %d\n",callconv);
6396 res = -1;
6397 break;
6399 TRACE("returns %08x\n",res);
6400 return res;
6403 #elif defined(__x86_64__)
6405 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
6406 __ASM_GLOBAL_FUNC( call_method,
6407 "pushq %rbp\n\t"
6408 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6409 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6410 "movq %rsp,%rbp\n\t"
6411 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6412 "pushq %rsi\n\t"
6413 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6414 "pushq %rdi\n\t"
6415 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6416 "movq %rcx,%rax\n\t"
6417 "movq $4,%rcx\n\t"
6418 "cmp %rcx,%rdx\n\t"
6419 "cmovgq %rdx,%rcx\n\t"
6420 "leaq 0(,%rcx,8),%rdx\n\t"
6421 "subq %rdx,%rsp\n\t"
6422 "andq $~15,%rsp\n\t"
6423 "movq %rsp,%rdi\n\t"
6424 "movq %r8,%rsi\n\t"
6425 "rep; movsq\n\t"
6426 "movq 0(%rsp),%rcx\n\t"
6427 "movq 8(%rsp),%rdx\n\t"
6428 "movq 16(%rsp),%r8\n\t"
6429 "movq 24(%rsp),%r9\n\t"
6430 "movq %rcx,%xmm0\n\t"
6431 "movq %rdx,%xmm1\n\t"
6432 "movq %r8,%xmm2\n\t"
6433 "movq %r9,%xmm3\n\t"
6434 "callq *%rax\n\t"
6435 "leaq -16(%rbp),%rsp\n\t"
6436 "popq %rdi\n\t"
6437 __ASM_CFI(".cfi_same_value %rdi\n\t")
6438 "popq %rsi\n\t"
6439 __ASM_CFI(".cfi_same_value %rsi\n\t")
6440 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6441 "popq %rbp\n\t"
6442 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6443 __ASM_CFI(".cfi_same_value %rbp\n\t")
6444 "ret")
6446 /* same function but returning floating point */
6447 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
6449 #endif /* __x86_64__ */
6451 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6453 HRESULT hr = S_OK;
6454 ITypeInfo *tinfo2 = NULL;
6455 TYPEATTR *tattr = NULL;
6457 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6458 if (hr)
6460 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6461 "hr = 0x%08x\n",
6462 tdesc->u.hreftype, hr);
6463 return hr;
6465 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6466 if (hr)
6468 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
6469 ITypeInfo_Release(tinfo2);
6470 return hr;
6473 switch (tattr->typekind)
6475 case TKIND_ENUM:
6476 *vt |= VT_I4;
6477 break;
6479 case TKIND_ALIAS:
6480 tdesc = &tattr->tdescAlias;
6481 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
6482 break;
6484 case TKIND_INTERFACE:
6485 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
6486 *vt |= VT_DISPATCH;
6487 else
6488 *vt |= VT_UNKNOWN;
6489 break;
6491 case TKIND_DISPATCH:
6492 *vt |= VT_DISPATCH;
6493 break;
6495 case TKIND_COCLASS:
6496 *vt |= VT_DISPATCH;
6497 break;
6499 case TKIND_RECORD:
6500 FIXME("TKIND_RECORD unhandled.\n");
6501 hr = E_NOTIMPL;
6502 break;
6504 case TKIND_UNION:
6505 FIXME("TKIND_UNION unhandled.\n");
6506 hr = E_NOTIMPL;
6507 break;
6509 default:
6510 FIXME("TKIND %d unhandled.\n",tattr->typekind);
6511 hr = E_NOTIMPL;
6512 break;
6514 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6515 ITypeInfo_Release(tinfo2);
6516 return hr;
6519 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6521 HRESULT hr = S_OK;
6523 /* enforce only one level of pointer indirection */
6524 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
6526 tdesc = tdesc->u.lptdesc;
6528 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6529 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6530 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6531 if ((tdesc->vt == VT_USERDEFINED) ||
6532 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
6534 VARTYPE vt_userdefined = 0;
6535 const TYPEDESC *tdesc_userdefined = tdesc;
6536 if (tdesc->vt == VT_PTR)
6538 vt_userdefined = VT_BYREF;
6539 tdesc_userdefined = tdesc->u.lptdesc;
6541 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
6542 if ((hr == S_OK) &&
6543 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
6544 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
6546 *vt |= vt_userdefined;
6547 return S_OK;
6550 *vt = VT_BYREF;
6553 switch (tdesc->vt)
6555 case VT_HRESULT:
6556 *vt |= VT_ERROR;
6557 break;
6558 case VT_USERDEFINED:
6559 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
6560 break;
6561 case VT_VOID:
6562 case VT_CARRAY:
6563 case VT_PTR:
6564 case VT_LPSTR:
6565 case VT_LPWSTR:
6566 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
6567 hr = DISP_E_BADVARTYPE;
6568 break;
6569 case VT_SAFEARRAY:
6570 *vt |= VT_ARRAY;
6571 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
6572 break;
6573 case VT_INT:
6574 *vt |= VT_I4;
6575 break;
6576 case VT_UINT:
6577 *vt |= VT_UI4;
6578 break;
6579 default:
6580 *vt |= tdesc->vt;
6581 break;
6583 return hr;
6586 static HRESULT get_iface_guid(ITypeInfo *tinfo, const TYPEDESC *tdesc, GUID *guid)
6588 ITypeInfo *tinfo2;
6589 TYPEATTR *tattr;
6590 HRESULT hres;
6592 hres = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6593 if(FAILED(hres))
6594 return hres;
6596 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6597 if(FAILED(hres)) {
6598 ITypeInfo_Release(tinfo2);
6599 return hres;
6602 switch(tattr->typekind) {
6603 case TKIND_ALIAS:
6604 hres = get_iface_guid(tinfo2, &tattr->tdescAlias, guid);
6605 break;
6607 case TKIND_INTERFACE:
6608 case TKIND_DISPATCH:
6609 *guid = tattr->guid;
6610 break;
6612 default:
6613 ERR("Unexpected typekind %d\n", tattr->typekind);
6614 hres = E_UNEXPECTED;
6617 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6618 ITypeInfo_Release(tinfo2);
6619 return hres;
6622 /***********************************************************************
6623 * DispCallFunc (OLEAUT32.@)
6625 * Invokes a function of the specified calling convention, passing the
6626 * specified arguments and returns the result.
6628 * PARAMS
6629 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6630 * oVft [I] The offset in the vtable. See notes.
6631 * cc [I] Calling convention of the function to call.
6632 * vtReturn [I] The return type of the function.
6633 * cActuals [I] Number of parameters.
6634 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6635 * prgpvarg [I] The arguments to pass.
6636 * pvargResult [O] The return value of the function. Can be NULL.
6638 * RETURNS
6639 * Success: S_OK.
6640 * Failure: HRESULT code.
6642 * NOTES
6643 * The HRESULT return value of this function is not affected by the return
6644 * value of the user supplied function, which is returned in pvargResult.
6646 * If pvInstance is NULL then a non-object function is to be called and oVft
6647 * is the address of the function to call.
6649 * The cc parameter can be one of the following values:
6650 *|CC_FASTCALL
6651 *|CC_CDECL
6652 *|CC_PASCAL
6653 *|CC_STDCALL
6654 *|CC_FPFASTCALL
6655 *|CC_SYSCALL
6656 *|CC_MPWCDECL
6657 *|CC_MPWPASCAL
6660 HRESULT WINAPI
6661 DispCallFunc(
6662 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
6663 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
6665 #ifdef __i386__
6666 int argspos, stack_offset;
6667 void *func;
6668 UINT i;
6669 DWORD *args;
6671 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6672 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6673 pvargResult, V_VT(pvargResult));
6675 if (cc != CC_STDCALL && cc != CC_CDECL)
6677 FIXME("unsupported calling convention %d\n",cc);
6678 return E_INVALIDARG;
6681 /* maximum size for an argument is sizeof(VARIANT) */
6682 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6684 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6685 argspos = 1;
6686 if (pvInstance)
6688 const FARPROC *vtable = *(FARPROC **)pvInstance;
6689 func = vtable[oVft/sizeof(void *)];
6690 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6692 else func = (void *)oVft;
6694 for (i = 0; i < cActuals; i++)
6696 VARIANT *arg = prgpvarg[i];
6698 switch (prgvt[i])
6700 case VT_EMPTY:
6701 break;
6702 case VT_I8:
6703 case VT_UI8:
6704 case VT_R8:
6705 case VT_DATE:
6706 case VT_CY:
6707 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6708 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6709 break;
6710 case VT_DECIMAL:
6711 case VT_VARIANT:
6712 memcpy( &args[argspos], arg, sizeof(*arg) );
6713 argspos += sizeof(*arg) / sizeof(DWORD);
6714 break;
6715 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6716 args[argspos++] = V_BOOL(arg);
6717 break;
6718 default:
6719 args[argspos++] = V_UI4(arg);
6720 break;
6722 TRACE("arg %u: type %d\n",i,prgvt[i]);
6723 dump_Variant(arg);
6726 switch (vtReturn)
6728 case VT_EMPTY:
6729 call_method( func, argspos - 1, args + 1, &stack_offset );
6730 break;
6731 case VT_R4:
6732 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6733 break;
6734 case VT_R8:
6735 case VT_DATE:
6736 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6737 break;
6738 case VT_DECIMAL:
6739 case VT_VARIANT:
6740 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6741 call_method( func, argspos, args, &stack_offset );
6742 break;
6743 case VT_I8:
6744 case VT_UI8:
6745 case VT_CY:
6746 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6747 break;
6748 case VT_HRESULT:
6749 WARN("invalid return type %u\n", vtReturn);
6750 heap_free( args );
6751 return E_INVALIDARG;
6752 default:
6753 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6754 break;
6756 heap_free( args );
6757 if (stack_offset && cc == CC_STDCALL)
6759 WARN( "stack pointer off by %d\n", stack_offset );
6760 return DISP_E_BADCALLEE;
6762 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6763 TRACE("retval: "); dump_Variant(pvargResult);
6764 return S_OK;
6766 #elif defined(__x86_64__)
6767 int argspos;
6768 UINT i;
6769 DWORD_PTR *args;
6770 void *func;
6772 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6773 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6774 pvargResult, V_VT(pvargResult));
6776 if (cc != CC_STDCALL && cc != CC_CDECL)
6778 FIXME("unsupported calling convention %d\n",cc);
6779 return E_INVALIDARG;
6782 /* maximum size for an argument is sizeof(DWORD_PTR) */
6783 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6785 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6786 argspos = 1;
6787 if (pvInstance)
6789 const FARPROC *vtable = *(FARPROC **)pvInstance;
6790 func = vtable[oVft/sizeof(void *)];
6791 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6793 else func = (void *)oVft;
6795 for (i = 0; i < cActuals; i++)
6797 VARIANT *arg = prgpvarg[i];
6799 switch (prgvt[i])
6801 case VT_DECIMAL:
6802 case VT_VARIANT:
6803 args[argspos++] = (ULONG_PTR)arg;
6804 break;
6805 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6806 args[argspos++] = V_BOOL(arg);
6807 break;
6808 default:
6809 args[argspos++] = V_UI8(arg);
6810 break;
6812 TRACE("arg %u: type %d\n",i,prgvt[i]);
6813 dump_Variant(arg);
6816 switch (vtReturn)
6818 case VT_R4:
6819 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6820 break;
6821 case VT_R8:
6822 case VT_DATE:
6823 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6824 break;
6825 case VT_DECIMAL:
6826 case VT_VARIANT:
6827 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6828 call_method( func, argspos, args );
6829 break;
6830 case VT_HRESULT:
6831 WARN("invalid return type %u\n", vtReturn);
6832 heap_free( args );
6833 return E_INVALIDARG;
6834 default:
6835 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6836 break;
6838 heap_free( args );
6839 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6840 TRACE("retval: "); dump_Variant(pvargResult);
6841 return S_OK;
6843 #else
6844 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6845 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6846 return E_NOTIMPL;
6847 #endif
6850 static inline BOOL func_restricted( const FUNCDESC *desc )
6852 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
6855 #define INVBUF_ELEMENT_SIZE \
6856 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6857 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6858 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6859 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6860 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6861 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6862 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6863 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6865 static HRESULT WINAPI ITypeInfo_fnInvoke(
6866 ITypeInfo2 *iface,
6867 VOID *pIUnk,
6868 MEMBERID memid,
6869 UINT16 wFlags,
6870 DISPPARAMS *pDispParams,
6871 VARIANT *pVarResult,
6872 EXCEPINFO *pExcepInfo,
6873 UINT *pArgErr)
6875 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6876 int i;
6877 unsigned int var_index;
6878 TYPEKIND type_kind;
6879 HRESULT hres;
6880 const TLBFuncDesc *pFuncInfo;
6881 UINT fdc;
6883 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6884 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6887 if( This->wTypeFlags & TYPEFLAG_FRESTRICTED )
6888 return DISP_E_MEMBERNOTFOUND;
6890 if (!pDispParams)
6892 ERR("NULL pDispParams not allowed\n");
6893 return E_INVALIDARG;
6896 dump_DispParms(pDispParams);
6898 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6900 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6901 pDispParams->cNamedArgs, pDispParams->cArgs);
6902 return E_INVALIDARG;
6905 /* we do this instead of using GetFuncDesc since it will return a fake
6906 * FUNCDESC for dispinterfaces and we want the real function description */
6907 for (fdc = 0; fdc < This->cFuncs; ++fdc){
6908 pFuncInfo = &This->funcdescs[fdc];
6909 if ((memid == pFuncInfo->funcdesc.memid) &&
6910 (wFlags & pFuncInfo->funcdesc.invkind) &&
6911 !func_restricted( &pFuncInfo->funcdesc ))
6912 break;
6915 if (fdc < This->cFuncs) {
6916 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6918 if (TRACE_ON(ole))
6920 TRACE("invoking:\n");
6921 dump_TLBFuncDescOne(pFuncInfo);
6924 switch (func_desc->funckind) {
6925 case FUNC_PUREVIRTUAL:
6926 case FUNC_VIRTUAL: {
6927 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
6928 VARIANT varresult;
6929 VARIANT retval; /* pointer for storing byref retvals in */
6930 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6931 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6932 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6933 UINT cNamedArgs = pDispParams->cNamedArgs;
6934 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6935 UINT vargs_converted=0;
6937 hres = S_OK;
6939 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6941 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6943 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6944 hres = DISP_E_PARAMNOTFOUND;
6945 goto func_fail;
6949 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6951 ERR("functions with the vararg attribute do not support named arguments\n");
6952 hres = DISP_E_NONAMEDARGS;
6953 goto func_fail;
6956 for (i = 0; i < func_desc->cParams; i++)
6958 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6959 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6960 if (FAILED(hres))
6961 goto func_fail;
6964 TRACE("changing args\n");
6965 for (i = 0; i < func_desc->cParams; i++)
6967 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6968 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6969 VARIANTARG *src_arg;
6971 if (wParamFlags & PARAMFLAG_FLCID)
6973 VARIANTARG *arg;
6974 arg = prgpvarg[i] = &rgvarg[i];
6975 V_VT(arg) = VT_I4;
6976 V_I4(arg) = This->pTypeLib->lcid;
6977 continue;
6980 src_arg = NULL;
6982 if (cNamedArgs)
6984 USHORT j;
6985 for (j = 0; j < cNamedArgs; j++)
6986 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
6988 src_arg = &pDispParams->rgvarg[j];
6989 break;
6993 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
6995 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6996 vargs_converted++;
6999 if (wParamFlags & PARAMFLAG_FRETVAL)
7001 /* under most conditions the caller is not allowed to
7002 * pass in a dispparam arg in the index of what would be
7003 * the retval parameter. however, there is an exception
7004 * where the extra parameter is used in an extra
7005 * IDispatch::Invoke below */
7006 if ((i < pDispParams->cArgs) &&
7007 ((func_desc->cParams != 1) || !pVarResult ||
7008 !(func_desc->invkind & INVOKE_PROPERTYGET)))
7010 hres = DISP_E_BADPARAMCOUNT;
7011 break;
7014 /* note: this check is placed so that if the caller passes
7015 * in a VARIANTARG for the retval we just ignore it, like
7016 * native does */
7017 if (i == func_desc->cParams - 1)
7019 VARIANTARG *arg;
7020 arg = prgpvarg[i] = &rgvarg[i];
7021 memset(arg, 0, sizeof(*arg));
7022 V_VT(arg) = rgvt[i];
7023 memset(&retval, 0, sizeof(retval));
7024 V_BYREF(arg) = &retval;
7026 else
7028 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
7029 hres = E_UNEXPECTED;
7030 break;
7033 else if (src_arg)
7035 dump_Variant(src_arg);
7037 if(rgvt[i]!=V_VT(src_arg))
7039 if (rgvt[i] == VT_VARIANT)
7040 hres = VariantCopy(&rgvarg[i], src_arg);
7041 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
7043 if (rgvt[i] == V_VT(src_arg))
7044 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
7045 else
7047 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7048 if (wParamFlags & PARAMFLAG_FIN)
7049 hres = VariantCopy(&missing_arg[i], src_arg);
7050 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
7052 V_VT(&rgvarg[i]) = rgvt[i];
7054 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
7056 SAFEARRAY *a;
7057 SAFEARRAYBOUND bound;
7058 VARIANT *v;
7059 LONG j;
7060 bound.lLbound = 0;
7061 bound.cElements = pDispParams->cArgs-i;
7062 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
7064 ERR("SafeArrayCreate failed\n");
7065 break;
7067 hres = SafeArrayAccessData(a, (LPVOID)&v);
7068 if (hres != S_OK)
7070 ERR("SafeArrayAccessData failed with %x\n", hres);
7071 SafeArrayDestroy(a);
7072 break;
7074 for (j = 0; j < bound.cElements; j++)
7075 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
7076 hres = SafeArrayUnaccessData(a);
7077 if (hres != S_OK)
7079 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7080 SafeArrayDestroy(a);
7081 break;
7083 V_ARRAY(&rgvarg[i]) = a;
7084 V_VT(&rgvarg[i]) = rgvt[i];
7086 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
7088 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7089 if (wParamFlags & PARAMFLAG_FIN)
7090 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
7091 else
7092 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
7093 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
7094 V_VT(&rgvarg[i]) = rgvt[i];
7096 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
7098 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
7099 V_VT(&rgvarg[i]) = rgvt[i];
7101 else
7103 /* FIXME: this doesn't work for VT_BYREF arguments if
7104 * they are not the same type as in the paramdesc */
7105 V_VT(&rgvarg[i]) = V_VT(src_arg);
7106 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
7107 V_VT(&rgvarg[i]) = rgvt[i];
7110 if (FAILED(hres))
7112 ERR("failed to convert param %d to %s%s from %s%s\n", i,
7113 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
7114 debugstr_VT(src_arg), debugstr_VF(src_arg));
7115 break;
7117 prgpvarg[i] = &rgvarg[i];
7119 else
7121 prgpvarg[i] = src_arg;
7124 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
7125 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
7126 && V_UNKNOWN(prgpvarg[i])) {
7127 IUnknown *userdefined_iface;
7128 GUID guid;
7130 hres = get_iface_guid((ITypeInfo*)iface, tdesc->vt == VT_PTR ? tdesc->u.lptdesc : tdesc, &guid);
7131 if(FAILED(hres))
7132 break;
7134 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
7135 if(FAILED(hres)) {
7136 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
7137 break;
7140 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
7141 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
7144 else if (wParamFlags & PARAMFLAG_FOPT)
7146 VARIANTARG *arg;
7147 arg = prgpvarg[i] = &rgvarg[i];
7148 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7150 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
7151 if (FAILED(hres))
7152 break;
7154 else
7156 VARIANTARG *missing_arg;
7157 /* if the function wants a pointer to a variant then
7158 * set that up, otherwise just pass the VT_ERROR in
7159 * the argument by value */
7160 if (rgvt[i] & VT_BYREF)
7162 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
7163 V_VT(arg) = VT_VARIANT | VT_BYREF;
7164 V_VARIANTREF(arg) = missing_arg;
7166 else
7167 missing_arg = arg;
7168 V_VT(missing_arg) = VT_ERROR;
7169 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
7172 else
7174 hres = DISP_E_BADPARAMCOUNT;
7175 break;
7178 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7180 /* VT_VOID is a special case for return types, so it is not
7181 * handled in the general function */
7182 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
7183 V_VT(&varresult) = VT_EMPTY;
7184 else
7186 V_VT(&varresult) = 0;
7187 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
7188 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7191 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv,
7192 V_VT(&varresult), func_desc->cParams, rgvt,
7193 prgpvarg, &varresult);
7195 vargs_converted = 0;
7197 for (i = 0; i < func_desc->cParams; i++)
7199 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7200 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7202 if (wParamFlags & PARAMFLAG_FLCID)
7203 continue;
7204 else if (wParamFlags & PARAMFLAG_FRETVAL)
7206 if (TRACE_ON(ole))
7208 TRACE("[retval] value: ");
7209 dump_Variant(prgpvarg[i]);
7212 if (pVarResult)
7214 VariantInit(pVarResult);
7215 /* deref return value */
7216 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
7219 VARIANT_ClearInd(prgpvarg[i]);
7221 else if (vargs_converted < pDispParams->cArgs)
7223 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7224 if (wParamFlags & PARAMFLAG_FOUT)
7226 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
7228 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
7230 if (FAILED(hres))
7232 ERR("failed to convert param %d to vt %d\n", i,
7233 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
7234 break;
7238 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
7239 func_desc->cParamsOpt < 0 &&
7240 i == func_desc->cParams-1)
7242 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
7243 LONG j, ubound;
7244 VARIANT *v;
7245 hres = SafeArrayGetUBound(a, 1, &ubound);
7246 if (hres != S_OK)
7248 ERR("SafeArrayGetUBound failed with %x\n", hres);
7249 break;
7251 hres = SafeArrayAccessData(a, (LPVOID)&v);
7252 if (hres != S_OK)
7254 ERR("SafeArrayAccessData failed with %x\n", hres);
7255 break;
7257 for (j = 0; j <= ubound; j++)
7258 VariantClear(&v[j]);
7259 hres = SafeArrayUnaccessData(a);
7260 if (hres != S_OK)
7262 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7263 break;
7266 VariantClear(&rgvarg[i]);
7267 vargs_converted++;
7269 else if (wParamFlags & PARAMFLAG_FOPT)
7271 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7272 VariantClear(&rgvarg[i]);
7275 VariantClear(&missing_arg[i]);
7278 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
7280 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
7281 hres = DISP_E_EXCEPTION;
7282 if (pExcepInfo)
7284 IErrorInfo *pErrorInfo;
7285 pExcepInfo->scode = V_ERROR(&varresult);
7286 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
7288 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
7289 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
7290 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
7291 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
7293 IErrorInfo_Release(pErrorInfo);
7297 if (V_VT(&varresult) != VT_ERROR)
7299 TRACE("varresult value: ");
7300 dump_Variant(&varresult);
7302 if (pVarResult)
7304 VariantClear(pVarResult);
7305 *pVarResult = varresult;
7307 else
7308 VariantClear(&varresult);
7311 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
7312 (func_desc->invkind & INVOKE_PROPERTYGET) &&
7313 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
7314 (pDispParams->cArgs != 0))
7316 if (V_VT(pVarResult) == VT_DISPATCH)
7318 IDispatch *pDispatch = V_DISPATCH(pVarResult);
7319 /* Note: not VariantClear; we still need the dispatch
7320 * pointer to be valid */
7321 VariantInit(pVarResult);
7322 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
7323 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
7324 pDispParams, pVarResult, pExcepInfo, pArgErr);
7325 IDispatch_Release(pDispatch);
7327 else
7329 VariantClear(pVarResult);
7330 hres = DISP_E_NOTACOLLECTION;
7334 func_fail:
7335 heap_free(buffer);
7336 break;
7338 case FUNC_DISPATCH: {
7339 IDispatch *disp;
7341 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
7342 if (SUCCEEDED(hres)) {
7343 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7344 hres = IDispatch_Invoke(
7345 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
7346 pVarResult,pExcepInfo,pArgErr
7348 if (FAILED(hres))
7349 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
7350 IDispatch_Release(disp);
7351 } else
7352 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7353 break;
7355 default:
7356 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
7357 hres = E_FAIL;
7358 break;
7361 TRACE("-- 0x%08x\n", hres);
7362 return hres;
7364 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
7365 VARDESC *var_desc;
7367 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
7368 if(FAILED(hres)) return hres;
7370 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7371 dump_VARDESC(var_desc);
7372 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
7373 return E_NOTIMPL;
7376 /* not found, look for it in inherited interfaces */
7377 ITypeInfo2_GetTypeKind(iface, &type_kind);
7378 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
7379 if(This->impltypes) {
7380 /* recursive search */
7381 ITypeInfo *pTInfo;
7382 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7383 if(SUCCEEDED(hres)){
7384 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
7385 ITypeInfo_Release(pTInfo);
7386 return hres;
7388 WARN("Could not search inherited interface!\n");
7391 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
7392 return DISP_E_MEMBERNOTFOUND;
7395 /* ITypeInfo::GetDocumentation
7397 * Retrieves the documentation string, the complete Help file name and path,
7398 * and the context ID for the Help topic for a specified type description.
7400 * (Can be tested by the Visual Basic Editor in Word for instance.)
7402 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
7403 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
7404 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
7406 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7407 const TLBFuncDesc *pFDesc;
7408 const TLBVarDesc *pVDesc;
7409 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7410 " HelpContext(%p) HelpFile(%p)\n",
7411 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
7412 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7413 if(pBstrName)
7414 *pBstrName=SysAllocString(TLB_get_bstr(This->Name));
7415 if(pBstrDocString)
7416 *pBstrDocString=SysAllocString(TLB_get_bstr(This->DocString));
7417 if(pdwHelpContext)
7418 *pdwHelpContext=This->dwHelpContext;
7419 if(pBstrHelpFile)
7420 *pBstrHelpFile=SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7421 return S_OK;
7422 }else {/* for a member */
7423 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7424 if(pFDesc){
7425 if(pBstrName)
7426 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Name));
7427 if(pBstrDocString)
7428 *pBstrDocString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7429 if(pdwHelpContext)
7430 *pdwHelpContext=pFDesc->helpcontext;
7431 if(pBstrHelpFile)
7432 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7433 return S_OK;
7435 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
7436 if(pVDesc){
7437 if(pBstrName)
7438 *pBstrName = SysAllocString(TLB_get_bstr(pVDesc->Name));
7439 if(pBstrDocString)
7440 *pBstrDocString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7441 if(pdwHelpContext)
7442 *pdwHelpContext=pVDesc->HelpContext;
7443 if(pBstrHelpFile)
7444 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7445 return S_OK;
7449 if(This->impltypes &&
7450 (This->typekind==TKIND_INTERFACE || This->typekind==TKIND_DISPATCH)) {
7451 /* recursive search */
7452 ITypeInfo *pTInfo;
7453 HRESULT result;
7454 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7455 if(SUCCEEDED(result)) {
7456 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
7457 pBstrDocString, pdwHelpContext, pBstrHelpFile);
7458 ITypeInfo_Release(pTInfo);
7459 return result;
7461 WARN("Could not search inherited interface!\n");
7464 WARN("member %d not found\n", memid);
7465 return TYPE_E_ELEMENTNOTFOUND;
7468 /* ITypeInfo::GetDllEntry
7470 * Retrieves a description or specification of an entry point for a function
7471 * in a DLL.
7473 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
7474 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
7475 WORD *pwOrdinal)
7477 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7478 const TLBFuncDesc *pFDesc;
7480 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
7482 if (pBstrDllName) *pBstrDllName = NULL;
7483 if (pBstrName) *pBstrName = NULL;
7484 if (pwOrdinal) *pwOrdinal = 0;
7486 if (This->typekind != TKIND_MODULE)
7487 return TYPE_E_BADMODULEKIND;
7489 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7490 if(pFDesc){
7491 dump_TypeInfo(This);
7492 if (TRACE_ON(ole))
7493 dump_TLBFuncDescOne(pFDesc);
7495 if (pBstrDllName)
7496 *pBstrDllName = SysAllocString(TLB_get_bstr(This->DllName));
7498 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
7499 if (pBstrName)
7500 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Entry));
7501 if (pwOrdinal)
7502 *pwOrdinal = -1;
7503 return S_OK;
7505 if (pBstrName)
7506 *pBstrName = NULL;
7507 if (pwOrdinal)
7508 *pwOrdinal = LOWORD(pFDesc->Entry);
7509 return S_OK;
7511 return TYPE_E_ELEMENTNOTFOUND;
7514 /* internal function to make the inherited interfaces' methods appear
7515 * part of the interface */
7516 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7517 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7519 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7520 HRESULT hr;
7522 TRACE("%p, 0x%x\n", iface, *hRefType);
7524 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7526 ITypeInfo *pSubTypeInfo;
7528 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7529 if (FAILED(hr))
7530 return hr;
7532 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7533 hRefType, ppTInfo);
7534 ITypeInfo_Release(pSubTypeInfo);
7535 if (SUCCEEDED(hr))
7536 return hr;
7538 *hRefType -= DISPATCH_HREF_OFFSET;
7540 if (!(*hRefType & DISPATCH_HREF_MASK))
7541 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7542 else
7543 return E_FAIL;
7546 /* ITypeInfo::GetRefTypeInfo
7548 * If a type description references other type descriptions, it retrieves
7549 * the referenced type descriptions.
7551 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7552 ITypeInfo2 *iface,
7553 HREFTYPE hRefType,
7554 ITypeInfo **ppTInfo)
7556 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7557 HRESULT result = E_FAIL;
7559 if(!ppTInfo)
7560 return E_INVALIDARG;
7562 if ((INT)hRefType < 0) {
7563 ITypeInfoImpl *pTypeInfoImpl;
7565 if (!(This->wTypeFlags & TYPEFLAG_FDUAL) ||
7566 !(This->typekind == TKIND_INTERFACE ||
7567 This->typekind == TKIND_DISPATCH))
7568 return TYPE_E_ELEMENTNOTFOUND;
7570 /* when we meet a DUAL typeinfo, we must create the alternate
7571 * version of it.
7573 pTypeInfoImpl = ITypeInfoImpl_Constructor();
7575 *pTypeInfoImpl = *This;
7576 pTypeInfoImpl->ref = 0;
7577 list_init(&pTypeInfoImpl->custdata_list);
7579 if (This->typekind == TKIND_INTERFACE)
7580 pTypeInfoImpl->typekind = TKIND_DISPATCH;
7581 else
7582 pTypeInfoImpl->typekind = TKIND_INTERFACE;
7584 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface;
7585 /* the AddRef implicitly adds a reference to the parent typelib, which
7586 * stops the copied data from being destroyed until the new typeinfo's
7587 * refcount goes to zero, but we need to signal to the new instance to
7588 * not free its data structures when it is destroyed */
7589 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7591 ITypeInfo_AddRef(*ppTInfo);
7593 result = S_OK;
7594 } else if ((hRefType & DISPATCH_HREF_MASK) &&
7595 (This->typekind == TKIND_DISPATCH))
7597 HREFTYPE href_dispatch = hRefType;
7598 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
7599 } else {
7600 TLBRefType *ref_type;
7601 ITypeLib *pTLib = NULL;
7602 UINT i;
7604 if(!(hRefType & 0x1)){
7605 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
7607 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
7609 result = S_OK;
7610 *ppTInfo = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
7611 ITypeInfo_AddRef(*ppTInfo);
7612 goto end;
7617 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7619 if(ref_type->reference == (hRefType & (~0x3)))
7620 break;
7622 if(&ref_type->entry == &This->pTypeLib->ref_list)
7624 FIXME("Can't find pRefType for ref %x\n", hRefType);
7625 goto end;
7628 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7629 UINT Index;
7630 TRACE("internal reference\n");
7631 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7632 } else {
7633 if(ref_type->pImpTLInfo->pImpTypeLib) {
7634 TRACE("typeinfo in imported typelib that is already loaded\n");
7635 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
7636 ITypeLib_AddRef(pTLib);
7637 result = S_OK;
7638 } else {
7639 BSTR libnam;
7641 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7643 result = query_typelib_path(TLB_get_guid_null(ref_type->pImpTLInfo->guid),
7644 ref_type->pImpTLInfo->wVersionMajor,
7645 ref_type->pImpTLInfo->wVersionMinor,
7646 This->pTypeLib->syskind,
7647 ref_type->pImpTLInfo->lcid, &libnam);
7648 if(FAILED(result))
7649 libnam = SysAllocString(ref_type->pImpTLInfo->name);
7651 result = LoadTypeLib(libnam, &pTLib);
7652 SysFreeString(libnam);
7654 if(SUCCEEDED(result)) {
7655 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
7656 ITypeLib_AddRef(pTLib);
7660 if(SUCCEEDED(result)) {
7661 if(ref_type->index == TLB_REF_USE_GUID)
7662 result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), ppTInfo);
7663 else
7664 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, ppTInfo);
7666 if (pTLib != NULL)
7667 ITypeLib_Release(pTLib);
7670 end:
7671 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
7672 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
7673 return result;
7676 /* ITypeInfo::AddressOfMember
7678 * Retrieves the addresses of static functions or variables, such as those
7679 * defined in a DLL.
7681 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
7682 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
7684 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7685 HRESULT hr;
7686 BSTR dll, entry;
7687 WORD ordinal;
7688 HMODULE module;
7690 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
7692 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
7693 if (FAILED(hr))
7694 return hr;
7696 module = LoadLibraryW(dll);
7697 if (!module)
7699 ERR("couldn't load %s\n", debugstr_w(dll));
7700 SysFreeString(dll);
7701 SysFreeString(entry);
7702 return STG_E_FILENOTFOUND;
7704 /* FIXME: store library somewhere where we can free it */
7706 if (entry)
7708 LPSTR entryA;
7709 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
7710 entryA = heap_alloc(len);
7711 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
7713 *ppv = GetProcAddress(module, entryA);
7714 if (!*ppv)
7715 ERR("function not found %s\n", debugstr_a(entryA));
7717 heap_free(entryA);
7719 else
7721 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7722 if (!*ppv)
7723 ERR("function not found %d\n", ordinal);
7726 SysFreeString(dll);
7727 SysFreeString(entry);
7729 if (!*ppv)
7730 return TYPE_E_DLLFUNCTIONNOTFOUND;
7732 return S_OK;
7735 /* ITypeInfo::CreateInstance
7737 * Creates a new instance of a type that describes a component object class
7738 * (coclass).
7740 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7741 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7743 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7744 HRESULT hr;
7745 TYPEATTR *pTA;
7747 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7749 *ppvObj = NULL;
7751 if(pOuterUnk)
7753 WARN("Not able to aggregate\n");
7754 return CLASS_E_NOAGGREGATION;
7757 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
7758 if(FAILED(hr)) return hr;
7760 if(pTA->typekind != TKIND_COCLASS)
7762 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7763 hr = E_INVALIDARG;
7764 goto end;
7767 hr = S_FALSE;
7768 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7770 IUnknown *pUnk;
7771 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7772 TRACE("GetActiveObject rets %08x\n", hr);
7773 if(hr == S_OK)
7775 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7776 IUnknown_Release(pUnk);
7780 if(hr != S_OK)
7781 hr = CoCreateInstance(&pTA->guid, NULL,
7782 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7783 riid, ppvObj);
7785 end:
7786 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
7787 return hr;
7790 /* ITypeInfo::GetMops
7792 * Retrieves marshalling information.
7794 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7795 BSTR *pBstrMops)
7797 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7798 FIXME("(%p %d) stub!\n", This, memid);
7799 *pBstrMops = NULL;
7800 return S_OK;
7803 /* ITypeInfo::GetContainingTypeLib
7805 * Retrieves the containing type library and the index of the type description
7806 * within that type library.
7808 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7809 ITypeLib * *ppTLib, UINT *pIndex)
7811 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7813 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7814 if (pIndex) {
7815 *pIndex=This->index;
7816 TRACE("returning pIndex=%d\n", *pIndex);
7819 if (ppTLib) {
7820 *ppTLib=(LPTYPELIB )(This->pTypeLib);
7821 ITypeLib_AddRef(*ppTLib);
7822 TRACE("returning ppTLib=%p\n", *ppTLib);
7825 return S_OK;
7828 /* ITypeInfo::ReleaseTypeAttr
7830 * Releases a TYPEATTR previously returned by Get
7833 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7834 TYPEATTR* pTypeAttr)
7836 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7837 TRACE("(%p)->(%p)\n", This, pTypeAttr);
7838 heap_free(pTypeAttr);
7841 /* ITypeInfo::ReleaseFuncDesc
7843 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7845 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7846 ITypeInfo2 *iface,
7847 FUNCDESC *pFuncDesc)
7849 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7850 SHORT i;
7852 TRACE("(%p)->(%p)\n", This, pFuncDesc);
7854 for (i = 0; i < pFuncDesc->cParams; i++)
7855 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7856 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7858 SysFreeString((BSTR)pFuncDesc);
7861 /* ITypeInfo::ReleaseVarDesc
7863 * Releases a VARDESC previously returned by GetVarDesc.
7865 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7866 VARDESC *pVarDesc)
7868 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7869 TRACE("(%p)->(%p)\n", This, pVarDesc);
7871 TLB_FreeVarDesc(pVarDesc);
7874 /* ITypeInfo2::GetTypeKind
7876 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7879 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7880 TYPEKIND *pTypeKind)
7882 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7883 *pTypeKind=This->typekind;
7884 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7885 return S_OK;
7888 /* ITypeInfo2::GetTypeFlags
7890 * Returns the type flags without any allocations. This returns a DWORD type
7891 * flag, which expands the type flags without growing the TYPEATTR (type
7892 * attribute).
7895 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7897 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7898 *pTypeFlags=This->wTypeFlags;
7899 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7900 return S_OK;
7903 /* ITypeInfo2::GetFuncIndexOfMemId
7904 * Binds to a specific member based on a known DISPID, where the member name
7905 * is not known (for example, when binding to a default member).
7908 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7909 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7911 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7912 UINT fdc;
7913 HRESULT result;
7915 for (fdc = 0; fdc < This->cFuncs; ++fdc){
7916 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
7917 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7918 break;
7920 if(fdc < This->cFuncs) {
7921 *pFuncIndex = fdc;
7922 result = S_OK;
7923 } else
7924 result = TYPE_E_ELEMENTNOTFOUND;
7926 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7927 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7928 return result;
7931 /* TypeInfo2::GetVarIndexOfMemId
7933 * Binds to a specific member based on a known DISPID, where the member name
7934 * is not known (for example, when binding to a default member).
7937 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7938 MEMBERID memid, UINT *pVarIndex)
7940 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7941 TLBVarDesc *pVarInfo;
7943 TRACE("%p %d %p\n", iface, memid, pVarIndex);
7945 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
7946 if(!pVarInfo)
7947 return TYPE_E_ELEMENTNOTFOUND;
7949 *pVarIndex = (pVarInfo - This->vardescs);
7951 return S_OK;
7954 /* ITypeInfo2::GetCustData
7956 * Gets the custom data
7958 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7959 ITypeInfo2 * iface,
7960 REFGUID guid,
7961 VARIANT *pVarVal)
7963 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7964 TLBCustData *pCData;
7966 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7968 if(!guid || !pVarVal)
7969 return E_INVALIDARG;
7971 pCData = TLB_get_custdata_by_guid(This->pcustdata_list, guid);
7973 VariantInit( pVarVal);
7974 if (pCData)
7975 VariantCopy( pVarVal, &pCData->data);
7976 else
7977 VariantClear( pVarVal );
7978 return S_OK;
7981 /* ITypeInfo2::GetFuncCustData
7983 * Gets the custom data
7985 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7986 ITypeInfo2 * iface,
7987 UINT index,
7988 REFGUID guid,
7989 VARIANT *pVarVal)
7991 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7992 TLBCustData *pCData;
7993 TLBFuncDesc *pFDesc = &This->funcdescs[index];
7995 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
7997 if(index >= This->cFuncs)
7998 return TYPE_E_ELEMENTNOTFOUND;
8000 pCData = TLB_get_custdata_by_guid(&pFDesc->custdata_list, guid);
8001 if(!pCData)
8002 return TYPE_E_ELEMENTNOTFOUND;
8004 VariantInit(pVarVal);
8005 VariantCopy(pVarVal, &pCData->data);
8007 return S_OK;
8010 /* ITypeInfo2::GetParamCustData
8012 * Gets the custom data
8014 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
8015 ITypeInfo2 * iface,
8016 UINT indexFunc,
8017 UINT indexParam,
8018 REFGUID guid,
8019 VARIANT *pVarVal)
8021 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8022 TLBCustData *pCData;
8023 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8025 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
8026 debugstr_guid(guid), pVarVal);
8028 if(indexFunc >= This->cFuncs)
8029 return TYPE_E_ELEMENTNOTFOUND;
8031 if(indexParam >= pFDesc->funcdesc.cParams)
8032 return TYPE_E_ELEMENTNOTFOUND;
8034 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
8035 if(!pCData)
8036 return TYPE_E_ELEMENTNOTFOUND;
8038 VariantInit(pVarVal);
8039 VariantCopy(pVarVal, &pCData->data);
8041 return S_OK;
8044 /* ITypeInfo2::GetVarCustData
8046 * Gets the custom data
8048 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
8049 ITypeInfo2 * iface,
8050 UINT index,
8051 REFGUID guid,
8052 VARIANT *pVarVal)
8054 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8055 TLBCustData *pCData;
8056 TLBVarDesc *pVDesc = &This->vardescs[index];
8058 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8060 if(index >= This->cVars)
8061 return TYPE_E_ELEMENTNOTFOUND;
8063 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
8064 if(!pCData)
8065 return TYPE_E_ELEMENTNOTFOUND;
8067 VariantInit(pVarVal);
8068 VariantCopy(pVarVal, &pCData->data);
8070 return S_OK;
8073 /* ITypeInfo2::GetImplCustData
8075 * Gets the custom data
8077 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
8078 ITypeInfo2 * iface,
8079 UINT index,
8080 REFGUID guid,
8081 VARIANT *pVarVal)
8083 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8084 TLBCustData *pCData;
8085 TLBImplType *pRDesc = &This->impltypes[index];
8087 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8089 if(index >= This->cImplTypes)
8090 return TYPE_E_ELEMENTNOTFOUND;
8092 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
8093 if(!pCData)
8094 return TYPE_E_ELEMENTNOTFOUND;
8096 VariantInit(pVarVal);
8097 VariantCopy(pVarVal, &pCData->data);
8099 return S_OK;
8102 /* ITypeInfo2::GetDocumentation2
8104 * Retrieves the documentation string, the complete Help file name and path,
8105 * the localization context to use, and the context ID for the library Help
8106 * topic in the Help file.
8109 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
8110 ITypeInfo2 * iface,
8111 MEMBERID memid,
8112 LCID lcid,
8113 BSTR *pbstrHelpString,
8114 DWORD *pdwHelpStringContext,
8115 BSTR *pbstrHelpStringDll)
8117 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8118 const TLBFuncDesc *pFDesc;
8119 const TLBVarDesc *pVDesc;
8120 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8121 "HelpStringContext(%p) HelpStringDll(%p)\n",
8122 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
8123 pbstrHelpStringDll );
8124 /* the help string should be obtained from the helpstringdll,
8125 * using the _DLLGetDocumentation function, based on the supplied
8126 * lcid. Nice to do sometime...
8128 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
8129 if(pbstrHelpString)
8130 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->Name));
8131 if(pdwHelpStringContext)
8132 *pdwHelpStringContext=This->dwHelpStringContext;
8133 if(pbstrHelpStringDll)
8134 *pbstrHelpStringDll=
8135 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8136 return S_OK;
8137 }else {/* for a member */
8138 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
8139 if(pFDesc){
8140 if(pbstrHelpString)
8141 *pbstrHelpString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
8142 if(pdwHelpStringContext)
8143 *pdwHelpStringContext=pFDesc->HelpStringContext;
8144 if(pbstrHelpStringDll)
8145 *pbstrHelpStringDll=
8146 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8147 return S_OK;
8149 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
8150 if(pVDesc){
8151 if(pbstrHelpString)
8152 *pbstrHelpString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
8153 if(pdwHelpStringContext)
8154 *pdwHelpStringContext=pVDesc->HelpStringContext;
8155 if(pbstrHelpStringDll)
8156 *pbstrHelpStringDll=
8157 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8158 return S_OK;
8161 return TYPE_E_ELEMENTNOTFOUND;
8164 /* ITypeInfo2::GetAllCustData
8166 * Gets all custom data items for the Type info.
8169 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
8170 ITypeInfo2 * iface,
8171 CUSTDATA *pCustData)
8173 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8175 TRACE("%p %p\n", This, pCustData);
8177 return TLB_copy_all_custdata(This->pcustdata_list, pCustData);
8180 /* ITypeInfo2::GetAllFuncCustData
8182 * Gets all custom data items for the specified Function
8185 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
8186 ITypeInfo2 * iface,
8187 UINT index,
8188 CUSTDATA *pCustData)
8190 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8191 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8193 TRACE("%p %u %p\n", This, index, pCustData);
8195 if(index >= This->cFuncs)
8196 return TYPE_E_ELEMENTNOTFOUND;
8198 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
8201 /* ITypeInfo2::GetAllParamCustData
8203 * Gets all custom data items for the Functions
8206 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
8207 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
8209 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8210 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8212 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
8214 if(indexFunc >= This->cFuncs)
8215 return TYPE_E_ELEMENTNOTFOUND;
8217 if(indexParam >= pFDesc->funcdesc.cParams)
8218 return TYPE_E_ELEMENTNOTFOUND;
8220 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
8223 /* ITypeInfo2::GetAllVarCustData
8225 * Gets all custom data items for the specified Variable
8228 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
8229 UINT index, CUSTDATA *pCustData)
8231 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8232 TLBVarDesc * pVDesc = &This->vardescs[index];
8234 TRACE("%p %u %p\n", This, index, pCustData);
8236 if(index >= This->cVars)
8237 return TYPE_E_ELEMENTNOTFOUND;
8239 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
8242 /* ITypeInfo2::GetAllImplCustData
8244 * Gets all custom data items for the specified implementation type
8247 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
8248 ITypeInfo2 * iface,
8249 UINT index,
8250 CUSTDATA *pCustData)
8252 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8253 TLBImplType *pRDesc = &This->impltypes[index];
8255 TRACE("%p %u %p\n", This, index, pCustData);
8257 if(index >= This->cImplTypes)
8258 return TYPE_E_ELEMENTNOTFOUND;
8260 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
8263 static const ITypeInfo2Vtbl tinfvt =
8266 ITypeInfo_fnQueryInterface,
8267 ITypeInfo_fnAddRef,
8268 ITypeInfo_fnRelease,
8270 ITypeInfo_fnGetTypeAttr,
8271 ITypeInfo_fnGetTypeComp,
8272 ITypeInfo_fnGetFuncDesc,
8273 ITypeInfo_fnGetVarDesc,
8274 ITypeInfo_fnGetNames,
8275 ITypeInfo_fnGetRefTypeOfImplType,
8276 ITypeInfo_fnGetImplTypeFlags,
8277 ITypeInfo_fnGetIDsOfNames,
8278 ITypeInfo_fnInvoke,
8279 ITypeInfo_fnGetDocumentation,
8280 ITypeInfo_fnGetDllEntry,
8281 ITypeInfo_fnGetRefTypeInfo,
8282 ITypeInfo_fnAddressOfMember,
8283 ITypeInfo_fnCreateInstance,
8284 ITypeInfo_fnGetMops,
8285 ITypeInfo_fnGetContainingTypeLib,
8286 ITypeInfo_fnReleaseTypeAttr,
8287 ITypeInfo_fnReleaseFuncDesc,
8288 ITypeInfo_fnReleaseVarDesc,
8290 ITypeInfo2_fnGetTypeKind,
8291 ITypeInfo2_fnGetTypeFlags,
8292 ITypeInfo2_fnGetFuncIndexOfMemId,
8293 ITypeInfo2_fnGetVarIndexOfMemId,
8294 ITypeInfo2_fnGetCustData,
8295 ITypeInfo2_fnGetFuncCustData,
8296 ITypeInfo2_fnGetParamCustData,
8297 ITypeInfo2_fnGetVarCustData,
8298 ITypeInfo2_fnGetImplTypeCustData,
8299 ITypeInfo2_fnGetDocumentation2,
8300 ITypeInfo2_fnGetAllCustData,
8301 ITypeInfo2_fnGetAllFuncCustData,
8302 ITypeInfo2_fnGetAllParamCustData,
8303 ITypeInfo2_fnGetAllVarCustData,
8304 ITypeInfo2_fnGetAllImplTypeCustData,
8307 /******************************************************************************
8308 * CreateDispTypeInfo [OLEAUT32.31]
8310 * Build type information for an object so it can be called through an
8311 * IDispatch interface.
8313 * RETURNS
8314 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8315 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8317 * NOTES
8318 * This call allows an objects methods to be accessed through IDispatch, by
8319 * building an ITypeInfo object that IDispatch can use to call through.
8321 HRESULT WINAPI CreateDispTypeInfo(
8322 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
8323 LCID lcid, /* [I] Locale Id */
8324 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
8326 ITypeInfoImpl *pTIClass, *pTIIface;
8327 ITypeLibImpl *pTypeLibImpl;
8328 unsigned int param, func;
8329 TLBFuncDesc *pFuncDesc;
8330 TLBRefType *ref;
8332 TRACE("\n");
8333 pTypeLibImpl = TypeLibImpl_Constructor();
8334 if (!pTypeLibImpl) return E_FAIL;
8336 pTypeLibImpl->TypeInfoCount = 2;
8337 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
8339 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
8340 pTIIface->pTypeLib = pTypeLibImpl;
8341 pTIIface->index = 0;
8342 pTIIface->Name = NULL;
8343 pTIIface->dwHelpContext = -1;
8344 pTIIface->guid = NULL;
8345 pTIIface->lcid = lcid;
8346 pTIIface->typekind = TKIND_INTERFACE;
8347 pTIIface->wMajorVerNum = 0;
8348 pTIIface->wMinorVerNum = 0;
8349 pTIIface->cbAlignment = 2;
8350 pTIIface->cbSizeInstance = -1;
8351 pTIIface->cbSizeVft = -1;
8352 pTIIface->cFuncs = 0;
8353 pTIIface->cImplTypes = 0;
8354 pTIIface->cVars = 0;
8355 pTIIface->wTypeFlags = 0;
8356 pTIIface->hreftype = 0;
8358 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers);
8359 pFuncDesc = pTIIface->funcdescs;
8360 for(func = 0; func < pidata->cMembers; func++) {
8361 METHODDATA *md = pidata->pmethdata + func;
8362 pFuncDesc->Name = TLB_append_str(&pTypeLibImpl->name_list, md->szName);
8363 pFuncDesc->funcdesc.memid = md->dispid;
8364 pFuncDesc->funcdesc.lprgscode = NULL;
8365 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
8366 pFuncDesc->funcdesc.invkind = md->wFlags;
8367 pFuncDesc->funcdesc.callconv = md->cc;
8368 pFuncDesc->funcdesc.cParams = md->cArgs;
8369 pFuncDesc->funcdesc.cParamsOpt = 0;
8370 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
8371 pFuncDesc->funcdesc.cScodes = 0;
8372 pFuncDesc->funcdesc.wFuncFlags = 0;
8373 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
8374 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
8375 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
8376 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8377 md->cArgs * sizeof(ELEMDESC));
8378 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
8379 for(param = 0; param < md->cArgs; param++) {
8380 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
8381 pFuncDesc->pParamDesc[param].Name = TLB_append_str(&pTypeLibImpl->name_list, md->ppdata[param].szName);
8383 pFuncDesc->helpcontext = 0;
8384 pFuncDesc->HelpStringContext = 0;
8385 pFuncDesc->HelpString = NULL;
8386 pFuncDesc->Entry = NULL;
8387 list_init(&pFuncDesc->custdata_list);
8388 pTIIface->cFuncs++;
8389 ++pFuncDesc;
8392 dump_TypeInfo(pTIIface);
8394 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
8395 pTIClass->pTypeLib = pTypeLibImpl;
8396 pTIClass->index = 1;
8397 pTIClass->Name = NULL;
8398 pTIClass->dwHelpContext = -1;
8399 pTIClass->guid = NULL;
8400 pTIClass->lcid = lcid;
8401 pTIClass->typekind = TKIND_COCLASS;
8402 pTIClass->wMajorVerNum = 0;
8403 pTIClass->wMinorVerNum = 0;
8404 pTIClass->cbAlignment = 2;
8405 pTIClass->cbSizeInstance = -1;
8406 pTIClass->cbSizeVft = -1;
8407 pTIClass->cFuncs = 0;
8408 pTIClass->cImplTypes = 1;
8409 pTIClass->cVars = 0;
8410 pTIClass->wTypeFlags = 0;
8411 pTIClass->hreftype = sizeof(MSFT_TypeInfoBase);
8413 pTIClass->impltypes = TLBImplType_Alloc(1);
8415 ref = heap_alloc_zero(sizeof(*ref));
8416 ref->pImpTLInfo = TLB_REF_INTERNAL;
8417 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
8419 dump_TypeInfo(pTIClass);
8421 *pptinfo = (ITypeInfo *)&pTIClass->ITypeInfo2_iface;
8423 ITypeInfo_AddRef(*pptinfo);
8424 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
8426 return S_OK;
8430 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
8432 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8434 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, ppv);
8437 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
8439 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8441 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
8444 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
8446 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8448 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
8451 static HRESULT WINAPI ITypeComp_fnBind(
8452 ITypeComp * iface,
8453 OLECHAR * szName,
8454 ULONG lHash,
8455 WORD wFlags,
8456 ITypeInfo ** ppTInfo,
8457 DESCKIND * pDescKind,
8458 BINDPTR * pBindPtr)
8460 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8461 const TLBFuncDesc *pFDesc;
8462 const TLBVarDesc *pVDesc;
8463 HRESULT hr = DISP_E_MEMBERNOTFOUND;
8464 UINT fdc;
8466 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8468 *pDescKind = DESCKIND_NONE;
8469 pBindPtr->lpfuncdesc = NULL;
8470 *ppTInfo = NULL;
8472 for(fdc = 0; fdc < This->cFuncs; ++fdc){
8473 pFDesc = &This->funcdescs[fdc];
8474 if (!lstrcmpiW(TLB_get_bstr(pFDesc->Name), szName)) {
8475 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
8476 break;
8477 else
8478 /* name found, but wrong flags */
8479 hr = TYPE_E_TYPEMISMATCH;
8483 if (fdc < This->cFuncs)
8485 HRESULT hr = TLB_AllocAndInitFuncDesc(
8486 &pFDesc->funcdesc,
8487 &pBindPtr->lpfuncdesc,
8488 This->typekind == TKIND_DISPATCH);
8489 if (FAILED(hr))
8490 return hr;
8491 *pDescKind = DESCKIND_FUNCDESC;
8492 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8493 ITypeInfo_AddRef(*ppTInfo);
8494 return S_OK;
8495 } else {
8496 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->cVars, szName);
8497 if(pVDesc){
8498 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
8499 if (FAILED(hr))
8500 return hr;
8501 *pDescKind = DESCKIND_VARDESC;
8502 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8503 ITypeInfo_AddRef(*ppTInfo);
8504 return S_OK;
8508 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
8509 /* recursive search */
8510 ITypeInfo *pTInfo;
8511 ITypeComp *pTComp;
8512 HRESULT hr;
8513 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
8514 if (SUCCEEDED(hr))
8516 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
8517 ITypeInfo_Release(pTInfo);
8519 if (SUCCEEDED(hr))
8521 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8522 ITypeComp_Release(pTComp);
8523 if (SUCCEEDED(hr) && *pDescKind == DESCKIND_FUNCDESC &&
8524 This->typekind == TKIND_DISPATCH)
8526 FUNCDESC *tmp = pBindPtr->lpfuncdesc;
8527 hr = TLB_AllocAndInitFuncDesc(tmp, &pBindPtr->lpfuncdesc, TRUE);
8528 SysFreeString((BSTR)tmp);
8530 return hr;
8532 WARN("Could not search inherited interface!\n");
8534 if (hr == DISP_E_MEMBERNOTFOUND)
8535 hr = S_OK;
8536 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
8537 return hr;
8540 static HRESULT WINAPI ITypeComp_fnBindType(
8541 ITypeComp * iface,
8542 OLECHAR * szName,
8543 ULONG lHash,
8544 ITypeInfo ** ppTInfo,
8545 ITypeComp ** ppTComp)
8547 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
8549 /* strange behaviour (does nothing) but like the
8550 * original */
8552 if (!ppTInfo || !ppTComp)
8553 return E_POINTER;
8555 *ppTInfo = NULL;
8556 *ppTComp = NULL;
8558 return S_OK;
8561 static const ITypeCompVtbl tcompvt =
8564 ITypeComp_fnQueryInterface,
8565 ITypeComp_fnAddRef,
8566 ITypeComp_fnRelease,
8568 ITypeComp_fnBind,
8569 ITypeComp_fnBindType
8572 HRESULT WINAPI CreateTypeLib2(SYSKIND syskind, LPCOLESTR szFile,
8573 ICreateTypeLib2** ppctlib)
8575 ITypeLibImpl *This;
8576 HRESULT hres;
8578 TRACE("(%d,%s,%p)\n", syskind, debugstr_w(szFile), ppctlib);
8580 if (!szFile) return E_INVALIDARG;
8582 This = TypeLibImpl_Constructor();
8583 if (!This)
8584 return E_OUTOFMEMORY;
8586 This->lcid = GetSystemDefaultLCID();
8587 This->syskind = syskind;
8588 This->ptr_size = get_ptr_size(syskind);
8590 This->path = heap_alloc((lstrlenW(szFile) + 1) * sizeof(WCHAR));
8591 if (!This->path) {
8592 ITypeLib2_Release(&This->ITypeLib2_iface);
8593 return E_OUTOFMEMORY;
8595 lstrcpyW(This->path, szFile);
8597 hres = ITypeLib2_QueryInterface(&This->ITypeLib2_iface, &IID_ICreateTypeLib2, (LPVOID*)ppctlib);
8598 ITypeLib2_Release(&This->ITypeLib2_iface);
8599 return hres;
8602 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
8603 REFIID riid, void **object)
8605 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8607 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, object);
8610 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
8612 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8614 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
8617 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
8619 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8621 return ITypeLib2_Release(&This->ITypeLib2_iface);
8624 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
8625 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
8627 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8628 ITypeInfoImpl *info;
8629 HRESULT hres;
8631 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo);
8633 if (!ctinfo || !name)
8634 return E_INVALIDARG;
8636 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, name);
8637 if (info)
8638 return TYPE_E_NAMECONFLICT;
8640 if (This->typeinfos)
8641 This->typeinfos = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->typeinfos,
8642 sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1));
8643 else
8644 This->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*));
8646 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor();
8648 info->pTypeLib = This;
8649 info->Name = TLB_append_str(&This->name_list, name);
8650 info->index = This->TypeInfoCount;
8651 info->typekind = kind;
8652 info->cbAlignment = 4;
8654 switch(info->typekind) {
8655 case TKIND_ENUM:
8656 case TKIND_INTERFACE:
8657 case TKIND_DISPATCH:
8658 case TKIND_COCLASS:
8659 info->cbSizeInstance = This->ptr_size;
8660 break;
8661 case TKIND_RECORD:
8662 case TKIND_UNION:
8663 info->cbSizeInstance = 0;
8664 break;
8665 case TKIND_MODULE:
8666 info->cbSizeInstance = 2;
8667 break;
8668 case TKIND_ALIAS:
8669 info->cbSizeInstance = -0x75;
8670 break;
8671 default:
8672 FIXME("unrecognized typekind %d\n", info->typekind);
8673 info->cbSizeInstance = 0xdeadbeef;
8674 break;
8677 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface,
8678 &IID_ICreateTypeInfo, (void **)ctinfo);
8679 if (FAILED(hres)) {
8680 ITypeInfo2_Release(&info->ITypeInfo2_iface);
8681 return hres;
8684 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase);
8686 ++This->TypeInfoCount;
8688 return S_OK;
8691 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
8692 LPOLESTR name)
8694 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8696 TRACE("%p %s\n", This, wine_dbgstr_w(name));
8698 if (!name)
8699 return E_INVALIDARG;
8701 This->Name = TLB_append_str(&This->name_list, name);
8703 return S_OK;
8706 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
8707 WORD majorVerNum, WORD minorVerNum)
8709 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8711 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
8713 This->ver_major = majorVerNum;
8714 This->ver_minor = minorVerNum;
8716 return S_OK;
8719 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
8720 REFGUID guid)
8722 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8724 TRACE("%p %s\n", This, debugstr_guid(guid));
8726 This->guid = TLB_append_guid(&This->guid_list, guid, -2);
8728 return S_OK;
8731 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
8732 LPOLESTR doc)
8734 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8736 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
8738 if (!doc)
8739 return E_INVALIDARG;
8741 This->DocString = TLB_append_str(&This->string_list, doc);
8743 return S_OK;
8746 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
8747 LPOLESTR helpFileName)
8749 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8751 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
8753 if (!helpFileName)
8754 return E_INVALIDARG;
8756 This->HelpFile = TLB_append_str(&This->string_list, helpFileName);
8758 return S_OK;
8761 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
8762 DWORD helpContext)
8764 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8766 TRACE("%p %d\n", This, helpContext);
8768 This->dwHelpContext = helpContext;
8770 return S_OK;
8773 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
8774 LCID lcid)
8776 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8778 TRACE("%p %x\n", This, lcid);
8780 This->set_lcid = lcid;
8782 return S_OK;
8785 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
8786 UINT libFlags)
8788 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8790 TRACE("%p %x\n", This, libFlags);
8792 This->libflags = libFlags;
8794 return S_OK;
8797 typedef struct tagWMSFT_SegContents {
8798 DWORD len;
8799 void *data;
8800 } WMSFT_SegContents;
8802 typedef struct tagWMSFT_TLBFile {
8803 MSFT_Header header;
8804 WMSFT_SegContents typeinfo_seg;
8805 WMSFT_SegContents impfile_seg;
8806 WMSFT_SegContents impinfo_seg;
8807 WMSFT_SegContents ref_seg;
8808 WMSFT_SegContents guidhash_seg;
8809 WMSFT_SegContents guid_seg;
8810 WMSFT_SegContents namehash_seg;
8811 WMSFT_SegContents name_seg;
8812 WMSFT_SegContents string_seg;
8813 WMSFT_SegContents typdesc_seg;
8814 WMSFT_SegContents arraydesc_seg;
8815 WMSFT_SegContents custdata_seg;
8816 WMSFT_SegContents cdguids_seg;
8817 MSFT_SegDir segdir;
8818 WMSFT_SegContents aux_seg;
8819 } WMSFT_TLBFile;
8821 static HRESULT WMSFT_compile_strings(ITypeLibImpl *This,
8822 WMSFT_TLBFile *file)
8824 TLBString *str;
8825 UINT last_offs;
8826 char *data;
8828 file->string_seg.len = 0;
8829 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8830 int size;
8832 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str), NULL, 0, NULL, NULL);
8833 if (size == 0)
8834 return E_UNEXPECTED;
8836 size += sizeof(INT16);
8837 if (size % 4)
8838 size = (size + 4) & ~0x3;
8839 if (size < 8)
8840 size = 8;
8842 file->string_seg.len += size;
8844 /* temporarily use str->offset to store the length of the aligned,
8845 * converted string */
8846 str->offset = size;
8849 file->string_seg.data = data = heap_alloc(file->string_seg.len);
8851 last_offs = 0;
8852 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8853 int size;
8855 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8856 data + sizeof(INT16), file->string_seg.len - last_offs - sizeof(INT16), NULL, NULL);
8857 if (size == 0) {
8858 heap_free(file->string_seg.data);
8859 return E_UNEXPECTED;
8862 *((INT16*)data) = size;
8864 memset(data + sizeof(INT16) + size, 0x57, str->offset - size - sizeof(INT16));
8866 size = str->offset;
8867 data += size;
8868 str->offset = last_offs;
8869 last_offs += size;
8872 return S_OK;
8875 static HRESULT WMSFT_compile_names(ITypeLibImpl *This,
8876 WMSFT_TLBFile *file)
8878 TLBString *str;
8879 UINT last_offs;
8880 char *data;
8881 MSFT_NameIntro *last_intro = NULL;
8883 file->header.nametablecount = 0;
8884 file->header.nametablechars = 0;
8886 file->name_seg.len = 0;
8887 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8888 int size;
8890 size = strlenW(str->str);
8891 file->header.nametablechars += size;
8892 file->header.nametablecount++;
8894 size = WideCharToMultiByte(CP_ACP, 0, str->str, size, NULL, 0, NULL, NULL);
8895 if (size == 0)
8896 return E_UNEXPECTED;
8898 size += sizeof(MSFT_NameIntro);
8899 if (size % 4)
8900 size = (size + 4) & ~0x3;
8901 if (size < 8)
8902 size = 8;
8904 file->name_seg.len += size;
8906 /* temporarily use str->offset to store the length of the aligned,
8907 * converted string */
8908 str->offset = size;
8911 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
8912 file->name_seg.data = data = heap_alloc(file->name_seg.len+1);
8914 last_offs = 0;
8915 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8916 int size, hash;
8917 MSFT_NameIntro *intro = (MSFT_NameIntro*)data;
8919 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8920 data + sizeof(MSFT_NameIntro),
8921 file->name_seg.len - last_offs - sizeof(MSFT_NameIntro), NULL, NULL);
8922 if (size == 0) {
8923 heap_free(file->name_seg.data);
8924 return E_UNEXPECTED;
8926 data[sizeof(MSFT_NameIntro) + size] = '\0';
8928 intro->hreftype = -1; /* TODO? */
8929 intro->namelen = size & 0xFF;
8930 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
8931 hash = LHashValOfNameSysA(This->syskind, This->lcid, data + sizeof(MSFT_NameIntro));
8932 intro->namelen |= hash << 16;
8933 intro->next_hash = ((DWORD*)file->namehash_seg.data)[hash & 0x7f];
8934 ((DWORD*)file->namehash_seg.data)[hash & 0x7f] = last_offs;
8936 memset(data + sizeof(MSFT_NameIntro) + size, 0x57,
8937 str->offset - size - sizeof(MSFT_NameIntro));
8939 /* update str->offset to actual value to use in other
8940 * compilation functions that require positions within
8941 * the string table */
8942 last_intro = intro;
8943 size = str->offset;
8944 data += size;
8945 str->offset = last_offs;
8946 last_offs += size;
8949 if(last_intro)
8950 last_intro->hreftype = 0; /* last one is 0? */
8952 return S_OK;
8955 static inline int hash_guid(GUID *guid)
8957 int i, hash = 0;
8959 for (i = 0; i < 8; i ++)
8960 hash ^= ((const short *)guid)[i];
8962 return hash & 0x1f;
8965 static HRESULT WMSFT_compile_guids(ITypeLibImpl *This, WMSFT_TLBFile *file)
8967 TLBGuid *guid;
8968 MSFT_GuidEntry *entry;
8969 DWORD offs;
8970 int hash_key, *guidhashtab;
8972 file->guid_seg.len = sizeof(MSFT_GuidEntry) * list_count(&This->guid_list);
8973 file->guid_seg.data = heap_alloc(file->guid_seg.len);
8975 entry = file->guid_seg.data;
8976 offs = 0;
8977 guidhashtab = file->guidhash_seg.data;
8978 LIST_FOR_EACH_ENTRY(guid, &This->guid_list, TLBGuid, entry){
8979 memcpy(&entry->guid, &guid->guid, sizeof(GUID));
8980 entry->hreftype = guid->hreftype;
8982 hash_key = hash_guid(&guid->guid);
8983 entry->next_hash = guidhashtab[hash_key];
8984 guidhashtab[hash_key] = offs;
8986 guid->offset = offs;
8987 offs += sizeof(MSFT_GuidEntry);
8988 ++entry;
8991 return S_OK;
8994 static DWORD WMSFT_encode_variant(VARIANT *value, WMSFT_TLBFile *file)
8996 VARIANT v = *value;
8997 VARTYPE arg_type = V_VT(value);
8998 int mask = 0;
8999 HRESULT hres;
9000 DWORD ret = file->custdata_seg.len;
9002 if(arg_type == VT_INT)
9003 arg_type = VT_I4;
9004 if(arg_type == VT_UINT)
9005 arg_type = VT_UI4;
9007 v = *value;
9008 if(V_VT(value) != arg_type) {
9009 hres = VariantChangeType(&v, value, 0, arg_type);
9010 if(FAILED(hres)){
9011 ERR("VariantChangeType failed: %08x\n", hres);
9012 return -1;
9016 /* Check if default value can be stored in-place */
9017 switch(arg_type){
9018 case VT_I4:
9019 case VT_UI4:
9020 mask = 0x3ffffff;
9021 if(V_UI4(&v) > 0x3ffffff)
9022 break;
9023 /* fall through */
9024 case VT_I1:
9025 case VT_UI1:
9026 case VT_BOOL:
9027 if(!mask)
9028 mask = 0xff;
9029 /* fall through */
9030 case VT_I2:
9031 case VT_UI2:
9032 if(!mask)
9033 mask = 0xffff;
9034 return ((0x80 + 0x4 * V_VT(value)) << 24) | (V_UI4(&v) & mask);
9037 /* have to allocate space in custdata_seg */
9038 switch(arg_type) {
9039 case VT_I4:
9040 case VT_R4:
9041 case VT_UI4:
9042 case VT_INT:
9043 case VT_UINT:
9044 case VT_HRESULT:
9045 case VT_PTR: {
9046 /* Construct the data to be allocated */
9047 int *data;
9049 if(file->custdata_seg.data){
9050 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + sizeof(int) * 2);
9051 data = (int *)(((char *)file->custdata_seg.data) + file->custdata_seg.len);
9052 file->custdata_seg.len += sizeof(int) * 2;
9053 }else{
9054 file->custdata_seg.len = sizeof(int) * 2;
9055 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9058 data[0] = V_VT(value) + (V_UI4(&v) << 16);
9059 data[1] = (V_UI4(&v) >> 16) + 0x57570000;
9061 /* TODO: Check if the encoded data is already present in custdata_seg */
9063 return ret;
9066 case VT_BSTR: {
9067 int i, len = (6+SysStringLen(V_BSTR(&v))+3) & ~0x3;
9068 char *data;
9070 if(file->custdata_seg.data){
9071 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + len);
9072 data = ((char *)file->custdata_seg.data) + file->custdata_seg.len;
9073 file->custdata_seg.len += len;
9074 }else{
9075 file->custdata_seg.len = len;
9076 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9079 *((unsigned short *)data) = V_VT(value);
9080 *((unsigned int *)(data+2)) = SysStringLen(V_BSTR(&v));
9081 for(i=0; i<SysStringLen(V_BSTR(&v)); i++) {
9082 if(V_BSTR(&v)[i] <= 0x7f)
9083 data[i+6] = V_BSTR(&v)[i];
9084 else
9085 data[i+6] = '?';
9087 WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], len-6, NULL, NULL);
9088 for(i=6+SysStringLen(V_BSTR(&v)); i<len; i++)
9089 data[i] = 0x57;
9091 /* TODO: Check if the encoded data is already present in custdata_seg */
9093 return ret;
9095 default:
9096 FIXME("Argument type not yet handled\n");
9097 return -1;
9101 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size);
9103 static DWORD WMSFT_append_arraydesc(ARRAYDESC *desc, WMSFT_TLBFile *file)
9105 DWORD offs = file->arraydesc_seg.len;
9106 DWORD *encoded;
9107 USHORT i;
9109 /* TODO: we should check for duplicates, but that's harder because each
9110 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9111 * at the library-level) */
9113 file->arraydesc_seg.len += (2 + desc->cDims * 2) * sizeof(DWORD);
9114 if(!file->arraydesc_seg.data)
9115 file->arraydesc_seg.data = heap_alloc(file->arraydesc_seg.len);
9116 else
9117 file->arraydesc_seg.data = heap_realloc(file->arraydesc_seg.data, file->arraydesc_seg.len);
9118 encoded = (DWORD*)((char *)file->arraydesc_seg.data) + offs;
9120 encoded[0] = WMSFT_append_typedesc(&desc->tdescElem, file, NULL, NULL);
9121 encoded[1] = desc->cDims | ((desc->cDims * 2 * sizeof(DWORD)) << 16);
9122 for(i = 0; i < desc->cDims; ++i){
9123 encoded[2 + i * 2] = desc->rgbounds[i].cElements;
9124 encoded[2 + i * 2 + 1] = desc->rgbounds[i].lLbound;
9127 return offs;
9130 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size)
9132 DWORD junk;
9133 INT16 junk2;
9134 DWORD offs = 0;
9135 DWORD encoded[2];
9136 VARTYPE vt, subtype;
9137 char *data;
9139 if(!desc)
9140 return -1;
9142 if(!out_mix)
9143 out_mix = &junk;
9144 if(!out_size)
9145 out_size = &junk2;
9147 vt = desc->vt & VT_TYPEMASK;
9149 if(vt == VT_PTR || vt == VT_SAFEARRAY){
9150 DWORD mix;
9151 encoded[1] = WMSFT_append_typedesc(desc->u.lptdesc, file, &mix, out_size);
9152 encoded[0] = desc->vt | ((mix | VT_BYREF) << 16);
9153 *out_mix = 0x7FFF;
9154 *out_size += 2 * sizeof(DWORD);
9155 }else if(vt == VT_CARRAY){
9156 encoded[0] = desc->vt | (0x7FFE << 16);
9157 encoded[1] = WMSFT_append_arraydesc(desc->u.lpadesc, file);
9158 *out_mix = 0x7FFE;
9159 }else if(vt == VT_USERDEFINED){
9160 encoded[0] = desc->vt | (0x7FFF << 16);
9161 encoded[1] = desc->u.hreftype;
9162 *out_mix = 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9163 }else{
9164 TRACE("Mixing in-place, VT: 0x%x\n", desc->vt);
9166 switch(vt){
9167 case VT_INT:
9168 subtype = VT_I4;
9169 break;
9170 case VT_UINT:
9171 subtype = VT_UI4;
9172 break;
9173 case VT_VOID:
9174 subtype = VT_EMPTY;
9175 break;
9176 default:
9177 subtype = vt;
9178 break;
9181 *out_mix = subtype;
9182 return 0x80000000 | (subtype << 16) | desc->vt;
9185 data = file->typdesc_seg.data;
9186 while(offs < file->typdesc_seg.len){
9187 if(!memcmp(&data[offs], encoded, sizeof(encoded)))
9188 return offs;
9189 offs += sizeof(encoded);
9192 file->typdesc_seg.len += sizeof(encoded);
9193 if(!file->typdesc_seg.data)
9194 data = file->typdesc_seg.data = heap_alloc(file->typdesc_seg.len);
9195 else
9196 data = file->typdesc_seg.data = heap_realloc(file->typdesc_seg.data, file->typdesc_seg.len);
9198 memcpy(&data[offs], encoded, sizeof(encoded));
9200 return offs;
9203 static DWORD WMSFT_compile_custdata(struct list *custdata_list, WMSFT_TLBFile *file)
9205 WMSFT_SegContents *cdguids_seg = &file->cdguids_seg;
9206 DWORD ret = cdguids_seg->len, offs;
9207 MSFT_CDGuid *cdguid = cdguids_seg->data;
9208 TLBCustData *cd;
9210 if(list_empty(custdata_list))
9211 return -1;
9213 cdguids_seg->len += sizeof(MSFT_CDGuid) * list_count(custdata_list);
9214 if(!cdguids_seg->data){
9215 cdguid = cdguids_seg->data = heap_alloc(cdguids_seg->len);
9216 }else
9217 cdguids_seg->data = heap_realloc(cdguids_seg->data, cdguids_seg->len);
9219 offs = ret + sizeof(MSFT_CDGuid);
9220 LIST_FOR_EACH_ENTRY(cd, custdata_list, TLBCustData, entry){
9221 cdguid->GuidOffset = cd->guid->offset;
9222 cdguid->DataOffset = WMSFT_encode_variant(&cd->data, file);
9223 cdguid->next = offs;
9224 offs += sizeof(MSFT_CDGuid);
9225 ++cdguid;
9228 --cdguid;
9229 cdguid->next = -1;
9231 return ret;
9234 static DWORD WMSFT_compile_typeinfo_aux(ITypeInfoImpl *info,
9235 WMSFT_TLBFile *file)
9237 WMSFT_SegContents *aux_seg = &file->aux_seg;
9238 DWORD ret = aux_seg->len, i, j, recorded_size = 0, extra_size = 0;
9239 MSFT_VarRecord *varrecord;
9240 MSFT_FuncRecord *funcrecord;
9241 MEMBERID *memid;
9242 DWORD *name, *offsets, offs;
9244 for(i = 0; i < info->cFuncs; ++i){
9245 TLBFuncDesc *desc = &info->funcdescs[i];
9247 recorded_size += 6 * sizeof(INT); /* mandatory fields */
9249 /* optional fields */
9250 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9251 if(!list_empty(&desc->custdata_list))
9252 recorded_size += 7 * sizeof(INT);
9253 else if(desc->HelpStringContext != 0)
9254 recorded_size += 6 * sizeof(INT);
9255 /* res9? resA? */
9256 else if(desc->Entry)
9257 recorded_size += 3 * sizeof(INT);
9258 else if(desc->HelpString)
9259 recorded_size += 2 * sizeof(INT);
9260 else if(desc->helpcontext)
9261 recorded_size += sizeof(INT);
9263 recorded_size += desc->funcdesc.cParams * sizeof(MSFT_ParameterInfo);
9265 for(j = 0; j < desc->funcdesc.cParams; ++j){
9266 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9267 recorded_size += desc->funcdesc.cParams * sizeof(INT);
9268 break;
9272 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9275 for(i = 0; i < info->cVars; ++i){
9276 TLBVarDesc *desc = &info->vardescs[i];
9278 recorded_size += 5 * sizeof(INT); /* mandatory fields */
9280 /* optional fields */
9281 if(desc->HelpStringContext != 0)
9282 recorded_size += 5 * sizeof(INT);
9283 else if(!list_empty(&desc->custdata_list))
9284 recorded_size += 4 * sizeof(INT);
9285 /* res9? */
9286 else if(desc->HelpString)
9287 recorded_size += 2 * sizeof(INT);
9288 else if(desc->HelpContext != 0)
9289 recorded_size += sizeof(INT);
9291 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9294 if(!recorded_size && !extra_size)
9295 return ret;
9297 extra_size += sizeof(INT); /* total aux size for this typeinfo */
9299 aux_seg->len += recorded_size + extra_size;
9301 aux_seg->len += sizeof(INT) * (info->cVars + info->cFuncs); /* offsets at the end */
9303 if(aux_seg->data)
9304 aux_seg->data = heap_realloc(aux_seg->data, aux_seg->len);
9305 else
9306 aux_seg->data = heap_alloc(aux_seg->len);
9308 *((DWORD*)((char *)aux_seg->data + ret)) = recorded_size;
9310 offsets = (DWORD*)((char *)aux_seg->data + ret + recorded_size + extra_size);
9311 offs = 0;
9313 funcrecord = (MSFT_FuncRecord*)(((char *)aux_seg->data) + ret + sizeof(INT));
9314 for(i = 0; i < info->cFuncs; ++i){
9315 TLBFuncDesc *desc = &info->funcdescs[i];
9316 DWORD size = 6 * sizeof(INT), paramdefault_size = 0, *paramdefault;
9318 funcrecord->funcdescsize = sizeof(desc->funcdesc) + desc->funcdesc.cParams * sizeof(ELEMDESC);
9319 funcrecord->DataType = WMSFT_append_typedesc(&desc->funcdesc.elemdescFunc.tdesc, file, NULL, &funcrecord->funcdescsize);
9320 funcrecord->Flags = desc->funcdesc.wFuncFlags;
9321 funcrecord->VtableOffset = desc->funcdesc.oVft;
9323 /* FKCCIC:
9324 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9325 * ^^^funckind
9326 * ^^^ ^invkind
9327 * ^has_cust_data
9328 * ^^^^callconv
9329 * ^has_param_defaults
9330 * ^oEntry_is_intresource
9332 funcrecord->FKCCIC =
9333 desc->funcdesc.funckind |
9334 (desc->funcdesc.invkind << 3) |
9335 (list_empty(&desc->custdata_list) ? 0 : 0x80) |
9336 (desc->funcdesc.callconv << 8);
9338 if(desc->Entry && desc->Entry != (TLBString*)-1 && IS_INTRESOURCE(desc->Entry))
9339 funcrecord->FKCCIC |= 0x2000;
9341 for(j = 0; j < desc->funcdesc.cParams; ++j){
9342 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9343 paramdefault_size = sizeof(INT) * desc->funcdesc.cParams;
9344 funcrecord->funcdescsize += sizeof(PARAMDESCEX);
9347 if(paramdefault_size > 0)
9348 funcrecord->FKCCIC |= 0x1000;
9350 funcrecord->nrargs = desc->funcdesc.cParams;
9351 funcrecord->nroargs = desc->funcdesc.cParamsOpt;
9353 /* optional fields */
9354 /* res9? resA? */
9355 if(!list_empty(&desc->custdata_list)){
9356 size += 7 * sizeof(INT);
9357 funcrecord->HelpContext = desc->helpcontext;
9358 if(desc->HelpString)
9359 funcrecord->oHelpString = desc->HelpString->offset;
9360 else
9361 funcrecord->oHelpString = -1;
9362 if(!desc->Entry)
9363 funcrecord->oEntry = -1;
9364 else if(IS_INTRESOURCE(desc->Entry))
9365 funcrecord->oEntry = LOWORD(desc->Entry);
9366 else
9367 funcrecord->oEntry = desc->Entry->offset;
9368 funcrecord->res9 = -1;
9369 funcrecord->resA = -1;
9370 funcrecord->HelpStringContext = desc->HelpStringContext;
9371 funcrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9372 }else if(desc->HelpStringContext != 0){
9373 size += 6 * sizeof(INT);
9374 funcrecord->HelpContext = desc->helpcontext;
9375 if(desc->HelpString)
9376 funcrecord->oHelpString = desc->HelpString->offset;
9377 else
9378 funcrecord->oHelpString = -1;
9379 if(!desc->Entry)
9380 funcrecord->oEntry = -1;
9381 else if(IS_INTRESOURCE(desc->Entry))
9382 funcrecord->oEntry = LOWORD(desc->Entry);
9383 else
9384 funcrecord->oEntry = desc->Entry->offset;
9385 funcrecord->res9 = -1;
9386 funcrecord->resA = -1;
9387 funcrecord->HelpStringContext = desc->HelpStringContext;
9388 }else if(desc->Entry){
9389 size += 3 * sizeof(INT);
9390 funcrecord->HelpContext = desc->helpcontext;
9391 if(desc->HelpString)
9392 funcrecord->oHelpString = desc->HelpString->offset;
9393 else
9394 funcrecord->oHelpString = -1;
9395 if(!desc->Entry)
9396 funcrecord->oEntry = -1;
9397 else if(IS_INTRESOURCE(desc->Entry))
9398 funcrecord->oEntry = LOWORD(desc->Entry);
9399 else
9400 funcrecord->oEntry = desc->Entry->offset;
9401 }else if(desc->HelpString){
9402 size += 2 * sizeof(INT);
9403 funcrecord->HelpContext = desc->helpcontext;
9404 funcrecord->oHelpString = desc->HelpString->offset;
9405 }else if(desc->helpcontext){
9406 size += sizeof(INT);
9407 funcrecord->HelpContext = desc->helpcontext;
9410 paramdefault = (DWORD*)((char *)funcrecord + size);
9411 size += paramdefault_size;
9413 for(j = 0; j < desc->funcdesc.cParams; ++j){
9414 MSFT_ParameterInfo *info = (MSFT_ParameterInfo*)(((char *)funcrecord) + size);
9416 info->DataType = WMSFT_append_typedesc(&desc->funcdesc.lprgelemdescParam[j].tdesc, file, NULL, &funcrecord->funcdescsize);
9417 if(desc->pParamDesc[j].Name)
9418 info->oName = desc->pParamDesc[j].Name->offset;
9419 else
9420 info->oName = -1;
9421 info->Flags = desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags;
9423 if(paramdefault_size){
9424 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
9425 *paramdefault = WMSFT_encode_variant(&desc->funcdesc.lprgelemdescParam[j].u.paramdesc.pparamdescex->varDefaultValue, file);
9426 else if(paramdefault_size)
9427 *paramdefault = -1;
9428 ++paramdefault;
9431 size += sizeof(MSFT_ParameterInfo);
9434 funcrecord->Info = size | (i << 16); /* is it just the index? */
9436 *offsets = offs;
9437 offs += size;
9438 ++offsets;
9440 funcrecord = (MSFT_FuncRecord*)(((char*)funcrecord) + size);
9443 varrecord = (MSFT_VarRecord*)funcrecord;
9444 for(i = 0; i < info->cVars; ++i){
9445 TLBVarDesc *desc = &info->vardescs[i];
9446 DWORD size = 5 * sizeof(INT);
9448 varrecord->vardescsize = sizeof(desc->vardesc);
9449 varrecord->DataType = WMSFT_append_typedesc(&desc->vardesc.elemdescVar.tdesc, file, NULL, &varrecord->vardescsize);
9450 varrecord->Flags = desc->vardesc.wVarFlags;
9451 varrecord->VarKind = desc->vardesc.varkind;
9453 if(desc->vardesc.varkind == VAR_CONST){
9454 varrecord->vardescsize += sizeof(VARIANT);
9455 varrecord->OffsValue = WMSFT_encode_variant(desc->vardesc.u.lpvarValue, file);
9456 }else
9457 varrecord->OffsValue = desc->vardesc.u.oInst;
9459 /* res9? */
9460 if(desc->HelpStringContext != 0){
9461 size += 5 * sizeof(INT);
9462 varrecord->HelpContext = desc->HelpContext;
9463 if(desc->HelpString)
9464 varrecord->HelpString = desc->HelpString->offset;
9465 else
9466 varrecord->HelpString = -1;
9467 varrecord->res9 = -1;
9468 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9469 varrecord->HelpStringContext = desc->HelpStringContext;
9470 }else if(!list_empty(&desc->custdata_list)){
9471 size += 4 * sizeof(INT);
9472 varrecord->HelpContext = desc->HelpContext;
9473 if(desc->HelpString)
9474 varrecord->HelpString = desc->HelpString->offset;
9475 else
9476 varrecord->HelpString = -1;
9477 varrecord->res9 = -1;
9478 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9479 }else if(desc->HelpString){
9480 size += 2 * sizeof(INT);
9481 varrecord->HelpContext = desc->HelpContext;
9482 if(desc->HelpString)
9483 varrecord->HelpString = desc->HelpString->offset;
9484 else
9485 varrecord->HelpString = -1;
9486 }else if(desc->HelpContext != 0){
9487 size += sizeof(INT);
9488 varrecord->HelpContext = desc->HelpContext;
9491 varrecord->Info = size | (i << 16);
9493 *offsets = offs;
9494 offs += size;
9495 ++offsets;
9497 varrecord = (MSFT_VarRecord*)(((char*)varrecord) + size);
9500 memid = (MEMBERID*)varrecord;
9501 for(i = 0; i < info->cFuncs; ++i){
9502 TLBFuncDesc *desc = &info->funcdescs[i];
9503 *memid = desc->funcdesc.memid;
9504 ++memid;
9506 for(i = 0; i < info->cVars; ++i){
9507 TLBVarDesc *desc = &info->vardescs[i];
9508 *memid = desc->vardesc.memid;
9509 ++memid;
9512 name = (UINT*)memid;
9513 for(i = 0; i < info->cFuncs; ++i){
9514 TLBFuncDesc *desc = &info->funcdescs[i];
9515 if(desc->Name)
9516 *name = desc->Name->offset;
9517 else
9518 *name = -1;
9519 ++name;
9521 for(i = 0; i < info->cVars; ++i){
9522 TLBVarDesc *desc = &info->vardescs[i];
9523 if(desc->Name)
9524 *name = desc->Name->offset;
9525 else
9526 *name = -1;
9527 ++name;
9530 return ret;
9533 typedef struct tagWMSFT_RefChunk {
9534 DWORD href;
9535 DWORD res04;
9536 DWORD res08;
9537 DWORD next;
9538 } WMSFT_RefChunk;
9540 static DWORD WMSFT_compile_typeinfo_ref(ITypeInfoImpl *info, WMSFT_TLBFile *file)
9542 DWORD offs = file->ref_seg.len, i;
9543 WMSFT_RefChunk *chunk;
9545 file->ref_seg.len += info->cImplTypes * sizeof(WMSFT_RefChunk);
9546 if(!file->ref_seg.data)
9547 file->ref_seg.data = heap_alloc(file->ref_seg.len);
9548 else
9549 file->ref_seg.data = heap_realloc(file->ref_seg.data, file->ref_seg.len);
9551 chunk = (WMSFT_RefChunk*)((char*)file->ref_seg.data + offs);
9553 for(i = 0; i < info->cImplTypes; ++i){
9554 chunk->href = info->impltypes[i].hRef;
9555 chunk->res04 = info->impltypes[i].implflags;
9556 chunk->res08 = -1;
9557 if(i < info->cImplTypes - 1)
9558 chunk->next = offs + sizeof(WMSFT_RefChunk) * (i + 1);
9559 else
9560 chunk->next = -1;
9561 ++chunk;
9564 return offs;
9567 static DWORD WMSFT_compile_typeinfo(ITypeInfoImpl *info, INT16 index, WMSFT_TLBFile *file, char *data)
9569 DWORD size;
9571 size = sizeof(MSFT_TypeInfoBase);
9573 if(data){
9574 MSFT_TypeInfoBase *base = (void*)data;
9575 if(info->wTypeFlags & TYPEFLAG_FDUAL)
9576 base->typekind = TKIND_DISPATCH;
9577 else
9578 base->typekind = info->typekind;
9579 base->typekind |= index << 16; /* TODO: There are some other flags here */
9580 base->typekind |= (info->cbAlignment << 11) | (info->cbAlignment << 6);
9581 base->memoffset = WMSFT_compile_typeinfo_aux(info, file);
9582 base->res2 = 0;
9583 base->res3 = 0;
9584 base->res4 = 3;
9585 base->res5 = 0;
9586 base->cElement = (info->cVars << 16) | info->cFuncs;
9587 base->res7 = 0;
9588 base->res8 = 0;
9589 base->res9 = 0;
9590 base->resA = 0;
9591 if(info->guid)
9592 base->posguid = info->guid->offset;
9593 else
9594 base->posguid = -1;
9595 base->flags = info->wTypeFlags;
9596 if(info->Name) {
9597 base->NameOffset = info->Name->offset;
9599 ((unsigned char*)file->name_seg.data)[info->Name->offset+9] = 0x38;
9600 *(HREFTYPE*)((unsigned char*)file->name_seg.data+info->Name->offset) = info->hreftype;
9601 }else {
9602 base->NameOffset = -1;
9604 base->version = (info->wMinorVerNum << 16) | info->wMajorVerNum;
9605 if(info->DocString)
9606 base->docstringoffs = info->DocString->offset;
9607 else
9608 base->docstringoffs = -1;
9609 base->helpstringcontext = info->dwHelpStringContext;
9610 base->helpcontext = info->dwHelpContext;
9611 base->oCustData = WMSFT_compile_custdata(info->pcustdata_list, file);
9612 base->cImplTypes = info->cImplTypes;
9613 base->cbSizeVft = info->cbSizeVft;
9614 base->size = info->cbSizeInstance;
9615 if(info->typekind == TKIND_COCLASS){
9616 base->datatype1 = WMSFT_compile_typeinfo_ref(info, file);
9617 }else if(info->typekind == TKIND_ALIAS){
9618 base->datatype1 = WMSFT_append_typedesc(info->tdescAlias, file, NULL, NULL);
9619 }else if(info->typekind == TKIND_MODULE){
9620 if(info->DllName)
9621 base->datatype1 = info->DllName->offset;
9622 else
9623 base->datatype1 = -1;
9624 }else{
9625 if(info->cImplTypes > 0)
9626 base->datatype1 = info->impltypes[0].hRef;
9627 else
9628 base->datatype1 = -1;
9630 base->datatype2 = index; /* FIXME: i think there's more here */
9631 base->res18 = 0;
9632 base->res19 = -1;
9635 return size;
9638 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl *This, WMSFT_TLBFile *file, DWORD *junk)
9640 UINT i;
9642 file->typeinfo_seg.len = 0;
9643 for(i = 0; i < This->TypeInfoCount; ++i){
9644 ITypeInfoImpl *info = This->typeinfos[i];
9645 *junk = file->typeinfo_seg.len;
9646 ++junk;
9647 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, NULL, NULL);
9650 file->typeinfo_seg.data = heap_alloc(file->typeinfo_seg.len);
9651 memset(file->typeinfo_seg.data, 0x96, file->typeinfo_seg.len);
9653 file->aux_seg.len = 0;
9654 file->aux_seg.data = NULL;
9656 file->typeinfo_seg.len = 0;
9657 for(i = 0; i < This->TypeInfoCount; ++i){
9658 ITypeInfoImpl *info = This->typeinfos[i];
9659 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, file,
9660 ((char *)file->typeinfo_seg.data) + file->typeinfo_seg.len);
9664 typedef struct tagWMSFT_ImpFile {
9665 INT guid_offs;
9666 LCID lcid;
9667 DWORD version;
9668 } WMSFT_ImpFile;
9670 static void WMSFT_compile_impfile(ITypeLibImpl *This, WMSFT_TLBFile *file)
9672 TLBImpLib *implib;
9673 WMSFT_ImpFile *impfile;
9674 char *data;
9675 DWORD last_offs = 0;
9677 file->impfile_seg.len = 0;
9678 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9679 int size = 0;
9681 if(implib->name){
9682 WCHAR *path = strrchrW(implib->name, '\\');
9683 if(path)
9684 ++path;
9685 else
9686 path = implib->name;
9687 size = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path), NULL, 0, NULL, NULL);
9688 if (size == 0)
9689 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9692 size += sizeof(INT16);
9693 if (size % 4)
9694 size = (size + 4) & ~0x3;
9695 if (size < 8)
9696 size = 8;
9698 file->impfile_seg.len += sizeof(WMSFT_ImpFile) + size;
9701 data = file->impfile_seg.data = heap_alloc(file->impfile_seg.len);
9703 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9704 int strlen = 0, size;
9706 impfile = (WMSFT_ImpFile*)data;
9707 impfile->guid_offs = implib->guid->offset;
9708 impfile->lcid = implib->lcid;
9709 impfile->version = (implib->wVersionMinor << 16) | implib->wVersionMajor;
9711 data += sizeof(WMSFT_ImpFile);
9713 if(implib->name){
9714 WCHAR *path= strrchrW(implib->name, '\\');
9715 if(path)
9716 ++path;
9717 else
9718 path = implib->name;
9719 strlen = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path),
9720 data + sizeof(INT16), file->impfile_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9721 if (strlen == 0)
9722 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9725 *((INT16*)data) = (strlen << 2) | 1; /* FIXME: is that a flag, or what? */
9727 size = strlen + sizeof(INT16);
9728 if (size % 4)
9729 size = (size + 4) & ~0x3;
9730 if (size < 8)
9731 size = 8;
9732 memset(data + sizeof(INT16) + strlen, 0x57, size - strlen - sizeof(INT16));
9734 data += size;
9735 implib->offset = last_offs;
9736 last_offs += size + sizeof(WMSFT_ImpFile);
9740 static void WMSFT_compile_impinfo(ITypeLibImpl *This, WMSFT_TLBFile *file)
9742 MSFT_ImpInfo *info;
9743 TLBRefType *ref_type;
9744 UINT i = 0;
9746 WMSFT_compile_impfile(This, file);
9748 file->impinfo_seg.len = sizeof(MSFT_ImpInfo) * list_count(&This->ref_list);
9749 info = file->impinfo_seg.data = heap_alloc(file->impinfo_seg.len);
9751 LIST_FOR_EACH_ENTRY(ref_type, &This->ref_list, TLBRefType, entry){
9752 info->flags = i | ((ref_type->tkind & 0xFF) << 24);
9753 if(ref_type->index == TLB_REF_USE_GUID){
9754 info->flags |= MSFT_IMPINFO_OFFSET_IS_GUID;
9755 info->oGuid = ref_type->guid->offset;
9756 }else
9757 info->oGuid = ref_type->index;
9758 info->oImpFile = ref_type->pImpTLInfo->offset;
9759 ++i;
9760 ++info;
9764 static void WMSFT_compile_guidhash(ITypeLibImpl *This, WMSFT_TLBFile *file)
9766 file->guidhash_seg.len = 0x80;
9767 file->guidhash_seg.data = heap_alloc(file->guidhash_seg.len);
9768 memset(file->guidhash_seg.data, 0xFF, file->guidhash_seg.len);
9771 static void WMSFT_compile_namehash(ITypeLibImpl *This, WMSFT_TLBFile *file)
9773 file->namehash_seg.len = 0x200;
9774 file->namehash_seg.data = heap_alloc(file->namehash_seg.len);
9775 memset(file->namehash_seg.data, 0xFF, file->namehash_seg.len);
9778 static void tmp_fill_segdir_seg(MSFT_pSeg *segdir, WMSFT_SegContents *contents, DWORD *running_offset)
9780 if(contents && contents->len){
9781 segdir->offset = *running_offset;
9782 segdir->length = contents->len;
9783 *running_offset += segdir->length;
9784 }else{
9785 segdir->offset = -1;
9786 segdir->length = 0;
9789 /* TODO: do these ever change? */
9790 segdir->res08 = -1;
9791 segdir->res0c = 0xf;
9794 static void WMSFT_write_segment(HANDLE outfile, WMSFT_SegContents *segment)
9796 DWORD written;
9797 if(segment)
9798 WriteFile(outfile, segment->data, segment->len, &written, NULL);
9801 static HRESULT WMSFT_fixup_typeinfos(ITypeLibImpl *This, WMSFT_TLBFile *file,
9802 DWORD file_len)
9804 DWORD i;
9805 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase *)file->typeinfo_seg.data;
9807 for(i = 0; i < This->TypeInfoCount; ++i){
9808 base->memoffset += file_len;
9809 ++base;
9812 return S_OK;
9815 static void WMSFT_free_file(WMSFT_TLBFile *file)
9817 HeapFree(GetProcessHeap(), 0, file->typeinfo_seg.data);
9818 HeapFree(GetProcessHeap(), 0, file->guidhash_seg.data);
9819 HeapFree(GetProcessHeap(), 0, file->guid_seg.data);
9820 HeapFree(GetProcessHeap(), 0, file->ref_seg.data);
9821 HeapFree(GetProcessHeap(), 0, file->impinfo_seg.data);
9822 HeapFree(GetProcessHeap(), 0, file->impfile_seg.data);
9823 HeapFree(GetProcessHeap(), 0, file->namehash_seg.data);
9824 HeapFree(GetProcessHeap(), 0, file->name_seg.data);
9825 HeapFree(GetProcessHeap(), 0, file->string_seg.data);
9826 HeapFree(GetProcessHeap(), 0, file->typdesc_seg.data);
9827 HeapFree(GetProcessHeap(), 0, file->arraydesc_seg.data);
9828 HeapFree(GetProcessHeap(), 0, file->custdata_seg.data);
9829 HeapFree(GetProcessHeap(), 0, file->cdguids_seg.data);
9830 HeapFree(GetProcessHeap(), 0, file->aux_seg.data);
9833 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
9835 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9836 WMSFT_TLBFile file;
9837 DWORD written, junk_size, junk_offs, running_offset;
9838 BOOL br;
9839 HANDLE outfile;
9840 HRESULT hres;
9841 DWORD *junk;
9842 UINT i;
9844 TRACE("%p\n", This);
9846 for(i = 0; i < This->TypeInfoCount; ++i)
9847 if(This->typeinfos[i]->needs_layout)
9848 ICreateTypeInfo2_LayOut(&This->typeinfos[i]->ICreateTypeInfo2_iface);
9850 memset(&file, 0, sizeof(file));
9852 file.header.magic1 = 0x5446534D;
9853 file.header.magic2 = 0x00010002;
9854 file.header.lcid = This->set_lcid ? This->set_lcid : MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
9855 file.header.lcid2 = This->set_lcid;
9856 file.header.varflags = 0x40 | This->syskind;
9857 if (This->HelpFile)
9858 file.header.varflags |= 0x10;
9859 if (This->HelpStringDll)
9860 file.header.varflags |= HELPDLLFLAG;
9861 file.header.version = (This->ver_minor << 16) | This->ver_major;
9862 file.header.flags = This->libflags;
9863 file.header.helpstringcontext = 0; /* TODO - SetHelpStringContext not implemented yet */
9864 file.header.helpcontext = This->dwHelpContext;
9865 file.header.res44 = 0x20;
9866 file.header.res48 = 0x80;
9867 file.header.dispatchpos = This->dispatch_href;
9869 WMSFT_compile_namehash(This, &file);
9870 /* do name and string compilation to get offsets for other compilations */
9871 hres = WMSFT_compile_names(This, &file);
9872 if (FAILED(hres)){
9873 WMSFT_free_file(&file);
9874 return hres;
9877 hres = WMSFT_compile_strings(This, &file);
9878 if (FAILED(hres)){
9879 WMSFT_free_file(&file);
9880 return hres;
9883 WMSFT_compile_guidhash(This, &file);
9884 hres = WMSFT_compile_guids(This, &file);
9885 if (FAILED(hres)){
9886 WMSFT_free_file(&file);
9887 return hres;
9890 if(This->HelpFile)
9891 file.header.helpfile = This->HelpFile->offset;
9892 else
9893 file.header.helpfile = -1;
9895 if(This->DocString)
9896 file.header.helpstring = This->DocString->offset;
9897 else
9898 file.header.helpstring = -1;
9900 /* do some more segment compilation */
9901 file.header.nimpinfos = list_count(&This->ref_list);
9902 file.header.nrtypeinfos = This->TypeInfoCount;
9904 if(This->Name)
9905 file.header.NameOffset = This->Name->offset;
9906 else
9907 file.header.NameOffset = -1;
9909 file.header.CustomDataOffset = -1; /* TODO SetCustData not impl yet */
9911 if(This->guid)
9912 file.header.posguid = This->guid->offset;
9913 else
9914 file.header.posguid = -1;
9916 junk_size = file.header.nrtypeinfos * sizeof(DWORD);
9917 if(file.header.varflags & HELPDLLFLAG)
9918 junk_size += sizeof(DWORD);
9919 if(junk_size){
9920 junk = heap_alloc_zero(junk_size);
9921 if(file.header.varflags & HELPDLLFLAG){
9922 *junk = This->HelpStringDll->offset;
9923 junk_offs = 1;
9924 }else
9925 junk_offs = 0;
9926 }else{
9927 junk = NULL;
9928 junk_offs = 0;
9931 WMSFT_compile_typeinfo_seg(This, &file, junk + junk_offs);
9932 WMSFT_compile_impinfo(This, &file);
9934 running_offset = 0;
9936 TRACE("header at: 0x%x\n", running_offset);
9937 running_offset += sizeof(file.header);
9939 TRACE("junk at: 0x%x\n", running_offset);
9940 running_offset += junk_size;
9942 TRACE("segdir at: 0x%x\n", running_offset);
9943 running_offset += sizeof(file.segdir);
9945 TRACE("typeinfo at: 0x%x\n", running_offset);
9946 tmp_fill_segdir_seg(&file.segdir.pTypeInfoTab, &file.typeinfo_seg, &running_offset);
9948 TRACE("guidhashtab at: 0x%x\n", running_offset);
9949 tmp_fill_segdir_seg(&file.segdir.pGuidHashTab, &file.guidhash_seg, &running_offset);
9951 TRACE("guidtab at: 0x%x\n", running_offset);
9952 tmp_fill_segdir_seg(&file.segdir.pGuidTab, &file.guid_seg, &running_offset);
9954 TRACE("reftab at: 0x%x\n", running_offset);
9955 tmp_fill_segdir_seg(&file.segdir.pRefTab, &file.ref_seg, &running_offset);
9957 TRACE("impinfo at: 0x%x\n", running_offset);
9958 tmp_fill_segdir_seg(&file.segdir.pImpInfo, &file.impinfo_seg, &running_offset);
9960 TRACE("impfiles at: 0x%x\n", running_offset);
9961 tmp_fill_segdir_seg(&file.segdir.pImpFiles, &file.impfile_seg, &running_offset);
9963 TRACE("namehashtab at: 0x%x\n", running_offset);
9964 tmp_fill_segdir_seg(&file.segdir.pNameHashTab, &file.namehash_seg, &running_offset);
9966 TRACE("nametab at: 0x%x\n", running_offset);
9967 tmp_fill_segdir_seg(&file.segdir.pNametab, &file.name_seg, &running_offset);
9969 TRACE("stringtab at: 0x%x\n", running_offset);
9970 tmp_fill_segdir_seg(&file.segdir.pStringtab, &file.string_seg, &running_offset);
9972 TRACE("typdesc at: 0x%x\n", running_offset);
9973 tmp_fill_segdir_seg(&file.segdir.pTypdescTab, &file.typdesc_seg, &running_offset);
9975 TRACE("arraydescriptions at: 0x%x\n", running_offset);
9976 tmp_fill_segdir_seg(&file.segdir.pArrayDescriptions, &file.arraydesc_seg, &running_offset);
9978 TRACE("custdata at: 0x%x\n", running_offset);
9979 tmp_fill_segdir_seg(&file.segdir.pCustData, &file.custdata_seg, &running_offset);
9981 TRACE("cdguids at: 0x%x\n", running_offset);
9982 tmp_fill_segdir_seg(&file.segdir.pCDGuids, &file.cdguids_seg, &running_offset);
9984 TRACE("res0e at: 0x%x\n", running_offset);
9985 tmp_fill_segdir_seg(&file.segdir.res0e, NULL, &running_offset);
9987 TRACE("res0f at: 0x%x\n", running_offset);
9988 tmp_fill_segdir_seg(&file.segdir.res0f, NULL, &running_offset);
9990 TRACE("aux_seg at: 0x%x\n", running_offset);
9992 WMSFT_fixup_typeinfos(This, &file, running_offset);
9994 outfile = CreateFileW(This->path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
9995 FILE_ATTRIBUTE_NORMAL, 0);
9996 if (outfile == INVALID_HANDLE_VALUE){
9997 WMSFT_free_file(&file);
9998 heap_free(junk);
9999 return TYPE_E_IOERROR;
10002 br = WriteFile(outfile, &file.header, sizeof(file.header), &written, NULL);
10003 if (!br) {
10004 WMSFT_free_file(&file);
10005 CloseHandle(outfile);
10006 heap_free(junk);
10007 return TYPE_E_IOERROR;
10010 br = WriteFile(outfile, junk, junk_size, &written, NULL);
10011 heap_free(junk);
10012 if (!br) {
10013 WMSFT_free_file(&file);
10014 CloseHandle(outfile);
10015 return TYPE_E_IOERROR;
10018 br = WriteFile(outfile, &file.segdir, sizeof(file.segdir), &written, NULL);
10019 if (!br) {
10020 WMSFT_free_file(&file);
10021 CloseHandle(outfile);
10022 return TYPE_E_IOERROR;
10025 WMSFT_write_segment(outfile, &file.typeinfo_seg);
10026 WMSFT_write_segment(outfile, &file.guidhash_seg);
10027 WMSFT_write_segment(outfile, &file.guid_seg);
10028 WMSFT_write_segment(outfile, &file.ref_seg);
10029 WMSFT_write_segment(outfile, &file.impinfo_seg);
10030 WMSFT_write_segment(outfile, &file.impfile_seg);
10031 WMSFT_write_segment(outfile, &file.namehash_seg);
10032 WMSFT_write_segment(outfile, &file.name_seg);
10033 WMSFT_write_segment(outfile, &file.string_seg);
10034 WMSFT_write_segment(outfile, &file.typdesc_seg);
10035 WMSFT_write_segment(outfile, &file.arraydesc_seg);
10036 WMSFT_write_segment(outfile, &file.custdata_seg);
10037 WMSFT_write_segment(outfile, &file.cdguids_seg);
10038 WMSFT_write_segment(outfile, &file.aux_seg);
10040 WMSFT_free_file(&file);
10042 CloseHandle(outfile);
10044 return S_OK;
10047 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
10048 LPOLESTR name)
10050 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10051 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
10052 return E_NOTIMPL;
10055 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
10056 REFGUID guid, VARIANT *varVal)
10058 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10059 FIXME("%p %s %p - stub\n", This, debugstr_guid(guid), varVal);
10060 return E_NOTIMPL;
10063 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
10064 ULONG helpStringContext)
10066 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10067 FIXME("%p %u - stub\n", This, helpStringContext);
10068 return E_NOTIMPL;
10071 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
10072 LPOLESTR filename)
10074 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10075 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
10077 if (!filename)
10078 return E_INVALIDARG;
10080 This->HelpStringDll = TLB_append_str(&This->string_list, filename);
10082 return S_OK;
10085 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
10086 ICreateTypeLib2_fnQueryInterface,
10087 ICreateTypeLib2_fnAddRef,
10088 ICreateTypeLib2_fnRelease,
10089 ICreateTypeLib2_fnCreateTypeInfo,
10090 ICreateTypeLib2_fnSetName,
10091 ICreateTypeLib2_fnSetVersion,
10092 ICreateTypeLib2_fnSetGuid,
10093 ICreateTypeLib2_fnSetDocString,
10094 ICreateTypeLib2_fnSetHelpFileName,
10095 ICreateTypeLib2_fnSetHelpContext,
10096 ICreateTypeLib2_fnSetLcid,
10097 ICreateTypeLib2_fnSetLibFlags,
10098 ICreateTypeLib2_fnSaveAllChanges,
10099 ICreateTypeLib2_fnDeleteTypeInfo,
10100 ICreateTypeLib2_fnSetCustData,
10101 ICreateTypeLib2_fnSetHelpStringContext,
10102 ICreateTypeLib2_fnSetHelpStringDll
10105 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
10106 REFIID riid, void **object)
10108 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10110 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, object);
10113 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
10115 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10117 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
10120 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
10122 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10124 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
10127 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
10128 REFGUID guid)
10130 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10132 TRACE("%p %s\n", This, debugstr_guid(guid));
10134 This->guid = TLB_append_guid(&This->pTypeLib->guid_list, guid, This->hreftype);
10136 return S_OK;
10139 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
10140 UINT typeFlags)
10142 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10143 WORD old_flags;
10144 HRESULT hres;
10146 TRACE("%p %x\n", This, typeFlags);
10148 if (typeFlags & TYPEFLAG_FDUAL) {
10149 static const WCHAR stdole2tlb[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10150 ITypeLib *stdole;
10151 ITypeInfo *dispatch;
10152 HREFTYPE hreftype;
10153 HRESULT hres;
10155 hres = LoadTypeLib(stdole2tlb, &stdole);
10156 if(FAILED(hres))
10157 return hres;
10159 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
10160 ITypeLib_Release(stdole);
10161 if(FAILED(hres))
10162 return hres;
10164 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
10165 ITypeInfo_Release(dispatch);
10166 if(FAILED(hres))
10167 return hres;
10170 old_flags = This->wTypeFlags;
10171 This->wTypeFlags = typeFlags;
10173 hres = ICreateTypeInfo2_LayOut(iface);
10174 if (FAILED(hres)) {
10175 This->wTypeFlags = old_flags;
10176 return hres;
10179 return S_OK;
10182 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
10183 LPOLESTR doc)
10185 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10187 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
10189 if (!doc)
10190 return E_INVALIDARG;
10192 This->DocString = TLB_append_str(&This->pTypeLib->string_list, doc);
10194 return S_OK;
10197 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
10198 DWORD helpContext)
10200 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10202 TRACE("%p %d\n", This, helpContext);
10204 This->dwHelpContext = helpContext;
10206 return S_OK;
10209 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
10210 WORD majorVerNum, WORD minorVerNum)
10212 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10214 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
10216 This->wMajorVerNum = majorVerNum;
10217 This->wMinorVerNum = minorVerNum;
10219 return S_OK;
10222 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
10223 ITypeInfo *typeInfo, HREFTYPE *refType)
10225 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10226 UINT index;
10227 ITypeLib *container;
10228 TLBRefType *ref_type;
10229 TLBImpLib *implib;
10230 TYPEATTR *typeattr;
10231 TLIBATTR *libattr;
10232 HRESULT hres;
10234 TRACE("%p %p %p\n", This, typeInfo, refType);
10236 if (!typeInfo || !refType)
10237 return E_INVALIDARG;
10239 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
10240 if (FAILED(hres))
10241 return hres;
10243 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
10244 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
10246 ITypeLib_Release(container);
10248 *refType = target->hreftype;
10250 return S_OK;
10253 hres = ITypeLib_GetLibAttr(container, &libattr);
10254 if (FAILED(hres)) {
10255 ITypeLib_Release(container);
10256 return hres;
10259 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
10260 if(IsEqualGUID(&implib->guid->guid, &libattr->guid) &&
10261 implib->lcid == libattr->lcid &&
10262 implib->wVersionMajor == libattr->wMajorVerNum &&
10263 implib->wVersionMinor == libattr->wMinorVerNum)
10264 break;
10267 if(&implib->entry == &This->pTypeLib->implib_list){
10268 implib = heap_alloc_zero(sizeof(TLBImpLib));
10270 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
10271 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
10272 implib->name = SysAllocString(our_container->path);
10273 }else{
10274 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
10275 libattr->wMinorVerNum, libattr->lcid, &implib->name);
10276 if(FAILED(hres)){
10277 implib->name = NULL;
10278 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres);
10282 implib->guid = TLB_append_guid(&This->pTypeLib->guid_list, &libattr->guid, 2);
10283 implib->lcid = libattr->lcid;
10284 implib->wVersionMajor = libattr->wMajorVerNum;
10285 implib->wVersionMinor = libattr->wMinorVerNum;
10287 list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
10290 ITypeLib_ReleaseTLibAttr(container, libattr);
10291 ITypeLib_Release(container);
10293 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
10294 if (FAILED(hres))
10295 return hres;
10297 index = 0;
10298 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
10299 if(ref_type->index == TLB_REF_USE_GUID &&
10300 IsEqualGUID(&ref_type->guid->guid, &typeattr->guid) &&
10301 ref_type->tkind == typeattr->typekind)
10302 break;
10303 ++index;
10306 if(&ref_type->entry == &This->pTypeLib->ref_list){
10307 ref_type = heap_alloc_zero(sizeof(TLBRefType));
10309 ref_type->tkind = typeattr->typekind;
10310 ref_type->pImpTLInfo = implib;
10311 ref_type->reference = index * sizeof(MSFT_ImpInfo);
10313 ref_type->index = TLB_REF_USE_GUID;
10315 ref_type->guid = TLB_append_guid(&This->pTypeLib->guid_list, &typeattr->guid, ref_type->reference+1);
10317 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
10320 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
10322 *refType = ref_type->reference | 0x1;
10324 if(IsEqualGUID(&ref_type->guid->guid, &IID_IDispatch))
10325 This->pTypeLib->dispatch_href = *refType;
10327 return S_OK;
10330 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
10331 UINT index, FUNCDESC *funcDesc)
10333 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10334 TLBFuncDesc tmp_func_desc, *func_desc;
10335 int buf_size, i;
10336 char *buffer;
10337 HRESULT hres;
10339 TRACE("%p %u %p\n", This, index, funcDesc);
10341 if (!funcDesc || funcDesc->oVft & 3)
10342 return E_INVALIDARG;
10344 switch (This->typekind) {
10345 case TKIND_MODULE:
10346 if (funcDesc->funckind != FUNC_STATIC)
10347 return TYPE_E_BADMODULEKIND;
10348 break;
10349 case TKIND_DISPATCH:
10350 if (funcDesc->funckind != FUNC_DISPATCH)
10351 return TYPE_E_BADMODULEKIND;
10352 break;
10353 default:
10354 if (funcDesc->funckind != FUNC_PUREVIRTUAL)
10355 return TYPE_E_BADMODULEKIND;
10358 if (index > This->cFuncs)
10359 return TYPE_E_ELEMENTNOTFOUND;
10361 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) &&
10362 !funcDesc->cParams)
10363 return TYPE_E_INCONSISTENTPROPFUNCS;
10365 #ifdef _WIN64
10366 if(This->pTypeLib->syskind == SYS_WIN64 &&
10367 funcDesc->oVft % 8 != 0)
10368 return E_INVALIDARG;
10369 #endif
10371 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc));
10372 TLBFuncDesc_Constructor(&tmp_func_desc);
10374 tmp_func_desc.funcdesc = *funcDesc;
10376 if (tmp_func_desc.funcdesc.oVft != 0)
10377 tmp_func_desc.funcdesc.oVft |= 1;
10379 if (funcDesc->cScodes) {
10380 tmp_func_desc.funcdesc.lprgscode = heap_alloc(sizeof(SCODE) * funcDesc->cScodes);
10381 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes);
10382 } else
10383 tmp_func_desc.funcdesc.lprgscode = NULL;
10385 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc);
10386 for (i = 0; i < funcDesc->cParams; ++i) {
10387 buf_size += sizeof(ELEMDESC);
10388 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i);
10390 tmp_func_desc.funcdesc.lprgelemdescParam = heap_alloc(buf_size);
10391 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams);
10393 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer);
10394 if (FAILED(hres)) {
10395 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10396 heap_free(tmp_func_desc.funcdesc.lprgscode);
10397 return hres;
10400 for (i = 0; i < funcDesc->cParams; ++i) {
10401 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i,
10402 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer);
10403 if (FAILED(hres)) {
10404 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10405 heap_free(tmp_func_desc.funcdesc.lprgscode);
10406 return hres;
10408 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT &&
10409 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT &&
10410 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){
10411 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
10412 if (FAILED(hres)) {
10413 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10414 heap_free(tmp_func_desc.funcdesc.lprgscode);
10415 return hres;
10420 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams);
10422 if (This->funcdescs) {
10423 This->funcdescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->funcdescs,
10424 sizeof(TLBFuncDesc) * (This->cFuncs + 1));
10426 if (index < This->cFuncs) {
10427 memmove(This->funcdescs + index + 1, This->funcdescs + index,
10428 (This->cFuncs - index) * sizeof(TLBFuncDesc));
10429 func_desc = This->funcdescs + index;
10430 } else
10431 func_desc = This->funcdescs + This->cFuncs;
10433 /* move custdata lists to the new memory location */
10434 for(i = 0; i < This->cFuncs + 1; ++i){
10435 if(index != i){
10436 TLBFuncDesc *fd = &This->funcdescs[i];
10437 if(fd->custdata_list.prev == fd->custdata_list.next)
10438 list_init(&fd->custdata_list);
10439 else{
10440 fd->custdata_list.prev->next = &fd->custdata_list;
10441 fd->custdata_list.next->prev = &fd->custdata_list;
10445 } else
10446 func_desc = This->funcdescs = heap_alloc(sizeof(TLBFuncDesc));
10448 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc));
10449 list_init(&func_desc->custdata_list);
10451 ++This->cFuncs;
10453 This->needs_layout = TRUE;
10455 return S_OK;
10458 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
10459 UINT index, HREFTYPE refType)
10461 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10462 TLBImplType *impl_type;
10463 HRESULT hres;
10465 TRACE("%p %u %d\n", This, index, refType);
10467 switch(This->typekind){
10468 case TKIND_COCLASS: {
10469 if (index == -1) {
10470 FIXME("Unhandled index: -1\n");
10471 return E_NOTIMPL;
10474 if(index != This->cImplTypes)
10475 return TYPE_E_ELEMENTNOTFOUND;
10477 break;
10479 case TKIND_INTERFACE:
10480 case TKIND_DISPATCH:
10481 if (index != 0 || This->cImplTypes)
10482 return TYPE_E_ELEMENTNOTFOUND;
10483 break;
10484 default:
10485 FIXME("Unimplemented typekind: %d\n", This->typekind);
10486 return E_NOTIMPL;
10489 if (This->impltypes){
10490 UINT i;
10492 This->impltypes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->impltypes,
10493 sizeof(TLBImplType) * (This->cImplTypes + 1));
10495 if (index < This->cImplTypes) {
10496 memmove(This->impltypes + index + 1, This->impltypes + index,
10497 (This->cImplTypes - index) * sizeof(TLBImplType));
10498 impl_type = This->impltypes + index;
10499 } else
10500 impl_type = This->impltypes + This->cImplTypes;
10502 /* move custdata lists to the new memory location */
10503 for(i = 0; i < This->cImplTypes + 1; ++i){
10504 if(index != i){
10505 TLBImplType *it = &This->impltypes[i];
10506 if(it->custdata_list.prev == it->custdata_list.next)
10507 list_init(&it->custdata_list);
10508 else{
10509 it->custdata_list.prev->next = &it->custdata_list;
10510 it->custdata_list.next->prev = &it->custdata_list;
10514 } else
10515 impl_type = This->impltypes = heap_alloc(sizeof(TLBImplType));
10517 memset(impl_type, 0, sizeof(TLBImplType));
10518 TLBImplType_Constructor(impl_type);
10519 impl_type->hRef = refType;
10521 ++This->cImplTypes;
10523 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
10524 This->wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
10526 hres = ICreateTypeInfo2_LayOut(iface);
10527 if (FAILED(hres))
10528 return hres;
10530 return S_OK;
10533 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
10534 UINT index, INT implTypeFlags)
10536 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10537 TLBImplType *impl_type = &This->impltypes[index];
10539 TRACE("%p %u %x\n", This, index, implTypeFlags);
10541 if (This->typekind != TKIND_COCLASS)
10542 return TYPE_E_BADMODULEKIND;
10544 if (index >= This->cImplTypes)
10545 return TYPE_E_ELEMENTNOTFOUND;
10547 impl_type->implflags = implTypeFlags;
10549 return S_OK;
10552 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
10553 WORD alignment)
10555 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10557 TRACE("%p %d\n", This, alignment);
10559 This->cbAlignment = alignment;
10561 return S_OK;
10564 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
10565 LPOLESTR schema)
10567 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10569 TRACE("%p %s\n", This, wine_dbgstr_w(schema));
10571 if (!schema)
10572 return E_INVALIDARG;
10574 This->Schema = TLB_append_str(&This->pTypeLib->string_list, schema);
10576 This->lpstrSchema = This->Schema->str;
10578 return S_OK;
10581 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
10582 UINT index, VARDESC *varDesc)
10584 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10585 TLBVarDesc *var_desc;
10587 TRACE("%p %u %p\n", This, index, varDesc);
10589 if (This->vardescs){
10590 UINT i;
10592 This->vardescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->vardescs,
10593 sizeof(TLBVarDesc) * (This->cVars + 1));
10595 if (index < This->cVars) {
10596 memmove(This->vardescs + index + 1, This->vardescs + index,
10597 (This->cVars - index) * sizeof(TLBVarDesc));
10598 var_desc = This->vardescs + index;
10599 } else
10600 var_desc = This->vardescs + This->cVars;
10602 /* move custdata lists to the new memory location */
10603 for(i = 0; i < This->cVars + 1; ++i){
10604 if(index != i){
10605 TLBVarDesc *var = &This->vardescs[i];
10606 if(var->custdata_list.prev == var->custdata_list.next)
10607 list_init(&var->custdata_list);
10608 else{
10609 var->custdata_list.prev->next = &var->custdata_list;
10610 var->custdata_list.next->prev = &var->custdata_list;
10614 } else
10615 var_desc = This->vardescs = heap_alloc_zero(sizeof(TLBVarDesc));
10617 TLBVarDesc_Constructor(var_desc);
10618 TLB_AllocAndInitVarDesc(varDesc, &var_desc->vardesc_create);
10619 var_desc->vardesc = *var_desc->vardesc_create;
10621 ++This->cVars;
10623 This->needs_layout = TRUE;
10625 return S_OK;
10628 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
10629 UINT index, LPOLESTR *names, UINT numNames)
10631 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10632 TLBFuncDesc *func_desc = &This->funcdescs[index];
10633 int i;
10635 TRACE("%p %u %p %u\n", This, index, names, numNames);
10637 if (!names)
10638 return E_INVALIDARG;
10640 if (index >= This->cFuncs || numNames == 0)
10641 return TYPE_E_ELEMENTNOTFOUND;
10643 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){
10644 if(numNames > func_desc->funcdesc.cParams)
10645 return TYPE_E_ELEMENTNOTFOUND;
10646 } else
10647 if(numNames > func_desc->funcdesc.cParams + 1)
10648 return TYPE_E_ELEMENTNOTFOUND;
10650 for(i = 0; i < This->cFuncs; ++i) {
10651 TLBFuncDesc *iter = &This->funcdescs[i];
10652 if (iter->Name && !strcmpW(TLB_get_bstr(iter->Name), *names)) {
10653 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10654 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10655 func_desc->funcdesc.invkind != iter->funcdesc.invkind)
10656 continue;
10657 return TYPE_E_AMBIGUOUSNAME;
10661 func_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *names);
10663 for (i = 1; i < numNames; ++i) {
10664 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1;
10665 par_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *(names + i));
10668 return S_OK;
10671 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
10672 UINT index, LPOLESTR name)
10674 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10676 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(name));
10678 if(!name)
10679 return E_INVALIDARG;
10681 if(index >= This->cVars)
10682 return TYPE_E_ELEMENTNOTFOUND;
10684 This->vardescs[index].Name = TLB_append_str(&This->pTypeLib->name_list, name);
10685 return S_OK;
10688 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
10689 TYPEDESC *tdescAlias)
10691 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10692 HRESULT hr;
10694 TRACE("%p %p\n", This, tdescAlias);
10696 if(!tdescAlias)
10697 return E_INVALIDARG;
10699 if(This->typekind != TKIND_ALIAS)
10700 return TYPE_E_BADMODULEKIND;
10702 hr = TLB_size_instance(This, This->pTypeLib->syskind, tdescAlias, &This->cbSizeInstance, &This->cbAlignment);
10703 if(FAILED(hr))
10704 return hr;
10706 heap_free(This->tdescAlias);
10707 This->tdescAlias = heap_alloc(TLB_SizeTypeDesc(tdescAlias, TRUE));
10708 TLB_CopyTypeDesc(NULL, tdescAlias, This->tdescAlias);
10710 return S_OK;
10713 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
10714 UINT index, LPOLESTR dllName, LPOLESTR procName)
10716 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10717 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
10718 return E_NOTIMPL;
10721 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
10722 UINT index, LPOLESTR docString)
10724 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10725 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(docString));
10726 return E_NOTIMPL;
10729 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
10730 UINT index, LPOLESTR docString)
10732 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10733 TLBVarDesc *var_desc = &This->vardescs[index];
10735 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10737 if(!docString)
10738 return E_INVALIDARG;
10740 if(index >= This->cVars)
10741 return TYPE_E_ELEMENTNOTFOUND;
10743 var_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10745 return S_OK;
10748 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
10749 UINT index, DWORD helpContext)
10751 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10752 TLBFuncDesc *func_desc = &This->funcdescs[index];
10754 TRACE("%p %u %d\n", This, index, helpContext);
10756 if(index >= This->cFuncs)
10757 return TYPE_E_ELEMENTNOTFOUND;
10759 func_desc->helpcontext = helpContext;
10761 return S_OK;
10764 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
10765 UINT index, DWORD helpContext)
10767 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10768 TLBVarDesc *var_desc = &This->vardescs[index];
10770 TRACE("%p %u %d\n", This, index, helpContext);
10772 if(index >= This->cVars)
10773 return TYPE_E_ELEMENTNOTFOUND;
10775 var_desc->HelpContext = helpContext;
10777 return S_OK;
10780 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
10781 UINT index, BSTR bstrMops)
10783 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10784 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
10785 return E_NOTIMPL;
10788 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
10789 IDLDESC *idlDesc)
10791 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10793 TRACE("%p %p\n", This, idlDesc);
10795 if (!idlDesc)
10796 return E_INVALIDARG;
10798 This->idldescType.dwReserved = idlDesc->dwReserved;
10799 This->idldescType.wIDLFlags = idlDesc->wIDLFlags;
10801 return S_OK;
10804 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
10806 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10807 ITypeInfo *tinfo;
10808 TLBFuncDesc *func_desc;
10809 UINT user_vft = 0, i, depth = 0;
10810 HRESULT hres = S_OK;
10812 TRACE("%p\n", This);
10814 This->needs_layout = FALSE;
10816 hres = ICreateTypeInfo2_QueryInterface(iface, &IID_ITypeInfo, (LPVOID*)&tinfo);
10817 if (FAILED(hres))
10818 return hres;
10820 if (This->typekind == TKIND_INTERFACE) {
10821 ITypeInfo *inh;
10822 TYPEATTR *attr;
10823 HREFTYPE inh_href;
10825 hres = ITypeInfo_GetRefTypeOfImplType(tinfo, 0, &inh_href);
10827 if (SUCCEEDED(hres)) {
10828 hres = ITypeInfo_GetRefTypeInfo(tinfo, inh_href, &inh);
10830 if (SUCCEEDED(hres)) {
10831 hres = ITypeInfo_GetTypeAttr(inh, &attr);
10832 if (FAILED(hres)) {
10833 ITypeInfo_Release(inh);
10834 ITypeInfo_Release(tinfo);
10835 return hres;
10837 This->cbSizeVft = attr->cbSizeVft;
10838 ITypeInfo_ReleaseTypeAttr(inh, attr);
10841 ++depth;
10842 hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href);
10843 if(SUCCEEDED(hres)){
10844 ITypeInfo *next;
10845 hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next);
10846 if(SUCCEEDED(hres)){
10847 ITypeInfo_Release(inh);
10848 inh = next;
10851 }while(SUCCEEDED(hres));
10852 hres = S_OK;
10854 ITypeInfo_Release(inh);
10855 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10856 This->cbSizeVft = 0;
10857 hres = S_OK;
10858 } else {
10859 ITypeInfo_Release(tinfo);
10860 return hres;
10862 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10863 This->cbSizeVft = 0;
10864 hres = S_OK;
10865 } else {
10866 ITypeInfo_Release(tinfo);
10867 return hres;
10869 } else if (This->typekind == TKIND_DISPATCH)
10870 This->cbSizeVft = 7 * This->pTypeLib->ptr_size;
10871 else
10872 This->cbSizeVft = 0;
10874 func_desc = This->funcdescs;
10875 i = 0;
10876 while (i < This->cFuncs) {
10877 if (!(func_desc->funcdesc.oVft & 0x1))
10878 func_desc->funcdesc.oVft = This->cbSizeVft;
10880 if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft)
10881 user_vft = func_desc->funcdesc.oVft & 0xFFFC;
10883 This->cbSizeVft += This->pTypeLib->ptr_size;
10885 if (func_desc->funcdesc.memid == MEMBERID_NIL) {
10886 TLBFuncDesc *iter;
10887 UINT j = 0;
10888 BOOL reset = FALSE;
10890 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i;
10892 iter = This->funcdescs;
10893 while (j < This->cFuncs) {
10894 if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) {
10895 if (!reset) {
10896 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->cFuncs;
10897 reset = TRUE;
10898 } else
10899 ++func_desc->funcdesc.memid;
10900 iter = This->funcdescs;
10901 j = 0;
10902 } else {
10903 ++iter;
10904 ++j;
10909 ++func_desc;
10910 ++i;
10913 if (user_vft > This->cbSizeVft)
10914 This->cbSizeVft = user_vft + This->pTypeLib->ptr_size;
10916 for(i = 0; i < This->cVars; ++i){
10917 TLBVarDesc *var_desc = &This->vardescs[i];
10918 if(var_desc->vardesc.memid == MEMBERID_NIL){
10919 UINT j = 0;
10920 BOOL reset = FALSE;
10921 TLBVarDesc *iter;
10923 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + i;
10925 iter = This->vardescs;
10926 while (j < This->cVars) {
10927 if (iter != var_desc && iter->vardesc.memid == var_desc->vardesc.memid) {
10928 if (!reset) {
10929 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + This->cVars;
10930 reset = TRUE;
10931 } else
10932 ++var_desc->vardesc.memid;
10933 iter = This->vardescs;
10934 j = 0;
10935 } else {
10936 ++iter;
10937 ++j;
10943 ITypeInfo_Release(tinfo);
10944 return hres;
10947 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
10948 UINT index)
10950 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10951 FIXME("%p %u - stub\n", This, index);
10952 return E_NOTIMPL;
10955 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
10956 MEMBERID memid, INVOKEKIND invKind)
10958 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10959 FIXME("%p %x %d - stub\n", This, memid, invKind);
10960 return E_NOTIMPL;
10963 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
10964 UINT index)
10966 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10967 FIXME("%p %u - stub\n", This, index);
10968 return E_NOTIMPL;
10971 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
10972 MEMBERID memid)
10974 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10975 FIXME("%p %x - stub\n", This, memid);
10976 return E_NOTIMPL;
10979 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
10980 UINT index)
10982 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10983 FIXME("%p %u - stub\n", This, index);
10984 return E_NOTIMPL;
10987 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
10988 REFGUID guid, VARIANT *varVal)
10990 TLBGuid *tlbguid;
10992 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10994 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
10996 if (!guid || !varVal)
10997 return E_INVALIDARG;
10999 tlbguid = TLB_append_guid(&This->pTypeLib->guid_list, guid, -1);
11001 return TLB_set_custdata(This->pcustdata_list, tlbguid, varVal);
11004 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
11005 UINT index, REFGUID guid, VARIANT *varVal)
11007 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11008 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11009 return E_NOTIMPL;
11012 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
11013 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
11015 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11016 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
11017 return E_NOTIMPL;
11020 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
11021 UINT index, REFGUID guid, VARIANT *varVal)
11023 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11024 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11025 return E_NOTIMPL;
11028 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
11029 UINT index, REFGUID guid, VARIANT *varVal)
11031 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11032 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11033 return E_NOTIMPL;
11036 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
11037 ULONG helpStringContext)
11039 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11041 TRACE("%p %u\n", This, helpStringContext);
11043 This->dwHelpStringContext = helpStringContext;
11045 return S_OK;
11048 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
11049 UINT index, ULONG helpStringContext)
11051 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11052 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11053 return E_NOTIMPL;
11056 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
11057 UINT index, ULONG helpStringContext)
11059 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11060 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11061 return E_NOTIMPL;
11064 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
11066 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11067 FIXME("%p - stub\n", This);
11068 return E_NOTIMPL;
11071 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
11072 LPOLESTR name)
11074 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11076 TRACE("%p %s\n", This, wine_dbgstr_w(name));
11078 if (!name)
11079 return E_INVALIDARG;
11081 This->Name = TLB_append_str(&This->pTypeLib->name_list, name);
11083 return S_OK;
11086 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
11087 ICreateTypeInfo2_fnQueryInterface,
11088 ICreateTypeInfo2_fnAddRef,
11089 ICreateTypeInfo2_fnRelease,
11090 ICreateTypeInfo2_fnSetGuid,
11091 ICreateTypeInfo2_fnSetTypeFlags,
11092 ICreateTypeInfo2_fnSetDocString,
11093 ICreateTypeInfo2_fnSetHelpContext,
11094 ICreateTypeInfo2_fnSetVersion,
11095 ICreateTypeInfo2_fnAddRefTypeInfo,
11096 ICreateTypeInfo2_fnAddFuncDesc,
11097 ICreateTypeInfo2_fnAddImplType,
11098 ICreateTypeInfo2_fnSetImplTypeFlags,
11099 ICreateTypeInfo2_fnSetAlignment,
11100 ICreateTypeInfo2_fnSetSchema,
11101 ICreateTypeInfo2_fnAddVarDesc,
11102 ICreateTypeInfo2_fnSetFuncAndParamNames,
11103 ICreateTypeInfo2_fnSetVarName,
11104 ICreateTypeInfo2_fnSetTypeDescAlias,
11105 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
11106 ICreateTypeInfo2_fnSetFuncDocString,
11107 ICreateTypeInfo2_fnSetVarDocString,
11108 ICreateTypeInfo2_fnSetFuncHelpContext,
11109 ICreateTypeInfo2_fnSetVarHelpContext,
11110 ICreateTypeInfo2_fnSetMops,
11111 ICreateTypeInfo2_fnSetTypeIdldesc,
11112 ICreateTypeInfo2_fnLayOut,
11113 ICreateTypeInfo2_fnDeleteFuncDesc,
11114 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
11115 ICreateTypeInfo2_fnDeleteVarDesc,
11116 ICreateTypeInfo2_fnDeleteVarDescByMemId,
11117 ICreateTypeInfo2_fnDeleteImplType,
11118 ICreateTypeInfo2_fnSetCustData,
11119 ICreateTypeInfo2_fnSetFuncCustData,
11120 ICreateTypeInfo2_fnSetParamCustData,
11121 ICreateTypeInfo2_fnSetVarCustData,
11122 ICreateTypeInfo2_fnSetImplTypeCustData,
11123 ICreateTypeInfo2_fnSetHelpStringContext,
11124 ICreateTypeInfo2_fnSetFuncHelpStringContext,
11125 ICreateTypeInfo2_fnSetVarHelpStringContext,
11126 ICreateTypeInfo2_fnInvalidate,
11127 ICreateTypeInfo2_fnSetName
11130 /******************************************************************************
11131 * ClearCustData (OLEAUT32.171)
11133 * Clear a custom data type's data.
11135 * PARAMS
11136 * lpCust [I] The custom data type instance
11138 * RETURNS
11139 * Nothing.
11141 void WINAPI ClearCustData(CUSTDATA *lpCust)
11143 if (lpCust && lpCust->cCustData)
11145 if (lpCust->prgCustData)
11147 DWORD i;
11149 for (i = 0; i < lpCust->cCustData; i++)
11150 VariantClear(&lpCust->prgCustData[i].varValue);
11152 /* FIXME - Should be using a per-thread IMalloc */
11153 heap_free(lpCust->prgCustData);
11154 lpCust->prgCustData = NULL;
11156 lpCust->cCustData = 0;