oleaut32: Don't prevent 64-bit from loading 32-bit typelibs.
[wine.git] / dlls / oleaut32 / typelib.c
blobd8e9840222d95e486b22786676afe28b8a342084
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 /**********************************************************************
1914 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1916 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1918 return pcx->pos;
1921 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
1923 if (where != DO_NOT_SEEK)
1925 where += pcx->oStart;
1926 if (where > pcx->length)
1928 /* FIXME */
1929 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
1930 TLB_abort();
1932 pcx->pos = where;
1936 /* read function */
1937 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
1939 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
1940 pcx->pos, count, pcx->oStart, pcx->length, where);
1942 MSFT_Seek(pcx, where);
1943 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1944 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1945 pcx->pos += count;
1946 return count;
1949 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1950 LONG where )
1952 DWORD ret;
1954 ret = MSFT_Read(buffer, count, pcx, where);
1955 FromLEDWords(buffer, ret);
1957 return ret;
1960 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1961 LONG where )
1963 DWORD ret;
1965 ret = MSFT_Read(buffer, count, pcx, where);
1966 FromLEWords(buffer, ret);
1968 return ret;
1971 static HRESULT MSFT_ReadAllGuids(TLBContext *pcx)
1973 TLBGuid *guid;
1974 MSFT_GuidEntry entry;
1975 int offs = 0;
1977 MSFT_Seek(pcx, pcx->pTblDir->pGuidTab.offset);
1978 while (1) {
1979 if (offs >= pcx->pTblDir->pGuidTab.length)
1980 return S_OK;
1982 MSFT_ReadLEWords(&entry, sizeof(MSFT_GuidEntry), pcx, DO_NOT_SEEK);
1984 guid = heap_alloc(sizeof(TLBGuid));
1986 guid->offset = offs;
1987 guid->guid = entry.guid;
1988 guid->hreftype = entry.hreftype;
1990 list_add_tail(&pcx->pLibInfo->guid_list, &guid->entry);
1992 offs += sizeof(MSFT_GuidEntry);
1996 static TLBGuid *MSFT_ReadGuid( int offset, TLBContext *pcx)
1998 TLBGuid *ret;
2000 LIST_FOR_EACH_ENTRY(ret, &pcx->pLibInfo->guid_list, TLBGuid, entry){
2001 if(ret->offset == offset){
2002 TRACE_(typelib)("%s\n", debugstr_guid(&ret->guid));
2003 return ret;
2007 return NULL;
2010 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
2012 MSFT_NameIntro niName;
2014 if (offset < 0)
2016 ERR_(typelib)("bad offset %d\n", offset);
2017 return -1;
2020 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
2021 pcx->pTblDir->pNametab.offset+offset);
2023 return niName.hreftype;
2026 static HRESULT MSFT_ReadAllNames(TLBContext *pcx)
2028 char *string;
2029 MSFT_NameIntro intro;
2030 INT16 len_piece;
2031 int offs = 0, lengthInChars;
2033 MSFT_Seek(pcx, pcx->pTblDir->pNametab.offset);
2034 while (1) {
2035 TLBString *tlbstr;
2037 if (offs >= pcx->pTblDir->pNametab.length)
2038 return S_OK;
2040 MSFT_ReadLEWords(&intro, sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2041 intro.namelen &= 0xFF;
2042 len_piece = intro.namelen + sizeof(MSFT_NameIntro);
2043 if(len_piece % 4)
2044 len_piece = (len_piece + 4) & ~0x3;
2045 if(len_piece < 8)
2046 len_piece = 8;
2048 string = heap_alloc(len_piece + 1);
2049 MSFT_Read(string, len_piece - sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2050 string[intro.namelen] = '\0';
2052 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2053 string, -1, NULL, 0);
2054 if (!lengthInChars) {
2055 heap_free(string);
2056 return E_UNEXPECTED;
2059 tlbstr = heap_alloc(sizeof(TLBString));
2061 tlbstr->offset = offs;
2062 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2063 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2065 heap_free(string);
2067 list_add_tail(&pcx->pLibInfo->name_list, &tlbstr->entry);
2069 offs += len_piece;
2073 static TLBString *MSFT_ReadName( TLBContext *pcx, int offset)
2075 TLBString *tlbstr;
2077 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->name_list, TLBString, entry) {
2078 if (tlbstr->offset == offset) {
2079 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2080 return tlbstr;
2084 return NULL;
2087 static TLBString *MSFT_ReadString( TLBContext *pcx, int offset)
2089 TLBString *tlbstr;
2091 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->string_list, TLBString, entry) {
2092 if (tlbstr->offset == offset) {
2093 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2094 return tlbstr;
2098 return NULL;
2102 * read a value and fill a VARIANT structure
2104 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
2106 int size;
2108 TRACE_(typelib)("\n");
2110 if(offset <0) { /* data are packed in here */
2111 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
2112 V_I4(pVar) = offset & 0x3ffffff;
2113 return;
2115 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
2116 pcx->pTblDir->pCustData.offset + offset );
2117 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
2118 switch (V_VT(pVar)){
2119 case VT_EMPTY: /* FIXME: is this right? */
2120 case VT_NULL: /* FIXME: is this right? */
2121 case VT_I2 : /* this should not happen */
2122 case VT_I4 :
2123 case VT_R4 :
2124 case VT_ERROR :
2125 case VT_BOOL :
2126 case VT_I1 :
2127 case VT_UI1 :
2128 case VT_UI2 :
2129 case VT_UI4 :
2130 case VT_INT :
2131 case VT_UINT :
2132 case VT_VOID : /* FIXME: is this right? */
2133 case VT_HRESULT :
2134 size=4; break;
2135 case VT_R8 :
2136 case VT_CY :
2137 case VT_DATE :
2138 case VT_I8 :
2139 case VT_UI8 :
2140 case VT_DECIMAL : /* FIXME: is this right? */
2141 case VT_FILETIME :
2142 size=8;break;
2143 /* pointer types with known behaviour */
2144 case VT_BSTR :{
2145 char * ptr;
2146 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
2147 if(size < 0) {
2148 char next;
2149 DWORD origPos = MSFT_Tell(pcx), nullPos;
2151 do {
2152 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
2153 } while (next);
2154 nullPos = MSFT_Tell(pcx);
2155 size = nullPos - origPos;
2156 MSFT_Seek(pcx, origPos);
2158 ptr = heap_alloc_zero(size);/* allocate temp buffer */
2159 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
2160 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
2161 /* FIXME: do we need a AtoW conversion here? */
2162 V_UNION(pVar, bstrVal[size])='\0';
2163 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
2164 heap_free(ptr);
2166 size=-4; break;
2167 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2168 case VT_DISPATCH :
2169 case VT_VARIANT :
2170 case VT_UNKNOWN :
2171 case VT_PTR :
2172 case VT_SAFEARRAY :
2173 case VT_CARRAY :
2174 case VT_USERDEFINED :
2175 case VT_LPSTR :
2176 case VT_LPWSTR :
2177 case VT_BLOB :
2178 case VT_STREAM :
2179 case VT_STORAGE :
2180 case VT_STREAMED_OBJECT :
2181 case VT_STORED_OBJECT :
2182 case VT_BLOB_OBJECT :
2183 case VT_CF :
2184 case VT_CLSID :
2185 default:
2186 size=0;
2187 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2188 V_VT(pVar));
2191 if(size>0) /* (big|small) endian correct? */
2192 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
2193 return;
2196 * create a linked list with custom data
2198 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
2200 MSFT_CDGuid entry;
2201 TLBCustData* pNew;
2202 int count=0;
2204 TRACE_(typelib)("\n");
2206 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
2208 while(offset >=0){
2209 count++;
2210 pNew=heap_alloc_zero(sizeof(TLBCustData));
2211 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
2212 pNew->guid = MSFT_ReadGuid(entry.GuidOffset, pcx);
2213 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
2214 list_add_head(custdata_list, &pNew->entry);
2215 offset = entry.next;
2217 return count;
2220 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
2221 ITypeInfoImpl *pTI)
2223 if(type <0)
2224 pTd->vt=type & VT_TYPEMASK;
2225 else
2226 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
2228 TRACE_(typelib)("vt type = %X\n", pTd->vt);
2231 static int TLB_is_propgetput(INVOKEKIND invkind)
2233 return (invkind == INVOKE_PROPERTYGET ||
2234 invkind == INVOKE_PROPERTYPUT ||
2235 invkind == INVOKE_PROPERTYPUTREF);
2238 static void
2239 MSFT_DoFuncs(TLBContext* pcx,
2240 ITypeInfoImpl* pTI,
2241 int cFuncs,
2242 int cVars,
2243 int offset,
2244 TLBFuncDesc** pptfd)
2247 * member information is stored in a data structure at offset
2248 * indicated by the memoffset field of the typeinfo structure
2249 * There are several distinctive parts.
2250 * The first part starts with a field that holds the total length
2251 * of this (first) part excluding this field. Then follow the records,
2252 * for each member there is one record.
2254 * The first entry is always the length of the record (including this
2255 * length word).
2256 * The rest of the record depends on the type of the member. If there is
2257 * a field indicating the member type (function, variable, interface, etc)
2258 * I have not found it yet. At this time we depend on the information
2259 * in the type info and the usual order how things are stored.
2261 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2262 * for each member;
2264 * Third is an equal sized array with file offsets to the name entry
2265 * of each member.
2267 * The fourth and last (?) part is an array with offsets to the records
2268 * in the first part of this file segment.
2271 int infolen, nameoffset, reclength, i;
2272 int recoffset = offset + sizeof(INT);
2274 char *recbuf = heap_alloc(0xffff);
2275 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2276 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2278 TRACE_(typelib)("\n");
2280 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2282 *pptfd = TLBFuncDesc_Alloc(cFuncs);
2283 ptfd = *pptfd;
2284 for ( i = 0; i < cFuncs ; i++ )
2286 int optional;
2288 /* name, eventually add to a hash table */
2289 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2290 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2292 /* read the function information record */
2293 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2295 reclength &= 0xffff;
2297 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2299 /* size without argument data */
2300 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2301 if (pFuncRec->FKCCIC & 0x1000)
2302 optional -= pFuncRec->nrargs * sizeof(INT);
2304 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2305 ptfd->helpcontext = pFuncRec->HelpContext;
2307 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2308 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2310 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2312 if (pFuncRec->FKCCIC & 0x2000 )
2314 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2315 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2316 ptfd->Entry = (TLBString*)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2318 else
2319 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2321 else
2322 ptfd->Entry = (TLBString*)-1;
2324 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2325 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2327 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2328 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2330 /* fill the FuncDesc Structure */
2331 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2332 offset + infolen + ( i + 1) * sizeof(INT));
2334 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2335 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2336 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2337 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2338 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2339 ptfd->funcdesc.oVft = pFuncRec->VtableOffset & ~1;
2340 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2342 /* nameoffset is sometimes -1 on the second half of a propget/propput
2343 * pair of functions */
2344 if ((nameoffset == -1) && (i > 0) &&
2345 TLB_is_propgetput(ptfd_prev->funcdesc.invkind) &&
2346 TLB_is_propgetput(ptfd->funcdesc.invkind))
2347 ptfd->Name = ptfd_prev->Name;
2348 else
2349 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2351 MSFT_GetTdesc(pcx,
2352 pFuncRec->DataType,
2353 &ptfd->funcdesc.elemdescFunc.tdesc,
2354 pTI);
2356 /* do the parameters/arguments */
2357 if(pFuncRec->nrargs)
2359 int j = 0;
2360 MSFT_ParameterInfo paraminfo;
2362 ptfd->funcdesc.lprgelemdescParam =
2363 heap_alloc_zero(pFuncRec->nrargs * (sizeof(ELEMDESC) + sizeof(PARAMDESCEX)));
2365 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2367 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2368 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2370 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2372 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2374 MSFT_GetTdesc(pcx,
2375 paraminfo.DataType,
2376 &elemdesc->tdesc,
2377 pTI);
2379 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2381 /* name */
2382 if (paraminfo.oName != -1)
2383 ptfd->pParamDesc[j].Name =
2384 MSFT_ReadName( pcx, paraminfo.oName );
2385 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(TLB_get_bstr(ptfd->pParamDesc[j].Name)));
2387 /* default value */
2388 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2389 (pFuncRec->FKCCIC & 0x1000) )
2391 INT* pInt = (INT *)((char *)pFuncRec +
2392 reclength -
2393 (pFuncRec->nrargs * 4) * sizeof(INT) );
2395 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2397 pParamDesc->pparamdescex = (PARAMDESCEX*)(ptfd->funcdesc.lprgelemdescParam+pFuncRec->nrargs)+j;
2398 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2400 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2401 pInt[j], pcx);
2403 else
2404 elemdesc->u.paramdesc.pparamdescex = NULL;
2406 /* custom info */
2407 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2408 j*sizeof(pFuncRec->oArgCustData[0])) &&
2409 pFuncRec->FKCCIC & 0x80 )
2411 MSFT_CustData(pcx,
2412 pFuncRec->oArgCustData[j],
2413 &ptfd->pParamDesc[j].custdata_list);
2416 /* SEEK value = jump to offset,
2417 * from there jump to the end of record,
2418 * go back by (j-1) arguments
2420 MSFT_ReadLEDWords( &paraminfo ,
2421 sizeof(MSFT_ParameterInfo), pcx,
2422 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2423 * sizeof(MSFT_ParameterInfo)));
2427 /* scode is not used: archaic win16 stuff FIXME: right? */
2428 ptfd->funcdesc.cScodes = 0 ;
2429 ptfd->funcdesc.lprgscode = NULL ;
2431 ptfd_prev = ptfd;
2432 ++ptfd;
2433 recoffset += reclength;
2435 heap_free(recbuf);
2438 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2439 int cVars, int offset, TLBVarDesc ** pptvd)
2441 int infolen, nameoffset, reclength;
2442 char recbuf[256];
2443 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2444 TLBVarDesc *ptvd;
2445 int i;
2446 int recoffset;
2448 TRACE_(typelib)("\n");
2450 ptvd = *pptvd = TLBVarDesc_Alloc(cVars);
2451 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2452 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2453 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2454 recoffset += offset+sizeof(INT);
2455 for(i=0;i<cVars;i++, ++ptvd){
2456 /* name, eventually add to a hash table */
2457 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2458 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2459 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2460 /* read the variable information record */
2461 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2462 reclength &= 0xff;
2463 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2465 /* optional data */
2466 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2467 ptvd->HelpContext = pVarRec->HelpContext;
2469 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2470 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2472 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2473 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2475 /* fill the VarDesc Structure */
2476 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2477 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2478 ptvd->vardesc.varkind = pVarRec->VarKind;
2479 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2480 MSFT_GetTdesc(pcx, pVarRec->DataType,
2481 &ptvd->vardesc.elemdescVar.tdesc, pTI);
2482 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2483 if(pVarRec->VarKind == VAR_CONST ){
2484 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2485 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2486 pVarRec->OffsValue, pcx);
2487 } else
2488 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2489 recoffset += reclength;
2493 /* process Implemented Interfaces of a com class */
2494 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2495 int offset)
2497 int i;
2498 MSFT_RefRecord refrec;
2499 TLBImplType *pImpl;
2501 TRACE_(typelib)("\n");
2503 pTI->impltypes = TLBImplType_Alloc(count);
2504 pImpl = pTI->impltypes;
2505 for(i=0;i<count;i++){
2506 if(offset<0) break; /* paranoia */
2507 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2508 pImpl->hRef = refrec.reftype;
2509 pImpl->implflags=refrec.flags;
2510 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2511 offset=refrec.onext;
2512 ++pImpl;
2516 * process a typeinfo record
2518 static ITypeInfoImpl * MSFT_DoTypeInfo(
2519 TLBContext *pcx,
2520 int count,
2521 ITypeLibImpl * pLibInfo)
2523 MSFT_TypeInfoBase tiBase;
2524 ITypeInfoImpl *ptiRet;
2526 TRACE_(typelib)("count=%u\n", count);
2528 ptiRet = ITypeInfoImpl_Constructor();
2529 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2530 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2532 /* this is where we are coming from */
2533 ptiRet->pTypeLib = pLibInfo;
2534 ptiRet->index=count;
2536 ptiRet->guid = MSFT_ReadGuid(tiBase.posguid, pcx);
2537 ptiRet->lcid=pLibInfo->set_lcid; /* FIXME: correct? */
2538 ptiRet->lpstrSchema=NULL; /* reserved */
2539 ptiRet->cbSizeInstance=tiBase.size;
2540 ptiRet->typekind=tiBase.typekind & 0xF;
2541 ptiRet->cFuncs=LOWORD(tiBase.cElement);
2542 ptiRet->cVars=HIWORD(tiBase.cElement);
2543 ptiRet->cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2544 ptiRet->wTypeFlags=tiBase.flags;
2545 ptiRet->wMajorVerNum=LOWORD(tiBase.version);
2546 ptiRet->wMinorVerNum=HIWORD(tiBase.version);
2547 ptiRet->cImplTypes=tiBase.cImplTypes;
2548 ptiRet->cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2549 if(ptiRet->typekind == TKIND_ALIAS)
2550 MSFT_GetTdesc(pcx, tiBase.datatype1,
2551 &ptiRet->tdescAlias, ptiRet);
2553 /* FIXME: */
2554 /* IDLDESC idldescType; *//* never saw this one != zero */
2556 /* name, eventually add to a hash table */
2557 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2558 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2559 TRACE_(typelib)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet->Name)));
2560 /* help info */
2561 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2562 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2563 ptiRet->dwHelpContext=tiBase.helpcontext;
2565 if (ptiRet->typekind == TKIND_MODULE)
2566 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2568 /* note: InfoType's Help file and HelpStringDll come from the containing
2569 * library. Further HelpString and Docstring appear to be the same thing :(
2571 /* functions */
2572 if(ptiRet->cFuncs >0 )
2573 MSFT_DoFuncs(pcx, ptiRet, ptiRet->cFuncs,
2574 ptiRet->cVars,
2575 tiBase.memoffset, &ptiRet->funcdescs);
2576 /* variables */
2577 if(ptiRet->cVars >0 )
2578 MSFT_DoVars(pcx, ptiRet, ptiRet->cFuncs,
2579 ptiRet->cVars,
2580 tiBase.memoffset, &ptiRet->vardescs);
2581 if(ptiRet->cImplTypes >0 ) {
2582 switch(ptiRet->typekind)
2584 case TKIND_COCLASS:
2585 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->cImplTypes,
2586 tiBase.datatype1);
2587 break;
2588 case TKIND_DISPATCH:
2589 /* This is not -1 when the interface is a non-base dual interface or
2590 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2591 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2592 not this interface.
2595 if (tiBase.datatype1 != -1)
2597 ptiRet->impltypes = TLBImplType_Alloc(1);
2598 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2600 break;
2601 default:
2602 ptiRet->impltypes = TLBImplType_Alloc(1);
2603 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2604 break;
2607 MSFT_CustData(pcx, tiBase.oCustData, ptiRet->pcustdata_list);
2609 TRACE_(typelib)("%s guid: %s kind:%s\n",
2610 debugstr_w(TLB_get_bstr(ptiRet->Name)),
2611 debugstr_guid(TLB_get_guidref(ptiRet->guid)),
2612 typekind_desc[ptiRet->typekind]);
2613 if (TRACE_ON(typelib))
2614 dump_TypeInfo(ptiRet);
2616 return ptiRet;
2619 static HRESULT MSFT_ReadAllStrings(TLBContext *pcx)
2621 char *string;
2622 INT16 len_str, len_piece;
2623 int offs = 0, lengthInChars;
2625 MSFT_Seek(pcx, pcx->pTblDir->pStringtab.offset);
2626 while (1) {
2627 TLBString *tlbstr;
2629 if (offs >= pcx->pTblDir->pStringtab.length)
2630 return S_OK;
2632 MSFT_ReadLEWords(&len_str, sizeof(INT16), pcx, DO_NOT_SEEK);
2633 len_piece = len_str + sizeof(INT16);
2634 if(len_piece % 4)
2635 len_piece = (len_piece + 4) & ~0x3;
2636 if(len_piece < 8)
2637 len_piece = 8;
2639 string = heap_alloc(len_piece + 1);
2640 MSFT_Read(string, len_piece - sizeof(INT16), pcx, DO_NOT_SEEK);
2641 string[len_str] = '\0';
2643 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2644 string, -1, NULL, 0);
2645 if (!lengthInChars) {
2646 heap_free(string);
2647 return E_UNEXPECTED;
2650 tlbstr = heap_alloc(sizeof(TLBString));
2652 tlbstr->offset = offs;
2653 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2654 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2656 heap_free(string);
2658 list_add_tail(&pcx->pLibInfo->string_list, &tlbstr->entry);
2660 offs += len_piece;
2664 static HRESULT MSFT_ReadAllRefs(TLBContext *pcx)
2666 TLBRefType *ref;
2667 int offs = 0;
2669 MSFT_Seek(pcx, pcx->pTblDir->pImpInfo.offset);
2670 while (offs < pcx->pTblDir->pImpInfo.length) {
2671 MSFT_ImpInfo impinfo;
2672 TLBImpLib *pImpLib;
2674 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx, DO_NOT_SEEK);
2676 ref = heap_alloc_zero(sizeof(TLBRefType));
2677 list_add_tail(&pcx->pLibInfo->ref_list, &ref->entry);
2679 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2680 if(pImpLib->offset==impinfo.oImpFile)
2681 break;
2683 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2684 ref->reference = offs;
2685 ref->pImpTLInfo = pImpLib;
2686 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2687 ref->guid = MSFT_ReadGuid(impinfo.oGuid, pcx);
2688 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
2689 ref->index = TLB_REF_USE_GUID;
2690 } else
2691 ref->index = impinfo.oGuid;
2692 }else{
2693 ERR("Cannot find a reference\n");
2694 ref->reference = -1;
2695 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2698 offs += sizeof(impinfo);
2701 return S_OK;
2704 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2705 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2706 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2707 * tradeoff here.
2709 static struct list tlb_cache = LIST_INIT(tlb_cache);
2710 static CRITICAL_SECTION cache_section;
2711 static CRITICAL_SECTION_DEBUG cache_section_debug =
2713 0, 0, &cache_section,
2714 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2715 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2717 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2720 typedef struct TLB_PEFile
2722 IUnknown IUnknown_iface;
2723 LONG refs;
2724 HMODULE dll;
2725 HRSRC typelib_resource;
2726 HGLOBAL typelib_global;
2727 LPVOID typelib_base;
2728 } TLB_PEFile;
2730 static inline TLB_PEFile *pefile_impl_from_IUnknown(IUnknown *iface)
2732 return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2735 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2737 if (IsEqualIID(riid, &IID_IUnknown))
2739 *ppv = iface;
2740 IUnknown_AddRef(iface);
2741 return S_OK;
2743 *ppv = NULL;
2744 return E_NOINTERFACE;
2747 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2749 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2750 return InterlockedIncrement(&This->refs);
2753 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2755 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2756 ULONG refs = InterlockedDecrement(&This->refs);
2757 if (!refs)
2759 if (This->typelib_global)
2760 FreeResource(This->typelib_global);
2761 if (This->dll)
2762 FreeLibrary(This->dll);
2763 heap_free(This);
2765 return refs;
2768 static const IUnknownVtbl TLB_PEFile_Vtable =
2770 TLB_PEFile_QueryInterface,
2771 TLB_PEFile_AddRef,
2772 TLB_PEFile_Release
2775 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2777 TLB_PEFile *This;
2778 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2780 This = heap_alloc(sizeof(TLB_PEFile));
2781 if (!This)
2782 return E_OUTOFMEMORY;
2784 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
2785 This->refs = 1;
2786 This->dll = NULL;
2787 This->typelib_resource = NULL;
2788 This->typelib_global = NULL;
2789 This->typelib_base = NULL;
2791 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2792 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2794 if (This->dll)
2796 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2797 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2798 if (This->typelib_resource)
2800 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2801 if (This->typelib_global)
2803 This->typelib_base = LockResource(This->typelib_global);
2805 if (This->typelib_base)
2807 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2808 *ppBase = This->typelib_base;
2809 *ppFile = &This->IUnknown_iface;
2810 return S_OK;
2815 TRACE("No TYPELIB resource found\n");
2816 hr = E_FAIL;
2819 TLB_PEFile_Release(&This->IUnknown_iface);
2820 return hr;
2823 typedef struct TLB_NEFile
2825 IUnknown IUnknown_iface;
2826 LONG refs;
2827 LPVOID typelib_base;
2828 } TLB_NEFile;
2830 static inline TLB_NEFile *nefile_impl_from_IUnknown(IUnknown *iface)
2832 return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
2835 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2837 if (IsEqualIID(riid, &IID_IUnknown))
2839 *ppv = iface;
2840 IUnknown_AddRef(iface);
2841 return S_OK;
2843 *ppv = NULL;
2844 return E_NOINTERFACE;
2847 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2849 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2850 return InterlockedIncrement(&This->refs);
2853 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2855 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2856 ULONG refs = InterlockedDecrement(&This->refs);
2857 if (!refs)
2859 heap_free(This->typelib_base);
2860 heap_free(This);
2862 return refs;
2865 static const IUnknownVtbl TLB_NEFile_Vtable =
2867 TLB_NEFile_QueryInterface,
2868 TLB_NEFile_AddRef,
2869 TLB_NEFile_Release
2872 /***********************************************************************
2873 * read_xx_header [internal]
2875 static int read_xx_header( HFILE lzfd )
2877 IMAGE_DOS_HEADER mzh;
2878 char magic[3];
2880 LZSeek( lzfd, 0, SEEK_SET );
2881 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2882 return 0;
2883 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2884 return 0;
2886 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2887 if ( 2 != LZRead( lzfd, magic, 2 ) )
2888 return 0;
2890 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2892 if ( magic[0] == 'N' && magic[1] == 'E' )
2893 return IMAGE_OS2_SIGNATURE;
2894 if ( magic[0] == 'P' && magic[1] == 'E' )
2895 return IMAGE_NT_SIGNATURE;
2897 magic[2] = '\0';
2898 WARN("Can't handle %s files.\n", magic );
2899 return 0;
2903 /***********************************************************************
2904 * find_ne_resource [internal]
2906 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2907 DWORD *resLen, DWORD *resOff )
2909 IMAGE_OS2_HEADER nehd;
2910 NE_TYPEINFO *typeInfo;
2911 NE_NAMEINFO *nameInfo;
2912 DWORD nehdoffset;
2913 LPBYTE resTab;
2914 DWORD resTabSize;
2915 int count;
2917 /* Read in NE header */
2918 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2919 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2921 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2922 if ( !resTabSize )
2924 TRACE("No resources in NE dll\n" );
2925 return FALSE;
2928 /* Read in resource table */
2929 resTab = heap_alloc( resTabSize );
2930 if ( !resTab ) return FALSE;
2932 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2933 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2935 heap_free( resTab );
2936 return FALSE;
2939 /* Find resource */
2940 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2942 if (!IS_INTRESOURCE(typeid)) /* named type */
2944 BYTE len = strlen( typeid );
2945 while (typeInfo->type_id)
2947 if (!(typeInfo->type_id & 0x8000))
2949 BYTE *p = resTab + typeInfo->type_id;
2950 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2952 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2953 typeInfo->count * sizeof(NE_NAMEINFO));
2956 else /* numeric type id */
2958 WORD id = LOWORD(typeid) | 0x8000;
2959 while (typeInfo->type_id)
2961 if (typeInfo->type_id == id) goto found_type;
2962 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2963 typeInfo->count * sizeof(NE_NAMEINFO));
2966 TRACE("No typeid entry found for %p\n", typeid );
2967 heap_free( resTab );
2968 return FALSE;
2970 found_type:
2971 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2973 if (!IS_INTRESOURCE(resid)) /* named resource */
2975 BYTE len = strlen( resid );
2976 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2978 BYTE *p = resTab + nameInfo->id;
2979 if (nameInfo->id & 0x8000) continue;
2980 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2983 else /* numeric resource id */
2985 WORD id = LOWORD(resid) | 0x8000;
2986 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2987 if (nameInfo->id == id) goto found_name;
2989 TRACE("No resid entry found for %p\n", typeid );
2990 heap_free( resTab );
2991 return FALSE;
2993 found_name:
2994 /* Return resource data */
2995 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2996 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2998 heap_free( resTab );
2999 return TRUE;
3002 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
3004 HFILE lzfd = -1;
3005 OFSTRUCT ofs;
3006 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
3007 TLB_NEFile *This;
3009 This = heap_alloc(sizeof(TLB_NEFile));
3010 if (!This) return E_OUTOFMEMORY;
3012 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
3013 This->refs = 1;
3014 This->typelib_base = NULL;
3016 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
3017 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
3019 DWORD reslen, offset;
3020 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
3022 This->typelib_base = heap_alloc(reslen);
3023 if( !This->typelib_base )
3024 hr = E_OUTOFMEMORY;
3025 else
3027 LZSeek( lzfd, offset, SEEK_SET );
3028 reslen = LZRead( lzfd, This->typelib_base, reslen );
3029 LZClose( lzfd );
3030 *ppBase = This->typelib_base;
3031 *pdwTLBLength = reslen;
3032 *ppFile = &This->IUnknown_iface;
3033 return S_OK;
3038 if( lzfd >= 0) LZClose( lzfd );
3039 TLB_NEFile_Release(&This->IUnknown_iface);
3040 return hr;
3043 typedef struct TLB_Mapping
3045 IUnknown IUnknown_iface;
3046 LONG refs;
3047 HANDLE file;
3048 HANDLE mapping;
3049 LPVOID typelib_base;
3050 } TLB_Mapping;
3052 static inline TLB_Mapping *mapping_impl_from_IUnknown(IUnknown *iface)
3054 return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
3057 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3059 if (IsEqualIID(riid, &IID_IUnknown))
3061 *ppv = iface;
3062 IUnknown_AddRef(iface);
3063 return S_OK;
3065 *ppv = NULL;
3066 return E_NOINTERFACE;
3069 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
3071 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3072 return InterlockedIncrement(&This->refs);
3075 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
3077 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3078 ULONG refs = InterlockedDecrement(&This->refs);
3079 if (!refs)
3081 if (This->typelib_base)
3082 UnmapViewOfFile(This->typelib_base);
3083 if (This->mapping)
3084 CloseHandle(This->mapping);
3085 if (This->file != INVALID_HANDLE_VALUE)
3086 CloseHandle(This->file);
3087 heap_free(This);
3089 return refs;
3092 static const IUnknownVtbl TLB_Mapping_Vtable =
3094 TLB_Mapping_QueryInterface,
3095 TLB_Mapping_AddRef,
3096 TLB_Mapping_Release
3099 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
3101 TLB_Mapping *This;
3103 This = heap_alloc(sizeof(TLB_Mapping));
3104 if (!This)
3105 return E_OUTOFMEMORY;
3107 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
3108 This->refs = 1;
3109 This->file = INVALID_HANDLE_VALUE;
3110 This->mapping = NULL;
3111 This->typelib_base = NULL;
3113 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3114 if (INVALID_HANDLE_VALUE != This->file)
3116 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
3117 if (This->mapping)
3119 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
3120 if(This->typelib_base)
3122 /* retrieve file size */
3123 *pdwTLBLength = GetFileSize(This->file, NULL);
3124 *ppBase = This->typelib_base;
3125 *ppFile = &This->IUnknown_iface;
3126 return S_OK;
3131 IUnknown_Release(&This->IUnknown_iface);
3132 return TYPE_E_CANTLOADLIBRARY;
3135 /****************************************************************************
3136 * TLB_ReadTypeLib
3138 * find the type of the typelib file and map the typelib resource into
3139 * the memory
3142 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3143 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
3145 ITypeLibImpl *entry;
3146 HRESULT ret;
3147 INT index = 1;
3148 LPWSTR index_str, file = (LPWSTR)pszFileName;
3149 LPVOID pBase = NULL;
3150 DWORD dwTLBLength = 0;
3151 IUnknown *pFile = NULL;
3152 HANDLE h;
3154 *ppTypeLib = NULL;
3156 index_str = strrchrW(pszFileName, '\\');
3157 if(index_str && *++index_str != '\0')
3159 LPWSTR end_ptr;
3160 LONG idx = strtolW(index_str, &end_ptr, 10);
3161 if(*end_ptr == '\0')
3163 int str_len = index_str - pszFileName - 1;
3164 index = idx;
3165 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
3166 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
3167 file[str_len] = 0;
3171 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
3173 if(strchrW(file, '\\'))
3175 lstrcpyW(pszPath, file);
3177 else
3179 int len = GetSystemDirectoryW(pszPath, cchPath);
3180 pszPath[len] = '\\';
3181 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
3185 if(file != pszFileName) heap_free(file);
3187 h = CreateFileW(pszPath, GENERIC_READ, 0, NULL, OPEN_ALWAYS,
3188 FILE_ATTRIBUTE_NORMAL, NULL);
3189 if(h != INVALID_HANDLE_VALUE){
3190 FILE_NAME_INFORMATION *info;
3191 char data[MAX_PATH * sizeof(WCHAR) + sizeof(info->FileNameLength)];
3192 BOOL br;
3194 info = (FILE_NAME_INFORMATION*)data;
3195 /* GetFileInformationByHandleEx returns the path of the file without
3196 * WOW64 redirection */
3197 br = GetFileInformationByHandleEx(h, FileNameInfo, data, sizeof(data));
3198 if(br){
3199 info->FileName[info->FileNameLength / sizeof(WCHAR)] = 0;
3200 lstrcpynW(pszPath + 2, info->FileName, cchPath - 2);
3202 CloseHandle(h);
3205 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
3207 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3208 EnterCriticalSection(&cache_section);
3209 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
3211 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
3213 TRACE("cache hit\n");
3214 *ppTypeLib = &entry->ITypeLib2_iface;
3215 ITypeLib2_AddRef(*ppTypeLib);
3216 LeaveCriticalSection(&cache_section);
3217 return S_OK;
3220 LeaveCriticalSection(&cache_section);
3222 /* now actually load and parse the typelib */
3224 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3225 if (ret == TYPE_E_CANTLOADLIBRARY)
3226 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3227 if (ret == TYPE_E_CANTLOADLIBRARY)
3228 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
3229 if (SUCCEEDED(ret))
3231 if (dwTLBLength >= 4)
3233 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
3234 if (dwSignature == MSFT_SIGNATURE)
3235 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
3236 else if (dwSignature == SLTG_SIGNATURE)
3237 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
3238 else
3240 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
3241 ret = TYPE_E_CANTLOADLIBRARY;
3244 else
3245 ret = TYPE_E_CANTLOADLIBRARY;
3246 IUnknown_Release(pFile);
3249 if(*ppTypeLib) {
3250 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
3252 TRACE("adding to cache\n");
3253 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
3254 lstrcpyW(impl->path, pszPath);
3255 /* We should really canonicalise the path here. */
3256 impl->index = index;
3258 /* FIXME: check if it has added already in the meantime */
3259 EnterCriticalSection(&cache_section);
3260 list_add_head(&tlb_cache, &impl->entry);
3261 LeaveCriticalSection(&cache_section);
3262 ret = S_OK;
3264 else
3266 if(ret != E_FAIL)
3267 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
3269 ret = TYPE_E_CANTLOADLIBRARY;
3273 return ret;
3276 /*================== ITypeLib(2) Methods ===================================*/
3278 static ITypeLibImpl* TypeLibImpl_Constructor(void)
3280 ITypeLibImpl* pTypeLibImpl;
3282 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
3283 if (!pTypeLibImpl) return NULL;
3285 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3286 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3287 pTypeLibImpl->ICreateTypeLib2_iface.lpVtbl = &CreateTypeLib2Vtbl;
3288 pTypeLibImpl->ref = 1;
3290 list_init(&pTypeLibImpl->implib_list);
3291 list_init(&pTypeLibImpl->custdata_list);
3292 list_init(&pTypeLibImpl->name_list);
3293 list_init(&pTypeLibImpl->string_list);
3294 list_init(&pTypeLibImpl->guid_list);
3295 list_init(&pTypeLibImpl->ref_list);
3296 pTypeLibImpl->dispatch_href = -1;
3298 return pTypeLibImpl;
3301 /****************************************************************************
3302 * ITypeLib2_Constructor_MSFT
3304 * loading an MSFT typelib from an in-memory image
3306 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3308 TLBContext cx;
3309 LONG lPSegDir;
3310 MSFT_Header tlbHeader;
3311 MSFT_SegDir tlbSegDir;
3312 ITypeLibImpl * pTypeLibImpl;
3314 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3316 pTypeLibImpl = TypeLibImpl_Constructor();
3317 if (!pTypeLibImpl) return NULL;
3319 /* get pointer to beginning of typelib data */
3320 cx.pos = 0;
3321 cx.oStart=0;
3322 cx.mapping = pLib;
3323 cx.pLibInfo = pTypeLibImpl;
3324 cx.length = dwTLBLength;
3326 /* read header */
3327 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
3328 TRACE_(typelib)("header:\n");
3329 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3330 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3331 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3332 return NULL;
3334 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3336 /* there is a small amount of information here until the next important
3337 * part:
3338 * the segment directory . Try to calculate the amount of data */
3339 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3341 /* now read the segment directory */
3342 TRACE("read segment directory (at %d)\n",lPSegDir);
3343 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3344 cx.pTblDir = &tlbSegDir;
3346 /* just check two entries */
3347 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3349 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3350 heap_free(pTypeLibImpl);
3351 return NULL;
3354 MSFT_ReadAllNames(&cx);
3355 MSFT_ReadAllStrings(&cx);
3356 MSFT_ReadAllGuids(&cx);
3358 /* now fill our internal data */
3359 /* TLIBATTR fields */
3360 pTypeLibImpl->guid = MSFT_ReadGuid(tlbHeader.posguid, &cx);
3362 pTypeLibImpl->syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3363 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3364 pTypeLibImpl->ver_major = LOWORD(tlbHeader.version);
3365 pTypeLibImpl->ver_minor = HIWORD(tlbHeader.version);
3366 pTypeLibImpl->libflags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
3368 pTypeLibImpl->set_lcid = tlbHeader.lcid2;
3369 pTypeLibImpl->lcid = tlbHeader.lcid;
3371 /* name, eventually add to a hash table */
3372 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3374 /* help info */
3375 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3376 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3378 if( tlbHeader.varflags & HELPDLLFLAG)
3380 int offset;
3381 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3382 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3385 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3387 /* custom data */
3388 if(tlbHeader.CustomDataOffset >= 0)
3390 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3393 /* fill in type descriptions */
3394 if(tlbSegDir.pTypdescTab.length > 0)
3396 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3397 INT16 td[4];
3398 pTypeLibImpl->ctTypeDesc = cTD;
3399 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3400 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3401 for(i=0; i<cTD; )
3403 /* FIXME: add several sanity checks here */
3404 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3405 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3407 /* FIXME: check safearray */
3408 if(td[3] < 0)
3409 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3410 else
3411 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3413 else if(td[0] == VT_CARRAY)
3415 /* array descr table here */
3416 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3418 else if(td[0] == VT_USERDEFINED)
3420 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3422 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3425 /* second time around to fill the array subscript info */
3426 for(i=0;i<cTD;i++)
3428 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3429 if(tlbSegDir.pArrayDescriptions.offset>0)
3431 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3432 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3434 if(td[1]<0)
3435 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3436 else
3437 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3439 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3441 for(j = 0; j<td[2]; j++)
3443 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3444 sizeof(INT), &cx, DO_NOT_SEEK);
3445 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3446 sizeof(INT), &cx, DO_NOT_SEEK);
3449 else
3451 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3452 ERR("didn't find array description data\n");
3457 /* imported type libs */
3458 if(tlbSegDir.pImpFiles.offset>0)
3460 TLBImpLib *pImpLib;
3461 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3462 UINT16 size;
3464 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3466 char *name;
3468 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3469 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3470 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3472 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3473 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3474 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3475 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3477 size >>= 2;
3478 name = heap_alloc_zero(size+1);
3479 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3480 pImpLib->name = TLB_MultiByteToBSTR(name);
3481 heap_free(name);
3483 pImpLib->guid = MSFT_ReadGuid(oGuid, &cx);
3484 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3486 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3490 MSFT_ReadAllRefs(&cx);
3492 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3494 /* type infos */
3495 if(tlbHeader.nrtypeinfos >= 0 )
3497 ITypeInfoImpl **ppTI;
3498 int i;
3500 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3502 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3504 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3506 ++ppTI;
3507 (pTypeLibImpl->TypeInfoCount)++;
3511 TRACE("(%p)\n", pTypeLibImpl);
3512 return &pTypeLibImpl->ITypeLib2_iface;
3516 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3518 char b[3];
3519 int i;
3520 short s;
3522 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3523 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3524 return FALSE;
3527 guid->Data4[0] = s >> 8;
3528 guid->Data4[1] = s & 0xff;
3530 b[2] = '\0';
3531 for(i = 0; i < 6; i++) {
3532 memcpy(b, str + 24 + 2 * i, 2);
3533 guid->Data4[i + 2] = strtol(b, NULL, 16);
3535 return TRUE;
3538 static WORD SLTG_ReadString(const char *ptr, const TLBString **pStr, ITypeLibImpl *lib)
3540 WORD bytelen;
3541 DWORD len;
3542 BSTR tmp_str;
3544 *pStr = NULL;
3545 bytelen = *(const WORD*)ptr;
3546 if(bytelen == 0xffff) return 2;
3548 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3549 tmp_str = SysAllocStringLen(NULL, len);
3550 if (tmp_str) {
3551 MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, tmp_str, len);
3552 *pStr = TLB_append_str(&lib->string_list, tmp_str);
3553 SysFreeString(tmp_str);
3555 return bytelen + 2;
3558 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3560 WORD bytelen;
3562 *str = NULL;
3563 bytelen = *(const WORD*)ptr;
3564 if(bytelen == 0xffff) return 2;
3565 *str = heap_alloc(bytelen + 1);
3566 memcpy(*str, ptr + 2, bytelen);
3567 (*str)[bytelen] = '\0';
3568 return bytelen + 2;
3571 static TLBString *SLTG_ReadName(const char *pNameTable, int offset, ITypeLibImpl *lib)
3573 BSTR tmp_str;
3574 TLBString *tlbstr;
3576 LIST_FOR_EACH_ENTRY(tlbstr, &lib->name_list, TLBString, entry) {
3577 if (tlbstr->offset == offset)
3578 return tlbstr;
3581 tmp_str = TLB_MultiByteToBSTR(pNameTable + offset);
3582 tlbstr = TLB_append_str(&lib->name_list, tmp_str);
3583 SysFreeString(tmp_str);
3585 return tlbstr;
3588 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3590 char *ptr = pLibBlk;
3591 WORD w;
3593 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3594 FIXME("libblk magic = %04x\n", w);
3595 return 0;
3598 ptr += 6;
3599 if((w = *(WORD*)ptr) != 0xffff) {
3600 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3601 ptr += w;
3603 ptr += 2;
3605 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString, pTypeLibImpl);
3607 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile, pTypeLibImpl);
3609 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3610 ptr += 4;
3612 pTypeLibImpl->syskind = *(WORD*)ptr;
3613 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3614 ptr += 2;
3616 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3617 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3618 else
3619 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = 0;
3620 ptr += 2;
3622 ptr += 4; /* skip res12 */
3624 pTypeLibImpl->libflags = *(WORD*)ptr;
3625 ptr += 2;
3627 pTypeLibImpl->ver_major = *(WORD*)ptr;
3628 ptr += 2;
3630 pTypeLibImpl->ver_minor = *(WORD*)ptr;
3631 ptr += 2;
3633 pTypeLibImpl->guid = TLB_append_guid(&pTypeLibImpl->guid_list, (GUID*)ptr, -2);
3634 ptr += sizeof(GUID);
3636 return ptr - (char*)pLibBlk;
3639 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3640 typedef struct
3642 unsigned int num;
3643 HREFTYPE refs[1];
3644 } sltg_ref_lookup_t;
3646 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3647 HREFTYPE *typelib_ref)
3649 if(table && typeinfo_ref < table->num)
3651 *typelib_ref = table->refs[typeinfo_ref];
3652 return S_OK;
3655 ERR_(typelib)("Unable to find reference\n");
3656 *typelib_ref = -1;
3657 return E_FAIL;
3660 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3662 BOOL done = FALSE;
3664 while(!done) {
3665 if((*pType & 0xe00) == 0xe00) {
3666 pTD->vt = VT_PTR;
3667 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3668 pTD = pTD->u.lptdesc;
3670 switch(*pType & 0x3f) {
3671 case VT_PTR:
3672 pTD->vt = VT_PTR;
3673 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3674 pTD = pTD->u.lptdesc;
3675 break;
3677 case VT_USERDEFINED:
3678 pTD->vt = VT_USERDEFINED;
3679 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3680 done = TRUE;
3681 break;
3683 case VT_CARRAY:
3685 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3686 array */
3688 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3690 pTD->vt = VT_CARRAY;
3691 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3692 pTD->u.lpadesc->cDims = pSA->cDims;
3693 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3694 pSA->cDims * sizeof(SAFEARRAYBOUND));
3696 pTD = &pTD->u.lpadesc->tdescElem;
3697 break;
3700 case VT_SAFEARRAY:
3702 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3703 useful? */
3705 pType++;
3706 pTD->vt = VT_SAFEARRAY;
3707 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3708 pTD = pTD->u.lptdesc;
3709 break;
3711 default:
3712 pTD->vt = *pType & 0x3f;
3713 done = TRUE;
3714 break;
3716 pType++;
3718 return pType;
3721 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3722 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3724 /* Handle [in/out] first */
3725 if((*pType & 0xc000) == 0xc000)
3726 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3727 else if(*pType & 0x8000)
3728 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3729 else if(*pType & 0x4000)
3730 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3731 else
3732 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3734 if(*pType & 0x2000)
3735 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3737 if(*pType & 0x80)
3738 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3740 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3744 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3745 char *pNameTable)
3747 unsigned int ref;
3748 char *name;
3749 TLBRefType *ref_type;
3750 sltg_ref_lookup_t *table;
3751 HREFTYPE typelib_ref;
3753 if(pRef->magic != SLTG_REF_MAGIC) {
3754 FIXME("Ref magic = %x\n", pRef->magic);
3755 return NULL;
3757 name = ( (char*)pRef->names + pRef->number);
3759 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3760 table->num = pRef->number >> 3;
3762 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3764 /* We don't want the first href to be 0 */
3765 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3767 for(ref = 0; ref < pRef->number >> 3; ref++) {
3768 char *refname;
3769 unsigned int lib_offs, type_num;
3771 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3773 name += SLTG_ReadStringA(name, &refname);
3774 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3775 FIXME_(typelib)("Can't sscanf ref\n");
3776 if(lib_offs != 0xffff) {
3777 TLBImpLib *import;
3779 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
3780 if(import->offset == lib_offs)
3781 break;
3783 if(&import->entry == &pTL->implib_list) {
3784 char fname[MAX_PATH+1];
3785 int len;
3786 GUID tmpguid;
3788 import = heap_alloc_zero(sizeof(*import));
3789 import->offset = lib_offs;
3790 TLB_GUIDFromString( pNameTable + lib_offs + 4, &tmpguid);
3791 import->guid = TLB_append_guid(&pTL->guid_list, &tmpguid, 2);
3792 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3793 &import->wVersionMajor,
3794 &import->wVersionMinor,
3795 &import->lcid, fname) != 4) {
3796 FIXME_(typelib)("can't sscanf ref %s\n",
3797 pNameTable + lib_offs + 40);
3799 len = strlen(fname);
3800 if(fname[len-1] != '#')
3801 FIXME("fname = %s\n", fname);
3802 fname[len-1] = '\0';
3803 import->name = TLB_MultiByteToBSTR(fname);
3804 list_add_tail(&pTL->implib_list, &import->entry);
3806 ref_type->pImpTLInfo = import;
3808 /* Store a reference to IDispatch */
3809 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid->guid, &IID_StdOle) && type_num == 4)
3810 pTL->dispatch_href = typelib_ref;
3812 } else { /* internal ref */
3813 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3815 ref_type->reference = typelib_ref;
3816 ref_type->index = type_num;
3818 heap_free(refname);
3819 list_add_tail(&pTL->ref_list, &ref_type->entry);
3821 table->refs[ref] = typelib_ref;
3822 typelib_ref += 4;
3824 if((BYTE)*name != SLTG_REF_MAGIC)
3825 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3826 dump_TLBRefType(pTL);
3827 return table;
3830 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3831 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3833 SLTG_ImplInfo *info;
3834 TLBImplType *pImplType;
3835 /* I don't really get this structure, usually it's 0x16 bytes
3836 long, but iuser.tlb contains some that are 0x18 bytes long.
3837 That's ok because we can use the next ptr to jump to the next
3838 one. But how do we know the length of the last one? The WORD
3839 at offs 0x8 might be the clue. For now I'm just assuming that
3840 the last one is the regular 0x16 bytes. */
3842 info = (SLTG_ImplInfo*)pBlk;
3843 while(1){
3844 pTI->cImplTypes++;
3845 if(info->next == 0xffff)
3846 break;
3847 info = (SLTG_ImplInfo*)(pBlk + info->next);
3850 info = (SLTG_ImplInfo*)pBlk;
3851 pTI->impltypes = TLBImplType_Alloc(pTI->cImplTypes);
3852 pImplType = pTI->impltypes;
3853 while(1) {
3854 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
3855 pImplType->implflags = info->impltypeflags;
3856 ++pImplType;
3858 if(info->next == 0xffff)
3859 break;
3860 if(OneOnly)
3861 FIXME_(typelib)("Interface inheriting more than one interface\n");
3862 info = (SLTG_ImplInfo*)(pBlk + info->next);
3864 info++; /* see comment at top of function */
3865 return (char*)info;
3868 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3869 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3871 TLBVarDesc *pVarDesc;
3872 const TLBString *prevName = NULL;
3873 SLTG_Variable *pItem;
3874 unsigned short i;
3875 WORD *pType;
3877 pVarDesc = pTI->vardescs = TLBVarDesc_Alloc(cVars);
3879 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3880 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
3882 pVarDesc->vardesc.memid = pItem->memid;
3884 if (pItem->magic != SLTG_VAR_MAGIC &&
3885 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3886 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3887 return;
3890 if (pItem->name == 0xfffe)
3891 pVarDesc->Name = prevName;
3892 else
3893 pVarDesc->Name = SLTG_ReadName(pNameTable, pItem->name, pTI->pTypeLib);
3895 TRACE_(typelib)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc->Name)));
3896 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3897 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3899 if(pItem->flags & 0x02)
3900 pType = &pItem->type;
3901 else
3902 pType = (WORD*)(pBlk + pItem->type);
3904 if (pItem->flags & ~0xda)
3905 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3907 SLTG_DoElem(pType, pBlk,
3908 &pVarDesc->vardesc.elemdescVar, ref_lookup);
3910 if (TRACE_ON(typelib)) {
3911 char buf[300];
3912 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
3913 TRACE_(typelib)("elemdescVar: %s\n", buf);
3916 if (pItem->flags & 0x40) {
3917 TRACE_(typelib)("VAR_DISPATCH\n");
3918 pVarDesc->vardesc.varkind = VAR_DISPATCH;
3920 else if (pItem->flags & 0x10) {
3921 TRACE_(typelib)("VAR_CONST\n");
3922 pVarDesc->vardesc.varkind = VAR_CONST;
3923 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
3924 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
3925 if (pItem->flags & 0x08)
3926 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
3927 else {
3928 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
3930 case VT_LPSTR:
3931 case VT_LPWSTR:
3932 case VT_BSTR:
3934 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3935 BSTR str;
3936 TRACE_(typelib)("len = %u\n", len);
3937 if (len == 0xffff) {
3938 str = NULL;
3939 } else {
3940 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3941 str = SysAllocStringLen(NULL, alloc_len);
3942 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3944 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
3945 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
3946 break;
3948 case VT_I2:
3949 case VT_UI2:
3950 case VT_I4:
3951 case VT_UI4:
3952 case VT_INT:
3953 case VT_UINT:
3954 V_INT(pVarDesc->vardesc.u.lpvarValue) =
3955 *(INT*)(pBlk + pItem->byte_offs);
3956 break;
3957 default:
3958 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
3962 else {
3963 TRACE_(typelib)("VAR_PERINSTANCE\n");
3964 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
3965 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
3968 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3969 pVarDesc->vardesc.wVarFlags = pItem->varflags;
3971 if (pItem->flags & 0x80)
3972 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3974 prevName = pVarDesc->Name;
3976 pTI->cVars = cVars;
3979 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3980 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3982 SLTG_Function *pFunc;
3983 unsigned short i;
3984 TLBFuncDesc *pFuncDesc;
3986 pTI->funcdescs = TLBFuncDesc_Alloc(cFuncs);
3988 pFuncDesc = pTI->funcdescs;
3989 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
3990 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
3992 int param;
3993 WORD *pType, *pArg;
3995 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3996 case SLTG_FUNCTION_MAGIC:
3997 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
3998 break;
3999 case SLTG_DISPATCH_FUNCTION_MAGIC:
4000 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
4001 break;
4002 case SLTG_STATIC_FUNCTION_MAGIC:
4003 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
4004 break;
4005 default:
4006 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
4007 continue;
4009 pFuncDesc->Name = SLTG_ReadName(pNameTable, pFunc->name, pTI->pTypeLib);
4011 pFuncDesc->funcdesc.memid = pFunc->dispid;
4012 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
4013 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
4014 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
4015 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
4016 pFuncDesc->funcdesc.oVft = pFunc->vtblpos & ~1;
4018 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
4019 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
4021 if(pFunc->retnextopt & 0x80)
4022 pType = &pFunc->rettype;
4023 else
4024 pType = (WORD*)(pBlk + pFunc->rettype);
4026 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
4028 pFuncDesc->funcdesc.lprgelemdescParam =
4029 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
4030 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
4032 pArg = (WORD*)(pBlk + pFunc->arg_off);
4034 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
4035 char *paramName = pNameTable + *pArg;
4036 BOOL HaveOffs;
4037 /* If arg type follows then paramName points to the 2nd
4038 letter of the name, else the next WORD is an offset to
4039 the arg type and paramName points to the first letter.
4040 So let's take one char off paramName and see if we're
4041 pointing at an alpha-numeric char. However if *pArg is
4042 0xffff or 0xfffe then the param has no name, the former
4043 meaning that the next WORD is the type, the latter
4044 meaning that the next WORD is an offset to the type. */
4046 HaveOffs = FALSE;
4047 if(*pArg == 0xffff)
4048 paramName = NULL;
4049 else if(*pArg == 0xfffe) {
4050 paramName = NULL;
4051 HaveOffs = TRUE;
4053 else if(paramName[-1] && !isalnum(paramName[-1]))
4054 HaveOffs = TRUE;
4056 pArg++;
4058 if(HaveOffs) { /* the next word is an offset to type */
4059 pType = (WORD*)(pBlk + *pArg);
4060 SLTG_DoElem(pType, pBlk,
4061 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4062 pArg++;
4063 } else {
4064 if(paramName)
4065 paramName--;
4066 pArg = SLTG_DoElem(pArg, pBlk,
4067 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4070 /* Are we an optional param ? */
4071 if(pFuncDesc->funcdesc.cParams - param <=
4072 pFuncDesc->funcdesc.cParamsOpt)
4073 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
4075 if(paramName) {
4076 pFuncDesc->pParamDesc[param].Name = SLTG_ReadName(pNameTable,
4077 paramName - pNameTable, pTI->pTypeLib);
4078 } else {
4079 pFuncDesc->pParamDesc[param].Name = pFuncDesc->Name;
4083 pTI->cFuncs = cFuncs;
4086 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
4087 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4088 SLTG_TypeInfoTail *pTITail)
4090 char *pFirstItem;
4091 sltg_ref_lookup_t *ref_lookup = NULL;
4093 if(pTIHeader->href_table != 0xffffffff) {
4094 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4095 pNameTable);
4098 pFirstItem = pBlk;
4100 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4101 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
4103 heap_free(ref_lookup);
4107 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
4108 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4109 const SLTG_TypeInfoTail *pTITail)
4111 char *pFirstItem;
4112 sltg_ref_lookup_t *ref_lookup = NULL;
4114 if(pTIHeader->href_table != 0xffffffff) {
4115 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4116 pNameTable);
4119 pFirstItem = pBlk;
4121 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4122 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
4125 if (pTITail->funcs_off != 0xffff)
4126 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4128 heap_free(ref_lookup);
4130 if (TRACE_ON(typelib))
4131 dump_TLBFuncDesc(pTI->funcdescs, pTI->cFuncs);
4134 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
4135 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4136 const SLTG_TypeInfoTail *pTITail)
4138 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4141 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
4142 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4143 const SLTG_TypeInfoTail *pTITail)
4145 WORD *pType;
4146 sltg_ref_lookup_t *ref_lookup = NULL;
4148 if (pTITail->simple_alias) {
4149 /* if simple alias, no more processing required */
4150 pTI->tdescAlias.vt = pTITail->tdescalias_vt;
4151 return;
4154 if(pTIHeader->href_table != 0xffffffff) {
4155 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4156 pNameTable);
4159 /* otherwise it is an offset to a type */
4160 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
4162 SLTG_DoType(pType, pBlk, &pTI->tdescAlias, ref_lookup);
4164 heap_free(ref_lookup);
4167 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
4168 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4169 const SLTG_TypeInfoTail *pTITail)
4171 sltg_ref_lookup_t *ref_lookup = NULL;
4172 if (pTIHeader->href_table != 0xffffffff)
4173 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4174 pNameTable);
4176 if (pTITail->vars_off != 0xffff)
4177 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4179 if (pTITail->funcs_off != 0xffff)
4180 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4182 if (pTITail->impls_off != 0xffff)
4183 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
4185 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4186 * of dispinterface functions including the IDispatch ones, so
4187 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4188 pTI->cbSizeVft = pTI->cFuncs * pTI->pTypeLib->ptr_size;
4190 heap_free(ref_lookup);
4191 if (TRACE_ON(typelib))
4192 dump_TLBFuncDesc(pTI->funcdescs, pTI->cFuncs);
4195 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
4196 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4197 const SLTG_TypeInfoTail *pTITail)
4199 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4202 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
4203 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4204 const SLTG_TypeInfoTail *pTITail)
4206 sltg_ref_lookup_t *ref_lookup = NULL;
4207 if (pTIHeader->href_table != 0xffffffff)
4208 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4209 pNameTable);
4211 if (pTITail->vars_off != 0xffff)
4212 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4214 if (pTITail->funcs_off != 0xffff)
4215 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4216 heap_free(ref_lookup);
4217 if (TRACE_ON(typelib))
4218 dump_TypeInfo(pTI);
4221 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4222 manageable copy of it into this */
4223 typedef struct {
4224 WORD small_no;
4225 char *index_name;
4226 char *other_name;
4227 WORD res1a;
4228 WORD name_offs;
4229 WORD more_bytes;
4230 char *extra;
4231 WORD res20;
4232 DWORD helpcontext;
4233 WORD res26;
4234 GUID uuid;
4235 } SLTG_InternalOtherTypeInfo;
4237 /****************************************************************************
4238 * ITypeLib2_Constructor_SLTG
4240 * loading a SLTG typelib from an in-memory image
4242 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
4244 ITypeLibImpl *pTypeLibImpl;
4245 SLTG_Header *pHeader;
4246 SLTG_BlkEntry *pBlkEntry;
4247 SLTG_Magic *pMagic;
4248 SLTG_Index *pIndex;
4249 SLTG_Pad9 *pPad9;
4250 LPVOID pBlk, pFirstBlk;
4251 SLTG_LibBlk *pLibBlk;
4252 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
4253 char *pAfterOTIBlks = NULL;
4254 char *pNameTable, *ptr;
4255 int i;
4256 DWORD len, order;
4257 ITypeInfoImpl **ppTypeInfoImpl;
4259 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
4262 pTypeLibImpl = TypeLibImpl_Constructor();
4263 if (!pTypeLibImpl) return NULL;
4265 pHeader = pLib;
4267 TRACE_(typelib)("header:\n");
4268 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
4269 pHeader->nrOfFileBlks );
4270 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
4271 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
4272 pHeader->SLTG_magic);
4273 return NULL;
4276 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4277 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
4279 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4280 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
4282 /* Next we have a magic block */
4283 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
4285 /* Let's see if we're still in sync */
4286 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
4287 sizeof(SLTG_COMPOBJ_MAGIC))) {
4288 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
4289 return NULL;
4291 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
4292 sizeof(SLTG_DIR_MAGIC))) {
4293 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
4294 return NULL;
4297 pIndex = (SLTG_Index*)(pMagic+1);
4299 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
4301 pFirstBlk = pPad9 + 1;
4303 /* We'll set up a ptr to the main library block, which is the last one. */
4305 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4306 pBlkEntry[order].next != 0;
4307 order = pBlkEntry[order].next - 1, i++) {
4308 pBlk = (char*)pBlk + pBlkEntry[order].len;
4310 pLibBlk = pBlk;
4312 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
4314 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4315 interspersed */
4317 len += 0x40;
4319 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4321 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
4324 ptr = (char*)pLibBlk + len;
4326 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4327 WORD w, extra;
4328 len = 0;
4330 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
4332 w = *(WORD*)(ptr + 2);
4333 if(w != 0xffff) {
4334 len += w;
4335 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
4336 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4337 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4339 w = *(WORD*)(ptr + 4 + len);
4340 if(w != 0xffff) {
4341 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4342 len += w;
4343 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4344 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4345 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4347 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4348 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4349 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4350 if(extra) {
4351 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4352 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4353 len += extra;
4355 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4356 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4357 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4358 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4359 len += sizeof(SLTG_OtherTypeInfo);
4360 ptr += len;
4363 pAfterOTIBlks = ptr;
4365 /* Skip this WORD and get the next DWORD */
4366 len = *(DWORD*)(pAfterOTIBlks + 2);
4368 /* Now add this to pLibBLk look at what we're pointing at and
4369 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4370 dust and we should be pointing at the beginning of the name
4371 table */
4373 pNameTable = (char*)pLibBlk + len;
4375 switch(*(WORD*)pNameTable) {
4376 case 0xffff:
4377 break;
4378 case 0x0200:
4379 pNameTable += 0x20;
4380 break;
4381 default:
4382 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4383 break;
4386 pNameTable += 0x216;
4388 pNameTable += 2;
4390 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4392 pTypeLibImpl->Name = SLTG_ReadName(pNameTable, pLibBlk->name, pTypeLibImpl);
4395 /* Hopefully we now have enough ptrs set up to actually read in
4396 some TypeInfos. It's not clear which order to do them in, so
4397 I'll just follow the links along the BlkEntry chain and read
4398 them in the order in which they are in the file */
4400 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4401 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4403 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4404 pBlkEntry[order].next != 0;
4405 order = pBlkEntry[order].next - 1, i++) {
4407 SLTG_TypeInfoHeader *pTIHeader;
4408 SLTG_TypeInfoTail *pTITail;
4409 SLTG_MemberHeader *pMemHeader;
4411 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4412 FIXME_(typelib)("Index strings don't match\n");
4413 heap_free(pOtherTypeInfoBlks);
4414 return NULL;
4417 pTIHeader = pBlk;
4418 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4419 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4420 heap_free(pOtherTypeInfoBlks);
4421 return NULL;
4423 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4424 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4425 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4427 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4428 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4429 (*ppTypeInfoImpl)->index = i;
4430 (*ppTypeInfoImpl)->Name = SLTG_ReadName(pNameTable, pOtherTypeInfoBlks[i].name_offs, pTypeLibImpl);
4431 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4432 (*ppTypeInfoImpl)->guid = TLB_append_guid(&pTypeLibImpl->guid_list, &pOtherTypeInfoBlks[i].uuid, 2);
4433 (*ppTypeInfoImpl)->typekind = pTIHeader->typekind;
4434 (*ppTypeInfoImpl)->wMajorVerNum = pTIHeader->major_version;
4435 (*ppTypeInfoImpl)->wMinorVerNum = pTIHeader->minor_version;
4436 (*ppTypeInfoImpl)->wTypeFlags =
4437 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4439 if((*ppTypeInfoImpl)->wTypeFlags & TYPEFLAG_FDUAL)
4440 (*ppTypeInfoImpl)->typekind = TKIND_DISPATCH;
4442 if((pTIHeader->typeflags1 & 7) != 2)
4443 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4444 if(pTIHeader->typeflags3 != 2)
4445 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4447 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4448 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl)->Name)),
4449 typekind_desc[pTIHeader->typekind],
4450 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl)->guid)),
4451 (*ppTypeInfoImpl)->wTypeFlags);
4453 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4455 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4457 (*ppTypeInfoImpl)->cbAlignment = pTITail->cbAlignment;
4458 (*ppTypeInfoImpl)->cbSizeInstance = pTITail->cbSizeInstance;
4459 (*ppTypeInfoImpl)->cbSizeVft = pTITail->cbSizeVft;
4461 switch(pTIHeader->typekind) {
4462 case TKIND_ENUM:
4463 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4464 pTIHeader, pTITail);
4465 break;
4467 case TKIND_RECORD:
4468 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4469 pTIHeader, pTITail);
4470 break;
4472 case TKIND_INTERFACE:
4473 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4474 pTIHeader, pTITail);
4475 break;
4477 case TKIND_COCLASS:
4478 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4479 pTIHeader, pTITail);
4480 break;
4482 case TKIND_ALIAS:
4483 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4484 pTIHeader, pTITail);
4485 break;
4487 case TKIND_DISPATCH:
4488 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4489 pTIHeader, pTITail);
4490 break;
4492 case TKIND_MODULE:
4493 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4494 pTIHeader, pTITail);
4495 break;
4497 default:
4498 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4499 break;
4503 /* could get cFuncs, cVars and cImplTypes from here
4504 but we've already set those */
4505 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4506 X(06);
4507 X(16);
4508 X(18);
4509 X(1a);
4510 X(1e);
4511 X(24);
4512 X(26);
4513 X(2a);
4514 X(2c);
4515 X(2e);
4516 X(30);
4517 X(32);
4518 X(34);
4519 #undef X
4520 ++ppTypeInfoImpl;
4521 pBlk = (char*)pBlk + pBlkEntry[order].len;
4524 if(i != pTypeLibImpl->TypeInfoCount) {
4525 FIXME("Somehow processed %d TypeInfos\n", i);
4526 heap_free(pOtherTypeInfoBlks);
4527 return NULL;
4530 heap_free(pOtherTypeInfoBlks);
4531 return &pTypeLibImpl->ITypeLib2_iface;
4534 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4536 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4538 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4540 if(IsEqualIID(riid, &IID_IUnknown) ||
4541 IsEqualIID(riid,&IID_ITypeLib)||
4542 IsEqualIID(riid,&IID_ITypeLib2))
4544 *ppv = &This->ITypeLib2_iface;
4546 else if(IsEqualIID(riid, &IID_ICreateTypeLib) ||
4547 IsEqualIID(riid, &IID_ICreateTypeLib2))
4549 *ppv = &This->ICreateTypeLib2_iface;
4551 else
4553 *ppv = NULL;
4554 TRACE("-- Interface: E_NOINTERFACE\n");
4555 return E_NOINTERFACE;
4558 IUnknown_AddRef((IUnknown*)*ppv);
4559 return S_OK;
4562 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4564 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4565 ULONG ref = InterlockedIncrement(&This->ref);
4567 TRACE("(%p) ref=%u\n", This, ref);
4569 return ref;
4572 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4574 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4575 ULONG ref = InterlockedDecrement(&This->ref);
4577 TRACE("(%p) ref=%u\n",This, ref);
4579 if (!ref)
4581 TLBImpLib *pImpLib, *pImpLibNext;
4582 TLBRefType *ref_type;
4583 TLBString *tlbstr, *tlbstr_next;
4584 TLBGuid *tlbguid, *tlbguid_next;
4585 void *cursor2;
4586 int i;
4588 /* remove cache entry */
4589 if(This->path)
4591 TRACE("removing from cache list\n");
4592 EnterCriticalSection(&cache_section);
4593 if(This->entry.next)
4594 list_remove(&This->entry);
4595 LeaveCriticalSection(&cache_section);
4596 heap_free(This->path);
4598 TRACE(" destroying ITypeLib(%p)\n",This);
4600 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->string_list, TLBString, entry) {
4601 list_remove(&tlbstr->entry);
4602 SysFreeString(tlbstr->str);
4603 heap_free(tlbstr);
4606 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->name_list, TLBString, entry) {
4607 list_remove(&tlbstr->entry);
4608 SysFreeString(tlbstr->str);
4609 heap_free(tlbstr);
4612 LIST_FOR_EACH_ENTRY_SAFE(tlbguid, tlbguid_next, &This->guid_list, TLBGuid, entry) {
4613 list_remove(&tlbguid->entry);
4614 heap_free(tlbguid);
4617 TLB_FreeCustData(&This->custdata_list);
4619 for (i = 0; i < This->ctTypeDesc; i++)
4620 if (This->pTypeDesc[i].vt == VT_CARRAY)
4621 heap_free(This->pTypeDesc[i].u.lpadesc);
4623 heap_free(This->pTypeDesc);
4625 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4627 if (pImpLib->pImpTypeLib)
4628 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4629 SysFreeString(pImpLib->name);
4631 list_remove(&pImpLib->entry);
4632 heap_free(pImpLib);
4635 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4637 list_remove(&ref_type->entry);
4638 heap_free(ref_type);
4641 for (i = 0; i < This->TypeInfoCount; ++i)
4642 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4643 heap_free(This->typeinfos);
4644 heap_free(This);
4645 return 0;
4648 return ref;
4651 /* ITypeLib::GetTypeInfoCount
4653 * Returns the number of type descriptions in the type library
4655 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4657 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4658 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4659 return This->TypeInfoCount;
4662 /* ITypeLib::GetTypeInfo
4664 * retrieves the specified type description in the library.
4666 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4667 ITypeLib2 *iface,
4668 UINT index,
4669 ITypeInfo **ppTInfo)
4671 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4673 TRACE("%p %u %p\n", This, index, ppTInfo);
4675 if(!ppTInfo)
4676 return E_INVALIDARG;
4678 if(index >= This->TypeInfoCount)
4679 return TYPE_E_ELEMENTNOTFOUND;
4681 *ppTInfo = (ITypeInfo *)&This->typeinfos[index]->ITypeInfo2_iface;
4682 ITypeInfo_AddRef(*ppTInfo);
4684 return S_OK;
4688 /* ITypeLibs::GetTypeInfoType
4690 * Retrieves the type of a type description.
4692 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4693 ITypeLib2 *iface,
4694 UINT index,
4695 TYPEKIND *pTKind)
4697 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4699 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4701 if(!pTKind)
4702 return E_INVALIDARG;
4704 if(index >= This->TypeInfoCount)
4705 return TYPE_E_ELEMENTNOTFOUND;
4707 *pTKind = This->typeinfos[index]->typekind;
4709 return S_OK;
4712 /* ITypeLib::GetTypeInfoOfGuid
4714 * Retrieves the type description that corresponds to the specified GUID.
4717 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4718 ITypeLib2 *iface,
4719 REFGUID guid,
4720 ITypeInfo **ppTInfo)
4722 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4723 int i;
4725 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4727 for(i = 0; i < This->TypeInfoCount; ++i){
4728 if(IsEqualIID(TLB_get_guid_null(This->typeinfos[i]->guid), guid)){
4729 *ppTInfo = (ITypeInfo *)&This->typeinfos[i]->ITypeInfo2_iface;
4730 ITypeInfo_AddRef(*ppTInfo);
4731 return S_OK;
4735 return TYPE_E_ELEMENTNOTFOUND;
4738 /* ITypeLib::GetLibAttr
4740 * Retrieves the structure that contains the library's attributes.
4743 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4744 ITypeLib2 *iface,
4745 LPTLIBATTR *attr)
4747 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4749 TRACE("(%p, %p)\n", This, attr);
4751 if (!attr) return E_INVALIDARG;
4753 *attr = heap_alloc(sizeof(**attr));
4754 if (!*attr) return E_OUTOFMEMORY;
4756 (*attr)->guid = *TLB_get_guid_null(This->guid);
4757 (*attr)->lcid = This->set_lcid;
4758 (*attr)->syskind = This->syskind;
4759 (*attr)->wMajorVerNum = This->ver_major;
4760 (*attr)->wMinorVerNum = This->ver_minor;
4761 (*attr)->wLibFlags = This->libflags;
4763 return S_OK;
4766 /* ITypeLib::GetTypeComp
4768 * Enables a client compiler to bind to a library's types, variables,
4769 * constants, and global functions.
4772 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4773 ITypeLib2 *iface,
4774 ITypeComp **ppTComp)
4776 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4778 TRACE("(%p)->(%p)\n",This,ppTComp);
4779 *ppTComp = &This->ITypeComp_iface;
4780 ITypeComp_AddRef(*ppTComp);
4782 return S_OK;
4785 /* ITypeLib::GetDocumentation
4787 * Retrieves the library's documentation string, the complete Help file name
4788 * and path, and the context identifier for the library Help topic in the Help
4789 * file.
4791 * On a successful return all non-null BSTR pointers will have been set,
4792 * possibly to NULL.
4794 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4795 ITypeLib2 *iface,
4796 INT index,
4797 BSTR *pBstrName,
4798 BSTR *pBstrDocString,
4799 DWORD *pdwHelpContext,
4800 BSTR *pBstrHelpFile)
4802 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4803 HRESULT result = E_INVALIDARG;
4804 ITypeInfo *pTInfo;
4806 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4807 This, index,
4808 pBstrName, pBstrDocString,
4809 pdwHelpContext, pBstrHelpFile);
4811 if(index<0)
4813 /* documentation for the typelib */
4814 if(pBstrName)
4816 if (This->Name)
4818 if(!(*pBstrName = SysAllocString(TLB_get_bstr(This->Name))))
4819 goto memerr1;
4821 else
4822 *pBstrName = NULL;
4824 if(pBstrDocString)
4826 if (This->DocString)
4828 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->DocString))))
4829 goto memerr2;
4831 else
4832 *pBstrDocString = NULL;
4834 if(pdwHelpContext)
4836 *pdwHelpContext = This->dwHelpContext;
4838 if(pBstrHelpFile)
4840 if (This->HelpFile)
4842 if(!(*pBstrHelpFile = SysAllocString(TLB_get_bstr(This->HelpFile))))
4843 goto memerr3;
4845 else
4846 *pBstrHelpFile = NULL;
4849 result = S_OK;
4851 else
4853 /* for a typeinfo */
4854 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4856 if(SUCCEEDED(result))
4858 result = ITypeInfo_GetDocumentation(pTInfo,
4859 MEMBERID_NIL,
4860 pBstrName,
4861 pBstrDocString,
4862 pdwHelpContext, pBstrHelpFile);
4864 ITypeInfo_Release(pTInfo);
4867 return result;
4868 memerr3:
4869 if (pBstrDocString) SysFreeString (*pBstrDocString);
4870 memerr2:
4871 if (pBstrName) SysFreeString (*pBstrName);
4872 memerr1:
4873 return STG_E_INSUFFICIENTMEMORY;
4876 /* ITypeLib::IsName
4878 * Indicates whether a passed-in string contains the name of a type or member
4879 * described in the library.
4882 static HRESULT WINAPI ITypeLib2_fnIsName(
4883 ITypeLib2 *iface,
4884 LPOLESTR szNameBuf,
4885 ULONG lHashVal,
4886 BOOL *pfName)
4888 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4889 int tic;
4890 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
4892 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4893 pfName);
4895 *pfName=TRUE;
4896 for(tic = 0; tic < This->TypeInfoCount; ++tic){
4897 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
4898 if(!TLB_str_memcmp(szNameBuf, pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4899 for(fdc = 0; fdc < pTInfo->cFuncs; ++fdc) {
4900 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
4901 int pc;
4902 if(!TLB_str_memcmp(szNameBuf, pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4903 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++){
4904 if(!TLB_str_memcmp(szNameBuf, pFInfo->pParamDesc[pc].Name, nNameBufLen))
4905 goto ITypeLib2_fnIsName_exit;
4908 for(vrc = 0; vrc < pTInfo->cVars; ++vrc){
4909 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
4910 if(!TLB_str_memcmp(szNameBuf, pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4914 *pfName=FALSE;
4916 ITypeLib2_fnIsName_exit:
4917 TRACE("(%p)slow! search for %s: %s found!\n", This,
4918 debugstr_w(szNameBuf), *pfName?"NOT":"");
4920 return S_OK;
4923 /* ITypeLib::FindName
4925 * Finds occurrences of a type description in a type library. This may be used
4926 * to quickly verify that a name exists in a type library.
4929 static HRESULT WINAPI ITypeLib2_fnFindName(
4930 ITypeLib2 *iface,
4931 LPOLESTR name,
4932 ULONG hash,
4933 ITypeInfo **ppTInfo,
4934 MEMBERID *memid,
4935 UINT16 *found)
4937 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4938 int tic;
4939 UINT count = 0;
4940 UINT len;
4942 TRACE("(%p)->(%s %u %p %p %p)\n", This, debugstr_w(name), hash, ppTInfo, memid, found);
4944 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
4945 return E_INVALIDARG;
4947 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
4948 for(tic = 0; tic < This->TypeInfoCount; ++tic) {
4949 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
4950 TLBVarDesc *var;
4951 UINT fdc;
4953 if(!TLB_str_memcmp(name, pTInfo->Name, len)) goto ITypeLib2_fnFindName_exit;
4954 for(fdc = 0; fdc < pTInfo->cFuncs; ++fdc) {
4955 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
4956 int pc;
4958 if(!TLB_str_memcmp(name, func->Name, len)) goto ITypeLib2_fnFindName_exit;
4959 for(pc = 0; pc < func->funcdesc.cParams; pc++) {
4960 if(!TLB_str_memcmp(name, func->pParamDesc[pc].Name, len))
4961 goto ITypeLib2_fnFindName_exit;
4965 var = TLB_get_vardesc_by_name(pTInfo->vardescs, pTInfo->cVars, name);
4966 if (var)
4967 goto ITypeLib2_fnFindName_exit;
4969 continue;
4970 ITypeLib2_fnFindName_exit:
4971 ITypeInfo2_AddRef(&pTInfo->ITypeInfo2_iface);
4972 ppTInfo[count] = (ITypeInfo *)&pTInfo->ITypeInfo2_iface;
4973 count++;
4975 TRACE("found %d typeinfos\n", count);
4977 *found = count;
4979 return S_OK;
4982 /* ITypeLib::ReleaseTLibAttr
4984 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4987 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4988 ITypeLib2 *iface,
4989 TLIBATTR *pTLibAttr)
4991 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4992 TRACE("(%p)->(%p)\n", This, pTLibAttr);
4993 heap_free(pTLibAttr);
4996 /* ITypeLib2::GetCustData
4998 * gets the custom data
5000 static HRESULT WINAPI ITypeLib2_fnGetCustData(
5001 ITypeLib2 * iface,
5002 REFGUID guid,
5003 VARIANT *pVarVal)
5005 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5006 TLBCustData *pCData;
5008 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
5010 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
5011 if(!pCData)
5012 return TYPE_E_ELEMENTNOTFOUND;
5014 VariantInit(pVarVal);
5015 VariantCopy(pVarVal, &pCData->data);
5017 return S_OK;
5020 /* ITypeLib2::GetLibStatistics
5022 * Returns statistics about a type library that are required for efficient
5023 * sizing of hash tables.
5026 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
5027 ITypeLib2 * iface,
5028 ULONG *pcUniqueNames,
5029 ULONG *pcchUniqueNames)
5031 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5033 FIXME("(%p): stub!\n", This);
5035 if(pcUniqueNames) *pcUniqueNames=1;
5036 if(pcchUniqueNames) *pcchUniqueNames=1;
5037 return S_OK;
5040 /* ITypeLib2::GetDocumentation2
5042 * Retrieves the library's documentation string, the complete Help file name
5043 * and path, the localization context to use, and the context ID for the
5044 * library Help topic in the Help file.
5047 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
5048 ITypeLib2 * iface,
5049 INT index,
5050 LCID lcid,
5051 BSTR *pbstrHelpString,
5052 DWORD *pdwHelpStringContext,
5053 BSTR *pbstrHelpStringDll)
5055 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5056 HRESULT result;
5057 ITypeInfo *pTInfo;
5059 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
5061 /* the help string should be obtained from the helpstringdll,
5062 * using the _DLLGetDocumentation function, based on the supplied
5063 * lcid. Nice to do sometime...
5065 if(index<0)
5067 /* documentation for the typelib */
5068 if(pbstrHelpString)
5069 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->DocString));
5070 if(pdwHelpStringContext)
5071 *pdwHelpStringContext=This->dwHelpContext;
5072 if(pbstrHelpStringDll)
5073 *pbstrHelpStringDll=SysAllocString(TLB_get_bstr(This->HelpStringDll));
5075 result = S_OK;
5077 else
5079 /* for a typeinfo */
5080 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
5082 if(SUCCEEDED(result))
5084 ITypeInfo2 * pTInfo2;
5085 result = ITypeInfo_QueryInterface(pTInfo,
5086 &IID_ITypeInfo2,
5087 (LPVOID*) &pTInfo2);
5089 if(SUCCEEDED(result))
5091 result = ITypeInfo2_GetDocumentation2(pTInfo2,
5092 MEMBERID_NIL,
5093 lcid,
5094 pbstrHelpString,
5095 pdwHelpStringContext,
5096 pbstrHelpStringDll);
5098 ITypeInfo2_Release(pTInfo2);
5101 ITypeInfo_Release(pTInfo);
5104 return result;
5107 static HRESULT TLB_copy_all_custdata(struct list *custdata_list, CUSTDATA *pCustData)
5109 TLBCustData *pCData;
5110 unsigned int ct;
5111 CUSTDATAITEM *cdi;
5113 ct = list_count(custdata_list);
5115 pCustData->prgCustData = heap_alloc_zero(ct * sizeof(CUSTDATAITEM));
5116 if(!pCustData->prgCustData)
5117 return E_OUTOFMEMORY;
5119 pCustData->cCustData = ct;
5121 cdi = pCustData->prgCustData;
5122 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
5123 cdi->guid = *TLB_get_guid_null(pCData->guid);
5124 VariantCopy(&cdi->varValue, &pCData->data);
5125 ++cdi;
5128 return S_OK;
5132 /* ITypeLib2::GetAllCustData
5134 * Gets all custom data items for the library.
5137 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
5138 ITypeLib2 * iface,
5139 CUSTDATA *pCustData)
5141 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5142 TRACE("(%p)->(%p)\n", This, pCustData);
5143 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
5146 static const ITypeLib2Vtbl tlbvt = {
5147 ITypeLib2_fnQueryInterface,
5148 ITypeLib2_fnAddRef,
5149 ITypeLib2_fnRelease,
5150 ITypeLib2_fnGetTypeInfoCount,
5151 ITypeLib2_fnGetTypeInfo,
5152 ITypeLib2_fnGetTypeInfoType,
5153 ITypeLib2_fnGetTypeInfoOfGuid,
5154 ITypeLib2_fnGetLibAttr,
5155 ITypeLib2_fnGetTypeComp,
5156 ITypeLib2_fnGetDocumentation,
5157 ITypeLib2_fnIsName,
5158 ITypeLib2_fnFindName,
5159 ITypeLib2_fnReleaseTLibAttr,
5161 ITypeLib2_fnGetCustData,
5162 ITypeLib2_fnGetLibStatistics,
5163 ITypeLib2_fnGetDocumentation2,
5164 ITypeLib2_fnGetAllCustData
5168 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5170 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5172 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
5175 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
5177 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5179 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
5182 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
5184 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5186 return ITypeLib2_Release(&This->ITypeLib2_iface);
5189 static HRESULT WINAPI ITypeLibComp_fnBind(
5190 ITypeComp * iface,
5191 OLECHAR * szName,
5192 ULONG lHash,
5193 WORD wFlags,
5194 ITypeInfo ** ppTInfo,
5195 DESCKIND * pDescKind,
5196 BINDPTR * pBindPtr)
5198 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5199 int typemismatch=0, i;
5201 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5203 *pDescKind = DESCKIND_NONE;
5204 pBindPtr->lptcomp = NULL;
5205 *ppTInfo = NULL;
5207 for(i = 0; i < This->TypeInfoCount; ++i){
5208 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5209 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo->Name)));
5211 /* FIXME: check wFlags here? */
5212 /* FIXME: we should use a hash table to look this info up using lHash
5213 * instead of an O(n) search */
5214 if ((pTypeInfo->typekind == TKIND_ENUM) ||
5215 (pTypeInfo->typekind == TKIND_MODULE))
5217 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name->str, szName))
5219 *pDescKind = DESCKIND_TYPECOMP;
5220 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
5221 ITypeComp_AddRef(pBindPtr->lptcomp);
5222 TRACE("module or enum: %s\n", debugstr_w(szName));
5223 return S_OK;
5227 if ((pTypeInfo->typekind == TKIND_MODULE) ||
5228 (pTypeInfo->typekind == TKIND_ENUM))
5230 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5231 HRESULT hr;
5233 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5234 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
5236 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
5237 return S_OK;
5239 else if (hr == TYPE_E_TYPEMISMATCH)
5240 typemismatch = 1;
5243 if ((pTypeInfo->typekind == TKIND_COCLASS) &&
5244 (pTypeInfo->wTypeFlags & TYPEFLAG_FAPPOBJECT))
5246 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5247 HRESULT hr;
5248 ITypeInfo *subtypeinfo;
5249 BINDPTR subbindptr;
5250 DESCKIND subdesckind;
5252 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
5253 &subtypeinfo, &subdesckind, &subbindptr);
5254 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
5256 TYPEDESC tdesc_appobject;
5257 const VARDESC vardesc_appobject =
5259 -2, /* memid */
5260 NULL, /* lpstrSchema */
5262 0 /* oInst */
5265 /* ELEMDESC */
5267 /* TYPEDESC */
5269 &tdesc_appobject
5271 VT_PTR
5274 0, /* wVarFlags */
5275 VAR_STATIC /* varkind */
5278 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
5279 tdesc_appobject.vt = VT_USERDEFINED;
5281 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
5283 /* cleanup things filled in by Bind call so we can put our
5284 * application object data in there instead */
5285 switch (subdesckind)
5287 case DESCKIND_FUNCDESC:
5288 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
5289 break;
5290 case DESCKIND_VARDESC:
5291 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
5292 break;
5293 default:
5294 break;
5296 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
5298 if (pTypeInfo->hreftype == -1)
5299 FIXME("no hreftype for interface %p\n", pTypeInfo);
5301 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
5302 if (FAILED(hr))
5303 return hr;
5305 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5306 *ppTInfo = (ITypeInfo *)&pTypeInfo->ITypeInfo2_iface;
5307 ITypeInfo_AddRef(*ppTInfo);
5308 return S_OK;
5310 else if (hr == TYPE_E_TYPEMISMATCH)
5311 typemismatch = 1;
5315 if (typemismatch)
5317 TRACE("type mismatch %s\n", debugstr_w(szName));
5318 return TYPE_E_TYPEMISMATCH;
5320 else
5322 TRACE("name not found %s\n", debugstr_w(szName));
5323 return S_OK;
5327 static HRESULT WINAPI ITypeLibComp_fnBindType(
5328 ITypeComp * iface,
5329 OLECHAR * szName,
5330 ULONG lHash,
5331 ITypeInfo ** ppTInfo,
5332 ITypeComp ** ppTComp)
5334 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5335 ITypeInfoImpl *info;
5337 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5339 if(!szName || !ppTInfo || !ppTComp)
5340 return E_INVALIDARG;
5342 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, szName);
5343 if(!info){
5344 *ppTInfo = NULL;
5345 *ppTComp = NULL;
5346 return S_OK;
5349 *ppTInfo = (ITypeInfo *)&info->ITypeInfo2_iface;
5350 ITypeInfo_AddRef(*ppTInfo);
5351 *ppTComp = &info->ITypeComp_iface;
5352 ITypeComp_AddRef(*ppTComp);
5354 return S_OK;
5357 static const ITypeCompVtbl tlbtcvt =
5360 ITypeLibComp_fnQueryInterface,
5361 ITypeLibComp_fnAddRef,
5362 ITypeLibComp_fnRelease,
5364 ITypeLibComp_fnBind,
5365 ITypeLibComp_fnBindType
5368 /*================== ITypeInfo(2) Methods ===================================*/
5369 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5371 ITypeInfoImpl *pTypeInfoImpl;
5373 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5374 if (pTypeInfoImpl)
5376 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5377 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5378 pTypeInfoImpl->ICreateTypeInfo2_iface.lpVtbl = &CreateTypeInfo2Vtbl;
5379 pTypeInfoImpl->ref = 0;
5380 pTypeInfoImpl->hreftype = -1;
5381 pTypeInfoImpl->memidConstructor = MEMBERID_NIL;
5382 pTypeInfoImpl->memidDestructor = MEMBERID_NIL;
5383 pTypeInfoImpl->pcustdata_list = &pTypeInfoImpl->custdata_list;
5384 list_init(pTypeInfoImpl->pcustdata_list);
5386 TRACE("(%p)\n", pTypeInfoImpl);
5387 return pTypeInfoImpl;
5390 /* ITypeInfo::QueryInterface
5392 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5393 ITypeInfo2 *iface,
5394 REFIID riid,
5395 VOID **ppvObject)
5397 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5399 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5401 *ppvObject=NULL;
5402 if(IsEqualIID(riid, &IID_IUnknown) ||
5403 IsEqualIID(riid,&IID_ITypeInfo)||
5404 IsEqualIID(riid,&IID_ITypeInfo2))
5405 *ppvObject = This;
5406 else if(IsEqualIID(riid, &IID_ICreateTypeInfo) ||
5407 IsEqualIID(riid, &IID_ICreateTypeInfo2))
5408 *ppvObject = &This->ICreateTypeInfo2_iface;
5410 if(*ppvObject){
5411 ITypeInfo2_AddRef(iface);
5412 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5413 return S_OK;
5415 TRACE("-- Interface: E_NOINTERFACE\n");
5416 return E_NOINTERFACE;
5419 /* ITypeInfo::AddRef
5421 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5423 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5424 ULONG ref = InterlockedIncrement(&This->ref);
5426 TRACE("(%p)->ref is %u\n",This, ref);
5428 if (ref == 1 /* incremented from 0 */)
5429 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5431 return ref;
5434 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5436 UINT i;
5438 TRACE("destroying ITypeInfo(%p)\n",This);
5440 for (i = 0; i < This->cFuncs; ++i)
5442 int j;
5443 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5444 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5446 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5447 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5448 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5449 TLB_FreeCustData(&pFInfo->pParamDesc[j].custdata_list);
5451 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5452 heap_free(pFInfo->pParamDesc);
5453 TLB_FreeCustData(&pFInfo->custdata_list);
5455 heap_free(This->funcdescs);
5457 for(i = 0; i < This->cVars; ++i)
5459 TLBVarDesc *pVInfo = &This->vardescs[i];
5460 if (pVInfo->vardesc_create) {
5461 TLB_FreeVarDesc(pVInfo->vardesc_create);
5462 } else if (pVInfo->vardesc.varkind == VAR_CONST) {
5463 VariantClear(pVInfo->vardesc.u.lpvarValue);
5464 heap_free(pVInfo->vardesc.u.lpvarValue);
5466 TLB_FreeCustData(&pVInfo->custdata_list);
5468 heap_free(This->vardescs);
5470 if(This->impltypes){
5471 for (i = 0; i < This->cImplTypes; ++i){
5472 TLBImplType *pImpl = &This->impltypes[i];
5473 TLB_FreeCustData(&pImpl->custdata_list);
5475 heap_free(This->impltypes);
5478 TLB_FreeCustData(&This->custdata_list);
5480 heap_free(This);
5483 /* ITypeInfo::Release
5485 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5487 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5488 ULONG ref = InterlockedDecrement(&This->ref);
5490 TRACE("(%p)->(%u)\n",This, ref);
5492 if (!ref)
5494 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5495 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5496 if (not_attached_to_typelib)
5497 heap_free(This);
5498 /* otherwise This will be freed when typelib is freed */
5501 return ref;
5504 /* ITypeInfo::GetTypeAttr
5506 * Retrieves a TYPEATTR structure that contains the attributes of the type
5507 * description.
5510 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5511 LPTYPEATTR *ppTypeAttr)
5513 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5514 SIZE_T size;
5516 TRACE("(%p)\n",This);
5518 size = sizeof(**ppTypeAttr);
5519 if (This->typekind == TKIND_ALIAS)
5520 size += TLB_SizeTypeDesc(&This->tdescAlias, FALSE);
5522 *ppTypeAttr = heap_alloc(size);
5523 if (!*ppTypeAttr)
5524 return E_OUTOFMEMORY;
5526 (*ppTypeAttr)->guid = *TLB_get_guid_null(This->guid);
5527 (*ppTypeAttr)->lcid = This->lcid;
5528 (*ppTypeAttr)->memidConstructor = This->memidConstructor;
5529 (*ppTypeAttr)->memidDestructor = This->memidDestructor;
5530 (*ppTypeAttr)->lpstrSchema = This->lpstrSchema;
5531 (*ppTypeAttr)->cbSizeInstance = This->cbSizeInstance;
5532 (*ppTypeAttr)->typekind = This->typekind;
5533 (*ppTypeAttr)->cFuncs = This->cFuncs;
5534 (*ppTypeAttr)->cVars = This->cVars;
5535 (*ppTypeAttr)->cImplTypes = This->cImplTypes;
5536 (*ppTypeAttr)->cbSizeVft = This->cbSizeVft;
5537 (*ppTypeAttr)->cbAlignment = This->cbAlignment;
5538 (*ppTypeAttr)->wTypeFlags = This->wTypeFlags;
5539 (*ppTypeAttr)->wMajorVerNum = This->wMajorVerNum;
5540 (*ppTypeAttr)->wMinorVerNum = This->wMinorVerNum;
5541 (*ppTypeAttr)->tdescAlias = This->tdescAlias;
5542 (*ppTypeAttr)->idldescType = This->idldescType;
5544 if (This->typekind == TKIND_ALIAS)
5545 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5546 &This->tdescAlias, *ppTypeAttr + 1);
5548 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5549 /* This should include all the inherited funcs */
5550 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / This->pTypeLib->ptr_size;
5551 /* This is always the size of IDispatch's vtbl */
5552 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5553 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5555 return S_OK;
5558 /* ITypeInfo::GetTypeComp
5560 * Retrieves the ITypeComp interface for the type description, which enables a
5561 * client compiler to bind to the type description's members.
5564 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5565 ITypeComp * *ppTComp)
5567 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5569 TRACE("(%p)->(%p)\n", This, ppTComp);
5571 *ppTComp = &This->ITypeComp_iface;
5572 ITypeComp_AddRef(*ppTComp);
5573 return S_OK;
5576 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5578 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5579 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5580 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5581 return size;
5584 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5586 *dest = *src;
5587 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5588 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5590 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5591 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5592 *buffer += sizeof(PARAMDESCEX);
5593 *pparamdescex_dest = *pparamdescex_src;
5594 pparamdescex_dest->cBytes = sizeof(PARAMDESCEX);
5595 VariantInit(&pparamdescex_dest->varDefaultValue);
5596 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5597 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5599 else
5600 dest->u.paramdesc.pparamdescex = NULL;
5601 return S_OK;
5604 static HRESULT TLB_SanitizeBSTR(BSTR str)
5606 UINT len = SysStringLen(str), i;
5607 for (i = 0; i < len; ++i)
5608 if (str[i] > 0x7f)
5609 str[i] = '?';
5610 return S_OK;
5613 static HRESULT TLB_SanitizeVariant(VARIANT *var)
5615 if (V_VT(var) == VT_INT)
5616 return VariantChangeType(var, var, 0, VT_I4);
5617 else if (V_VT(var) == VT_UINT)
5618 return VariantChangeType(var, var, 0, VT_UI4);
5619 else if (V_VT(var) == VT_BSTR)
5620 return TLB_SanitizeBSTR(V_BSTR(var));
5622 return S_OK;
5625 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5627 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5628 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5631 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5633 FUNCDESC *dest;
5634 char *buffer;
5635 SIZE_T size = sizeof(*src);
5636 SHORT i;
5637 HRESULT hr;
5639 size += sizeof(*src->lprgscode) * src->cScodes;
5640 size += TLB_SizeElemDesc(&src->elemdescFunc);
5641 for (i = 0; i < src->cParams; i++)
5643 size += sizeof(ELEMDESC);
5644 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5647 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5648 if (!dest) return E_OUTOFMEMORY;
5650 *dest = *src;
5651 if (dispinterface) /* overwrite funckind */
5652 dest->funckind = FUNC_DISPATCH;
5653 buffer = (char *)(dest + 1);
5655 dest->oVft = dest->oVft & 0xFFFC;
5657 if (dest->cScodes) {
5658 dest->lprgscode = (SCODE *)buffer;
5659 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5660 buffer += sizeof(*src->lprgscode) * src->cScodes;
5661 } else
5662 dest->lprgscode = NULL;
5664 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5665 if (FAILED(hr))
5667 SysFreeString((BSTR)dest);
5668 return hr;
5671 if (dest->cParams) {
5672 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5673 buffer += sizeof(ELEMDESC) * src->cParams;
5674 for (i = 0; i < src->cParams; i++)
5676 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5677 if (FAILED(hr))
5678 break;
5680 if (FAILED(hr))
5682 /* undo the above actions */
5683 for (i = i - 1; i >= 0; i--)
5684 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5685 TLB_FreeElemDesc(&dest->elemdescFunc);
5686 SysFreeString((BSTR)dest);
5687 return hr;
5689 } else
5690 dest->lprgelemdescParam = NULL;
5692 /* special treatment for dispinterfaces: this makes functions appear
5693 * to return their [retval] value when it is really returning an
5694 * HRESULT */
5695 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5697 if (dest->cParams &&
5698 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5700 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5701 if (elemdesc->tdesc.vt != VT_PTR)
5703 ERR("elemdesc should have started with VT_PTR instead of:\n");
5704 if (ERR_ON(ole))
5705 dump_ELEMDESC(elemdesc);
5706 return E_UNEXPECTED;
5709 /* copy last parameter to the return value. we are using a flat
5710 * buffer so there is no danger of leaking memory in
5711 * elemdescFunc */
5712 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5714 /* remove the last parameter */
5715 dest->cParams--;
5717 else
5718 /* otherwise this function is made to appear to have no return
5719 * value */
5720 dest->elemdescFunc.tdesc.vt = VT_VOID;
5724 *dest_ptr = dest;
5725 return S_OK;
5728 static void TLB_FreeVarDesc(VARDESC *var_desc)
5730 TLB_FreeElemDesc(&var_desc->elemdescVar);
5731 if (var_desc->varkind == VAR_CONST)
5732 VariantClear(var_desc->u.lpvarValue);
5733 SysFreeString((BSTR)var_desc);
5736 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5738 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5740 if (index >= This->cFuncs)
5741 return TYPE_E_ELEMENTNOTFOUND;
5743 *ppFuncDesc = &This->funcdescs[index].funcdesc;
5744 return S_OK;
5747 /* internal function to make the inherited interfaces' methods appear
5748 * part of the interface */
5749 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5750 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5752 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5753 HRESULT hr;
5754 UINT implemented_funcs = 0;
5756 if (funcs)
5757 *funcs = 0;
5758 else
5759 *hrefoffset = DISPATCH_HREF_OFFSET;
5761 if(This->impltypes)
5763 ITypeInfo *pSubTypeInfo;
5764 UINT sub_funcs;
5766 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5767 if (FAILED(hr))
5768 return hr;
5770 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5771 index,
5772 ppFuncDesc,
5773 &sub_funcs, hrefoffset);
5774 implemented_funcs += sub_funcs;
5775 ITypeInfo_Release(pSubTypeInfo);
5776 if (SUCCEEDED(hr))
5777 return hr;
5778 *hrefoffset += DISPATCH_HREF_OFFSET;
5781 if (funcs)
5782 *funcs = implemented_funcs + This->cFuncs;
5783 else
5784 *hrefoffset = 0;
5786 if (index < implemented_funcs)
5787 return E_INVALIDARG;
5788 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5789 ppFuncDesc);
5792 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5794 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5795 while (TRUE)
5797 switch (pTypeDesc->vt)
5799 case VT_USERDEFINED:
5800 pTypeDesc->u.hreftype += hrefoffset;
5801 return;
5802 case VT_PTR:
5803 case VT_SAFEARRAY:
5804 pTypeDesc = pTypeDesc->u.lptdesc;
5805 break;
5806 case VT_CARRAY:
5807 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5808 break;
5809 default:
5810 return;
5815 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5817 SHORT i;
5818 for (i = 0; i < pFuncDesc->cParams; i++)
5819 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5820 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5823 /* ITypeInfo::GetFuncDesc
5825 * Retrieves the FUNCDESC structure that contains information about a
5826 * specified function.
5829 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5830 LPFUNCDESC *ppFuncDesc)
5832 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5833 const FUNCDESC *internal_funcdesc;
5834 HRESULT hr;
5835 UINT hrefoffset = 0;
5837 TRACE("(%p) index %d\n", This, index);
5839 if (!ppFuncDesc)
5840 return E_INVALIDARG;
5842 if (This->needs_layout)
5843 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
5845 if (This->typekind == TKIND_DISPATCH)
5846 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5847 &internal_funcdesc, NULL,
5848 &hrefoffset);
5849 else
5850 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5851 &internal_funcdesc);
5852 if (FAILED(hr))
5854 WARN("description for function %d not found\n", index);
5855 return hr;
5858 hr = TLB_AllocAndInitFuncDesc(
5859 internal_funcdesc,
5860 ppFuncDesc,
5861 This->typekind == TKIND_DISPATCH);
5863 if ((This->typekind == TKIND_DISPATCH) && hrefoffset)
5864 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5866 TRACE("-- 0x%08x\n", hr);
5867 return hr;
5870 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5872 VARDESC *dest;
5873 char *buffer;
5874 SIZE_T size = sizeof(*src);
5875 HRESULT hr;
5877 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5878 if (src->varkind == VAR_CONST)
5879 size += sizeof(VARIANT);
5880 size += TLB_SizeElemDesc(&src->elemdescVar);
5882 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5883 if (!dest) return E_OUTOFMEMORY;
5885 *dest = *src;
5886 buffer = (char *)(dest + 1);
5887 if (src->lpstrSchema)
5889 int len;
5890 dest->lpstrSchema = (LPOLESTR)buffer;
5891 len = strlenW(src->lpstrSchema);
5892 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5893 buffer += (len + 1) * sizeof(WCHAR);
5896 if (src->varkind == VAR_CONST)
5898 HRESULT hr;
5900 dest->u.lpvarValue = (VARIANT *)buffer;
5901 *dest->u.lpvarValue = *src->u.lpvarValue;
5902 buffer += sizeof(VARIANT);
5903 VariantInit(dest->u.lpvarValue);
5904 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5905 if (FAILED(hr))
5907 SysFreeString((BSTR)dest);
5908 return hr;
5911 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5912 if (FAILED(hr))
5914 if (src->varkind == VAR_CONST)
5915 VariantClear(dest->u.lpvarValue);
5916 SysFreeString((BSTR)dest);
5917 return hr;
5919 *dest_ptr = dest;
5920 return S_OK;
5923 /* ITypeInfo::GetVarDesc
5925 * Retrieves a VARDESC structure that describes the specified variable.
5928 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5929 LPVARDESC *ppVarDesc)
5931 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5932 const TLBVarDesc *pVDesc = &This->vardescs[index];
5934 TRACE("(%p) index %d\n", This, index);
5936 if(index >= This->cVars)
5937 return TYPE_E_ELEMENTNOTFOUND;
5939 if (This->needs_layout)
5940 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
5942 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5945 /* ITypeInfo_GetNames
5947 * Retrieves the variable with the specified member ID (or the name of the
5948 * property or method and its parameters) that correspond to the specified
5949 * function ID.
5951 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5952 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5954 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5955 const TLBFuncDesc *pFDesc;
5956 const TLBVarDesc *pVDesc;
5957 int i;
5958 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5960 if(!rgBstrNames)
5961 return E_INVALIDARG;
5963 *pcNames = 0;
5965 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
5966 if(pFDesc)
5968 if(!cMaxNames || !pFDesc->Name)
5969 return S_OK;
5971 *rgBstrNames = SysAllocString(TLB_get_bstr(pFDesc->Name));
5972 ++(*pcNames);
5974 for(i = 0; i < pFDesc->funcdesc.cParams; ++i){
5975 if(*pcNames >= cMaxNames || !pFDesc->pParamDesc[i].Name)
5976 return S_OK;
5977 rgBstrNames[*pcNames] = SysAllocString(TLB_get_bstr(pFDesc->pParamDesc[i].Name));
5978 ++(*pcNames);
5980 return S_OK;
5983 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
5984 if(pVDesc)
5986 *rgBstrNames=SysAllocString(TLB_get_bstr(pVDesc->Name));
5987 *pcNames=1;
5989 else
5991 if(This->impltypes &&
5992 (This->typekind==TKIND_INTERFACE || This->typekind==TKIND_DISPATCH)) {
5993 /* recursive search */
5994 ITypeInfo *pTInfo;
5995 HRESULT result;
5996 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
5997 if(SUCCEEDED(result))
5999 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
6000 ITypeInfo_Release(pTInfo);
6001 return result;
6003 WARN("Could not search inherited interface!\n");
6005 else
6007 WARN("no names found\n");
6009 *pcNames=0;
6010 return TYPE_E_ELEMENTNOTFOUND;
6012 return S_OK;
6016 /* ITypeInfo::GetRefTypeOfImplType
6018 * If a type description describes a COM class, it retrieves the type
6019 * description of the implemented interface types. For an interface,
6020 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6021 * if any exist.
6024 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
6025 ITypeInfo2 *iface,
6026 UINT index,
6027 HREFTYPE *pRefType)
6029 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6030 HRESULT hr = S_OK;
6032 TRACE("(%p) index %d\n", This, index);
6033 if (TRACE_ON(ole)) dump_TypeInfo(This);
6035 if(index==(UINT)-1)
6037 /* only valid on dual interfaces;
6038 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6041 if (This->wTypeFlags & TYPEFLAG_FDUAL)
6043 *pRefType = -2;
6045 else
6047 hr = TYPE_E_ELEMENTNOTFOUND;
6050 else if(index == 0 && This->typekind == TKIND_DISPATCH)
6052 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6053 *pRefType = This->pTypeLib->dispatch_href;
6055 else
6057 if(index >= This->cImplTypes)
6058 hr = TYPE_E_ELEMENTNOTFOUND;
6059 else{
6060 *pRefType = This->impltypes[index].hRef;
6061 if(This->typekind == TKIND_INTERFACE)
6062 *pRefType |= 0x2;
6066 if(TRACE_ON(ole))
6068 if(SUCCEEDED(hr))
6069 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
6070 else
6071 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
6074 return hr;
6077 /* ITypeInfo::GetImplTypeFlags
6079 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6080 * or base interface in a type description.
6082 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
6083 UINT index, INT *pImplTypeFlags)
6085 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6087 TRACE("(%p) index %d\n", This, index);
6089 if(!pImplTypeFlags)
6090 return E_INVALIDARG;
6092 if(This->typekind == TKIND_DISPATCH && index == 0){
6093 *pImplTypeFlags = 0;
6094 return S_OK;
6097 if(index >= This->cImplTypes)
6098 return TYPE_E_ELEMENTNOTFOUND;
6100 *pImplTypeFlags = This->impltypes[index].implflags;
6102 return S_OK;
6105 /* GetIDsOfNames
6106 * Maps between member names and member IDs, and parameter names and
6107 * parameter IDs.
6109 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
6110 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
6112 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6113 const TLBVarDesc *pVDesc;
6114 HRESULT ret=S_OK;
6115 UINT i, fdc;
6117 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
6118 cNames);
6120 /* init out parameters in case of failure */
6121 for (i = 0; i < cNames; i++)
6122 pMemId[i] = MEMBERID_NIL;
6124 for (fdc = 0; fdc < This->cFuncs; ++fdc) {
6125 int j;
6126 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
6127 if(!lstrcmpiW(*rgszNames, TLB_get_bstr(pFDesc->Name))) {
6128 if(cNames) *pMemId=pFDesc->funcdesc.memid;
6129 for(i=1; i < cNames; i++){
6130 for(j=0; j<pFDesc->funcdesc.cParams; j++)
6131 if(!lstrcmpiW(rgszNames[i],TLB_get_bstr(pFDesc->pParamDesc[j].Name)))
6132 break;
6133 if( j<pFDesc->funcdesc.cParams)
6134 pMemId[i]=j;
6135 else
6136 ret=DISP_E_UNKNOWNNAME;
6138 TRACE("-- 0x%08x\n", ret);
6139 return ret;
6142 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->cVars, *rgszNames);
6143 if(pVDesc){
6144 if(cNames)
6145 *pMemId = pVDesc->vardesc.memid;
6146 return ret;
6148 /* not found, see if it can be found in an inherited interface */
6149 if(This->impltypes) {
6150 /* recursive search */
6151 ITypeInfo *pTInfo;
6152 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6153 if(SUCCEEDED(ret)){
6154 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
6155 ITypeInfo_Release(pTInfo);
6156 return ret;
6158 WARN("Could not search inherited interface!\n");
6159 } else
6160 WARN("no names found\n");
6161 return DISP_E_UNKNOWNNAME;
6165 #ifdef __i386__
6167 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6168 __ASM_GLOBAL_FUNC( call_method,
6169 "pushl %ebp\n\t"
6170 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6171 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6172 "movl %esp,%ebp\n\t"
6173 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6174 "pushl %esi\n\t"
6175 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6176 "pushl %edi\n\t"
6177 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6178 "movl 12(%ebp),%edx\n\t"
6179 "movl %esp,%edi\n\t"
6180 "shll $2,%edx\n\t"
6181 "jz 1f\n\t"
6182 "subl %edx,%edi\n\t"
6183 "andl $~15,%edi\n\t"
6184 "movl %edi,%esp\n\t"
6185 "movl 12(%ebp),%ecx\n\t"
6186 "movl 16(%ebp),%esi\n\t"
6187 "cld\n\t"
6188 "rep; movsl\n"
6189 "1:\tcall *8(%ebp)\n\t"
6190 "subl %esp,%edi\n\t"
6191 "movl 20(%ebp),%ecx\n\t"
6192 "movl %edi,(%ecx)\n\t"
6193 "leal -8(%ebp),%esp\n\t"
6194 "popl %edi\n\t"
6195 __ASM_CFI(".cfi_same_value %edi\n\t")
6196 "popl %esi\n\t"
6197 __ASM_CFI(".cfi_same_value %esi\n\t")
6198 "popl %ebp\n\t"
6199 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6200 __ASM_CFI(".cfi_same_value %ebp\n\t")
6201 "ret" )
6203 /* same function but returning floating point */
6204 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
6206 /* ITypeInfo::Invoke
6208 * Invokes a method, or accesses a property of an object, that implements the
6209 * interface described by the type description.
6211 DWORD
6212 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
6213 DWORD res;
6214 int stack_offset;
6216 if (TRACE_ON(ole)) {
6217 int i;
6218 TRACE("Calling %p(",func);
6219 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
6220 if (nrargs > 30) TRACE("...");
6221 TRACE(")\n");
6224 switch (callconv) {
6225 case CC_STDCALL:
6226 case CC_CDECL:
6227 res = call_method( func, nrargs, args, &stack_offset );
6228 break;
6229 default:
6230 FIXME("unsupported calling convention %d\n",callconv);
6231 res = -1;
6232 break;
6234 TRACE("returns %08x\n",res);
6235 return res;
6238 #elif defined(__x86_64__)
6240 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
6241 __ASM_GLOBAL_FUNC( call_method,
6242 "pushq %rbp\n\t"
6243 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6244 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6245 "movq %rsp,%rbp\n\t"
6246 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6247 "pushq %rsi\n\t"
6248 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6249 "pushq %rdi\n\t"
6250 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6251 "movq %rcx,%rax\n\t"
6252 "movq $4,%rcx\n\t"
6253 "cmp %rcx,%rdx\n\t"
6254 "cmovgq %rdx,%rcx\n\t"
6255 "leaq 0(,%rcx,8),%rdx\n\t"
6256 "subq %rdx,%rsp\n\t"
6257 "andq $~15,%rsp\n\t"
6258 "movq %rsp,%rdi\n\t"
6259 "movq %r8,%rsi\n\t"
6260 "rep; movsq\n\t"
6261 "movq 0(%rsp),%rcx\n\t"
6262 "movq 8(%rsp),%rdx\n\t"
6263 "movq 16(%rsp),%r8\n\t"
6264 "movq 24(%rsp),%r9\n\t"
6265 "movq %rcx,%xmm0\n\t"
6266 "movq %rdx,%xmm1\n\t"
6267 "movq %r8,%xmm2\n\t"
6268 "movq %r9,%xmm3\n\t"
6269 "callq *%rax\n\t"
6270 "leaq -16(%rbp),%rsp\n\t"
6271 "popq %rdi\n\t"
6272 __ASM_CFI(".cfi_same_value %rdi\n\t")
6273 "popq %rsi\n\t"
6274 __ASM_CFI(".cfi_same_value %rsi\n\t")
6275 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6276 "popq %rbp\n\t"
6277 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6278 __ASM_CFI(".cfi_same_value %rbp\n\t")
6279 "ret")
6281 /* same function but returning floating point */
6282 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
6284 #endif /* __x86_64__ */
6286 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6288 HRESULT hr = S_OK;
6289 ITypeInfo *tinfo2 = NULL;
6290 TYPEATTR *tattr = NULL;
6292 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6293 if (hr)
6295 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6296 "hr = 0x%08x\n",
6297 tdesc->u.hreftype, hr);
6298 return hr;
6300 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6301 if (hr)
6303 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
6304 ITypeInfo_Release(tinfo2);
6305 return hr;
6308 switch (tattr->typekind)
6310 case TKIND_ENUM:
6311 *vt |= VT_I4;
6312 break;
6314 case TKIND_ALIAS:
6315 tdesc = &tattr->tdescAlias;
6316 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
6317 break;
6319 case TKIND_INTERFACE:
6320 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
6321 *vt |= VT_DISPATCH;
6322 else
6323 *vt |= VT_UNKNOWN;
6324 break;
6326 case TKIND_DISPATCH:
6327 *vt |= VT_DISPATCH;
6328 break;
6330 case TKIND_COCLASS:
6331 *vt |= VT_DISPATCH;
6332 break;
6334 case TKIND_RECORD:
6335 FIXME("TKIND_RECORD unhandled.\n");
6336 hr = E_NOTIMPL;
6337 break;
6339 case TKIND_UNION:
6340 FIXME("TKIND_UNION unhandled.\n");
6341 hr = E_NOTIMPL;
6342 break;
6344 default:
6345 FIXME("TKIND %d unhandled.\n",tattr->typekind);
6346 hr = E_NOTIMPL;
6347 break;
6349 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6350 ITypeInfo_Release(tinfo2);
6351 return hr;
6354 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6356 HRESULT hr = S_OK;
6358 /* enforce only one level of pointer indirection */
6359 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
6361 tdesc = tdesc->u.lptdesc;
6363 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6364 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6365 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6366 if ((tdesc->vt == VT_USERDEFINED) ||
6367 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
6369 VARTYPE vt_userdefined = 0;
6370 const TYPEDESC *tdesc_userdefined = tdesc;
6371 if (tdesc->vt == VT_PTR)
6373 vt_userdefined = VT_BYREF;
6374 tdesc_userdefined = tdesc->u.lptdesc;
6376 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
6377 if ((hr == S_OK) &&
6378 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
6379 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
6381 *vt |= vt_userdefined;
6382 return S_OK;
6385 *vt = VT_BYREF;
6388 switch (tdesc->vt)
6390 case VT_HRESULT:
6391 *vt |= VT_ERROR;
6392 break;
6393 case VT_USERDEFINED:
6394 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
6395 break;
6396 case VT_VOID:
6397 case VT_CARRAY:
6398 case VT_PTR:
6399 case VT_LPSTR:
6400 case VT_LPWSTR:
6401 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
6402 hr = DISP_E_BADVARTYPE;
6403 break;
6404 case VT_SAFEARRAY:
6405 *vt |= VT_ARRAY;
6406 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
6407 break;
6408 case VT_INT:
6409 *vt |= VT_I4;
6410 break;
6411 case VT_UINT:
6412 *vt |= VT_UI4;
6413 break;
6414 default:
6415 *vt |= tdesc->vt;
6416 break;
6418 return hr;
6421 static HRESULT get_iface_guid(ITypeInfo *tinfo, const TYPEDESC *tdesc, GUID *guid)
6423 ITypeInfo *tinfo2;
6424 TYPEATTR *tattr;
6425 HRESULT hres;
6427 hres = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6428 if(FAILED(hres))
6429 return hres;
6431 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6432 if(FAILED(hres)) {
6433 ITypeInfo_Release(tinfo2);
6434 return hres;
6437 switch(tattr->typekind) {
6438 case TKIND_ALIAS:
6439 hres = get_iface_guid(tinfo2, &tattr->tdescAlias, guid);
6440 break;
6442 case TKIND_INTERFACE:
6443 case TKIND_DISPATCH:
6444 *guid = tattr->guid;
6445 break;
6447 default:
6448 ERR("Unexpected typekind %d\n", tattr->typekind);
6449 hres = E_UNEXPECTED;
6452 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6453 ITypeInfo_Release(tinfo2);
6454 return hres;
6457 /***********************************************************************
6458 * DispCallFunc (OLEAUT32.@)
6460 * Invokes a function of the specified calling convention, passing the
6461 * specified arguments and returns the result.
6463 * PARAMS
6464 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6465 * oVft [I] The offset in the vtable. See notes.
6466 * cc [I] Calling convention of the function to call.
6467 * vtReturn [I] The return type of the function.
6468 * cActuals [I] Number of parameters.
6469 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6470 * prgpvarg [I] The arguments to pass.
6471 * pvargResult [O] The return value of the function. Can be NULL.
6473 * RETURNS
6474 * Success: S_OK.
6475 * Failure: HRESULT code.
6477 * NOTES
6478 * The HRESULT return value of this function is not affected by the return
6479 * value of the user supplied function, which is returned in pvargResult.
6481 * If pvInstance is NULL then a non-object function is to be called and oVft
6482 * is the address of the function to call.
6484 * The cc parameter can be one of the following values:
6485 *|CC_FASTCALL
6486 *|CC_CDECL
6487 *|CC_PASCAL
6488 *|CC_STDCALL
6489 *|CC_FPFASTCALL
6490 *|CC_SYSCALL
6491 *|CC_MPWCDECL
6492 *|CC_MPWPASCAL
6495 HRESULT WINAPI
6496 DispCallFunc(
6497 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
6498 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
6500 #ifdef __i386__
6501 int argspos, stack_offset;
6502 void *func;
6503 UINT i;
6504 DWORD *args;
6506 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6507 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6508 pvargResult, V_VT(pvargResult));
6510 if (cc != CC_STDCALL && cc != CC_CDECL)
6512 FIXME("unsupported calling convention %d\n",cc);
6513 return E_INVALIDARG;
6516 /* maximum size for an argument is sizeof(VARIANT) */
6517 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6519 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6520 argspos = 1;
6521 if (pvInstance)
6523 const FARPROC *vtable = *(FARPROC **)pvInstance;
6524 func = vtable[oVft/sizeof(void *)];
6525 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6527 else func = (void *)oVft;
6529 for (i = 0; i < cActuals; i++)
6531 VARIANT *arg = prgpvarg[i];
6533 switch (prgvt[i])
6535 case VT_EMPTY:
6536 break;
6537 case VT_I8:
6538 case VT_UI8:
6539 case VT_R8:
6540 case VT_DATE:
6541 case VT_CY:
6542 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6543 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6544 break;
6545 case VT_DECIMAL:
6546 case VT_VARIANT:
6547 memcpy( &args[argspos], arg, sizeof(*arg) );
6548 argspos += sizeof(*arg) / sizeof(DWORD);
6549 break;
6550 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6551 args[argspos++] = V_BOOL(arg);
6552 break;
6553 default:
6554 args[argspos++] = V_UI4(arg);
6555 break;
6557 TRACE("arg %u: type %d\n",i,prgvt[i]);
6558 dump_Variant(arg);
6561 switch (vtReturn)
6563 case VT_EMPTY:
6564 call_method( func, argspos - 1, args + 1, &stack_offset );
6565 break;
6566 case VT_R4:
6567 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6568 break;
6569 case VT_R8:
6570 case VT_DATE:
6571 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6572 break;
6573 case VT_DECIMAL:
6574 case VT_VARIANT:
6575 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6576 call_method( func, argspos, args, &stack_offset );
6577 break;
6578 case VT_I8:
6579 case VT_UI8:
6580 case VT_CY:
6581 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6582 break;
6583 case VT_HRESULT:
6584 WARN("invalid return type %u\n", vtReturn);
6585 heap_free( args );
6586 return E_INVALIDARG;
6587 default:
6588 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6589 break;
6591 heap_free( args );
6592 if (stack_offset && cc == CC_STDCALL)
6594 WARN( "stack pointer off by %d\n", stack_offset );
6595 return DISP_E_BADCALLEE;
6597 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6598 TRACE("retval: "); dump_Variant(pvargResult);
6599 return S_OK;
6601 #elif defined(__x86_64__)
6602 int argspos;
6603 UINT i;
6604 DWORD_PTR *args;
6605 void *func;
6607 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6608 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6609 pvargResult, V_VT(pvargResult));
6611 if (cc != CC_STDCALL && cc != CC_CDECL)
6613 FIXME("unsupported calling convention %d\n",cc);
6614 return E_INVALIDARG;
6617 /* maximum size for an argument is sizeof(DWORD_PTR) */
6618 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6620 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6621 argspos = 1;
6622 if (pvInstance)
6624 const FARPROC *vtable = *(FARPROC **)pvInstance;
6625 func = vtable[oVft/sizeof(void *)];
6626 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6628 else func = (void *)oVft;
6630 for (i = 0; i < cActuals; i++)
6632 VARIANT *arg = prgpvarg[i];
6634 switch (prgvt[i])
6636 case VT_DECIMAL:
6637 case VT_VARIANT:
6638 args[argspos++] = (ULONG_PTR)arg;
6639 break;
6640 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6641 args[argspos++] = V_BOOL(arg);
6642 break;
6643 default:
6644 args[argspos++] = V_UI8(arg);
6645 break;
6647 TRACE("arg %u: type %d\n",i,prgvt[i]);
6648 dump_Variant(arg);
6651 switch (vtReturn)
6653 case VT_R4:
6654 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6655 break;
6656 case VT_R8:
6657 case VT_DATE:
6658 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6659 break;
6660 case VT_DECIMAL:
6661 case VT_VARIANT:
6662 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6663 call_method( func, argspos, args );
6664 break;
6665 case VT_HRESULT:
6666 WARN("invalid return type %u\n", vtReturn);
6667 heap_free( args );
6668 return E_INVALIDARG;
6669 default:
6670 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6671 break;
6673 heap_free( args );
6674 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6675 TRACE("retval: "); dump_Variant(pvargResult);
6676 return S_OK;
6678 #else
6679 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6680 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6681 return E_NOTIMPL;
6682 #endif
6685 static inline BOOL func_restricted( const FUNCDESC *desc )
6687 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
6690 #define INVBUF_ELEMENT_SIZE \
6691 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6692 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6693 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6694 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6695 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6696 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6697 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6698 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6700 static HRESULT WINAPI ITypeInfo_fnInvoke(
6701 ITypeInfo2 *iface,
6702 VOID *pIUnk,
6703 MEMBERID memid,
6704 UINT16 wFlags,
6705 DISPPARAMS *pDispParams,
6706 VARIANT *pVarResult,
6707 EXCEPINFO *pExcepInfo,
6708 UINT *pArgErr)
6710 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6711 int i;
6712 unsigned int var_index;
6713 TYPEKIND type_kind;
6714 HRESULT hres;
6715 const TLBFuncDesc *pFuncInfo;
6716 UINT fdc;
6718 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6719 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6722 if( This->wTypeFlags & TYPEFLAG_FRESTRICTED )
6723 return DISP_E_MEMBERNOTFOUND;
6725 if (!pDispParams)
6727 ERR("NULL pDispParams not allowed\n");
6728 return E_INVALIDARG;
6731 dump_DispParms(pDispParams);
6733 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6735 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6736 pDispParams->cNamedArgs, pDispParams->cArgs);
6737 return E_INVALIDARG;
6740 /* we do this instead of using GetFuncDesc since it will return a fake
6741 * FUNCDESC for dispinterfaces and we want the real function description */
6742 for (fdc = 0; fdc < This->cFuncs; ++fdc){
6743 pFuncInfo = &This->funcdescs[fdc];
6744 if ((memid == pFuncInfo->funcdesc.memid) &&
6745 (wFlags & pFuncInfo->funcdesc.invkind) &&
6746 !func_restricted( &pFuncInfo->funcdesc ))
6747 break;
6750 if (fdc < This->cFuncs) {
6751 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6753 if (TRACE_ON(ole))
6755 TRACE("invoking:\n");
6756 dump_TLBFuncDescOne(pFuncInfo);
6759 switch (func_desc->funckind) {
6760 case FUNC_PUREVIRTUAL:
6761 case FUNC_VIRTUAL: {
6762 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
6763 VARIANT varresult;
6764 VARIANT retval; /* pointer for storing byref retvals in */
6765 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6766 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6767 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6768 UINT cNamedArgs = pDispParams->cNamedArgs;
6769 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6770 UINT vargs_converted=0;
6772 hres = S_OK;
6774 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6776 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6778 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6779 hres = DISP_E_PARAMNOTFOUND;
6780 goto func_fail;
6784 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6786 ERR("functions with the vararg attribute do not support named arguments\n");
6787 hres = DISP_E_NONAMEDARGS;
6788 goto func_fail;
6791 for (i = 0; i < func_desc->cParams; i++)
6793 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6794 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6795 if (FAILED(hres))
6796 goto func_fail;
6799 TRACE("changing args\n");
6800 for (i = 0; i < func_desc->cParams; i++)
6802 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6803 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6804 VARIANTARG *src_arg;
6806 if (wParamFlags & PARAMFLAG_FLCID)
6808 VARIANTARG *arg;
6809 arg = prgpvarg[i] = &rgvarg[i];
6810 V_VT(arg) = VT_I4;
6811 V_I4(arg) = This->pTypeLib->lcid;
6812 continue;
6815 src_arg = NULL;
6817 if (cNamedArgs)
6819 USHORT j;
6820 for (j = 0; j < cNamedArgs; j++)
6821 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
6823 src_arg = &pDispParams->rgvarg[j];
6824 break;
6828 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
6830 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6831 vargs_converted++;
6834 if (wParamFlags & PARAMFLAG_FRETVAL)
6836 /* under most conditions the caller is not allowed to
6837 * pass in a dispparam arg in the index of what would be
6838 * the retval parameter. however, there is an exception
6839 * where the extra parameter is used in an extra
6840 * IDispatch::Invoke below */
6841 if ((i < pDispParams->cArgs) &&
6842 ((func_desc->cParams != 1) || !pVarResult ||
6843 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6845 hres = DISP_E_BADPARAMCOUNT;
6846 break;
6849 /* note: this check is placed so that if the caller passes
6850 * in a VARIANTARG for the retval we just ignore it, like
6851 * native does */
6852 if (i == func_desc->cParams - 1)
6854 VARIANTARG *arg;
6855 arg = prgpvarg[i] = &rgvarg[i];
6856 memset(arg, 0, sizeof(*arg));
6857 V_VT(arg) = rgvt[i];
6858 memset(&retval, 0, sizeof(retval));
6859 V_BYREF(arg) = &retval;
6861 else
6863 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6864 hres = E_UNEXPECTED;
6865 break;
6868 else if (src_arg)
6870 dump_Variant(src_arg);
6872 if(rgvt[i]!=V_VT(src_arg))
6874 if (rgvt[i] == VT_VARIANT)
6875 hres = VariantCopy(&rgvarg[i], src_arg);
6876 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6878 if (rgvt[i] == V_VT(src_arg))
6879 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6880 else
6882 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6883 if (wParamFlags & PARAMFLAG_FIN)
6884 hres = VariantCopy(&missing_arg[i], src_arg);
6885 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6887 V_VT(&rgvarg[i]) = rgvt[i];
6889 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6891 SAFEARRAY *a;
6892 SAFEARRAYBOUND bound;
6893 VARIANT *v;
6894 LONG j;
6895 bound.lLbound = 0;
6896 bound.cElements = pDispParams->cArgs-i;
6897 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6899 ERR("SafeArrayCreate failed\n");
6900 break;
6902 hres = SafeArrayAccessData(a, (LPVOID)&v);
6903 if (hres != S_OK)
6905 ERR("SafeArrayAccessData failed with %x\n", hres);
6906 SafeArrayDestroy(a);
6907 break;
6909 for (j = 0; j < bound.cElements; j++)
6910 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6911 hres = SafeArrayUnaccessData(a);
6912 if (hres != S_OK)
6914 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6915 SafeArrayDestroy(a);
6916 break;
6918 V_ARRAY(&rgvarg[i]) = a;
6919 V_VT(&rgvarg[i]) = rgvt[i];
6921 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6923 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6924 if (wParamFlags & PARAMFLAG_FIN)
6925 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6926 else
6927 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
6928 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6929 V_VT(&rgvarg[i]) = rgvt[i];
6931 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6933 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6934 V_VT(&rgvarg[i]) = rgvt[i];
6936 else
6938 /* FIXME: this doesn't work for VT_BYREF arguments if
6939 * they are not the same type as in the paramdesc */
6940 V_VT(&rgvarg[i]) = V_VT(src_arg);
6941 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6942 V_VT(&rgvarg[i]) = rgvt[i];
6945 if (FAILED(hres))
6947 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6948 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6949 debugstr_VT(src_arg), debugstr_VF(src_arg));
6950 break;
6952 prgpvarg[i] = &rgvarg[i];
6954 else
6956 prgpvarg[i] = src_arg;
6959 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
6960 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
6961 && V_UNKNOWN(prgpvarg[i])) {
6962 IUnknown *userdefined_iface;
6963 GUID guid;
6965 hres = get_iface_guid((ITypeInfo*)iface, tdesc->vt == VT_PTR ? tdesc->u.lptdesc : tdesc, &guid);
6966 if(FAILED(hres))
6967 break;
6969 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
6970 if(FAILED(hres)) {
6971 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
6972 break;
6975 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
6976 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
6979 else if (wParamFlags & PARAMFLAG_FOPT)
6981 VARIANTARG *arg;
6982 arg = prgpvarg[i] = &rgvarg[i];
6983 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6985 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6986 if (FAILED(hres))
6987 break;
6989 else
6991 VARIANTARG *missing_arg;
6992 /* if the function wants a pointer to a variant then
6993 * set that up, otherwise just pass the VT_ERROR in
6994 * the argument by value */
6995 if (rgvt[i] & VT_BYREF)
6997 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6998 V_VT(arg) = VT_VARIANT | VT_BYREF;
6999 V_VARIANTREF(arg) = missing_arg;
7001 else
7002 missing_arg = arg;
7003 V_VT(missing_arg) = VT_ERROR;
7004 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
7007 else
7009 hres = DISP_E_BADPARAMCOUNT;
7010 break;
7013 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7015 /* VT_VOID is a special case for return types, so it is not
7016 * handled in the general function */
7017 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
7018 V_VT(&varresult) = VT_EMPTY;
7019 else
7021 V_VT(&varresult) = 0;
7022 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
7023 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7026 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv,
7027 V_VT(&varresult), func_desc->cParams, rgvt,
7028 prgpvarg, &varresult);
7030 vargs_converted = 0;
7032 for (i = 0; i < func_desc->cParams; i++)
7034 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7035 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7037 if (wParamFlags & PARAMFLAG_FLCID)
7038 continue;
7039 else if (wParamFlags & PARAMFLAG_FRETVAL)
7041 if (TRACE_ON(ole))
7043 TRACE("[retval] value: ");
7044 dump_Variant(prgpvarg[i]);
7047 if (pVarResult)
7049 VariantInit(pVarResult);
7050 /* deref return value */
7051 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
7054 VARIANT_ClearInd(prgpvarg[i]);
7056 else if (vargs_converted < pDispParams->cArgs)
7058 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7059 if (wParamFlags & PARAMFLAG_FOUT)
7061 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
7063 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
7065 if (FAILED(hres))
7067 ERR("failed to convert param %d to vt %d\n", i,
7068 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
7069 break;
7073 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
7074 func_desc->cParamsOpt < 0 &&
7075 i == func_desc->cParams-1)
7077 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
7078 LONG j, ubound;
7079 VARIANT *v;
7080 hres = SafeArrayGetUBound(a, 1, &ubound);
7081 if (hres != S_OK)
7083 ERR("SafeArrayGetUBound failed with %x\n", hres);
7084 break;
7086 hres = SafeArrayAccessData(a, (LPVOID)&v);
7087 if (hres != S_OK)
7089 ERR("SafeArrayAccessData failed with %x\n", hres);
7090 break;
7092 for (j = 0; j <= ubound; j++)
7093 VariantClear(&v[j]);
7094 hres = SafeArrayUnaccessData(a);
7095 if (hres != S_OK)
7097 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7098 break;
7101 VariantClear(&rgvarg[i]);
7102 vargs_converted++;
7104 else if (wParamFlags & PARAMFLAG_FOPT)
7106 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7107 VariantClear(&rgvarg[i]);
7110 VariantClear(&missing_arg[i]);
7113 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
7115 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
7116 hres = DISP_E_EXCEPTION;
7117 if (pExcepInfo)
7119 IErrorInfo *pErrorInfo;
7120 pExcepInfo->scode = V_ERROR(&varresult);
7121 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
7123 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
7124 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
7125 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
7126 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
7128 IErrorInfo_Release(pErrorInfo);
7132 if (V_VT(&varresult) != VT_ERROR)
7134 TRACE("varresult value: ");
7135 dump_Variant(&varresult);
7137 if (pVarResult)
7139 VariantClear(pVarResult);
7140 *pVarResult = varresult;
7142 else
7143 VariantClear(&varresult);
7146 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
7147 (func_desc->invkind & INVOKE_PROPERTYGET) &&
7148 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
7149 (pDispParams->cArgs != 0))
7151 if (V_VT(pVarResult) == VT_DISPATCH)
7153 IDispatch *pDispatch = V_DISPATCH(pVarResult);
7154 /* Note: not VariantClear; we still need the dispatch
7155 * pointer to be valid */
7156 VariantInit(pVarResult);
7157 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
7158 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
7159 pDispParams, pVarResult, pExcepInfo, pArgErr);
7160 IDispatch_Release(pDispatch);
7162 else
7164 VariantClear(pVarResult);
7165 hres = DISP_E_NOTACOLLECTION;
7169 func_fail:
7170 heap_free(buffer);
7171 break;
7173 case FUNC_DISPATCH: {
7174 IDispatch *disp;
7176 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
7177 if (SUCCEEDED(hres)) {
7178 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7179 hres = IDispatch_Invoke(
7180 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
7181 pVarResult,pExcepInfo,pArgErr
7183 if (FAILED(hres))
7184 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
7185 IDispatch_Release(disp);
7186 } else
7187 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7188 break;
7190 default:
7191 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
7192 hres = E_FAIL;
7193 break;
7196 TRACE("-- 0x%08x\n", hres);
7197 return hres;
7199 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
7200 VARDESC *var_desc;
7202 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
7203 if(FAILED(hres)) return hres;
7205 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7206 dump_VARDESC(var_desc);
7207 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
7208 return E_NOTIMPL;
7211 /* not found, look for it in inherited interfaces */
7212 ITypeInfo2_GetTypeKind(iface, &type_kind);
7213 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
7214 if(This->impltypes) {
7215 /* recursive search */
7216 ITypeInfo *pTInfo;
7217 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7218 if(SUCCEEDED(hres)){
7219 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
7220 ITypeInfo_Release(pTInfo);
7221 return hres;
7223 WARN("Could not search inherited interface!\n");
7226 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
7227 return DISP_E_MEMBERNOTFOUND;
7230 /* ITypeInfo::GetDocumentation
7232 * Retrieves the documentation string, the complete Help file name and path,
7233 * and the context ID for the Help topic for a specified type description.
7235 * (Can be tested by the Visual Basic Editor in Word for instance.)
7237 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
7238 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
7239 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
7241 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7242 const TLBFuncDesc *pFDesc;
7243 const TLBVarDesc *pVDesc;
7244 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7245 " HelpContext(%p) HelpFile(%p)\n",
7246 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
7247 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7248 if(pBstrName)
7249 *pBstrName=SysAllocString(TLB_get_bstr(This->Name));
7250 if(pBstrDocString)
7251 *pBstrDocString=SysAllocString(TLB_get_bstr(This->DocString));
7252 if(pdwHelpContext)
7253 *pdwHelpContext=This->dwHelpContext;
7254 if(pBstrHelpFile)
7255 *pBstrHelpFile=SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7256 return S_OK;
7257 }else {/* for a member */
7258 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7259 if(pFDesc){
7260 if(pBstrName)
7261 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Name));
7262 if(pBstrDocString)
7263 *pBstrDocString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7264 if(pdwHelpContext)
7265 *pdwHelpContext=pFDesc->helpcontext;
7266 if(pBstrHelpFile)
7267 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7268 return S_OK;
7270 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
7271 if(pVDesc){
7272 if(pBstrName)
7273 *pBstrName = SysAllocString(TLB_get_bstr(pVDesc->Name));
7274 if(pBstrDocString)
7275 *pBstrDocString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7276 if(pdwHelpContext)
7277 *pdwHelpContext=pVDesc->HelpContext;
7278 if(pBstrHelpFile)
7279 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7280 return S_OK;
7284 if(This->impltypes &&
7285 (This->typekind==TKIND_INTERFACE || This->typekind==TKIND_DISPATCH)) {
7286 /* recursive search */
7287 ITypeInfo *pTInfo;
7288 HRESULT result;
7289 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7290 if(SUCCEEDED(result)) {
7291 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
7292 pBstrDocString, pdwHelpContext, pBstrHelpFile);
7293 ITypeInfo_Release(pTInfo);
7294 return result;
7296 WARN("Could not search inherited interface!\n");
7299 WARN("member %d not found\n", memid);
7300 return TYPE_E_ELEMENTNOTFOUND;
7303 /* ITypeInfo::GetDllEntry
7305 * Retrieves a description or specification of an entry point for a function
7306 * in a DLL.
7308 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
7309 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
7310 WORD *pwOrdinal)
7312 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7313 const TLBFuncDesc *pFDesc;
7315 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
7317 if (pBstrDllName) *pBstrDllName = NULL;
7318 if (pBstrName) *pBstrName = NULL;
7319 if (pwOrdinal) *pwOrdinal = 0;
7321 if (This->typekind != TKIND_MODULE)
7322 return TYPE_E_BADMODULEKIND;
7324 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7325 if(pFDesc){
7326 dump_TypeInfo(This);
7327 if (TRACE_ON(ole))
7328 dump_TLBFuncDescOne(pFDesc);
7330 if (pBstrDllName)
7331 *pBstrDllName = SysAllocString(TLB_get_bstr(This->DllName));
7333 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
7334 if (pBstrName)
7335 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Entry));
7336 if (pwOrdinal)
7337 *pwOrdinal = -1;
7338 return S_OK;
7340 if (pBstrName)
7341 *pBstrName = NULL;
7342 if (pwOrdinal)
7343 *pwOrdinal = LOWORD(pFDesc->Entry);
7344 return S_OK;
7346 return TYPE_E_ELEMENTNOTFOUND;
7349 /* internal function to make the inherited interfaces' methods appear
7350 * part of the interface */
7351 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7352 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7354 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7355 HRESULT hr;
7357 TRACE("%p, 0x%x\n", iface, *hRefType);
7359 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7361 ITypeInfo *pSubTypeInfo;
7363 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7364 if (FAILED(hr))
7365 return hr;
7367 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7368 hRefType, ppTInfo);
7369 ITypeInfo_Release(pSubTypeInfo);
7370 if (SUCCEEDED(hr))
7371 return hr;
7373 *hRefType -= DISPATCH_HREF_OFFSET;
7375 if (!(*hRefType & DISPATCH_HREF_MASK))
7376 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7377 else
7378 return E_FAIL;
7381 /* ITypeInfo::GetRefTypeInfo
7383 * If a type description references other type descriptions, it retrieves
7384 * the referenced type descriptions.
7386 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7387 ITypeInfo2 *iface,
7388 HREFTYPE hRefType,
7389 ITypeInfo **ppTInfo)
7391 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7392 HRESULT result = E_FAIL;
7394 if(!ppTInfo)
7395 return E_INVALIDARG;
7397 if ((INT)hRefType < 0) {
7398 ITypeInfoImpl *pTypeInfoImpl;
7400 if (!(This->wTypeFlags & TYPEFLAG_FDUAL) ||
7401 !(This->typekind == TKIND_INTERFACE ||
7402 This->typekind == TKIND_DISPATCH))
7403 return TYPE_E_ELEMENTNOTFOUND;
7405 /* when we meet a DUAL typeinfo, we must create the alternate
7406 * version of it.
7408 pTypeInfoImpl = ITypeInfoImpl_Constructor();
7410 *pTypeInfoImpl = *This;
7411 pTypeInfoImpl->ref = 0;
7412 list_init(&pTypeInfoImpl->custdata_list);
7414 if (This->typekind == TKIND_INTERFACE)
7415 pTypeInfoImpl->typekind = TKIND_DISPATCH;
7416 else
7417 pTypeInfoImpl->typekind = TKIND_INTERFACE;
7419 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface;
7420 /* the AddRef implicitly adds a reference to the parent typelib, which
7421 * stops the copied data from being destroyed until the new typeinfo's
7422 * refcount goes to zero, but we need to signal to the new instance to
7423 * not free its data structures when it is destroyed */
7424 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7426 ITypeInfo_AddRef(*ppTInfo);
7428 result = S_OK;
7429 } else if ((hRefType & DISPATCH_HREF_MASK) &&
7430 (This->typekind == TKIND_DISPATCH))
7432 HREFTYPE href_dispatch = hRefType;
7433 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
7434 } else {
7435 TLBRefType *ref_type;
7436 ITypeLib *pTLib = NULL;
7437 UINT i;
7439 if(!(hRefType & 0x1)){
7440 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
7442 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
7444 result = S_OK;
7445 *ppTInfo = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
7446 ITypeInfo_AddRef(*ppTInfo);
7447 goto end;
7452 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7454 if(ref_type->reference == (hRefType & (~0x3)))
7455 break;
7457 if(&ref_type->entry == &This->pTypeLib->ref_list)
7459 FIXME("Can't find pRefType for ref %x\n", hRefType);
7460 goto end;
7463 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7464 UINT Index;
7465 TRACE("internal reference\n");
7466 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7467 } else {
7468 if(ref_type->pImpTLInfo->pImpTypeLib) {
7469 TRACE("typeinfo in imported typelib that is already loaded\n");
7470 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
7471 ITypeLib_AddRef(pTLib);
7472 result = S_OK;
7473 } else {
7474 BSTR libnam;
7476 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7478 result = query_typelib_path(TLB_get_guid_null(ref_type->pImpTLInfo->guid),
7479 ref_type->pImpTLInfo->wVersionMajor,
7480 ref_type->pImpTLInfo->wVersionMinor,
7481 This->pTypeLib->syskind,
7482 ref_type->pImpTLInfo->lcid, &libnam);
7483 if(FAILED(result))
7484 libnam = SysAllocString(ref_type->pImpTLInfo->name);
7486 result = LoadTypeLib(libnam, &pTLib);
7487 SysFreeString(libnam);
7489 if(SUCCEEDED(result)) {
7490 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
7491 ITypeLib_AddRef(pTLib);
7495 if(SUCCEEDED(result)) {
7496 if(ref_type->index == TLB_REF_USE_GUID)
7497 result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), ppTInfo);
7498 else
7499 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, ppTInfo);
7501 if (pTLib != NULL)
7502 ITypeLib_Release(pTLib);
7505 end:
7506 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
7507 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
7508 return result;
7511 /* ITypeInfo::AddressOfMember
7513 * Retrieves the addresses of static functions or variables, such as those
7514 * defined in a DLL.
7516 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
7517 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
7519 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7520 HRESULT hr;
7521 BSTR dll, entry;
7522 WORD ordinal;
7523 HMODULE module;
7525 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
7527 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
7528 if (FAILED(hr))
7529 return hr;
7531 module = LoadLibraryW(dll);
7532 if (!module)
7534 ERR("couldn't load %s\n", debugstr_w(dll));
7535 SysFreeString(dll);
7536 SysFreeString(entry);
7537 return STG_E_FILENOTFOUND;
7539 /* FIXME: store library somewhere where we can free it */
7541 if (entry)
7543 LPSTR entryA;
7544 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
7545 entryA = heap_alloc(len);
7546 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
7548 *ppv = GetProcAddress(module, entryA);
7549 if (!*ppv)
7550 ERR("function not found %s\n", debugstr_a(entryA));
7552 heap_free(entryA);
7554 else
7556 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7557 if (!*ppv)
7558 ERR("function not found %d\n", ordinal);
7561 SysFreeString(dll);
7562 SysFreeString(entry);
7564 if (!*ppv)
7565 return TYPE_E_DLLFUNCTIONNOTFOUND;
7567 return S_OK;
7570 /* ITypeInfo::CreateInstance
7572 * Creates a new instance of a type that describes a component object class
7573 * (coclass).
7575 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7576 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7578 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7579 HRESULT hr;
7580 TYPEATTR *pTA;
7582 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7584 *ppvObj = NULL;
7586 if(pOuterUnk)
7588 WARN("Not able to aggregate\n");
7589 return CLASS_E_NOAGGREGATION;
7592 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
7593 if(FAILED(hr)) return hr;
7595 if(pTA->typekind != TKIND_COCLASS)
7597 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7598 hr = E_INVALIDARG;
7599 goto end;
7602 hr = S_FALSE;
7603 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7605 IUnknown *pUnk;
7606 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7607 TRACE("GetActiveObject rets %08x\n", hr);
7608 if(hr == S_OK)
7610 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7611 IUnknown_Release(pUnk);
7615 if(hr != S_OK)
7616 hr = CoCreateInstance(&pTA->guid, NULL,
7617 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7618 riid, ppvObj);
7620 end:
7621 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
7622 return hr;
7625 /* ITypeInfo::GetMops
7627 * Retrieves marshalling information.
7629 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7630 BSTR *pBstrMops)
7632 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7633 FIXME("(%p %d) stub!\n", This, memid);
7634 *pBstrMops = NULL;
7635 return S_OK;
7638 /* ITypeInfo::GetContainingTypeLib
7640 * Retrieves the containing type library and the index of the type description
7641 * within that type library.
7643 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7644 ITypeLib * *ppTLib, UINT *pIndex)
7646 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7648 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7649 if (pIndex) {
7650 *pIndex=This->index;
7651 TRACE("returning pIndex=%d\n", *pIndex);
7654 if (ppTLib) {
7655 *ppTLib=(LPTYPELIB )(This->pTypeLib);
7656 ITypeLib_AddRef(*ppTLib);
7657 TRACE("returning ppTLib=%p\n", *ppTLib);
7660 return S_OK;
7663 /* ITypeInfo::ReleaseTypeAttr
7665 * Releases a TYPEATTR previously returned by Get
7668 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7669 TYPEATTR* pTypeAttr)
7671 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7672 TRACE("(%p)->(%p)\n", This, pTypeAttr);
7673 heap_free(pTypeAttr);
7676 /* ITypeInfo::ReleaseFuncDesc
7678 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7680 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7681 ITypeInfo2 *iface,
7682 FUNCDESC *pFuncDesc)
7684 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7685 SHORT i;
7687 TRACE("(%p)->(%p)\n", This, pFuncDesc);
7689 for (i = 0; i < pFuncDesc->cParams; i++)
7690 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7691 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7693 SysFreeString((BSTR)pFuncDesc);
7696 /* ITypeInfo::ReleaseVarDesc
7698 * Releases a VARDESC previously returned by GetVarDesc.
7700 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7701 VARDESC *pVarDesc)
7703 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7704 TRACE("(%p)->(%p)\n", This, pVarDesc);
7706 TLB_FreeVarDesc(pVarDesc);
7709 /* ITypeInfo2::GetTypeKind
7711 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7714 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7715 TYPEKIND *pTypeKind)
7717 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7718 *pTypeKind=This->typekind;
7719 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7720 return S_OK;
7723 /* ITypeInfo2::GetTypeFlags
7725 * Returns the type flags without any allocations. This returns a DWORD type
7726 * flag, which expands the type flags without growing the TYPEATTR (type
7727 * attribute).
7730 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7732 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7733 *pTypeFlags=This->wTypeFlags;
7734 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7735 return S_OK;
7738 /* ITypeInfo2::GetFuncIndexOfMemId
7739 * Binds to a specific member based on a known DISPID, where the member name
7740 * is not known (for example, when binding to a default member).
7743 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7744 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7746 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7747 UINT fdc;
7748 HRESULT result;
7750 for (fdc = 0; fdc < This->cFuncs; ++fdc){
7751 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
7752 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7753 break;
7755 if(fdc < This->cFuncs) {
7756 *pFuncIndex = fdc;
7757 result = S_OK;
7758 } else
7759 result = TYPE_E_ELEMENTNOTFOUND;
7761 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7762 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7763 return result;
7766 /* TypeInfo2::GetVarIndexOfMemId
7768 * Binds to a specific member based on a known DISPID, where the member name
7769 * is not known (for example, when binding to a default member).
7772 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7773 MEMBERID memid, UINT *pVarIndex)
7775 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7776 TLBVarDesc *pVarInfo;
7778 TRACE("%p %d %p\n", iface, memid, pVarIndex);
7780 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
7781 if(!pVarInfo)
7782 return TYPE_E_ELEMENTNOTFOUND;
7784 *pVarIndex = (pVarInfo - This->vardescs);
7786 return S_OK;
7789 /* ITypeInfo2::GetCustData
7791 * Gets the custom data
7793 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7794 ITypeInfo2 * iface,
7795 REFGUID guid,
7796 VARIANT *pVarVal)
7798 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7799 TLBCustData *pCData;
7801 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7803 if(!guid || !pVarVal)
7804 return E_INVALIDARG;
7806 pCData = TLB_get_custdata_by_guid(This->pcustdata_list, guid);
7808 VariantInit( pVarVal);
7809 if (pCData)
7810 VariantCopy( pVarVal, &pCData->data);
7811 else
7812 VariantClear( pVarVal );
7813 return S_OK;
7816 /* ITypeInfo2::GetFuncCustData
7818 * Gets the custom data
7820 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7821 ITypeInfo2 * iface,
7822 UINT index,
7823 REFGUID guid,
7824 VARIANT *pVarVal)
7826 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7827 TLBCustData *pCData;
7828 TLBFuncDesc *pFDesc = &This->funcdescs[index];
7830 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
7832 if(index >= This->cFuncs)
7833 return TYPE_E_ELEMENTNOTFOUND;
7835 pCData = TLB_get_custdata_by_guid(&pFDesc->custdata_list, guid);
7836 if(!pCData)
7837 return TYPE_E_ELEMENTNOTFOUND;
7839 VariantInit(pVarVal);
7840 VariantCopy(pVarVal, &pCData->data);
7842 return S_OK;
7845 /* ITypeInfo2::GetParamCustData
7847 * Gets the custom data
7849 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7850 ITypeInfo2 * iface,
7851 UINT indexFunc,
7852 UINT indexParam,
7853 REFGUID guid,
7854 VARIANT *pVarVal)
7856 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7857 TLBCustData *pCData;
7858 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
7860 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
7861 debugstr_guid(guid), pVarVal);
7863 if(indexFunc >= This->cFuncs)
7864 return TYPE_E_ELEMENTNOTFOUND;
7866 if(indexParam >= pFDesc->funcdesc.cParams)
7867 return TYPE_E_ELEMENTNOTFOUND;
7869 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
7870 if(!pCData)
7871 return TYPE_E_ELEMENTNOTFOUND;
7873 VariantInit(pVarVal);
7874 VariantCopy(pVarVal, &pCData->data);
7876 return S_OK;
7879 /* ITypeInfo2::GetVarCustData
7881 * Gets the custom data
7883 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7884 ITypeInfo2 * iface,
7885 UINT index,
7886 REFGUID guid,
7887 VARIANT *pVarVal)
7889 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7890 TLBCustData *pCData;
7891 TLBVarDesc *pVDesc = &This->vardescs[index];
7893 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7895 if(index >= This->cVars)
7896 return TYPE_E_ELEMENTNOTFOUND;
7898 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
7899 if(!pCData)
7900 return TYPE_E_ELEMENTNOTFOUND;
7902 VariantInit(pVarVal);
7903 VariantCopy(pVarVal, &pCData->data);
7905 return S_OK;
7908 /* ITypeInfo2::GetImplCustData
7910 * Gets the custom data
7912 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7913 ITypeInfo2 * iface,
7914 UINT index,
7915 REFGUID guid,
7916 VARIANT *pVarVal)
7918 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7919 TLBCustData *pCData;
7920 TLBImplType *pRDesc = &This->impltypes[index];
7922 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
7924 if(index >= This->cImplTypes)
7925 return TYPE_E_ELEMENTNOTFOUND;
7927 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
7928 if(!pCData)
7929 return TYPE_E_ELEMENTNOTFOUND;
7931 VariantInit(pVarVal);
7932 VariantCopy(pVarVal, &pCData->data);
7934 return S_OK;
7937 /* ITypeInfo2::GetDocumentation2
7939 * Retrieves the documentation string, the complete Help file name and path,
7940 * the localization context to use, and the context ID for the library Help
7941 * topic in the Help file.
7944 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7945 ITypeInfo2 * iface,
7946 MEMBERID memid,
7947 LCID lcid,
7948 BSTR *pbstrHelpString,
7949 DWORD *pdwHelpStringContext,
7950 BSTR *pbstrHelpStringDll)
7952 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7953 const TLBFuncDesc *pFDesc;
7954 const TLBVarDesc *pVDesc;
7955 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7956 "HelpStringContext(%p) HelpStringDll(%p)\n",
7957 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7958 pbstrHelpStringDll );
7959 /* the help string should be obtained from the helpstringdll,
7960 * using the _DLLGetDocumentation function, based on the supplied
7961 * lcid. Nice to do sometime...
7963 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7964 if(pbstrHelpString)
7965 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->Name));
7966 if(pdwHelpStringContext)
7967 *pdwHelpStringContext=This->dwHelpStringContext;
7968 if(pbstrHelpStringDll)
7969 *pbstrHelpStringDll=
7970 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
7971 return S_OK;
7972 }else {/* for a member */
7973 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7974 if(pFDesc){
7975 if(pbstrHelpString)
7976 *pbstrHelpString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7977 if(pdwHelpStringContext)
7978 *pdwHelpStringContext=pFDesc->HelpStringContext;
7979 if(pbstrHelpStringDll)
7980 *pbstrHelpStringDll=
7981 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
7982 return S_OK;
7984 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
7985 if(pVDesc){
7986 if(pbstrHelpString)
7987 *pbstrHelpString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7988 if(pdwHelpStringContext)
7989 *pdwHelpStringContext=pVDesc->HelpStringContext;
7990 if(pbstrHelpStringDll)
7991 *pbstrHelpStringDll=
7992 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
7993 return S_OK;
7996 return TYPE_E_ELEMENTNOTFOUND;
7999 /* ITypeInfo2::GetAllCustData
8001 * Gets all custom data items for the Type info.
8004 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
8005 ITypeInfo2 * iface,
8006 CUSTDATA *pCustData)
8008 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8010 TRACE("%p %p\n", This, pCustData);
8012 return TLB_copy_all_custdata(This->pcustdata_list, pCustData);
8015 /* ITypeInfo2::GetAllFuncCustData
8017 * Gets all custom data items for the specified Function
8020 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
8021 ITypeInfo2 * iface,
8022 UINT index,
8023 CUSTDATA *pCustData)
8025 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8026 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8028 TRACE("%p %u %p\n", This, index, pCustData);
8030 if(index >= This->cFuncs)
8031 return TYPE_E_ELEMENTNOTFOUND;
8033 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
8036 /* ITypeInfo2::GetAllParamCustData
8038 * Gets all custom data items for the Functions
8041 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
8042 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
8044 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8045 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8047 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
8049 if(indexFunc >= This->cFuncs)
8050 return TYPE_E_ELEMENTNOTFOUND;
8052 if(indexParam >= pFDesc->funcdesc.cParams)
8053 return TYPE_E_ELEMENTNOTFOUND;
8055 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
8058 /* ITypeInfo2::GetAllVarCustData
8060 * Gets all custom data items for the specified Variable
8063 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
8064 UINT index, CUSTDATA *pCustData)
8066 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8067 TLBVarDesc * pVDesc = &This->vardescs[index];
8069 TRACE("%p %u %p\n", This, index, pCustData);
8071 if(index >= This->cVars)
8072 return TYPE_E_ELEMENTNOTFOUND;
8074 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
8077 /* ITypeInfo2::GetAllImplCustData
8079 * Gets all custom data items for the specified implementation type
8082 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
8083 ITypeInfo2 * iface,
8084 UINT index,
8085 CUSTDATA *pCustData)
8087 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8088 TLBImplType *pRDesc = &This->impltypes[index];
8090 TRACE("%p %u %p\n", This, index, pCustData);
8092 if(index >= This->cImplTypes)
8093 return TYPE_E_ELEMENTNOTFOUND;
8095 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
8098 static const ITypeInfo2Vtbl tinfvt =
8101 ITypeInfo_fnQueryInterface,
8102 ITypeInfo_fnAddRef,
8103 ITypeInfo_fnRelease,
8105 ITypeInfo_fnGetTypeAttr,
8106 ITypeInfo_fnGetTypeComp,
8107 ITypeInfo_fnGetFuncDesc,
8108 ITypeInfo_fnGetVarDesc,
8109 ITypeInfo_fnGetNames,
8110 ITypeInfo_fnGetRefTypeOfImplType,
8111 ITypeInfo_fnGetImplTypeFlags,
8112 ITypeInfo_fnGetIDsOfNames,
8113 ITypeInfo_fnInvoke,
8114 ITypeInfo_fnGetDocumentation,
8115 ITypeInfo_fnGetDllEntry,
8116 ITypeInfo_fnGetRefTypeInfo,
8117 ITypeInfo_fnAddressOfMember,
8118 ITypeInfo_fnCreateInstance,
8119 ITypeInfo_fnGetMops,
8120 ITypeInfo_fnGetContainingTypeLib,
8121 ITypeInfo_fnReleaseTypeAttr,
8122 ITypeInfo_fnReleaseFuncDesc,
8123 ITypeInfo_fnReleaseVarDesc,
8125 ITypeInfo2_fnGetTypeKind,
8126 ITypeInfo2_fnGetTypeFlags,
8127 ITypeInfo2_fnGetFuncIndexOfMemId,
8128 ITypeInfo2_fnGetVarIndexOfMemId,
8129 ITypeInfo2_fnGetCustData,
8130 ITypeInfo2_fnGetFuncCustData,
8131 ITypeInfo2_fnGetParamCustData,
8132 ITypeInfo2_fnGetVarCustData,
8133 ITypeInfo2_fnGetImplTypeCustData,
8134 ITypeInfo2_fnGetDocumentation2,
8135 ITypeInfo2_fnGetAllCustData,
8136 ITypeInfo2_fnGetAllFuncCustData,
8137 ITypeInfo2_fnGetAllParamCustData,
8138 ITypeInfo2_fnGetAllVarCustData,
8139 ITypeInfo2_fnGetAllImplTypeCustData,
8142 /******************************************************************************
8143 * CreateDispTypeInfo [OLEAUT32.31]
8145 * Build type information for an object so it can be called through an
8146 * IDispatch interface.
8148 * RETURNS
8149 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8150 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8152 * NOTES
8153 * This call allows an objects methods to be accessed through IDispatch, by
8154 * building an ITypeInfo object that IDispatch can use to call through.
8156 HRESULT WINAPI CreateDispTypeInfo(
8157 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
8158 LCID lcid, /* [I] Locale Id */
8159 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
8161 ITypeInfoImpl *pTIClass, *pTIIface;
8162 ITypeLibImpl *pTypeLibImpl;
8163 unsigned int param, func;
8164 TLBFuncDesc *pFuncDesc;
8165 TLBRefType *ref;
8167 TRACE("\n");
8168 pTypeLibImpl = TypeLibImpl_Constructor();
8169 if (!pTypeLibImpl) return E_FAIL;
8171 pTypeLibImpl->TypeInfoCount = 2;
8172 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
8174 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
8175 pTIIface->pTypeLib = pTypeLibImpl;
8176 pTIIface->index = 0;
8177 pTIIface->Name = NULL;
8178 pTIIface->dwHelpContext = -1;
8179 pTIIface->guid = NULL;
8180 pTIIface->lcid = lcid;
8181 pTIIface->typekind = TKIND_INTERFACE;
8182 pTIIface->wMajorVerNum = 0;
8183 pTIIface->wMinorVerNum = 0;
8184 pTIIface->cbAlignment = 2;
8185 pTIIface->cbSizeInstance = -1;
8186 pTIIface->cbSizeVft = -1;
8187 pTIIface->cFuncs = 0;
8188 pTIIface->cImplTypes = 0;
8189 pTIIface->cVars = 0;
8190 pTIIface->wTypeFlags = 0;
8191 pTIIface->hreftype = 0;
8193 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers);
8194 pFuncDesc = pTIIface->funcdescs;
8195 for(func = 0; func < pidata->cMembers; func++) {
8196 METHODDATA *md = pidata->pmethdata + func;
8197 pFuncDesc->Name = TLB_append_str(&pTypeLibImpl->name_list, md->szName);
8198 pFuncDesc->funcdesc.memid = md->dispid;
8199 pFuncDesc->funcdesc.lprgscode = NULL;
8200 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
8201 pFuncDesc->funcdesc.invkind = md->wFlags;
8202 pFuncDesc->funcdesc.callconv = md->cc;
8203 pFuncDesc->funcdesc.cParams = md->cArgs;
8204 pFuncDesc->funcdesc.cParamsOpt = 0;
8205 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
8206 pFuncDesc->funcdesc.cScodes = 0;
8207 pFuncDesc->funcdesc.wFuncFlags = 0;
8208 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
8209 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
8210 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
8211 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8212 md->cArgs * sizeof(ELEMDESC));
8213 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
8214 for(param = 0; param < md->cArgs; param++) {
8215 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
8216 pFuncDesc->pParamDesc[param].Name = TLB_append_str(&pTypeLibImpl->name_list, md->ppdata[param].szName);
8218 pFuncDesc->helpcontext = 0;
8219 pFuncDesc->HelpStringContext = 0;
8220 pFuncDesc->HelpString = NULL;
8221 pFuncDesc->Entry = NULL;
8222 list_init(&pFuncDesc->custdata_list);
8223 pTIIface->cFuncs++;
8224 ++pFuncDesc;
8227 dump_TypeInfo(pTIIface);
8229 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
8230 pTIClass->pTypeLib = pTypeLibImpl;
8231 pTIClass->index = 1;
8232 pTIClass->Name = NULL;
8233 pTIClass->dwHelpContext = -1;
8234 pTIClass->guid = NULL;
8235 pTIClass->lcid = lcid;
8236 pTIClass->typekind = TKIND_COCLASS;
8237 pTIClass->wMajorVerNum = 0;
8238 pTIClass->wMinorVerNum = 0;
8239 pTIClass->cbAlignment = 2;
8240 pTIClass->cbSizeInstance = -1;
8241 pTIClass->cbSizeVft = -1;
8242 pTIClass->cFuncs = 0;
8243 pTIClass->cImplTypes = 1;
8244 pTIClass->cVars = 0;
8245 pTIClass->wTypeFlags = 0;
8246 pTIClass->hreftype = sizeof(MSFT_TypeInfoBase);
8248 pTIClass->impltypes = TLBImplType_Alloc(1);
8250 ref = heap_alloc_zero(sizeof(*ref));
8251 ref->pImpTLInfo = TLB_REF_INTERNAL;
8252 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
8254 dump_TypeInfo(pTIClass);
8256 *pptinfo = (ITypeInfo *)&pTIClass->ITypeInfo2_iface;
8258 ITypeInfo_AddRef(*pptinfo);
8259 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
8261 return S_OK;
8265 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
8267 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8269 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, ppv);
8272 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
8274 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8276 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
8279 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
8281 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8283 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
8286 static HRESULT WINAPI ITypeComp_fnBind(
8287 ITypeComp * iface,
8288 OLECHAR * szName,
8289 ULONG lHash,
8290 WORD wFlags,
8291 ITypeInfo ** ppTInfo,
8292 DESCKIND * pDescKind,
8293 BINDPTR * pBindPtr)
8295 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8296 const TLBFuncDesc *pFDesc;
8297 const TLBVarDesc *pVDesc;
8298 HRESULT hr = DISP_E_MEMBERNOTFOUND;
8299 UINT fdc;
8301 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8303 *pDescKind = DESCKIND_NONE;
8304 pBindPtr->lpfuncdesc = NULL;
8305 *ppTInfo = NULL;
8307 for(fdc = 0; fdc < This->cFuncs; ++fdc){
8308 pFDesc = &This->funcdescs[fdc];
8309 if (!strcmpiW(TLB_get_bstr(pFDesc->Name), szName)) {
8310 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
8311 break;
8312 else
8313 /* name found, but wrong flags */
8314 hr = TYPE_E_TYPEMISMATCH;
8318 if (fdc < This->cFuncs)
8320 HRESULT hr = TLB_AllocAndInitFuncDesc(
8321 &pFDesc->funcdesc,
8322 &pBindPtr->lpfuncdesc,
8323 This->typekind == TKIND_DISPATCH);
8324 if (FAILED(hr))
8325 return hr;
8326 *pDescKind = DESCKIND_FUNCDESC;
8327 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8328 ITypeInfo_AddRef(*ppTInfo);
8329 return S_OK;
8330 } else {
8331 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->cVars, szName);
8332 if(pVDesc){
8333 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
8334 if (FAILED(hr))
8335 return hr;
8336 *pDescKind = DESCKIND_VARDESC;
8337 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8338 ITypeInfo_AddRef(*ppTInfo);
8339 return S_OK;
8342 /* FIXME: search each inherited interface, not just the first */
8343 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
8344 /* recursive search */
8345 ITypeInfo *pTInfo;
8346 ITypeComp *pTComp;
8347 HRESULT hr;
8348 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
8349 if (SUCCEEDED(hr))
8351 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
8352 ITypeInfo_Release(pTInfo);
8354 if (SUCCEEDED(hr))
8356 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8357 ITypeComp_Release(pTComp);
8358 return hr;
8360 WARN("Could not search inherited interface!\n");
8362 if (hr == DISP_E_MEMBERNOTFOUND)
8363 hr = S_OK;
8364 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
8365 return hr;
8368 static HRESULT WINAPI ITypeComp_fnBindType(
8369 ITypeComp * iface,
8370 OLECHAR * szName,
8371 ULONG lHash,
8372 ITypeInfo ** ppTInfo,
8373 ITypeComp ** ppTComp)
8375 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
8377 /* strange behaviour (does nothing) but like the
8378 * original */
8380 if (!ppTInfo || !ppTComp)
8381 return E_POINTER;
8383 *ppTInfo = NULL;
8384 *ppTComp = NULL;
8386 return S_OK;
8389 static const ITypeCompVtbl tcompvt =
8392 ITypeComp_fnQueryInterface,
8393 ITypeComp_fnAddRef,
8394 ITypeComp_fnRelease,
8396 ITypeComp_fnBind,
8397 ITypeComp_fnBindType
8400 HRESULT WINAPI CreateTypeLib2(SYSKIND syskind, LPCOLESTR szFile,
8401 ICreateTypeLib2** ppctlib)
8403 ITypeLibImpl *This;
8404 HRESULT hres;
8406 TRACE("(%d,%s,%p)\n", syskind, debugstr_w(szFile), ppctlib);
8408 if (!szFile) return E_INVALIDARG;
8410 This = TypeLibImpl_Constructor();
8411 if (!This)
8412 return E_OUTOFMEMORY;
8414 This->lcid = GetSystemDefaultLCID();
8415 This->syskind = syskind;
8416 This->ptr_size = get_ptr_size(syskind);
8418 This->path = heap_alloc((lstrlenW(szFile) + 1) * sizeof(WCHAR));
8419 if (!This->path) {
8420 ITypeLib2_Release(&This->ITypeLib2_iface);
8421 return E_OUTOFMEMORY;
8423 lstrcpyW(This->path, szFile);
8425 hres = ITypeLib2_QueryInterface(&This->ITypeLib2_iface, &IID_ICreateTypeLib2, (LPVOID*)ppctlib);
8426 ITypeLib2_Release(&This->ITypeLib2_iface);
8427 return hres;
8430 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
8431 REFIID riid, void **object)
8433 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8435 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, object);
8438 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
8440 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8442 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
8445 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
8447 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8449 return ITypeLib2_Release(&This->ITypeLib2_iface);
8452 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
8453 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
8455 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8456 ITypeInfoImpl *info;
8457 HRESULT hres;
8459 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo);
8461 if (!ctinfo || !name)
8462 return E_INVALIDARG;
8464 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, name);
8465 if (info)
8466 return TYPE_E_NAMECONFLICT;
8468 if (This->typeinfos)
8469 This->typeinfos = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->typeinfos,
8470 sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1));
8471 else
8472 This->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*));
8474 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor();
8476 info->pTypeLib = This;
8477 info->Name = TLB_append_str(&This->name_list, name);
8478 info->index = This->TypeInfoCount;
8479 info->typekind = kind;
8480 info->cbAlignment = 4;
8482 switch(info->typekind) {
8483 case TKIND_ENUM:
8484 case TKIND_INTERFACE:
8485 case TKIND_DISPATCH:
8486 case TKIND_COCLASS:
8487 info->cbSizeInstance = 4;
8488 break;
8489 case TKIND_RECORD:
8490 case TKIND_UNION:
8491 info->cbSizeInstance = 0;
8492 break;
8493 case TKIND_MODULE:
8494 info->cbSizeInstance = 2;
8495 break;
8496 case TKIND_ALIAS:
8497 info->cbSizeInstance = -0x75;
8498 break;
8499 default:
8500 FIXME("unrecognized typekind %d\n", info->typekind);
8501 info->cbSizeInstance = 0xdeadbeef;
8502 break;
8505 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface,
8506 &IID_ICreateTypeInfo, (void **)ctinfo);
8507 if (FAILED(hres)) {
8508 ITypeInfo2_Release(&info->ITypeInfo2_iface);
8509 return hres;
8512 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase);
8514 ++This->TypeInfoCount;
8516 return S_OK;
8519 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
8520 LPOLESTR name)
8522 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8524 TRACE("%p %s\n", This, wine_dbgstr_w(name));
8526 if (!name)
8527 return E_INVALIDARG;
8529 This->Name = TLB_append_str(&This->name_list, name);
8531 return S_OK;
8534 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
8535 WORD majorVerNum, WORD minorVerNum)
8537 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8539 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
8541 This->ver_major = majorVerNum;
8542 This->ver_minor = minorVerNum;
8544 return S_OK;
8547 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
8548 REFGUID guid)
8550 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8552 TRACE("%p %s\n", This, debugstr_guid(guid));
8554 This->guid = TLB_append_guid(&This->guid_list, guid, -2);
8556 return S_OK;
8559 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
8560 LPOLESTR doc)
8562 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8564 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
8566 if (!doc)
8567 return E_INVALIDARG;
8569 This->DocString = TLB_append_str(&This->string_list, doc);
8571 return S_OK;
8574 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
8575 LPOLESTR helpFileName)
8577 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8579 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
8581 if (!helpFileName)
8582 return E_INVALIDARG;
8584 This->HelpFile = TLB_append_str(&This->string_list, helpFileName);
8586 return S_OK;
8589 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
8590 DWORD helpContext)
8592 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8594 TRACE("%p %d\n", This, helpContext);
8596 This->dwHelpContext = helpContext;
8598 return S_OK;
8601 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
8602 LCID lcid)
8604 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8606 TRACE("%p %x\n", This, lcid);
8608 This->set_lcid = lcid;
8610 return S_OK;
8613 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
8614 UINT libFlags)
8616 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8618 TRACE("%p %x\n", This, libFlags);
8620 This->libflags = libFlags;
8622 return S_OK;
8625 typedef struct tagWMSFT_SegContents {
8626 DWORD len;
8627 void *data;
8628 } WMSFT_SegContents;
8630 typedef struct tagWMSFT_TLBFile {
8631 MSFT_Header header;
8632 WMSFT_SegContents typeinfo_seg;
8633 WMSFT_SegContents impfile_seg;
8634 WMSFT_SegContents impinfo_seg;
8635 WMSFT_SegContents ref_seg;
8636 WMSFT_SegContents guidhash_seg;
8637 WMSFT_SegContents guid_seg;
8638 WMSFT_SegContents namehash_seg;
8639 WMSFT_SegContents name_seg;
8640 WMSFT_SegContents string_seg;
8641 WMSFT_SegContents typdesc_seg;
8642 WMSFT_SegContents arraydesc_seg;
8643 WMSFT_SegContents custdata_seg;
8644 WMSFT_SegContents cdguids_seg;
8645 MSFT_SegDir segdir;
8646 WMSFT_SegContents aux_seg;
8647 } WMSFT_TLBFile;
8649 static HRESULT WMSFT_compile_strings(ITypeLibImpl *This,
8650 WMSFT_TLBFile *file)
8652 TLBString *str;
8653 UINT last_offs;
8654 char *data;
8656 file->string_seg.len = 0;
8657 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8658 int size;
8660 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str), NULL, 0, NULL, NULL);
8661 if (size == 0)
8662 return E_UNEXPECTED;
8664 size += sizeof(INT16);
8665 if (size % 4)
8666 size = (size + 4) & ~0x3;
8667 if (size < 8)
8668 size = 8;
8670 file->string_seg.len += size;
8672 /* temporarily use str->offset to store the length of the aligned,
8673 * converted string */
8674 str->offset = size;
8677 file->string_seg.data = data = heap_alloc(file->string_seg.len);
8679 last_offs = 0;
8680 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8681 int size;
8683 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8684 data + sizeof(INT16), file->string_seg.len - last_offs - sizeof(INT16), NULL, NULL);
8685 if (size == 0) {
8686 heap_free(file->string_seg.data);
8687 return E_UNEXPECTED;
8690 *((INT16*)data) = size;
8692 memset(data + sizeof(INT16) + size, 0x57, str->offset - size - sizeof(INT16));
8694 size = str->offset;
8695 data += size;
8696 str->offset = last_offs;
8697 last_offs += size;
8700 return S_OK;
8703 static HRESULT WMSFT_compile_names(ITypeLibImpl *This,
8704 WMSFT_TLBFile *file)
8706 TLBString *str;
8707 UINT last_offs;
8708 char *data;
8709 MSFT_NameIntro *last_intro = NULL;
8711 file->header.nametablecount = 0;
8712 file->header.nametablechars = 0;
8714 file->name_seg.len = 0;
8715 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8716 int size;
8718 size = strlenW(str->str);
8719 file->header.nametablechars += size;
8720 file->header.nametablecount++;
8722 size = WideCharToMultiByte(CP_ACP, 0, str->str, size, NULL, 0, NULL, NULL);
8723 if (size == 0)
8724 return E_UNEXPECTED;
8726 size += sizeof(MSFT_NameIntro);
8727 if (size % 4)
8728 size = (size + 4) & ~0x3;
8729 if (size < 8)
8730 size = 8;
8732 file->name_seg.len += size;
8734 /* temporarily use str->offset to store the length of the aligned,
8735 * converted string */
8736 str->offset = size;
8739 file->name_seg.data = data = heap_alloc(file->name_seg.len);
8741 last_offs = 0;
8742 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8743 int size, hash;
8744 MSFT_NameIntro *intro = (MSFT_NameIntro*)data;
8746 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8747 data + sizeof(MSFT_NameIntro),
8748 file->name_seg.len - last_offs - sizeof(MSFT_NameIntro), NULL, NULL);
8749 if (size == 0) {
8750 heap_free(file->name_seg.data);
8751 return E_UNEXPECTED;
8753 data[sizeof(MSFT_NameIntro) + size] = '\0';
8755 intro->hreftype = -1; /* TODO? */
8756 intro->namelen = size & 0xFF;
8757 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
8758 hash = LHashValOfNameSysA(This->syskind, This->lcid, data + sizeof(MSFT_NameIntro));
8759 intro->namelen |= hash << 16;
8760 intro->next_hash = ((DWORD*)file->namehash_seg.data)[hash & 0x7f];
8761 ((DWORD*)file->namehash_seg.data)[hash & 0x7f] = last_offs;
8763 memset(data + sizeof(MSFT_NameIntro) + size, 0x57,
8764 str->offset - size - sizeof(MSFT_NameIntro));
8766 /* update str->offset to actual value to use in other
8767 * compilation functions that require positions within
8768 * the string table */
8769 last_intro = intro;
8770 size = str->offset;
8771 data += size;
8772 str->offset = last_offs;
8773 last_offs += size;
8776 if(last_intro)
8777 last_intro->hreftype = 0; /* last one is 0? */
8779 return S_OK;
8782 static inline int hash_guid(GUID *guid)
8784 int i, hash = 0;
8786 for (i = 0; i < 8; i ++)
8787 hash ^= ((const short *)guid)[i];
8789 return hash & 0x1f;
8792 static HRESULT WMSFT_compile_guids(ITypeLibImpl *This, WMSFT_TLBFile *file)
8794 TLBGuid *guid;
8795 MSFT_GuidEntry *entry;
8796 DWORD offs;
8797 int hash_key, *guidhashtab;
8799 file->guid_seg.len = sizeof(MSFT_GuidEntry) * list_count(&This->guid_list);
8800 file->guid_seg.data = heap_alloc(file->guid_seg.len);
8802 entry = file->guid_seg.data;
8803 offs = 0;
8804 guidhashtab = file->guidhash_seg.data;
8805 LIST_FOR_EACH_ENTRY(guid, &This->guid_list, TLBGuid, entry){
8806 memcpy(&entry->guid, &guid->guid, sizeof(GUID));
8807 entry->hreftype = guid->hreftype;
8809 hash_key = hash_guid(&guid->guid);
8810 entry->next_hash = guidhashtab[hash_key];
8811 guidhashtab[hash_key] = offs;
8813 guid->offset = offs;
8814 offs += sizeof(MSFT_GuidEntry);
8815 ++entry;
8818 return S_OK;
8821 static DWORD WMSFT_encode_variant(VARIANT *value, WMSFT_TLBFile *file)
8823 VARIANT v = *value;
8824 VARTYPE arg_type = V_VT(value);
8825 int mask = 0;
8826 HRESULT hres;
8827 DWORD ret = file->custdata_seg.len;
8829 if(arg_type == VT_INT)
8830 arg_type = VT_I4;
8831 if(arg_type == VT_UINT)
8832 arg_type = VT_UI4;
8834 v = *value;
8835 if(V_VT(value) != arg_type) {
8836 hres = VariantChangeType(&v, value, 0, arg_type);
8837 if(FAILED(hres)){
8838 ERR("VariantChangeType failed: %08x\n", hres);
8839 return -1;
8843 /* Check if default value can be stored in-place */
8844 switch(arg_type){
8845 case VT_I4:
8846 case VT_UI4:
8847 mask = 0x3ffffff;
8848 if(V_UI4(&v) > 0x3ffffff)
8849 break;
8850 /* fall through */
8851 case VT_I1:
8852 case VT_UI1:
8853 case VT_BOOL:
8854 if(!mask)
8855 mask = 0xff;
8856 /* fall through */
8857 case VT_I2:
8858 case VT_UI2:
8859 if(!mask)
8860 mask = 0xffff;
8861 return ((0x80 + 0x4 * V_VT(value)) << 24) | (V_UI4(&v) & mask);
8864 /* have to allocate space in custdata_seg */
8865 switch(arg_type) {
8866 case VT_I4:
8867 case VT_R4:
8868 case VT_UI4:
8869 case VT_INT:
8870 case VT_UINT:
8871 case VT_HRESULT:
8872 case VT_PTR: {
8873 /* Construct the data to be allocated */
8874 int *data;
8876 if(file->custdata_seg.data){
8877 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + sizeof(int) * 2);
8878 data = (int *)(((char *)file->custdata_seg.data) + file->custdata_seg.len);
8879 file->custdata_seg.len += sizeof(int) * 2;
8880 }else{
8881 file->custdata_seg.len = sizeof(int) * 2;
8882 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
8885 data[0] = V_VT(value) + (V_UI4(&v) << 16);
8886 data[1] = (V_UI4(&v) >> 16) + 0x57570000;
8888 /* TODO: Check if the encoded data is already present in custdata_seg */
8890 return ret;
8893 case VT_BSTR: {
8894 int i, len = (6+SysStringLen(V_BSTR(&v))+3) & ~0x3;
8895 char *data;
8897 if(file->custdata_seg.data){
8898 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + len);
8899 data = ((char *)file->custdata_seg.data) + file->custdata_seg.len;
8900 file->custdata_seg.len += len;
8901 }else{
8902 file->custdata_seg.len = len;
8903 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
8906 *((unsigned short *)data) = V_VT(value);
8907 *((unsigned int *)(data+2)) = SysStringLen(V_BSTR(&v));
8908 for(i=0; i<SysStringLen(V_BSTR(&v)); i++) {
8909 if(V_BSTR(&v)[i] <= 0x7f)
8910 data[i+6] = V_BSTR(&v)[i];
8911 else
8912 data[i+6] = '?';
8914 WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], len-6, NULL, NULL);
8915 for(i=6+SysStringLen(V_BSTR(&v)); i<len; i++)
8916 data[i] = 0x57;
8918 /* TODO: Check if the encoded data is already present in custdata_seg */
8920 return ret;
8922 default:
8923 FIXME("Argument type not yet handled\n");
8924 return -1;
8928 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size);
8930 static DWORD WMSFT_append_arraydesc(ARRAYDESC *desc, WMSFT_TLBFile *file)
8932 DWORD offs = file->arraydesc_seg.len;
8933 DWORD *encoded;
8934 USHORT i;
8936 /* TODO: we should check for duplicates, but that's harder because each
8937 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
8938 * at the library-level) */
8940 file->arraydesc_seg.len += (2 + desc->cDims * 2) * sizeof(DWORD);
8941 if(!file->arraydesc_seg.data)
8942 file->arraydesc_seg.data = heap_alloc(file->arraydesc_seg.len);
8943 else
8944 file->arraydesc_seg.data = heap_realloc(file->arraydesc_seg.data, file->arraydesc_seg.len);
8945 encoded = (DWORD*)((char *)file->arraydesc_seg.data) + offs;
8947 encoded[0] = WMSFT_append_typedesc(&desc->tdescElem, file, NULL, NULL);
8948 encoded[1] = desc->cDims | ((desc->cDims * 2 * sizeof(DWORD)) << 16);
8949 for(i = 0; i < desc->cDims; ++i){
8950 encoded[2 + i * 2] = desc->rgbounds[i].cElements;
8951 encoded[2 + i * 2 + 1] = desc->rgbounds[i].lLbound;
8954 return offs;
8957 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size)
8959 DWORD junk;
8960 INT16 junk2;
8961 DWORD offs = 0;
8962 DWORD encoded[2];
8963 VARTYPE vt = desc->vt & VT_TYPEMASK, subtype;
8964 char *data;
8966 if(!out_mix)
8967 out_mix = &junk;
8968 if(!out_size)
8969 out_size = &junk2;
8971 switch(vt){
8972 case VT_INT:
8973 subtype = VT_I4;
8974 break;
8975 case VT_UINT:
8976 subtype = VT_UI4;
8977 break;
8978 case VT_VOID:
8979 subtype = VT_EMPTY;
8980 break;
8981 default:
8982 subtype = vt;
8983 break;
8986 switch(vt){
8987 case VT_INT:
8988 case VT_UINT:
8989 case VT_I1:
8990 case VT_UI1:
8991 case VT_I2:
8992 case VT_UI2:
8993 case VT_I4:
8994 case VT_UI4:
8995 case VT_BOOL:
8996 case VT_R4:
8997 case VT_ERROR:
8998 case VT_BSTR:
8999 case VT_HRESULT:
9000 case VT_CY:
9001 case VT_VOID:
9002 case VT_VARIANT:
9003 *out_mix = subtype;
9004 return 0x80000000 | (subtype << 16) | desc->vt;
9007 if(vt == VT_PTR || vt == VT_SAFEARRAY){
9008 DWORD mix;
9009 encoded[1] = WMSFT_append_typedesc(desc->u.lptdesc, file, &mix, out_size);
9010 encoded[0] = desc->vt | ((mix | VT_BYREF) << 16);
9011 *out_mix = 0x7FFF;
9012 *out_size += 2 * sizeof(DWORD);
9013 }else if(vt == VT_CARRAY){
9014 encoded[0] = desc->vt | (0x7FFE << 16);
9015 encoded[1] = WMSFT_append_arraydesc(desc->u.lpadesc, file);
9016 *out_mix = 0x7FFE;
9017 }else if(vt == VT_USERDEFINED){
9018 encoded[0] = desc->vt | (0x7FFF << 16);
9019 encoded[1] = desc->u.hreftype;
9020 *out_mix = 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9021 }else{
9022 FIXME("Don't know what to do! VT: 0x%x\n", desc->vt);
9023 *out_mix = desc->vt;
9024 return 0x80000000 | (desc->vt << 16) | desc->vt;
9027 data = file->typdesc_seg.data;
9028 while(offs < file->typdesc_seg.len){
9029 if(!memcmp(&data[offs], encoded, sizeof(encoded)))
9030 return offs;
9031 offs += sizeof(encoded);
9034 file->typdesc_seg.len += sizeof(encoded);
9035 if(!file->typdesc_seg.data)
9036 data = file->typdesc_seg.data = heap_alloc(file->typdesc_seg.len);
9037 else
9038 data = file->typdesc_seg.data = heap_realloc(file->typdesc_seg.data, file->typdesc_seg.len);
9040 memcpy(&data[offs], encoded, sizeof(encoded));
9042 return offs;
9045 static DWORD WMSFT_compile_custdata(struct list *custdata_list, WMSFT_TLBFile *file)
9047 WMSFT_SegContents *cdguids_seg = &file->cdguids_seg;
9048 DWORD ret = cdguids_seg->len, offs;
9049 MSFT_CDGuid *cdguid = cdguids_seg->data;
9050 TLBCustData *cd;
9052 if(list_empty(custdata_list))
9053 return -1;
9055 cdguids_seg->len += sizeof(MSFT_CDGuid) * list_count(custdata_list);
9056 if(!cdguids_seg->data){
9057 cdguid = cdguids_seg->data = heap_alloc(cdguids_seg->len);
9058 }else
9059 cdguids_seg->data = heap_realloc(cdguids_seg->data, cdguids_seg->len);
9061 offs = ret + sizeof(MSFT_CDGuid);
9062 LIST_FOR_EACH_ENTRY(cd, custdata_list, TLBCustData, entry){
9063 cdguid->GuidOffset = cd->guid->offset;
9064 cdguid->DataOffset = WMSFT_encode_variant(&cd->data, file);
9065 cdguid->next = offs;
9066 offs += sizeof(MSFT_CDGuid);
9067 ++cdguid;
9070 --cdguid;
9071 cdguid->next = -1;
9073 return ret;
9076 static DWORD WMSFT_compile_typeinfo_aux(ITypeInfoImpl *info,
9077 WMSFT_TLBFile *file)
9079 WMSFT_SegContents *aux_seg = &file->aux_seg;
9080 DWORD ret = aux_seg->len, i, j, recorded_size = 0, extra_size = 0;
9081 MSFT_VarRecord *varrecord;
9082 MSFT_FuncRecord *funcrecord;
9083 MEMBERID *memid;
9084 DWORD *name, *offsets, offs;
9086 for(i = 0; i < info->cFuncs; ++i){
9087 TLBFuncDesc *desc = &info->funcdescs[i];
9089 recorded_size += 6 * sizeof(INT); /* mandatory fields */
9091 /* optional fields */
9092 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9093 if(!list_empty(&desc->custdata_list))
9094 recorded_size += 7 * sizeof(INT);
9095 else if(desc->HelpStringContext != 0)
9096 recorded_size += 6 * sizeof(INT);
9097 /* res9? resA? */
9098 else if(desc->Entry)
9099 recorded_size += 3 * sizeof(INT);
9100 else if(desc->HelpString)
9101 recorded_size += 2 * sizeof(INT);
9102 else if(desc->helpcontext)
9103 recorded_size += sizeof(INT);
9105 recorded_size += desc->funcdesc.cParams * sizeof(MSFT_ParameterInfo);
9107 for(j = 0; j < desc->funcdesc.cParams; ++j){
9108 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9109 recorded_size += desc->funcdesc.cParams * sizeof(INT);
9110 break;
9114 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9117 for(i = 0; i < info->cVars; ++i){
9118 TLBVarDesc *desc = &info->vardescs[i];
9120 recorded_size += 5 * sizeof(INT); /* mandatory fields */
9122 /* optional fields */
9123 if(desc->HelpStringContext != 0)
9124 recorded_size += 5 * sizeof(INT);
9125 else if(!list_empty(&desc->custdata_list))
9126 recorded_size += 4 * sizeof(INT);
9127 /* res9? */
9128 else if(desc->HelpString)
9129 recorded_size += 2 * sizeof(INT);
9130 else if(desc->HelpContext != 0)
9131 recorded_size += sizeof(INT);
9133 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9136 if(!recorded_size && !extra_size)
9137 return ret;
9139 extra_size += sizeof(INT); /* total aux size for this typeinfo */
9141 aux_seg->len += recorded_size + extra_size;
9143 aux_seg->len += sizeof(INT) * (info->cVars + info->cFuncs); /* offsets at the end */
9145 if(aux_seg->data)
9146 aux_seg->data = heap_realloc(aux_seg->data, aux_seg->len);
9147 else
9148 aux_seg->data = heap_alloc(aux_seg->len);
9150 *((DWORD*)((char *)aux_seg->data + ret)) = recorded_size;
9152 offsets = (DWORD*)((char *)aux_seg->data + ret + recorded_size + extra_size);
9153 offs = 0;
9155 funcrecord = (MSFT_FuncRecord*)(((char *)aux_seg->data) + ret + sizeof(INT));
9156 for(i = 0; i < info->cFuncs; ++i){
9157 TLBFuncDesc *desc = &info->funcdescs[i];
9158 DWORD size = 6 * sizeof(INT), paramdefault_size = 0, *paramdefault;
9160 funcrecord->funcdescsize = sizeof(desc->funcdesc) + desc->funcdesc.cParams * sizeof(ELEMDESC);
9161 funcrecord->DataType = WMSFT_append_typedesc(&desc->funcdesc.elemdescFunc.tdesc, file, NULL, &funcrecord->funcdescsize);
9162 funcrecord->Flags = desc->funcdesc.wFuncFlags;
9163 funcrecord->VtableOffset = desc->funcdesc.oVft;
9165 /* FKCCIC:
9166 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9167 * ^^^funckind
9168 * ^^^ ^invkind
9169 * ^has_cust_data
9170 * ^^^^callconv
9171 * ^has_param_defaults
9172 * ^oEntry_is_intresource
9174 funcrecord->FKCCIC =
9175 desc->funcdesc.funckind |
9176 (desc->funcdesc.invkind << 3) |
9177 (list_empty(&desc->custdata_list) ? 0 : 0x80) |
9178 (desc->funcdesc.callconv << 8);
9180 if(desc->Entry && desc->Entry != (TLBString*)-1 && IS_INTRESOURCE(desc->Entry))
9181 funcrecord->FKCCIC |= 0x2000;
9183 for(j = 0; j < desc->funcdesc.cParams; ++j){
9184 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9185 paramdefault_size = sizeof(INT) * desc->funcdesc.cParams;
9186 funcrecord->funcdescsize += sizeof(PARAMDESCEX);
9189 if(paramdefault_size > 0)
9190 funcrecord->FKCCIC |= 0x1000;
9192 funcrecord->nrargs = desc->funcdesc.cParams;
9193 funcrecord->nroargs = desc->funcdesc.cParamsOpt;
9195 /* optional fields */
9196 /* res9? resA? */
9197 if(!list_empty(&desc->custdata_list)){
9198 size += 7 * sizeof(INT);
9199 funcrecord->HelpContext = desc->helpcontext;
9200 if(desc->HelpString)
9201 funcrecord->oHelpString = desc->HelpString->offset;
9202 else
9203 funcrecord->oHelpString = -1;
9204 if(!desc->Entry)
9205 funcrecord->oEntry = -1;
9206 else if(IS_INTRESOURCE(desc->Entry))
9207 funcrecord->oEntry = LOWORD(desc->Entry);
9208 else
9209 funcrecord->oEntry = desc->Entry->offset;
9210 funcrecord->res9 = -1;
9211 funcrecord->resA = -1;
9212 funcrecord->HelpStringContext = desc->HelpStringContext;
9213 funcrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9214 }else if(desc->HelpStringContext != 0){
9215 size += 6 * sizeof(INT);
9216 funcrecord->HelpContext = desc->helpcontext;
9217 if(desc->HelpString)
9218 funcrecord->oHelpString = desc->HelpString->offset;
9219 else
9220 funcrecord->oHelpString = -1;
9221 if(!desc->Entry)
9222 funcrecord->oEntry = -1;
9223 else if(IS_INTRESOURCE(desc->Entry))
9224 funcrecord->oEntry = LOWORD(desc->Entry);
9225 else
9226 funcrecord->oEntry = desc->Entry->offset;
9227 funcrecord->res9 = -1;
9228 funcrecord->resA = -1;
9229 funcrecord->HelpStringContext = desc->HelpStringContext;
9230 }else if(desc->Entry){
9231 size += 3 * sizeof(INT);
9232 funcrecord->HelpContext = desc->helpcontext;
9233 if(desc->HelpString)
9234 funcrecord->oHelpString = desc->HelpString->offset;
9235 else
9236 funcrecord->oHelpString = -1;
9237 if(!desc->Entry)
9238 funcrecord->oEntry = -1;
9239 else if(IS_INTRESOURCE(desc->Entry))
9240 funcrecord->oEntry = LOWORD(desc->Entry);
9241 else
9242 funcrecord->oEntry = desc->Entry->offset;
9243 }else if(desc->HelpString){
9244 size += 2 * sizeof(INT);
9245 funcrecord->HelpContext = desc->helpcontext;
9246 funcrecord->oHelpString = desc->HelpString->offset;
9247 }else if(desc->helpcontext){
9248 size += sizeof(INT);
9249 funcrecord->HelpContext = desc->helpcontext;
9252 paramdefault = (DWORD*)((char *)funcrecord + size);
9253 size += paramdefault_size;
9255 for(j = 0; j < desc->funcdesc.cParams; ++j){
9256 MSFT_ParameterInfo *info = (MSFT_ParameterInfo*)(((char *)funcrecord) + size);
9258 info->DataType = WMSFT_append_typedesc(&desc->funcdesc.lprgelemdescParam[j].tdesc, file, NULL, &funcrecord->funcdescsize);
9259 if(desc->pParamDesc[j].Name)
9260 info->oName = desc->pParamDesc[j].Name->offset;
9261 else
9262 info->oName = -1;
9263 info->Flags = desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags;
9265 if(paramdefault_size){
9266 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
9267 *paramdefault = WMSFT_encode_variant(&desc->funcdesc.lprgelemdescParam[j].u.paramdesc.pparamdescex->varDefaultValue, file);
9268 else if(paramdefault_size)
9269 *paramdefault = -1;
9270 ++paramdefault;
9273 size += sizeof(MSFT_ParameterInfo);
9276 funcrecord->Info = size | (i << 16); /* is it just the index? */
9278 *offsets = offs;
9279 offs += size;
9280 ++offsets;
9282 funcrecord = (MSFT_FuncRecord*)(((char*)funcrecord) + size);
9285 varrecord = (MSFT_VarRecord*)funcrecord;
9286 for(i = 0; i < info->cVars; ++i){
9287 TLBVarDesc *desc = &info->vardescs[i];
9288 DWORD size = 5 * sizeof(INT);
9290 varrecord->vardescsize = sizeof(desc->vardesc);
9291 varrecord->DataType = WMSFT_append_typedesc(&desc->vardesc.elemdescVar.tdesc, file, NULL, &varrecord->vardescsize);
9292 varrecord->Flags = desc->vardesc.wVarFlags;
9293 varrecord->VarKind = desc->vardesc.varkind;
9295 if(desc->vardesc.varkind == VAR_CONST){
9296 varrecord->vardescsize += sizeof(VARIANT);
9297 varrecord->OffsValue = WMSFT_encode_variant(desc->vardesc.u.lpvarValue, file);
9298 }else
9299 varrecord->OffsValue = desc->vardesc.u.oInst;
9301 /* res9? */
9302 if(desc->HelpStringContext != 0){
9303 size += 5 * sizeof(INT);
9304 varrecord->HelpContext = desc->HelpContext;
9305 if(desc->HelpString)
9306 varrecord->HelpString = desc->HelpString->offset;
9307 else
9308 varrecord->HelpString = -1;
9309 varrecord->res9 = -1;
9310 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9311 varrecord->HelpStringContext = desc->HelpStringContext;
9312 }else if(!list_empty(&desc->custdata_list)){
9313 size += 4 * sizeof(INT);
9314 varrecord->HelpContext = desc->HelpContext;
9315 if(desc->HelpString)
9316 varrecord->HelpString = desc->HelpString->offset;
9317 else
9318 varrecord->HelpString = -1;
9319 varrecord->res9 = -1;
9320 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9321 }else if(desc->HelpString){
9322 size += 2 * sizeof(INT);
9323 varrecord->HelpContext = desc->HelpContext;
9324 if(desc->HelpString)
9325 varrecord->HelpString = desc->HelpString->offset;
9326 else
9327 varrecord->HelpString = -1;
9328 }else if(desc->HelpContext != 0){
9329 size += sizeof(INT);
9330 varrecord->HelpContext = desc->HelpContext;
9333 varrecord->Info = size | (i << 16);
9335 *offsets = offs;
9336 offs += size;
9337 ++offsets;
9339 varrecord = (MSFT_VarRecord*)(((char*)varrecord) + size);
9342 memid = (MEMBERID*)varrecord;
9343 for(i = 0; i < info->cFuncs; ++i){
9344 TLBFuncDesc *desc = &info->funcdescs[i];
9345 *memid = desc->funcdesc.memid;
9346 ++memid;
9348 for(i = 0; i < info->cVars; ++i){
9349 TLBVarDesc *desc = &info->vardescs[i];
9350 *memid = desc->vardesc.memid;
9351 ++memid;
9354 name = (UINT*)memid;
9355 for(i = 0; i < info->cFuncs; ++i){
9356 TLBFuncDesc *desc = &info->funcdescs[i];
9357 if(desc->Name)
9358 *name = desc->Name->offset;
9359 else
9360 *name = -1;
9361 ++name;
9363 for(i = 0; i < info->cVars; ++i){
9364 TLBVarDesc *desc = &info->vardescs[i];
9365 if(desc->Name)
9366 *name = desc->Name->offset;
9367 else
9368 *name = -1;
9369 ++name;
9372 return ret;
9375 typedef struct tagWMSFT_RefChunk {
9376 DWORD href;
9377 DWORD res04;
9378 DWORD res08;
9379 DWORD next;
9380 } WMSFT_RefChunk;
9382 static DWORD WMSFT_compile_typeinfo_ref(ITypeInfoImpl *info, WMSFT_TLBFile *file)
9384 DWORD offs = file->ref_seg.len, i;
9385 WMSFT_RefChunk *chunk;
9387 file->ref_seg.len += info->cImplTypes * sizeof(WMSFT_RefChunk);
9388 if(!file->ref_seg.data)
9389 file->ref_seg.data = heap_alloc(file->ref_seg.len);
9390 else
9391 file->ref_seg.data = heap_realloc(file->ref_seg.data, file->ref_seg.len);
9393 chunk = (WMSFT_RefChunk*)((char*)file->ref_seg.data + offs);
9395 for(i = 0; i < info->cImplTypes; ++i){
9396 chunk->href = info->impltypes[i].hRef;
9397 chunk->res04 = info->impltypes[i].implflags;
9398 chunk->res08 = -1;
9399 if(i < info->cImplTypes - 1)
9400 chunk->next = offs + sizeof(WMSFT_RefChunk) * (i + 1);
9401 else
9402 chunk->next = -1;
9403 ++chunk;
9406 return offs;
9409 static DWORD WMSFT_compile_typeinfo(ITypeInfoImpl *info, INT16 index, WMSFT_TLBFile *file, char *data)
9411 DWORD size;
9413 size = sizeof(MSFT_TypeInfoBase);
9415 if(data){
9416 MSFT_TypeInfoBase *base = (void*)data;
9417 if(info->wTypeFlags & TYPEFLAG_FDUAL)
9418 base->typekind = TKIND_DISPATCH;
9419 else
9420 base->typekind = info->typekind;
9421 base->typekind |= index << 16; /* TODO: There are some other flags here */
9422 base->typekind |= (info->cbAlignment << 11) | (info->cbAlignment << 6);
9423 base->memoffset = WMSFT_compile_typeinfo_aux(info, file);
9424 base->res2 = 0;
9425 base->res3 = 0;
9426 base->res4 = 3;
9427 base->res5 = 0;
9428 base->cElement = (info->cVars << 16) | info->cFuncs;
9429 base->res7 = 0;
9430 base->res8 = 0;
9431 base->res9 = 0;
9432 base->resA = 0;
9433 if(info->guid)
9434 base->posguid = info->guid->offset;
9435 else
9436 base->posguid = -1;
9437 base->flags = info->wTypeFlags;
9438 if(info->Name) {
9439 base->NameOffset = info->Name->offset;
9441 ((unsigned char*)file->name_seg.data)[info->Name->offset+9] = 0x38;
9442 *(HREFTYPE*)((unsigned char*)file->name_seg.data+info->Name->offset) = info->hreftype;
9443 }else {
9444 base->NameOffset = -1;
9446 base->version = (info->wMinorVerNum << 16) | info->wMajorVerNum;
9447 if(info->DocString)
9448 base->docstringoffs = info->DocString->offset;
9449 else
9450 base->docstringoffs = -1;
9451 base->helpstringcontext = info->dwHelpStringContext;
9452 base->helpcontext = info->dwHelpContext;
9453 base->oCustData = WMSFT_compile_custdata(info->pcustdata_list, file);
9454 base->cImplTypes = info->cImplTypes;
9455 base->cbSizeVft = info->cbSizeVft;
9456 base->size = info->cbSizeInstance;
9457 if(info->typekind == TKIND_COCLASS){
9458 base->datatype1 = WMSFT_compile_typeinfo_ref(info, file);
9459 }else if(info->typekind == TKIND_ALIAS){
9460 base->datatype1 = WMSFT_append_typedesc(&info->tdescAlias, file, NULL, NULL);
9461 }else if(info->typekind == TKIND_MODULE){
9462 if(info->DllName)
9463 base->datatype1 = info->DllName->offset;
9464 else
9465 base->datatype1 = -1;
9466 }else{
9467 if(info->cImplTypes > 0)
9468 base->datatype1 = info->impltypes[0].hRef;
9469 else
9470 base->datatype1 = -1;
9472 base->datatype2 = index; /* FIXME: i think there's more here */
9473 base->res18 = 0;
9474 base->res19 = -1;
9477 return size;
9480 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl *This, WMSFT_TLBFile *file, DWORD *junk)
9482 UINT i;
9484 file->typeinfo_seg.len = 0;
9485 for(i = 0; i < This->TypeInfoCount; ++i){
9486 ITypeInfoImpl *info = This->typeinfos[i];
9487 *junk = file->typeinfo_seg.len;
9488 ++junk;
9489 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, NULL, NULL);
9492 file->typeinfo_seg.data = heap_alloc(file->typeinfo_seg.len);
9493 memset(file->typeinfo_seg.data, 0x96, file->typeinfo_seg.len);
9495 file->aux_seg.len = 0;
9496 file->aux_seg.data = NULL;
9498 file->typeinfo_seg.len = 0;
9499 for(i = 0; i < This->TypeInfoCount; ++i){
9500 ITypeInfoImpl *info = This->typeinfos[i];
9501 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, file,
9502 ((char *)file->typeinfo_seg.data) + file->typeinfo_seg.len);
9506 typedef struct tagWMSFT_ImpFile {
9507 INT guid_offs;
9508 LCID lcid;
9509 DWORD version;
9510 } WMSFT_ImpFile;
9512 static void WMSFT_compile_impfile(ITypeLibImpl *This, WMSFT_TLBFile *file)
9514 TLBImpLib *implib;
9515 WMSFT_ImpFile *impfile;
9516 char *data;
9517 DWORD last_offs = 0;
9519 file->impfile_seg.len = 0;
9520 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9521 int size = 0;
9523 if(implib->name){
9524 WCHAR *path = strrchrW(implib->name, '\\');
9525 if(path)
9526 ++path;
9527 else
9528 path = implib->name;
9529 size = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path), NULL, 0, NULL, NULL);
9530 if (size == 0)
9531 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9534 size += sizeof(INT16);
9535 if (size % 4)
9536 size = (size + 4) & ~0x3;
9537 if (size < 8)
9538 size = 8;
9540 file->impfile_seg.len += sizeof(WMSFT_ImpFile) + size;
9543 data = file->impfile_seg.data = heap_alloc(file->impfile_seg.len);
9545 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9546 int strlen = 0, size;
9548 impfile = (WMSFT_ImpFile*)data;
9549 impfile->guid_offs = implib->guid->offset;
9550 impfile->lcid = implib->lcid;
9551 impfile->version = (implib->wVersionMinor << 16) | implib->wVersionMajor;
9553 data += sizeof(WMSFT_ImpFile);
9555 if(implib->name){
9556 WCHAR *path= strrchrW(implib->name, '\\');
9557 if(path)
9558 ++path;
9559 else
9560 path = implib->name;
9561 strlen = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path),
9562 data + sizeof(INT16), file->impfile_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9563 if (strlen == 0)
9564 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9567 *((INT16*)data) = (strlen << 2) | 1; /* FIXME: is that a flag, or what? */
9569 size = strlen + sizeof(INT16);
9570 if (size % 4)
9571 size = (size + 4) & ~0x3;
9572 if (size < 8)
9573 size = 8;
9574 memset(data + sizeof(INT16) + strlen, 0x57, size - strlen - sizeof(INT16));
9576 data += size;
9577 implib->offset = last_offs;
9578 last_offs += size + sizeof(WMSFT_ImpFile);
9582 static void WMSFT_compile_impinfo(ITypeLibImpl *This, WMSFT_TLBFile *file)
9584 MSFT_ImpInfo *info;
9585 TLBRefType *ref_type;
9586 UINT i = 0;
9588 WMSFT_compile_impfile(This, file);
9590 file->impinfo_seg.len = sizeof(MSFT_ImpInfo) * list_count(&This->ref_list);
9591 info = file->impinfo_seg.data = heap_alloc(file->impinfo_seg.len);
9593 LIST_FOR_EACH_ENTRY(ref_type, &This->ref_list, TLBRefType, entry){
9594 info->flags = i | ((ref_type->tkind & 0xFF) << 24);
9595 if(ref_type->index == TLB_REF_USE_GUID){
9596 info->flags |= MSFT_IMPINFO_OFFSET_IS_GUID;
9597 info->oGuid = ref_type->guid->offset;
9598 }else
9599 info->oGuid = ref_type->index;
9600 info->oImpFile = ref_type->pImpTLInfo->offset;
9601 ++i;
9602 ++info;
9606 static void WMSFT_compile_guidhash(ITypeLibImpl *This, WMSFT_TLBFile *file)
9608 file->guidhash_seg.len = 0x80;
9609 file->guidhash_seg.data = heap_alloc(file->guidhash_seg.len);
9610 memset(file->guidhash_seg.data, 0xFF, file->guidhash_seg.len);
9613 static void WMSFT_compile_namehash(ITypeLibImpl *This, WMSFT_TLBFile *file)
9615 file->namehash_seg.len = 0x200;
9616 file->namehash_seg.data = heap_alloc(file->namehash_seg.len);
9617 memset(file->namehash_seg.data, 0xFF, file->namehash_seg.len);
9620 static void tmp_fill_segdir_seg(MSFT_pSeg *segdir, WMSFT_SegContents *contents, DWORD *running_offset)
9622 if(contents && contents->len){
9623 segdir->offset = *running_offset;
9624 segdir->length = contents->len;
9625 *running_offset += segdir->length;
9626 }else{
9627 segdir->offset = -1;
9628 segdir->length = 0;
9631 /* TODO: do these ever change? */
9632 segdir->res08 = -1;
9633 segdir->res0c = 0xf;
9636 static void WMSFT_write_segment(HANDLE outfile, WMSFT_SegContents *segment)
9638 DWORD written;
9639 if(segment)
9640 WriteFile(outfile, segment->data, segment->len, &written, NULL);
9643 static HRESULT WMSFT_fixup_typeinfos(ITypeLibImpl *This, WMSFT_TLBFile *file,
9644 DWORD file_len)
9646 DWORD i;
9647 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase *)file->typeinfo_seg.data;
9649 for(i = 0; i < This->TypeInfoCount; ++i){
9650 base->memoffset += file_len;
9651 ++base;
9654 return S_OK;
9657 static void WMSFT_free_file(WMSFT_TLBFile *file)
9659 HeapFree(GetProcessHeap(), 0, file->typeinfo_seg.data);
9660 HeapFree(GetProcessHeap(), 0, file->guidhash_seg.data);
9661 HeapFree(GetProcessHeap(), 0, file->guid_seg.data);
9662 HeapFree(GetProcessHeap(), 0, file->ref_seg.data);
9663 HeapFree(GetProcessHeap(), 0, file->impinfo_seg.data);
9664 HeapFree(GetProcessHeap(), 0, file->impfile_seg.data);
9665 HeapFree(GetProcessHeap(), 0, file->namehash_seg.data);
9666 HeapFree(GetProcessHeap(), 0, file->name_seg.data);
9667 HeapFree(GetProcessHeap(), 0, file->string_seg.data);
9668 HeapFree(GetProcessHeap(), 0, file->typdesc_seg.data);
9669 HeapFree(GetProcessHeap(), 0, file->arraydesc_seg.data);
9670 HeapFree(GetProcessHeap(), 0, file->custdata_seg.data);
9671 HeapFree(GetProcessHeap(), 0, file->cdguids_seg.data);
9672 HeapFree(GetProcessHeap(), 0, file->aux_seg.data);
9675 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
9677 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9678 WMSFT_TLBFile file;
9679 DWORD written, junk_size, junk_offs, running_offset;
9680 BOOL br;
9681 HANDLE outfile;
9682 HRESULT hres;
9683 DWORD *junk;
9685 TRACE("%p\n", This);
9687 memset(&file, 0, sizeof(file));
9689 file.header.magic1 = 0x5446534D;
9690 file.header.magic2 = 0x00010002;
9691 file.header.lcid = This->set_lcid ? This->set_lcid : MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
9692 file.header.lcid2 = This->set_lcid;
9693 file.header.varflags = 0x41; /* TODO?? */
9694 if (This->HelpFile)
9695 file.header.varflags |= 0x10;
9696 if (This->HelpStringDll)
9697 file.header.varflags |= HELPDLLFLAG;
9698 file.header.version = (This->ver_major << 16) | This->ver_minor;
9699 file.header.flags = This->libflags;
9700 file.header.helpstringcontext = 0; /* TODO - SetHelpStringContext not implemented yet */
9701 file.header.helpcontext = This->dwHelpContext;
9702 file.header.res44 = 0x20;
9703 file.header.res48 = 0x80;
9704 file.header.dispatchpos = This->dispatch_href;
9706 WMSFT_compile_namehash(This, &file);
9707 /* do name and string compilation to get offsets for other compilations */
9708 hres = WMSFT_compile_names(This, &file);
9709 if (FAILED(hres)){
9710 WMSFT_free_file(&file);
9711 return hres;
9714 hres = WMSFT_compile_strings(This, &file);
9715 if (FAILED(hres)){
9716 WMSFT_free_file(&file);
9717 return hres;
9720 WMSFT_compile_guidhash(This, &file);
9721 hres = WMSFT_compile_guids(This, &file);
9722 if (FAILED(hres)){
9723 WMSFT_free_file(&file);
9724 return hres;
9727 if(This->HelpFile)
9728 file.header.helpfile = This->HelpFile->offset;
9729 else
9730 file.header.helpfile = -1;
9732 if(This->DocString)
9733 file.header.helpstring = This->DocString->offset;
9734 else
9735 file.header.helpstring = -1;
9737 /* do some more segment compilation */
9738 file.header.nimpinfos = list_count(&This->ref_list);
9739 file.header.nrtypeinfos = This->TypeInfoCount;
9741 if(This->Name)
9742 file.header.NameOffset = This->Name->offset;
9743 else
9744 file.header.NameOffset = -1;
9746 file.header.CustomDataOffset = -1; /* TODO SetCustData not impl yet */
9748 if(This->guid)
9749 file.header.posguid = This->guid->offset;
9750 else
9751 file.header.posguid = -1;
9753 junk_size = file.header.nrtypeinfos * sizeof(DWORD);
9754 if(file.header.varflags & HELPDLLFLAG)
9755 junk_size += sizeof(DWORD);
9756 if(junk_size){
9757 junk = heap_alloc_zero(junk_size);
9758 if(file.header.varflags & HELPDLLFLAG){
9759 *junk = This->HelpStringDll->offset;
9760 junk_offs = 1;
9761 }else
9762 junk_offs = 0;
9763 }else{
9764 junk = NULL;
9765 junk_offs = 0;
9768 WMSFT_compile_typeinfo_seg(This, &file, junk + junk_offs);
9769 WMSFT_compile_impinfo(This, &file);
9771 running_offset = 0;
9773 TRACE("header at: 0x%x\n", running_offset);
9774 running_offset += sizeof(file.header);
9776 TRACE("junk at: 0x%x\n", running_offset);
9777 running_offset += junk_size;
9779 TRACE("segdir at: 0x%x\n", running_offset);
9780 running_offset += sizeof(file.segdir);
9782 TRACE("typeinfo at: 0x%x\n", running_offset);
9783 tmp_fill_segdir_seg(&file.segdir.pTypeInfoTab, &file.typeinfo_seg, &running_offset);
9785 TRACE("guidhashtab at: 0x%x\n", running_offset);
9786 tmp_fill_segdir_seg(&file.segdir.pGuidHashTab, &file.guidhash_seg, &running_offset);
9788 TRACE("guidtab at: 0x%x\n", running_offset);
9789 tmp_fill_segdir_seg(&file.segdir.pGuidTab, &file.guid_seg, &running_offset);
9791 TRACE("reftab at: 0x%x\n", running_offset);
9792 tmp_fill_segdir_seg(&file.segdir.pRefTab, &file.ref_seg, &running_offset);
9794 TRACE("impinfo at: 0x%x\n", running_offset);
9795 tmp_fill_segdir_seg(&file.segdir.pImpInfo, &file.impinfo_seg, &running_offset);
9797 TRACE("impfiles at: 0x%x\n", running_offset);
9798 tmp_fill_segdir_seg(&file.segdir.pImpFiles, &file.impfile_seg, &running_offset);
9800 TRACE("namehashtab at: 0x%x\n", running_offset);
9801 tmp_fill_segdir_seg(&file.segdir.pNameHashTab, &file.namehash_seg, &running_offset);
9803 TRACE("nametab at: 0x%x\n", running_offset);
9804 tmp_fill_segdir_seg(&file.segdir.pNametab, &file.name_seg, &running_offset);
9806 TRACE("stringtab at: 0x%x\n", running_offset);
9807 tmp_fill_segdir_seg(&file.segdir.pStringtab, &file.string_seg, &running_offset);
9809 TRACE("typdesc at: 0x%x\n", running_offset);
9810 tmp_fill_segdir_seg(&file.segdir.pTypdescTab, &file.typdesc_seg, &running_offset);
9812 TRACE("arraydescriptions at: 0x%x\n", running_offset);
9813 tmp_fill_segdir_seg(&file.segdir.pArrayDescriptions, &file.arraydesc_seg, &running_offset);
9815 TRACE("custdata at: 0x%x\n", running_offset);
9816 tmp_fill_segdir_seg(&file.segdir.pCustData, &file.custdata_seg, &running_offset);
9818 TRACE("cdguids at: 0x%x\n", running_offset);
9819 tmp_fill_segdir_seg(&file.segdir.pCDGuids, &file.cdguids_seg, &running_offset);
9821 TRACE("res0e at: 0x%x\n", running_offset);
9822 tmp_fill_segdir_seg(&file.segdir.res0e, NULL, &running_offset);
9824 TRACE("res0f at: 0x%x\n", running_offset);
9825 tmp_fill_segdir_seg(&file.segdir.res0f, NULL, &running_offset);
9827 TRACE("aux_seg at: 0x%x\n", running_offset);
9829 WMSFT_fixup_typeinfos(This, &file, running_offset);
9831 outfile = CreateFileW(This->path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
9832 FILE_ATTRIBUTE_NORMAL, 0);
9833 if (outfile == INVALID_HANDLE_VALUE){
9834 WMSFT_free_file(&file);
9835 heap_free(junk);
9836 return TYPE_E_IOERROR;
9839 br = WriteFile(outfile, &file.header, sizeof(file.header), &written, NULL);
9840 if (!br) {
9841 WMSFT_free_file(&file);
9842 CloseHandle(outfile);
9843 heap_free(junk);
9844 return TYPE_E_IOERROR;
9847 br = WriteFile(outfile, junk, junk_size, &written, NULL);
9848 heap_free(junk);
9849 if (!br) {
9850 WMSFT_free_file(&file);
9851 CloseHandle(outfile);
9852 return TYPE_E_IOERROR;
9855 br = WriteFile(outfile, &file.segdir, sizeof(file.segdir), &written, NULL);
9856 if (!br) {
9857 WMSFT_free_file(&file);
9858 CloseHandle(outfile);
9859 return TYPE_E_IOERROR;
9862 WMSFT_write_segment(outfile, &file.typeinfo_seg);
9863 WMSFT_write_segment(outfile, &file.guidhash_seg);
9864 WMSFT_write_segment(outfile, &file.guid_seg);
9865 WMSFT_write_segment(outfile, &file.ref_seg);
9866 WMSFT_write_segment(outfile, &file.impinfo_seg);
9867 WMSFT_write_segment(outfile, &file.impfile_seg);
9868 WMSFT_write_segment(outfile, &file.namehash_seg);
9869 WMSFT_write_segment(outfile, &file.name_seg);
9870 WMSFT_write_segment(outfile, &file.string_seg);
9871 WMSFT_write_segment(outfile, &file.typdesc_seg);
9872 WMSFT_write_segment(outfile, &file.arraydesc_seg);
9873 WMSFT_write_segment(outfile, &file.custdata_seg);
9874 WMSFT_write_segment(outfile, &file.cdguids_seg);
9875 WMSFT_write_segment(outfile, &file.aux_seg);
9877 WMSFT_free_file(&file);
9879 CloseHandle(outfile);
9881 return S_OK;
9884 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
9885 LPOLESTR name)
9887 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9888 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
9889 return E_NOTIMPL;
9892 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
9893 REFGUID guid, VARIANT *varVal)
9895 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9896 FIXME("%p %s %p - stub\n", This, debugstr_guid(guid), varVal);
9897 return E_NOTIMPL;
9900 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
9901 ULONG helpStringContext)
9903 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9904 FIXME("%p %u - stub\n", This, helpStringContext);
9905 return E_NOTIMPL;
9908 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
9909 LPOLESTR filename)
9911 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9912 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
9914 if (!filename)
9915 return E_INVALIDARG;
9917 This->HelpStringDll = TLB_append_str(&This->string_list, filename);
9919 return S_OK;
9922 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
9923 ICreateTypeLib2_fnQueryInterface,
9924 ICreateTypeLib2_fnAddRef,
9925 ICreateTypeLib2_fnRelease,
9926 ICreateTypeLib2_fnCreateTypeInfo,
9927 ICreateTypeLib2_fnSetName,
9928 ICreateTypeLib2_fnSetVersion,
9929 ICreateTypeLib2_fnSetGuid,
9930 ICreateTypeLib2_fnSetDocString,
9931 ICreateTypeLib2_fnSetHelpFileName,
9932 ICreateTypeLib2_fnSetHelpContext,
9933 ICreateTypeLib2_fnSetLcid,
9934 ICreateTypeLib2_fnSetLibFlags,
9935 ICreateTypeLib2_fnSaveAllChanges,
9936 ICreateTypeLib2_fnDeleteTypeInfo,
9937 ICreateTypeLib2_fnSetCustData,
9938 ICreateTypeLib2_fnSetHelpStringContext,
9939 ICreateTypeLib2_fnSetHelpStringDll
9942 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
9943 REFIID riid, void **object)
9945 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9947 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, object);
9950 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
9952 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9954 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
9957 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
9959 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9961 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
9964 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
9965 REFGUID guid)
9967 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9969 TRACE("%p %s\n", This, debugstr_guid(guid));
9971 This->guid = TLB_append_guid(&This->pTypeLib->guid_list, guid, This->hreftype);
9973 return S_OK;
9976 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
9977 UINT typeFlags)
9979 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9980 WORD old_flags;
9981 HRESULT hres;
9983 TRACE("%p %x\n", This, typeFlags);
9985 if (typeFlags & TYPEFLAG_FDUAL) {
9986 static const WCHAR stdole2tlb[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
9987 ITypeLib *stdole;
9988 ITypeInfo *dispatch;
9989 HREFTYPE hreftype;
9990 HRESULT hres;
9992 hres = LoadTypeLib(stdole2tlb, &stdole);
9993 if(FAILED(hres))
9994 return hres;
9996 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
9997 ITypeLib_Release(stdole);
9998 if(FAILED(hres))
9999 return hres;
10001 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
10002 ITypeInfo_Release(dispatch);
10003 if(FAILED(hres))
10004 return hres;
10007 old_flags = This->wTypeFlags;
10008 This->wTypeFlags = typeFlags;
10010 hres = ICreateTypeInfo2_LayOut(iface);
10011 if (FAILED(hres)) {
10012 This->wTypeFlags = old_flags;
10013 return hres;
10016 return S_OK;
10019 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
10020 LPOLESTR doc)
10022 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10024 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
10026 if (!doc)
10027 return E_INVALIDARG;
10029 This->DocString = TLB_append_str(&This->pTypeLib->string_list, doc);
10031 return S_OK;
10034 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
10035 DWORD helpContext)
10037 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10039 TRACE("%p %d\n", This, helpContext);
10041 This->dwHelpContext = helpContext;
10043 return S_OK;
10046 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
10047 WORD majorVerNum, WORD minorVerNum)
10049 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10051 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
10053 This->wMajorVerNum = majorVerNum;
10054 This->wMinorVerNum = minorVerNum;
10056 return S_OK;
10059 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
10060 ITypeInfo *typeInfo, HREFTYPE *refType)
10062 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10063 UINT index;
10064 ITypeLib *container;
10065 TLBRefType *ref_type;
10066 TLBImpLib *implib;
10067 TYPEATTR *typeattr;
10068 TLIBATTR *libattr;
10069 HRESULT hres;
10071 TRACE("%p %p %p\n", This, typeInfo, refType);
10073 if (!typeInfo || !refType)
10074 return E_INVALIDARG;
10076 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
10077 if (FAILED(hres))
10078 return hres;
10080 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
10081 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
10083 ITypeLib_Release(container);
10085 *refType = target->hreftype;
10087 return S_OK;
10090 hres = ITypeLib_GetLibAttr(container, &libattr);
10091 if (FAILED(hres)) {
10092 ITypeLib_Release(container);
10093 return hres;
10096 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
10097 if(IsEqualGUID(&implib->guid->guid, &libattr->guid) &&
10098 implib->lcid == libattr->lcid &&
10099 implib->wVersionMajor == libattr->wMajorVerNum &&
10100 implib->wVersionMinor == libattr->wMinorVerNum)
10101 break;
10104 if(&implib->entry == &This->pTypeLib->implib_list){
10105 implib = heap_alloc_zero(sizeof(TLBImpLib));
10107 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
10108 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
10109 implib->name = SysAllocString(our_container->path);
10110 }else{
10111 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
10112 libattr->wMinorVerNum, libattr->lcid, &implib->name);
10113 if(FAILED(hres)){
10114 implib->name = NULL;
10115 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres);
10119 implib->guid = TLB_append_guid(&This->pTypeLib->guid_list, &libattr->guid, 2);
10120 implib->lcid = libattr->lcid;
10121 implib->wVersionMajor = libattr->wMajorVerNum;
10122 implib->wVersionMinor = libattr->wMinorVerNum;
10124 list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
10127 ITypeLib_ReleaseTLibAttr(container, libattr);
10128 ITypeLib_Release(container);
10130 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
10131 if (FAILED(hres))
10132 return hres;
10134 index = 0;
10135 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
10136 if(ref_type->index == TLB_REF_USE_GUID &&
10137 IsEqualGUID(&ref_type->guid->guid, &typeattr->guid) &&
10138 ref_type->tkind == typeattr->typekind)
10139 break;
10140 ++index;
10143 if(&ref_type->entry == &This->pTypeLib->ref_list){
10144 ref_type = heap_alloc_zero(sizeof(TLBRefType));
10146 ref_type->tkind = typeattr->typekind;
10147 ref_type->pImpTLInfo = implib;
10148 ref_type->reference = index * sizeof(MSFT_ImpInfo);
10150 ref_type->index = TLB_REF_USE_GUID;
10152 ref_type->guid = TLB_append_guid(&This->pTypeLib->guid_list, &typeattr->guid, ref_type->reference+1);
10154 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
10157 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
10159 *refType = ref_type->reference | 0x1;
10161 if(IsEqualGUID(&ref_type->guid->guid, &IID_IDispatch))
10162 This->pTypeLib->dispatch_href = *refType;
10164 return S_OK;
10167 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
10168 UINT index, FUNCDESC *funcDesc)
10170 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10171 TLBFuncDesc tmp_func_desc, *func_desc;
10172 int buf_size, i;
10173 char *buffer;
10174 HRESULT hres;
10176 TRACE("%p %u %p\n", This, index, funcDesc);
10178 if (!funcDesc || funcDesc->oVft & 3)
10179 return E_INVALIDARG;
10181 switch (This->typekind) {
10182 case TKIND_MODULE:
10183 if (funcDesc->funckind != FUNC_STATIC)
10184 return TYPE_E_BADMODULEKIND;
10185 break;
10186 case TKIND_DISPATCH:
10187 if (funcDesc->funckind != FUNC_DISPATCH)
10188 return TYPE_E_BADMODULEKIND;
10189 break;
10190 default:
10191 if (funcDesc->funckind != FUNC_PUREVIRTUAL)
10192 return TYPE_E_BADMODULEKIND;
10195 if (index > This->cFuncs)
10196 return TYPE_E_ELEMENTNOTFOUND;
10198 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) &&
10199 !funcDesc->cParams)
10200 return TYPE_E_INCONSISTENTPROPFUNCS;
10202 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc));
10203 TLBFuncDesc_Constructor(&tmp_func_desc);
10205 tmp_func_desc.funcdesc = *funcDesc;
10207 if (tmp_func_desc.funcdesc.oVft != 0)
10208 tmp_func_desc.funcdesc.oVft |= 1;
10210 if (funcDesc->cScodes) {
10211 tmp_func_desc.funcdesc.lprgscode = heap_alloc(sizeof(SCODE) * funcDesc->cScodes);
10212 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes);
10213 } else
10214 tmp_func_desc.funcdesc.lprgscode = NULL;
10216 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc);
10217 for (i = 0; i < funcDesc->cParams; ++i) {
10218 buf_size += sizeof(ELEMDESC);
10219 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i);
10221 tmp_func_desc.funcdesc.lprgelemdescParam = heap_alloc(buf_size);
10222 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams);
10224 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer);
10225 if (FAILED(hres)) {
10226 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10227 heap_free(tmp_func_desc.funcdesc.lprgscode);
10228 return hres;
10231 for (i = 0; i < funcDesc->cParams; ++i) {
10232 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i,
10233 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer);
10234 if (FAILED(hres)) {
10235 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10236 heap_free(tmp_func_desc.funcdesc.lprgscode);
10237 return hres;
10239 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT &&
10240 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT &&
10241 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){
10242 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
10243 if (FAILED(hres)) {
10244 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10245 heap_free(tmp_func_desc.funcdesc.lprgscode);
10246 return hres;
10251 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams);
10253 if (This->funcdescs) {
10254 This->funcdescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->funcdescs,
10255 sizeof(TLBFuncDesc) * (This->cFuncs + 1));
10257 if (index < This->cFuncs) {
10258 memmove(This->funcdescs + index + 1, This->funcdescs + index,
10259 (This->cFuncs - index) * sizeof(TLBFuncDesc));
10260 func_desc = This->funcdescs + index;
10261 } else
10262 func_desc = This->funcdescs + This->cFuncs;
10264 /* move custdata lists to the new memory location */
10265 for(i = 0; i < This->cFuncs + 1; ++i){
10266 if(index != i){
10267 TLBFuncDesc *fd = &This->funcdescs[i];
10268 if(fd->custdata_list.prev == fd->custdata_list.next)
10269 list_init(&fd->custdata_list);
10270 else{
10271 fd->custdata_list.prev->next = &fd->custdata_list;
10272 fd->custdata_list.next->prev = &fd->custdata_list;
10276 } else
10277 func_desc = This->funcdescs = heap_alloc(sizeof(TLBFuncDesc));
10279 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc));
10280 list_init(&func_desc->custdata_list);
10282 ++This->cFuncs;
10284 This->needs_layout = TRUE;
10286 return S_OK;
10289 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
10290 UINT index, HREFTYPE refType)
10292 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10293 TLBImplType *impl_type;
10294 HRESULT hres;
10296 TRACE("%p %u %d\n", This, index, refType);
10298 switch(This->typekind){
10299 case TKIND_COCLASS: {
10300 if (index == -1) {
10301 FIXME("Unhandled index: -1\n");
10302 return E_NOTIMPL;
10305 if(index != This->cImplTypes)
10306 return TYPE_E_ELEMENTNOTFOUND;
10308 break;
10310 case TKIND_INTERFACE:
10311 case TKIND_DISPATCH:
10312 if (index != 0 || This->cImplTypes)
10313 return TYPE_E_ELEMENTNOTFOUND;
10314 break;
10315 default:
10316 FIXME("Unimplemented typekind: %d\n", This->typekind);
10317 return E_NOTIMPL;
10320 if (This->impltypes){
10321 UINT i;
10323 This->impltypes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->impltypes,
10324 sizeof(TLBImplType) * (This->cImplTypes + 1));
10326 if (index < This->cImplTypes) {
10327 memmove(This->impltypes + index + 1, This->impltypes + index,
10328 (This->cImplTypes - index) * sizeof(TLBImplType));
10329 impl_type = This->impltypes + index;
10330 } else
10331 impl_type = This->impltypes + This->cImplTypes;
10333 /* move custdata lists to the new memory location */
10334 for(i = 0; i < This->cImplTypes + 1; ++i){
10335 if(index != i){
10336 TLBImplType *it = &This->impltypes[i];
10337 if(it->custdata_list.prev == it->custdata_list.next)
10338 list_init(&it->custdata_list);
10339 else{
10340 it->custdata_list.prev->next = &it->custdata_list;
10341 it->custdata_list.next->prev = &it->custdata_list;
10345 } else
10346 impl_type = This->impltypes = heap_alloc(sizeof(TLBImplType));
10348 memset(impl_type, 0, sizeof(TLBImplType));
10349 TLBImplType_Constructor(impl_type);
10350 impl_type->hRef = refType;
10352 ++This->cImplTypes;
10354 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
10355 This->wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
10357 hres = ICreateTypeInfo2_LayOut(iface);
10358 if (FAILED(hres))
10359 return hres;
10361 return S_OK;
10364 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
10365 UINT index, INT implTypeFlags)
10367 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10368 TLBImplType *impl_type = &This->impltypes[index];
10370 TRACE("%p %u %x\n", This, index, implTypeFlags);
10372 if (This->typekind != TKIND_COCLASS)
10373 return TYPE_E_BADMODULEKIND;
10375 if (index >= This->cImplTypes)
10376 return TYPE_E_ELEMENTNOTFOUND;
10378 impl_type->implflags = implTypeFlags;
10380 return S_OK;
10383 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
10384 WORD alignment)
10386 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10388 TRACE("%p %d\n", This, alignment);
10390 This->cbAlignment = alignment;
10392 return S_OK;
10395 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
10396 LPOLESTR schema)
10398 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10400 TRACE("%p %s\n", This, wine_dbgstr_w(schema));
10402 if (!schema)
10403 return E_INVALIDARG;
10405 This->Schema = TLB_append_str(&This->pTypeLib->string_list, schema);
10407 This->lpstrSchema = This->Schema->str;
10409 return S_OK;
10412 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
10413 UINT index, VARDESC *varDesc)
10415 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10416 TLBVarDesc *var_desc;
10418 TRACE("%p %u %p\n", This, index, varDesc);
10420 if (This->vardescs){
10421 UINT i;
10423 This->vardescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->vardescs,
10424 sizeof(TLBVarDesc) * (This->cVars + 1));
10426 if (index < This->cVars) {
10427 memmove(This->vardescs + index + 1, This->vardescs + index,
10428 (This->cVars - index) * sizeof(TLBVarDesc));
10429 var_desc = This->vardescs + index;
10430 } else
10431 var_desc = This->vardescs + This->cVars;
10433 /* move custdata lists to the new memory location */
10434 for(i = 0; i < This->cVars + 1; ++i){
10435 if(index != i){
10436 TLBVarDesc *var = &This->vardescs[i];
10437 if(var->custdata_list.prev == var->custdata_list.next)
10438 list_init(&var->custdata_list);
10439 else{
10440 var->custdata_list.prev->next = &var->custdata_list;
10441 var->custdata_list.next->prev = &var->custdata_list;
10445 } else
10446 var_desc = This->vardescs = heap_alloc_zero(sizeof(TLBVarDesc));
10448 TLBVarDesc_Constructor(var_desc);
10449 TLB_AllocAndInitVarDesc(varDesc, &var_desc->vardesc_create);
10450 var_desc->vardesc = *var_desc->vardesc_create;
10452 ++This->cVars;
10454 This->needs_layout = TRUE;
10456 return S_OK;
10459 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
10460 UINT index, LPOLESTR *names, UINT numNames)
10462 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10463 TLBFuncDesc *func_desc = &This->funcdescs[index];
10464 int i;
10466 TRACE("%p %u %p %u\n", This, index, names, numNames);
10468 if (!names)
10469 return E_INVALIDARG;
10471 if (index >= This->cFuncs || numNames == 0)
10472 return TYPE_E_ELEMENTNOTFOUND;
10474 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){
10475 if(numNames > func_desc->funcdesc.cParams)
10476 return TYPE_E_ELEMENTNOTFOUND;
10477 } else
10478 if(numNames > func_desc->funcdesc.cParams + 1)
10479 return TYPE_E_ELEMENTNOTFOUND;
10481 for(i = 0; i < This->cFuncs; ++i) {
10482 TLBFuncDesc *iter = &This->funcdescs[i];
10483 if (iter->Name && !strcmpW(TLB_get_bstr(iter->Name), *names)) {
10484 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10485 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10486 func_desc->funcdesc.invkind != iter->funcdesc.invkind)
10487 continue;
10488 return TYPE_E_AMBIGUOUSNAME;
10492 func_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *names);
10494 for (i = 1; i < numNames; ++i) {
10495 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1;
10496 par_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *(names + i));
10499 return S_OK;
10502 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
10503 UINT index, LPOLESTR name)
10505 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10506 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(name));
10507 return E_NOTIMPL;
10510 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
10511 TYPEDESC *tdescAlias)
10513 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10514 FIXME("%p %p - stub\n", This, tdescAlias);
10515 return E_NOTIMPL;
10518 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
10519 UINT index, LPOLESTR dllName, LPOLESTR procName)
10521 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10522 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
10523 return E_NOTIMPL;
10526 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
10527 UINT index, LPOLESTR docString)
10529 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10530 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(docString));
10531 return E_NOTIMPL;
10534 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
10535 UINT index, LPOLESTR docString)
10537 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10538 TLBVarDesc *var_desc = &This->vardescs[index];
10540 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10542 if(!docString)
10543 return E_INVALIDARG;
10545 if(index >= This->cVars)
10546 return TYPE_E_ELEMENTNOTFOUND;
10548 var_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10550 return S_OK;
10553 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
10554 UINT index, DWORD helpContext)
10556 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10557 TLBFuncDesc *func_desc = &This->funcdescs[index];
10559 TRACE("%p %u %d\n", This, index, helpContext);
10561 if(index >= This->cFuncs)
10562 return TYPE_E_ELEMENTNOTFOUND;
10564 func_desc->helpcontext = helpContext;
10566 return S_OK;
10569 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
10570 UINT index, DWORD helpContext)
10572 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10573 TLBVarDesc *var_desc = &This->vardescs[index];
10575 TRACE("%p %u %d\n", This, index, helpContext);
10577 if(index >= This->cVars)
10578 return TYPE_E_ELEMENTNOTFOUND;
10580 var_desc->HelpContext = helpContext;
10582 return S_OK;
10585 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
10586 UINT index, BSTR bstrMops)
10588 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10589 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
10590 return E_NOTIMPL;
10593 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
10594 IDLDESC *idlDesc)
10596 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10598 TRACE("%p %p\n", This, idlDesc);
10600 if (!idlDesc)
10601 return E_INVALIDARG;
10603 This->idldescType.dwReserved = idlDesc->dwReserved;
10604 This->idldescType.wIDLFlags = idlDesc->wIDLFlags;
10606 return S_OK;
10609 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
10611 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10612 ITypeInfo *tinfo;
10613 TLBFuncDesc *func_desc;
10614 UINT user_vft = 0, i, depth = 0;
10615 HRESULT hres = S_OK;
10617 TRACE("%p\n", This);
10619 This->needs_layout = FALSE;
10621 hres = ICreateTypeInfo2_QueryInterface(iface, &IID_ITypeInfo, (LPVOID*)&tinfo);
10622 if (FAILED(hres))
10623 return hres;
10625 if (This->typekind == TKIND_INTERFACE) {
10626 ITypeInfo *inh;
10627 TYPEATTR *attr;
10628 HREFTYPE inh_href;
10630 hres = ITypeInfo_GetRefTypeOfImplType(tinfo, 0, &inh_href);
10632 if (SUCCEEDED(hres)) {
10633 hres = ITypeInfo_GetRefTypeInfo(tinfo, inh_href, &inh);
10635 if (SUCCEEDED(hres)) {
10636 hres = ITypeInfo_GetTypeAttr(inh, &attr);
10637 if (FAILED(hres)) {
10638 ITypeInfo_Release(inh);
10639 ITypeInfo_Release(tinfo);
10640 return hres;
10642 This->cbSizeVft = attr->cbSizeVft;
10643 ITypeInfo_ReleaseTypeAttr(inh, attr);
10646 ++depth;
10647 hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href);
10648 if(SUCCEEDED(hres)){
10649 ITypeInfo *next;
10650 hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next);
10651 if(SUCCEEDED(hres)){
10652 ITypeInfo_Release(inh);
10653 inh = next;
10656 }while(SUCCEEDED(hres));
10657 hres = S_OK;
10659 ITypeInfo_Release(inh);
10660 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10661 This->cbSizeVft = 0;
10662 hres = S_OK;
10663 } else {
10664 ITypeInfo_Release(tinfo);
10665 return hres;
10667 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10668 This->cbSizeVft = 0;
10669 hres = S_OK;
10670 } else {
10671 ITypeInfo_Release(tinfo);
10672 return hres;
10674 } else if (This->typekind == TKIND_DISPATCH)
10675 This->cbSizeVft = 7 * This->pTypeLib->ptr_size;
10676 else
10677 This->cbSizeVft = 0;
10679 func_desc = This->funcdescs;
10680 i = 0;
10681 while (i < This->cFuncs) {
10682 if (!(func_desc->funcdesc.oVft & 0x1))
10683 func_desc->funcdesc.oVft = This->cbSizeVft;
10685 if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft)
10686 user_vft = func_desc->funcdesc.oVft & 0xFFFC;
10688 This->cbSizeVft += This->pTypeLib->ptr_size;
10690 if (func_desc->funcdesc.memid == MEMBERID_NIL) {
10691 TLBFuncDesc *iter;
10692 UINT j = 0;
10693 BOOL reset = FALSE;
10695 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i;
10697 iter = This->funcdescs;
10698 while (j < This->cFuncs) {
10699 if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) {
10700 if (!reset) {
10701 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->cFuncs;
10702 reset = TRUE;
10703 } else
10704 ++func_desc->funcdesc.memid;
10705 iter = This->funcdescs;
10706 j = 0;
10707 } else {
10708 ++iter;
10709 ++j;
10714 ++func_desc;
10715 ++i;
10718 if (user_vft > This->cbSizeVft)
10719 This->cbSizeVft = user_vft + This->pTypeLib->ptr_size;
10721 ITypeInfo_Release(tinfo);
10722 return hres;
10725 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
10726 UINT index)
10728 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10729 FIXME("%p %u - stub\n", This, index);
10730 return E_NOTIMPL;
10733 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
10734 MEMBERID memid, INVOKEKIND invKind)
10736 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10737 FIXME("%p %x %d - stub\n", This, memid, invKind);
10738 return E_NOTIMPL;
10741 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
10742 UINT index)
10744 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10745 FIXME("%p %u - stub\n", This, index);
10746 return E_NOTIMPL;
10749 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
10750 MEMBERID memid)
10752 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10753 FIXME("%p %x - stub\n", This, memid);
10754 return E_NOTIMPL;
10757 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
10758 UINT index)
10760 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10761 FIXME("%p %u - stub\n", This, index);
10762 return E_NOTIMPL;
10765 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
10766 REFGUID guid, VARIANT *varVal)
10768 TLBGuid *tlbguid;
10770 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10772 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
10774 if (!guid || !varVal)
10775 return E_INVALIDARG;
10777 tlbguid = TLB_append_guid(&This->pTypeLib->guid_list, guid, -1);
10779 return TLB_set_custdata(This->pcustdata_list, tlbguid, varVal);
10782 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
10783 UINT index, REFGUID guid, VARIANT *varVal)
10785 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10786 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
10787 return E_NOTIMPL;
10790 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
10791 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
10793 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10794 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
10795 return E_NOTIMPL;
10798 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
10799 UINT index, REFGUID guid, VARIANT *varVal)
10801 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10802 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
10803 return E_NOTIMPL;
10806 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
10807 UINT index, REFGUID guid, VARIANT *varVal)
10809 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10810 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
10811 return E_NOTIMPL;
10814 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
10815 ULONG helpStringContext)
10817 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10819 TRACE("%p %u\n", This, helpStringContext);
10821 This->dwHelpStringContext = helpStringContext;
10823 return S_OK;
10826 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
10827 UINT index, ULONG helpStringContext)
10829 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10830 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
10831 return E_NOTIMPL;
10834 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
10835 UINT index, ULONG helpStringContext)
10837 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10838 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
10839 return E_NOTIMPL;
10842 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
10844 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10845 FIXME("%p - stub\n", This);
10846 return E_NOTIMPL;
10849 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
10850 LPOLESTR name)
10852 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10854 TRACE("%p %s\n", This, wine_dbgstr_w(name));
10856 if (!name)
10857 return E_INVALIDARG;
10859 This->Name = TLB_append_str(&This->pTypeLib->name_list, name);
10861 return S_OK;
10864 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
10865 ICreateTypeInfo2_fnQueryInterface,
10866 ICreateTypeInfo2_fnAddRef,
10867 ICreateTypeInfo2_fnRelease,
10868 ICreateTypeInfo2_fnSetGuid,
10869 ICreateTypeInfo2_fnSetTypeFlags,
10870 ICreateTypeInfo2_fnSetDocString,
10871 ICreateTypeInfo2_fnSetHelpContext,
10872 ICreateTypeInfo2_fnSetVersion,
10873 ICreateTypeInfo2_fnAddRefTypeInfo,
10874 ICreateTypeInfo2_fnAddFuncDesc,
10875 ICreateTypeInfo2_fnAddImplType,
10876 ICreateTypeInfo2_fnSetImplTypeFlags,
10877 ICreateTypeInfo2_fnSetAlignment,
10878 ICreateTypeInfo2_fnSetSchema,
10879 ICreateTypeInfo2_fnAddVarDesc,
10880 ICreateTypeInfo2_fnSetFuncAndParamNames,
10881 ICreateTypeInfo2_fnSetVarName,
10882 ICreateTypeInfo2_fnSetTypeDescAlias,
10883 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
10884 ICreateTypeInfo2_fnSetFuncDocString,
10885 ICreateTypeInfo2_fnSetVarDocString,
10886 ICreateTypeInfo2_fnSetFuncHelpContext,
10887 ICreateTypeInfo2_fnSetVarHelpContext,
10888 ICreateTypeInfo2_fnSetMops,
10889 ICreateTypeInfo2_fnSetTypeIdldesc,
10890 ICreateTypeInfo2_fnLayOut,
10891 ICreateTypeInfo2_fnDeleteFuncDesc,
10892 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
10893 ICreateTypeInfo2_fnDeleteVarDesc,
10894 ICreateTypeInfo2_fnDeleteVarDescByMemId,
10895 ICreateTypeInfo2_fnDeleteImplType,
10896 ICreateTypeInfo2_fnSetCustData,
10897 ICreateTypeInfo2_fnSetFuncCustData,
10898 ICreateTypeInfo2_fnSetParamCustData,
10899 ICreateTypeInfo2_fnSetVarCustData,
10900 ICreateTypeInfo2_fnSetImplTypeCustData,
10901 ICreateTypeInfo2_fnSetHelpStringContext,
10902 ICreateTypeInfo2_fnSetFuncHelpStringContext,
10903 ICreateTypeInfo2_fnSetVarHelpStringContext,
10904 ICreateTypeInfo2_fnInvalidate,
10905 ICreateTypeInfo2_fnSetName
10908 /******************************************************************************
10909 * ClearCustData (OLEAUT32.171)
10911 * Clear a custom data type's data.
10913 * PARAMS
10914 * lpCust [I] The custom data type instance
10916 * RETURNS
10917 * Nothing.
10919 void WINAPI ClearCustData(CUSTDATA *lpCust)
10921 if (lpCust && lpCust->cCustData)
10923 if (lpCust->prgCustData)
10925 DWORD i;
10927 for (i = 0; i < lpCust->cCustData; i++)
10928 VariantClear(&lpCust->prgCustData[i].varValue);
10930 /* FIXME - Should be using a per-thread IMalloc */
10931 heap_free(lpCust->prgCustData);
10932 lpCust->prgCustData = NULL;
10934 lpCust->cCustData = 0;