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