push bc3e5bf5ba806943a97979264a1f2e4a4dde5c94
[wine/hacks.git] / dlls / oleaut32 / typelib.c
blobbf8673dfd9f46dadfcf4ec474f1f3ba193e55904
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 * 2005 Robert Shearman, for CodeWeavers
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 * --------------------------------------------------------------------------------------
25 * Known problems (2000, Francois Jacques)
27 * - Tested using OLEVIEW (Platform SDK tool) only.
29 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
30 * creating by doing a straight copy of the dispinterface instance and just changing
31 * its typekind. Pointed structures aren't copied - only the address of the pointers.
33 * - locale stuff is partially implemented but hasn't been tested.
35 * - typelib file is still read in its entirety, but it is released now.
37 * --------------------------------------------------------------------------------------
38 * Known problems left from previous implementation (1999, Rein Klazes) :
40 * -. Data structures are straightforward, but slow for look-ups.
41 * -. (related) nothing is hashed
42 * -. Most error return values are just guessed not checked with windows
43 * behaviour.
44 * -. lousy fatal error handling
48 #include "config.h"
49 #include "wine/port.h"
51 #include <stdlib.h>
52 #include <string.h>
53 #include <stdarg.h>
54 #include <stdio.h>
55 #include <ctype.h>
57 #define COBJMACROS
58 #define NONAMELESSUNION
59 #define NONAMELESSSTRUCT
61 #include "winerror.h"
62 #include "windef.h"
63 #include "winbase.h"
64 #include "winnls.h"
65 #include "winreg.h"
66 #include "winuser.h"
68 #include "wine/unicode.h"
69 #include "objbase.h"
70 #include "typelib.h"
71 #include "wine/debug.h"
72 #include "variant.h"
73 #include "wine/list.h"
75 WINE_DEFAULT_DEBUG_CHANNEL(ole);
76 WINE_DECLARE_DEBUG_CHANNEL(typelib);
78 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
79 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
81 /****************************************************************************
82 * FromLExxx
84 * Takes p_iVal (which is in little endian) and returns it
85 * in the host machine's byte order.
87 #ifdef WORDS_BIGENDIAN
88 static WORD FromLEWord(WORD p_iVal)
90 return (((p_iVal & 0x00FF) << 8) |
91 ((p_iVal & 0xFF00) >> 8));
95 static DWORD FromLEDWord(DWORD p_iVal)
97 return (((p_iVal & 0x000000FF) << 24) |
98 ((p_iVal & 0x0000FF00) << 8) |
99 ((p_iVal & 0x00FF0000) >> 8) |
100 ((p_iVal & 0xFF000000) >> 24));
102 #else
103 #define FromLEWord(X) (X)
104 #define FromLEDWord(X) (X)
105 #endif
107 #define DISPATCH_HREF_OFFSET 0x01000000
108 #define DISPATCH_HREF_MASK 0xff000000
110 /****************************************************************************
111 * FromLExxx
113 * Fix byte order in any structure if necessary
115 #ifdef WORDS_BIGENDIAN
116 static void FromLEWords(void *p_Val, int p_iSize)
118 WORD *Val = p_Val;
120 p_iSize /= sizeof(WORD);
122 while (p_iSize) {
123 *Val = FromLEWord(*Val);
124 Val++;
125 p_iSize--;
130 static void FromLEDWords(void *p_Val, int p_iSize)
132 DWORD *Val = p_Val;
134 p_iSize /= sizeof(DWORD);
136 while (p_iSize) {
137 *Val = FromLEDWord(*Val);
138 Val++;
139 p_iSize--;
142 #else
143 #define FromLEWords(X,Y) /*nothing*/
144 #define FromLEDWords(X,Y) /*nothing*/
145 #endif
148 * Find a typelib key which matches a requested maj.min version.
150 static BOOL find_typelib_key( REFGUID guid, WORD wMaj, WORD *wMin )
152 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
153 WCHAR buffer[60];
154 char key_name[16];
155 DWORD len, i;
156 INT best_min = -1;
157 HKEY hkey;
159 memcpy( buffer, typelibW, sizeof(typelibW) );
160 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
162 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
163 return FALSE;
165 len = sizeof(key_name);
166 i = 0;
167 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
169 INT v_maj, v_min;
171 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
173 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
175 if (wMaj == v_maj)
177 if (*wMin == v_min)
179 best_min = v_min;
180 break; /* exact match */
182 if (v_min > best_min) best_min = v_min;
185 len = sizeof(key_name);
187 RegCloseKey( hkey );
188 if (best_min >= 0)
190 *wMin = best_min;
191 return TRUE;
193 return FALSE;
196 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
197 /* buffer must be at least 60 characters long */
198 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
200 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
201 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
203 memcpy( buffer, TypelibW, sizeof(TypelibW) );
204 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
205 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
206 return buffer;
209 /* get the path of an interface key, in the form "Interface\\<guid>" */
210 /* buffer must be at least 50 characters long */
211 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
213 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
215 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
216 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
217 return buffer;
220 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
221 /* buffer must be at least 16 characters long */
222 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
224 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
225 static const WCHAR win16W[] = {'w','i','n','1','6',0};
226 static const WCHAR win32W[] = {'w','i','n','3','2',0};
228 sprintfW( buffer, LcidFormatW, lcid );
229 switch(syskind)
231 case SYS_WIN16: strcatW( buffer, win16W ); break;
232 case SYS_WIN32: strcatW( buffer, win32W ); break;
233 default:
234 TRACE("Typelib is for unsupported syskind %i\n", syskind);
235 return NULL;
237 return buffer;
240 static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
243 /****************************************************************************
244 * QueryPathOfRegTypeLib [OLEAUT32.164]
246 * Gets the path to a registered type library.
248 * PARAMS
249 * guid [I] referenced guid
250 * wMaj [I] major version
251 * wMin [I] minor version
252 * lcid [I] locale id
253 * path [O] path of typelib
255 * RETURNS
256 * Success: S_OK.
257 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
258 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
259 * opened.
261 HRESULT WINAPI QueryPathOfRegTypeLib(
262 REFGUID guid,
263 WORD wMaj,
264 WORD wMin,
265 LCID lcid,
266 LPBSTR path )
268 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
269 LCID myLCID = lcid;
270 HKEY hkey;
271 WCHAR buffer[60];
272 WCHAR Path[MAX_PATH];
273 LONG res;
275 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
277 if (!find_typelib_key( guid, wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
278 get_typelib_key( guid, wMaj, wMin, buffer );
280 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
281 if (res == ERROR_FILE_NOT_FOUND)
283 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
284 return TYPE_E_LIBNOTREGISTERED;
286 else if (res != ERROR_SUCCESS)
288 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
289 return TYPE_E_REGISTRYACCESS;
292 while (hr != S_OK)
294 LONG dwPathLen = sizeof(Path);
296 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
298 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
300 if (!lcid)
301 break;
302 else if (myLCID == lcid)
304 /* try with sub-langid */
305 myLCID = SUBLANGID(lcid);
307 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
309 /* try with system langid */
310 myLCID = 0;
312 else
314 break;
317 else
319 *path = SysAllocString( Path );
320 hr = S_OK;
323 RegCloseKey( hkey );
324 TRACE_(typelib)("-- 0x%08x\n", hr);
325 return hr;
328 /******************************************************************************
329 * CreateTypeLib [OLEAUT32.160] creates a typelib
331 * RETURNS
332 * Success: S_OK
333 * Failure: Status
335 HRESULT WINAPI CreateTypeLib(
336 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
338 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
339 return E_FAIL;
342 /******************************************************************************
343 * LoadTypeLib [OLEAUT32.161]
345 * Loads a type library
347 * PARAMS
348 * szFile [I] Name of file to load from.
349 * pptLib [O] Pointer that receives ITypeLib object on success.
351 * RETURNS
352 * Success: S_OK
353 * Failure: Status
355 * SEE
356 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
358 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
360 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
361 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
364 /******************************************************************************
365 * LoadTypeLibEx [OLEAUT32.183]
367 * Loads and optionally registers a type library
369 * RETURNS
370 * Success: S_OK
371 * Failure: Status
373 HRESULT WINAPI LoadTypeLibEx(
374 LPCOLESTR szFile, /* [in] Name of file to load from */
375 REGKIND regkind, /* [in] Specify kind of registration */
376 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
378 WCHAR szPath[MAX_PATH+1];
379 HRESULT res;
381 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
383 *pptLib = NULL;
385 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
387 if (SUCCEEDED(res))
388 switch(regkind)
390 case REGKIND_DEFAULT:
391 /* don't register typelibs supplied with full path. Experimentation confirms the following */
392 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
393 (szFile[0] && (szFile[1] == ':'))) break;
394 /* else fall-through */
396 case REGKIND_REGISTER:
397 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
399 IUnknown_Release(*pptLib);
400 *pptLib = 0;
402 break;
403 case REGKIND_NONE:
404 break;
407 TRACE(" returns %08x\n",res);
408 return res;
411 /******************************************************************************
412 * LoadRegTypeLib [OLEAUT32.162]
414 * Loads a registered type library.
416 * PARAMS
417 * rguid [I] GUID of the registered type library.
418 * wVerMajor [I] major version.
419 * wVerMinor [I] minor version.
420 * lcid [I] locale ID.
421 * ppTLib [O] pointer that receives an ITypeLib object on success.
423 * RETURNS
424 * Success: S_OK.
425 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
426 * LoadTypeLib.
428 HRESULT WINAPI LoadRegTypeLib(
429 REFGUID rguid,
430 WORD wVerMajor,
431 WORD wVerMinor,
432 LCID lcid,
433 ITypeLib **ppTLib)
435 BSTR bstr=NULL;
436 HRESULT res;
438 *ppTLib = NULL;
440 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
442 if(SUCCEEDED(res))
444 res= LoadTypeLib(bstr, ppTLib);
445 SysFreeString(bstr);
448 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
450 return res;
454 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
455 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
456 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
457 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
458 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
459 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
461 /******************************************************************************
462 * RegisterTypeLib [OLEAUT32.163]
463 * Adds information about a type library to the System Registry
464 * NOTES
465 * Docs: ITypeLib FAR * ptlib
466 * Docs: OLECHAR FAR* szFullPath
467 * Docs: OLECHAR FAR* szHelpDir
469 * RETURNS
470 * Success: S_OK
471 * Failure: Status
473 HRESULT WINAPI RegisterTypeLib(
474 ITypeLib * ptlib, /* [in] Pointer to the library*/
475 OLECHAR * szFullPath, /* [in] full Path of the library*/
476 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
477 may be NULL*/
479 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
480 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
481 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
482 HRESULT res;
483 TLIBATTR *attr;
484 WCHAR keyName[60];
485 WCHAR tmp[16];
486 HKEY key, subKey;
487 UINT types, tidx;
488 TYPEKIND kind;
489 DWORD disposition;
491 if (ptlib == NULL || szFullPath == NULL)
492 return E_INVALIDARG;
494 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
495 return E_FAIL;
497 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
499 res = S_OK;
500 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
501 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
503 LPOLESTR doc;
505 /* Set the human-readable name of the typelib */
506 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
508 if (RegSetValueExW(key, NULL, 0, REG_SZ,
509 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
510 res = E_FAIL;
512 SysFreeString(doc);
514 else
515 res = E_FAIL;
517 /* Make up the name of the typelib path subkey */
518 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
520 /* Create the typelib path subkey */
521 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
522 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
524 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
525 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
526 res = E_FAIL;
528 RegCloseKey(subKey);
530 else
531 res = E_FAIL;
533 /* Create the flags subkey */
534 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
535 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
537 /* FIXME: is %u correct? */
538 static const WCHAR formatW[] = {'%','u',0};
539 WCHAR buf[20];
540 sprintfW(buf, formatW, attr->wLibFlags);
541 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
542 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
543 res = E_FAIL;
545 RegCloseKey(subKey);
547 else
548 res = E_FAIL;
550 /* create the helpdir subkey */
551 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
552 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
554 BOOL freeHelpDir = FALSE;
555 OLECHAR* pIndexStr;
557 /* if we created a new key, and helpDir was null, set the helpdir
558 to the directory which contains the typelib. However,
559 if we just opened an existing key, we leave the helpdir alone */
560 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
561 szHelpDir = SysAllocString(szFullPath);
562 pIndexStr = strrchrW(szHelpDir, '\\');
563 if (pIndexStr) {
564 *pIndexStr = 0;
566 freeHelpDir = TRUE;
569 /* if we have an szHelpDir, set it! */
570 if (szHelpDir != NULL) {
571 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
572 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
573 res = E_FAIL;
577 /* tidy up */
578 if (freeHelpDir) SysFreeString(szHelpDir);
579 RegCloseKey(subKey);
581 } else {
582 res = E_FAIL;
585 RegCloseKey(key);
587 else
588 res = E_FAIL;
590 /* register OLE Automation-compatible interfaces for this typelib */
591 types = ITypeLib_GetTypeInfoCount(ptlib);
592 for (tidx=0; tidx<types; tidx++) {
593 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
594 LPOLESTR name = NULL;
595 ITypeInfo *tinfo = NULL;
597 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
599 switch (kind) {
600 case TKIND_INTERFACE:
601 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
602 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
603 break;
605 case TKIND_DISPATCH:
606 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
607 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
608 break;
610 default:
611 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
612 break;
615 if (tinfo) {
616 TYPEATTR *tattr = NULL;
617 ITypeInfo_GetTypeAttr(tinfo, &tattr);
619 if (tattr) {
620 TRACE_(typelib)("guid=%s, flags=%04x (",
621 debugstr_guid(&tattr->guid),
622 tattr->wTypeFlags);
624 if (TRACE_ON(typelib)) {
625 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
626 XX(FAPPOBJECT);
627 XX(FCANCREATE);
628 XX(FLICENSED);
629 XX(FPREDECLID);
630 XX(FHIDDEN);
631 XX(FCONTROL);
632 XX(FDUAL);
633 XX(FNONEXTENSIBLE);
634 XX(FOLEAUTOMATION);
635 XX(FRESTRICTED);
636 XX(FAGGREGATABLE);
637 XX(FREPLACEABLE);
638 XX(FDISPATCHABLE);
639 XX(FREVERSEBIND);
640 XX(FPROXY);
641 #undef XX
642 MESSAGE("\n");
645 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL|TYPEFLAG_FDISPATCHABLE))
647 /* register interface<->typelib coupling */
648 get_interface_key( &tattr->guid, keyName );
649 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
650 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
652 if (name)
653 RegSetValueExW(key, NULL, 0, REG_SZ,
654 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
656 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
657 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
658 RegSetValueExW(subKey, NULL, 0, REG_SZ,
659 (const BYTE *)PSOA, sizeof PSOA);
660 RegCloseKey(subKey);
663 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
664 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
665 RegSetValueExW(subKey, NULL, 0, REG_SZ,
666 (const BYTE *)PSOA, sizeof PSOA);
667 RegCloseKey(subKey);
670 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
671 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
673 WCHAR buffer[40];
674 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
675 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
677 StringFromGUID2(&attr->guid, buffer, 40);
678 RegSetValueExW(subKey, NULL, 0, REG_SZ,
679 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
680 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
681 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
682 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
683 RegCloseKey(subKey);
686 RegCloseKey(key);
690 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
693 ITypeInfo_Release(tinfo);
696 SysFreeString(name);
700 ITypeLib_ReleaseTLibAttr(ptlib, attr);
702 return res;
706 /******************************************************************************
707 * UnRegisterTypeLib [OLEAUT32.186]
708 * Removes information about a type library from the System Registry
709 * NOTES
711 * RETURNS
712 * Success: S_OK
713 * Failure: Status
715 HRESULT WINAPI UnRegisterTypeLib(
716 REFGUID libid, /* [in] Guid of the library */
717 WORD wVerMajor, /* [in] major version */
718 WORD wVerMinor, /* [in] minor version */
719 LCID lcid, /* [in] locale id */
720 SYSKIND syskind)
722 BSTR tlibPath = NULL;
723 DWORD tmpLength;
724 WCHAR keyName[60];
725 WCHAR subKeyName[50];
726 int result = S_OK;
727 DWORD i = 0;
728 BOOL deleteOtherStuff;
729 HKEY key = NULL;
730 HKEY subKey = NULL;
731 TYPEATTR* typeAttr = NULL;
732 TYPEKIND kind;
733 ITypeInfo* typeInfo = NULL;
734 ITypeLib* typeLib = NULL;
735 int numTypes;
737 TRACE("(IID: %s)\n",debugstr_guid(libid));
739 /* Create the path to the key */
740 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
742 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
744 TRACE("Unsupported syskind %i\n", syskind);
745 result = E_INVALIDARG;
746 goto end;
749 /* get the path to the typelib on disk */
750 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
751 result = E_INVALIDARG;
752 goto end;
755 /* Try and open the key to the type library. */
756 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
757 result = E_INVALIDARG;
758 goto end;
761 /* Try and load the type library */
762 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
763 result = TYPE_E_INVALIDSTATE;
764 goto end;
767 /* remove any types registered with this typelib */
768 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
769 for (i=0; i<numTypes; i++) {
770 /* get the kind of type */
771 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
772 goto enddeleteloop;
775 /* skip non-interfaces, and get type info for the type */
776 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
777 goto enddeleteloop;
779 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
780 goto enddeleteloop;
782 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
783 goto enddeleteloop;
786 /* the path to the type */
787 get_interface_key( &typeAttr->guid, subKeyName );
789 /* Delete its bits */
790 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS) {
791 goto enddeleteloop;
793 RegDeleteKeyW(subKey, ProxyStubClsidW);
794 RegDeleteKeyW(subKey, ProxyStubClsid32W);
795 RegDeleteKeyW(subKey, TypeLibW);
796 RegCloseKey(subKey);
797 subKey = NULL;
798 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
800 enddeleteloop:
801 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
802 typeAttr = NULL;
803 if (typeInfo) ITypeInfo_Release(typeInfo);
804 typeInfo = NULL;
807 /* Now, delete the type library path subkey */
808 get_lcid_subkey( lcid, syskind, subKeyName );
809 RegDeleteKeyW(key, subKeyName);
810 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
811 RegDeleteKeyW(key, subKeyName);
813 /* check if there is anything besides the FLAGS/HELPDIR keys.
814 If there is, we don't delete them */
815 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
816 deleteOtherStuff = TRUE;
817 i = 0;
818 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
819 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
821 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
822 if (!strcmpW(subKeyName, FLAGSW)) continue;
823 if (!strcmpW(subKeyName, HELPDIRW)) continue;
824 deleteOtherStuff = FALSE;
825 break;
828 /* only delete the other parts of the key if we're absolutely sure */
829 if (deleteOtherStuff) {
830 RegDeleteKeyW(key, FLAGSW);
831 RegDeleteKeyW(key, HELPDIRW);
832 RegCloseKey(key);
833 key = NULL;
835 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
836 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
837 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
840 end:
841 if (tlibPath) SysFreeString(tlibPath);
842 if (typeLib) ITypeLib_Release(typeLib);
843 if (subKey) RegCloseKey(subKey);
844 if (key) RegCloseKey(key);
845 return result;
848 /*======================= ITypeLib implementation =======================*/
850 typedef struct tagTLBCustData
852 GUID guid;
853 VARIANT data;
854 struct tagTLBCustData* next;
855 } TLBCustData;
857 /* data structure for import typelibs */
858 typedef struct tagTLBImpLib
860 int offset; /* offset in the file (MSFT)
861 offset in nametable (SLTG)
862 just used to identify library while reading
863 data from file */
864 GUID guid; /* libid */
865 BSTR name; /* name */
867 LCID lcid; /* lcid of imported typelib */
869 WORD wVersionMajor; /* major version number */
870 WORD wVersionMinor; /* minor version number */
872 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
873 NULL if not yet loaded */
874 struct tagTLBImpLib * next;
875 } TLBImpLib;
877 /* internal ITypeLib data */
878 typedef struct tagITypeLibImpl
880 const ITypeLib2Vtbl *lpVtbl;
881 const ITypeCompVtbl *lpVtblTypeComp;
882 LONG ref;
883 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
885 /* strings can be stored in tlb as multibyte strings BUT they are *always*
886 * exported to the application as a UNICODE string.
888 BSTR Name;
889 BSTR DocString;
890 BSTR HelpFile;
891 BSTR HelpStringDll;
892 unsigned long dwHelpContext;
893 int TypeInfoCount; /* nr of typeinfo's in librarry */
894 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
895 int ctCustData; /* number of items in cust data list */
896 TLBCustData * pCustData; /* linked list to cust data */
897 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
898 int ctTypeDesc; /* number of items in type desc array */
899 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
900 library. Only used while reading MSFT
901 typelibs */
902 struct list ref_list; /* list of ref types in this typelib */
903 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
906 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
907 struct tagITypeLibImpl *next, *prev;
908 WCHAR *path;
909 INT index;
910 } ITypeLibImpl;
912 static const ITypeLib2Vtbl tlbvt;
913 static const ITypeCompVtbl tlbtcvt;
915 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
917 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
920 /* ITypeLib methods */
921 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
922 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
924 /*======================= ITypeInfo implementation =======================*/
926 /* data for referenced types */
927 typedef struct tagTLBRefType
929 INT index; /* Type index for internal ref or for external ref
930 it the format is SLTG. -2 indicates to
931 use guid */
933 GUID guid; /* guid of the referenced type */
934 /* if index == TLB_REF_USE_GUID */
936 HREFTYPE reference; /* The href of this ref */
937 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
938 TLB_REF_INTERNAL for internal refs
939 TLB_REF_NOT_FOUND for broken refs */
941 struct list entry;
942 } TLBRefType;
944 #define TLB_REF_USE_GUID -2
946 #define TLB_REF_INTERNAL (void*)-2
947 #define TLB_REF_NOT_FOUND (void*)-1
949 /* internal Parameter data */
950 typedef struct tagTLBParDesc
952 BSTR Name;
953 int ctCustData;
954 TLBCustData * pCustData; /* linked list to cust data */
955 } TLBParDesc;
957 /* internal Function data */
958 typedef struct tagTLBFuncDesc
960 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
961 BSTR Name; /* the name of this function */
962 TLBParDesc *pParamDesc; /* array with param names and custom data */
963 int helpcontext;
964 int HelpStringContext;
965 BSTR HelpString;
966 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
967 int ctCustData;
968 TLBCustData * pCustData; /* linked list to cust data; */
969 struct tagTLBFuncDesc * next;
970 } TLBFuncDesc;
972 /* internal Variable data */
973 typedef struct tagTLBVarDesc
975 VARDESC vardesc; /* lots of info on the variable and its attributes. */
976 BSTR Name; /* the name of this variable */
977 int HelpContext;
978 int HelpStringContext; /* FIXME: where? */
979 BSTR HelpString;
980 int ctCustData;
981 TLBCustData * pCustData;/* linked list to cust data; */
982 struct tagTLBVarDesc * next;
983 } TLBVarDesc;
985 /* internal implemented interface data */
986 typedef struct tagTLBImplType
988 HREFTYPE hRef; /* hRef of interface */
989 int implflags; /* IMPLFLAG_*s */
990 int ctCustData;
991 TLBCustData * pCustData;/* linked list to custom data; */
992 struct tagTLBImplType *next;
993 } TLBImplType;
995 /* internal TypeInfo data */
996 typedef struct tagITypeInfoImpl
998 const ITypeInfo2Vtbl *lpVtbl;
999 const ITypeCompVtbl *lpVtblTypeComp;
1000 LONG ref;
1001 BOOL no_free_data; /* don't free data structurees */
1002 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1003 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1004 int index; /* index in this typelib; */
1005 HREFTYPE hreftype; /* hreftype for app object binding */
1006 /* type libs seem to store the doc strings in ascii
1007 * so why should we do it in unicode?
1009 BSTR Name;
1010 BSTR DocString;
1011 BSTR DllName;
1012 unsigned long dwHelpContext;
1013 unsigned long dwHelpStringContext;
1015 /* functions */
1016 TLBFuncDesc * funclist; /* linked list with function descriptions */
1018 /* variables */
1019 TLBVarDesc * varlist; /* linked list with variable descriptions */
1021 /* Implemented Interfaces */
1022 TLBImplType * impltypelist;
1024 int ctCustData;
1025 TLBCustData * pCustData; /* linked list to cust data; */
1026 struct tagITypeInfoImpl * next;
1027 } ITypeInfoImpl;
1029 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1031 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1034 static const ITypeInfo2Vtbl tinfvt;
1035 static const ITypeCompVtbl tcompvt;
1037 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
1039 typedef struct tagTLBContext
1041 unsigned int oStart; /* start of TLB in file */
1042 unsigned int pos; /* current pos */
1043 unsigned int length; /* total length */
1044 void *mapping; /* memory mapping */
1045 MSFT_SegDir * pTblDir;
1046 ITypeLibImpl* pLibInfo;
1047 } TLBContext;
1050 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1053 debug
1055 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1056 if (pTD->vt & VT_RESERVED)
1057 szVarType += strlen(strcpy(szVarType, "reserved | "));
1058 if (pTD->vt & VT_BYREF)
1059 szVarType += strlen(strcpy(szVarType, "ref to "));
1060 if (pTD->vt & VT_ARRAY)
1061 szVarType += strlen(strcpy(szVarType, "array of "));
1062 if (pTD->vt & VT_VECTOR)
1063 szVarType += strlen(strcpy(szVarType, "vector of "));
1064 switch(pTD->vt & VT_TYPEMASK) {
1065 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1066 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1067 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1068 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1069 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1070 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1071 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1072 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1073 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1074 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1075 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1076 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1077 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1078 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1079 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1080 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1081 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1082 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1083 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1084 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1085 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1086 pTD->u.hreftype); break;
1087 case VT_PTR: sprintf(szVarType, "ptr to ");
1088 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1089 break;
1090 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1091 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1092 break;
1093 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1094 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1095 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1096 break;
1098 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1102 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1103 char buf[200];
1104 USHORT flags = edesc->u.paramdesc.wParamFlags;
1105 dump_TypeDesc(&edesc->tdesc,buf);
1106 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1107 MESSAGE("\t\tu.paramdesc.wParamFlags");
1108 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1109 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1110 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1111 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1112 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1113 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1114 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1115 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1116 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1118 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1119 int i;
1120 MESSAGE("memid is %08x\n",funcdesc->memid);
1121 for (i=0;i<funcdesc->cParams;i++) {
1122 MESSAGE("Param %d:\n",i);
1123 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1125 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1126 switch (funcdesc->funckind) {
1127 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1128 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1129 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1130 case FUNC_STATIC: MESSAGE("static");break;
1131 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1132 default: MESSAGE("unknown");break;
1134 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1135 switch (funcdesc->invkind) {
1136 case INVOKE_FUNC: MESSAGE("func");break;
1137 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1138 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1139 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1141 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1142 switch (funcdesc->callconv) {
1143 case CC_CDECL: MESSAGE("cdecl");break;
1144 case CC_PASCAL: MESSAGE("pascal");break;
1145 case CC_STDCALL: MESSAGE("stdcall");break;
1146 case CC_SYSCALL: MESSAGE("syscall");break;
1147 default:break;
1149 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1150 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1151 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1153 MESSAGE("\telemdescFunc (return value type):\n");
1154 dump_ELEMDESC(&funcdesc->elemdescFunc);
1157 static const char * const typekind_desc[] =
1159 "TKIND_ENUM",
1160 "TKIND_RECORD",
1161 "TKIND_MODULE",
1162 "TKIND_INTERFACE",
1163 "TKIND_DISPATCH",
1164 "TKIND_COCLASS",
1165 "TKIND_ALIAS",
1166 "TKIND_UNION",
1167 "TKIND_MAX"
1170 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1172 int i;
1173 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1174 for (i=0;i<pfd->funcdesc.cParams;i++)
1175 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1178 dump_FUNCDESC(&(pfd->funcdesc));
1180 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1181 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1183 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1185 while (pfd)
1187 dump_TLBFuncDescOne(pfd);
1188 pfd = pfd->next;
1191 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1193 while (pvd)
1195 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1196 pvd = pvd->next;
1200 static void dump_TLBImpLib(const TLBImpLib *import)
1202 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1203 debugstr_w(import->name));
1204 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1205 import->wVersionMinor, import->lcid, import->offset);
1208 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1210 TLBRefType *ref;
1212 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1214 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1215 if(ref->index == -1)
1216 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1217 else
1218 TRACE_(typelib)("type no: %d\n", ref->index);
1220 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1222 TRACE_(typelib)("in lib\n");
1223 dump_TLBImpLib(ref->pImpTLInfo);
1228 static void dump_TLBImplType(const TLBImplType * impl)
1230 while (impl) {
1231 TRACE_(typelib)(
1232 "implementing/inheriting interface hRef = %x implflags %x\n",
1233 impl->hRef, impl->implflags);
1234 impl = impl->next;
1238 static void dump_Variant(const VARIANT * pvar)
1240 SYSTEMTIME st;
1242 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1244 if (pvar)
1246 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1247 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1249 TRACE(",%p", V_BYREF(pvar));
1251 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1253 TRACE(",%p", V_ARRAY(pvar));
1255 else switch (V_TYPE(pvar))
1257 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1258 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1259 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1260 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1261 case VT_INT:
1262 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1263 case VT_UINT:
1264 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1265 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1266 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1267 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1268 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1269 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1270 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1271 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1272 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1273 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1274 V_CY(pvar).s.Lo); break;
1275 case VT_DATE:
1276 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1277 TRACE(",<invalid>");
1278 else
1279 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1280 st.wHour, st.wMinute, st.wSecond);
1281 break;
1282 case VT_ERROR:
1283 case VT_VOID:
1284 case VT_USERDEFINED:
1285 case VT_EMPTY:
1286 case VT_NULL: break;
1287 default: TRACE(",?"); break;
1290 TRACE("}\n");
1293 static void dump_DispParms(const DISPPARAMS * pdp)
1295 int index;
1297 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1299 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1301 TRACE("named args:\n");
1302 for (index = 0; index < pdp->cNamedArgs; index++)
1303 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1306 if (pdp->cArgs && pdp->rgvarg)
1308 TRACE("args:\n");
1309 for (index = 0; index < pdp->cArgs; index++)
1310 dump_Variant( &pdp->rgvarg[index] );
1314 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1316 TRACE("%p ref=%u\n", pty, pty->ref);
1317 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1318 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1319 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1320 TRACE("fct:%u var:%u impl:%u\n",
1321 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1322 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1323 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1324 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1325 if (TRACE_ON(ole))
1326 dump_TLBFuncDesc(pty->funclist);
1327 dump_TLBVarDesc(pty->varlist);
1328 dump_TLBImplType(pty->impltypelist);
1331 static void dump_VARDESC(const VARDESC *v)
1333 MESSAGE("memid %d\n",v->memid);
1334 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1335 MESSAGE("oInst %d\n",v->u.oInst);
1336 dump_ELEMDESC(&(v->elemdescVar));
1337 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1338 MESSAGE("varkind %d\n",v->varkind);
1341 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1343 /* VT_LPWSTR is largest type that */
1344 /* may appear in type description*/
1345 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1346 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1347 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1348 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1349 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1350 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1351 {{0},30},{{0},31}
1354 static void TLB_abort(void)
1356 DebugBreak();
1358 static void * TLB_Alloc(unsigned size)
1360 void * ret;
1361 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1362 /* FIXME */
1363 ERR("cannot allocate memory\n");
1365 return ret;
1368 static void TLB_Free(void * ptr)
1370 HeapFree(GetProcessHeap(), 0, ptr);
1373 /* returns the size required for a deep copy of a typedesc into a
1374 * flat buffer */
1375 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1377 SIZE_T size = 0;
1379 if (alloc_initial_space)
1380 size += sizeof(TYPEDESC);
1382 switch (tdesc->vt)
1384 case VT_PTR:
1385 case VT_SAFEARRAY:
1386 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1387 break;
1388 case VT_CARRAY:
1389 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1390 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1391 break;
1393 return size;
1396 /* deep copy a typedesc into a flat buffer */
1397 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1399 if (!dest)
1401 dest = buffer;
1402 buffer = (char *)buffer + sizeof(TYPEDESC);
1405 *dest = *src;
1407 switch (src->vt)
1409 case VT_PTR:
1410 case VT_SAFEARRAY:
1411 dest->u.lptdesc = buffer;
1412 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1413 break;
1414 case VT_CARRAY:
1415 dest->u.lpadesc = buffer;
1416 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1417 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1418 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1419 break;
1421 return buffer;
1424 /**********************************************************************
1426 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1428 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1430 return pcx->pos;
1433 static inline void MSFT_Seek(TLBContext *pcx, long where)
1435 if (where != DO_NOT_SEEK)
1437 where += pcx->oStart;
1438 if (where > pcx->length)
1440 /* FIXME */
1441 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1442 TLB_abort();
1444 pcx->pos = where;
1448 /* read function */
1449 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1451 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1452 pcx->pos, count, pcx->oStart, pcx->length, where);
1454 MSFT_Seek(pcx, where);
1455 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1456 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1457 pcx->pos += count;
1458 return count;
1461 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1462 long where )
1464 DWORD ret;
1466 ret = MSFT_Read(buffer, count, pcx, where);
1467 FromLEDWords(buffer, ret);
1469 return ret;
1472 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1473 long where )
1475 DWORD ret;
1477 ret = MSFT_Read(buffer, count, pcx, where);
1478 FromLEWords(buffer, ret);
1480 return ret;
1483 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1485 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1486 memset(pGuid,0, sizeof(GUID));
1487 return;
1489 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1490 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1491 pGuid->Data2 = FromLEWord(pGuid->Data2);
1492 pGuid->Data3 = FromLEWord(pGuid->Data3);
1493 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1496 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1498 MSFT_NameIntro niName;
1500 if (offset < 0)
1502 ERR_(typelib)("bad offset %d\n", offset);
1503 return -1;
1506 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1507 pcx->pTblDir->pNametab.offset+offset);
1509 return niName.hreftype;
1512 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1514 char * name;
1515 MSFT_NameIntro niName;
1516 int lengthInChars;
1517 BSTR bstrName = NULL;
1519 if (offset < 0)
1521 ERR_(typelib)("bad offset %d\n", offset);
1522 return NULL;
1524 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1525 pcx->pTblDir->pNametab.offset+offset);
1526 niName.namelen &= 0xFF; /* FIXME: correct ? */
1527 name=TLB_Alloc((niName.namelen & 0xff) +1);
1528 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1529 name[niName.namelen & 0xff]='\0';
1531 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1532 name, -1, NULL, 0);
1534 /* no invalid characters in string */
1535 if (lengthInChars)
1537 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1539 /* don't check for invalid character since this has been done previously */
1540 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1542 TLB_Free(name);
1544 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1545 return bstrName;
1548 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1550 char * string;
1551 INT16 length;
1552 int lengthInChars;
1553 BSTR bstr = NULL;
1555 if(offset<0) return NULL;
1556 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1557 if(length <= 0) return 0;
1558 string=TLB_Alloc(length +1);
1559 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1560 string[length]='\0';
1562 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1563 string, -1, NULL, 0);
1565 /* no invalid characters in string */
1566 if (lengthInChars)
1568 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1570 /* don't check for invalid character since this has been done previously */
1571 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1573 TLB_Free(string);
1575 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1576 return bstr;
1579 * read a value and fill a VARIANT structure
1581 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1583 int size;
1585 TRACE_(typelib)("\n");
1587 if(offset <0) { /* data are packed in here */
1588 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1589 V_I4(pVar) = offset & 0x3ffffff;
1590 return;
1592 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1593 pcx->pTblDir->pCustData.offset + offset );
1594 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1595 switch (V_VT(pVar)){
1596 case VT_EMPTY: /* FIXME: is this right? */
1597 case VT_NULL: /* FIXME: is this right? */
1598 case VT_I2 : /* this should not happen */
1599 case VT_I4 :
1600 case VT_R4 :
1601 case VT_ERROR :
1602 case VT_BOOL :
1603 case VT_I1 :
1604 case VT_UI1 :
1605 case VT_UI2 :
1606 case VT_UI4 :
1607 case VT_INT :
1608 case VT_UINT :
1609 case VT_VOID : /* FIXME: is this right? */
1610 case VT_HRESULT :
1611 size=4; break;
1612 case VT_R8 :
1613 case VT_CY :
1614 case VT_DATE :
1615 case VT_I8 :
1616 case VT_UI8 :
1617 case VT_DECIMAL : /* FIXME: is this right? */
1618 case VT_FILETIME :
1619 size=8;break;
1620 /* pointer types with known behaviour */
1621 case VT_BSTR :{
1622 char * ptr;
1623 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1624 if(size < 0) {
1625 char next;
1626 DWORD origPos = MSFT_Tell(pcx), nullPos;
1628 do {
1629 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1630 } while (next);
1631 nullPos = MSFT_Tell(pcx);
1632 size = nullPos - origPos;
1633 MSFT_Seek(pcx, origPos);
1635 ptr=TLB_Alloc(size);/* allocate temp buffer */
1636 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1637 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1638 /* FIXME: do we need a AtoW conversion here? */
1639 V_UNION(pVar, bstrVal[size])='\0';
1640 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1641 TLB_Free(ptr);
1643 size=-4; break;
1644 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1645 case VT_DISPATCH :
1646 case VT_VARIANT :
1647 case VT_UNKNOWN :
1648 case VT_PTR :
1649 case VT_SAFEARRAY :
1650 case VT_CARRAY :
1651 case VT_USERDEFINED :
1652 case VT_LPSTR :
1653 case VT_LPWSTR :
1654 case VT_BLOB :
1655 case VT_STREAM :
1656 case VT_STORAGE :
1657 case VT_STREAMED_OBJECT :
1658 case VT_STORED_OBJECT :
1659 case VT_BLOB_OBJECT :
1660 case VT_CF :
1661 case VT_CLSID :
1662 default:
1663 size=0;
1664 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1665 V_VT(pVar));
1668 if(size>0) /* (big|small) endian correct? */
1669 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1670 return;
1673 * create a linked list with custom data
1675 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1677 MSFT_CDGuid entry;
1678 TLBCustData* pNew;
1679 int count=0;
1681 TRACE_(typelib)("\n");
1683 while(offset >=0){
1684 count++;
1685 pNew=TLB_Alloc(sizeof(TLBCustData));
1686 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1687 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1688 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1689 /* add new custom data at head of the list */
1690 pNew->next=*ppCustData;
1691 *ppCustData=pNew;
1692 offset = entry.next;
1694 return count;
1697 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1698 ITypeInfoImpl *pTI)
1700 if(type <0)
1701 pTd->vt=type & VT_TYPEMASK;
1702 else
1703 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1705 if(pTd->vt == VT_USERDEFINED)
1706 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1708 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1711 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1713 /* resolve referenced type if any */
1714 while (lpTypeDesc)
1716 switch (lpTypeDesc->vt)
1718 case VT_PTR:
1719 lpTypeDesc = lpTypeDesc->u.lptdesc;
1720 break;
1722 case VT_CARRAY:
1723 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1724 break;
1726 case VT_USERDEFINED:
1727 MSFT_DoRefType(pcx, pTI->pTypeLib,
1728 lpTypeDesc->u.hreftype);
1730 lpTypeDesc = NULL;
1731 break;
1733 default:
1734 lpTypeDesc = NULL;
1739 static void
1740 MSFT_DoFuncs(TLBContext* pcx,
1741 ITypeInfoImpl* pTI,
1742 int cFuncs,
1743 int cVars,
1744 int offset,
1745 TLBFuncDesc** pptfd)
1748 * member information is stored in a data structure at offset
1749 * indicated by the memoffset field of the typeinfo structure
1750 * There are several distinctive parts.
1751 * The first part starts with a field that holds the total length
1752 * of this (first) part excluding this field. Then follow the records,
1753 * for each member there is one record.
1755 * The first entry is always the length of the record (including this
1756 * length word).
1757 * The rest of the record depends on the type of the member. If there is
1758 * a field indicating the member type (function, variable, interface, etc)
1759 * I have not found it yet. At this time we depend on the information
1760 * in the type info and the usual order how things are stored.
1762 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1763 * for each member;
1765 * Third is an equal sized array with file offsets to the name entry
1766 * of each member.
1768 * The fourth and last (?) part is an array with offsets to the records
1769 * in the first part of this file segment.
1772 int infolen, nameoffset, reclength, nrattributes, i;
1773 int recoffset = offset + sizeof(INT);
1775 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1776 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1777 TLBFuncDesc *ptfd_prev = NULL;
1779 TRACE_(typelib)("\n");
1781 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1783 for ( i = 0; i < cFuncs ; i++ )
1785 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1787 /* name, eventually add to a hash table */
1788 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1789 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1791 /* nameoffset is sometimes -1 on the second half of a propget/propput
1792 * pair of functions */
1793 if ((nameoffset == -1) && (i > 0))
1794 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1795 else
1796 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1798 /* read the function information record */
1799 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1801 reclength &= 0xffff;
1803 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1805 /* do the attributes */
1806 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1807 / sizeof(int);
1809 if ( nrattributes > 0 )
1811 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1813 if ( nrattributes > 1 )
1815 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1816 pFuncRec->OptAttr[1]) ;
1818 if ( nrattributes > 2 )
1820 if ( pFuncRec->FKCCIC & 0x2000 )
1822 if (HIWORD(pFuncRec->OptAttr[2]) != 0)
1823 ERR("ordinal 0x%08x invalid, HIWORD != 0\n", pFuncRec->OptAttr[2]);
1824 (*pptfd)->Entry = (BSTR)pFuncRec->OptAttr[2];
1826 else
1828 (*pptfd)->Entry = MSFT_ReadString(pcx,
1829 pFuncRec->OptAttr[2]);
1831 if( nrattributes > 5 )
1833 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1835 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1837 MSFT_CustData(pcx,
1838 pFuncRec->OptAttr[6],
1839 &(*pptfd)->pCustData);
1843 else
1845 (*pptfd)->Entry = (BSTR)-1;
1850 /* fill the FuncDesc Structure */
1851 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1852 offset + infolen + ( i + 1) * sizeof(INT));
1854 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1855 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1856 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1857 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1858 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1859 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1860 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1862 MSFT_GetTdesc(pcx,
1863 pFuncRec->DataType,
1864 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1865 pTI);
1866 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1868 /* do the parameters/arguments */
1869 if(pFuncRec->nrargs)
1871 int j = 0;
1872 MSFT_ParameterInfo paraminfo;
1874 (*pptfd)->funcdesc.lprgelemdescParam =
1875 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1877 (*pptfd)->pParamDesc =
1878 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1880 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1881 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1883 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1885 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1887 MSFT_GetTdesc(pcx,
1888 paraminfo.DataType,
1889 &elemdesc->tdesc,
1890 pTI);
1892 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1894 /* name */
1895 if (paraminfo.oName == -1)
1896 /* this occurs for [propput] or [propget] methods, so
1897 * we should just set the name of the parameter to the
1898 * name of the method. */
1899 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1900 else
1901 (*pptfd)->pParamDesc[j].Name =
1902 MSFT_ReadName( pcx, paraminfo.oName );
1903 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1905 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1907 /* default value */
1908 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1909 (pFuncRec->FKCCIC & 0x1000) )
1911 INT* pInt = (INT *)((char *)pFuncRec +
1912 reclength -
1913 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1915 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1917 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1918 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1920 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1921 pInt[j], pcx);
1923 else
1924 elemdesc->u.paramdesc.pparamdescex = NULL;
1925 /* custom info */
1926 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1928 MSFT_CustData(pcx,
1929 pFuncRec->OptAttr[7+j],
1930 &(*pptfd)->pParamDesc[j].pCustData);
1933 /* SEEK value = jump to offset,
1934 * from there jump to the end of record,
1935 * go back by (j-1) arguments
1937 MSFT_ReadLEDWords( &paraminfo ,
1938 sizeof(MSFT_ParameterInfo), pcx,
1939 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1940 * sizeof(MSFT_ParameterInfo)));
1944 /* scode is not used: archaic win16 stuff FIXME: right? */
1945 (*pptfd)->funcdesc.cScodes = 0 ;
1946 (*pptfd)->funcdesc.lprgscode = NULL ;
1948 ptfd_prev = *pptfd;
1949 pptfd = & ((*pptfd)->next);
1950 recoffset += reclength;
1952 HeapFree(GetProcessHeap(), 0, recbuf);
1955 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1956 int cVars, int offset, TLBVarDesc ** pptvd)
1958 int infolen, nameoffset, reclength;
1959 char recbuf[256];
1960 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1961 int i;
1962 int recoffset;
1964 TRACE_(typelib)("\n");
1966 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1967 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1968 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1969 recoffset += offset+sizeof(INT);
1970 for(i=0;i<cVars;i++){
1971 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1972 /* name, eventually add to a hash table */
1973 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1974 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
1975 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1976 /* read the variable information record */
1977 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1978 reclength &=0xff;
1979 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1980 /* Optional data */
1981 if(reclength >(6*sizeof(INT)) )
1982 (*pptvd)->HelpContext=pVarRec->HelpContext;
1983 if(reclength >(7*sizeof(INT)) )
1984 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1985 if(reclength >(8*sizeof(INT)) )
1986 if(reclength >(9*sizeof(INT)) )
1987 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1988 /* fill the VarDesc Structure */
1989 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1990 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
1991 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1992 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1993 MSFT_GetTdesc(pcx, pVarRec->DataType,
1994 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1995 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1996 if(pVarRec->VarKind == VAR_CONST ){
1997 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1998 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1999 pVarRec->OffsValue, pcx);
2000 } else
2001 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
2002 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
2003 pptvd=&((*pptvd)->next);
2004 recoffset += reclength;
2007 /* fill in data for a hreftype (offset). When the referenced type is contained
2008 * in the typelib, it's just an (file) offset in the type info base dir.
2009 * If comes from import, it's an offset+1 in the ImpInfo table
2010 * */
2011 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2012 int offset)
2014 int j;
2015 TLBRefType *ref;
2017 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2019 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2021 if(ref->reference == offset) return;
2024 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
2025 list_add_tail(&pTL->ref_list, &ref->entry);
2027 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2028 /* external typelib */
2029 MSFT_ImpInfo impinfo;
2030 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2032 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2034 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2035 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2036 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
2037 if(pImpLib->offset==impinfo.oImpFile) break;
2038 pImpLib=pImpLib->next;
2040 if(pImpLib){
2041 ref->reference = offset;
2042 ref->pImpTLInfo = pImpLib;
2043 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2044 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2045 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2046 ref->index = TLB_REF_USE_GUID;
2047 } else
2048 ref->index = impinfo.oGuid;
2049 }else{
2050 ERR("Cannot find a reference\n");
2051 ref->reference = -1;
2052 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2054 }else{
2055 /* in this typelib */
2056 ref->index = MSFT_HREFTYPE_INDEX(offset);
2057 ref->reference = offset;
2058 ref->pImpTLInfo = TLB_REF_INTERNAL;
2062 /* process Implemented Interfaces of a com class */
2063 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2064 int offset)
2066 int i;
2067 MSFT_RefRecord refrec;
2068 TLBImplType **ppImpl = &pTI->impltypelist;
2070 TRACE_(typelib)("\n");
2072 for(i=0;i<count;i++){
2073 if(offset<0) break; /* paranoia */
2074 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2075 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2076 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2077 (*ppImpl)->hRef = refrec.reftype;
2078 (*ppImpl)->implflags=refrec.flags;
2079 (*ppImpl)->ctCustData=
2080 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2081 offset=refrec.onext;
2082 ppImpl=&((*ppImpl)->next);
2086 * process a typeinfo record
2088 static ITypeInfoImpl * MSFT_DoTypeInfo(
2089 TLBContext *pcx,
2090 int count,
2091 ITypeLibImpl * pLibInfo)
2093 MSFT_TypeInfoBase tiBase;
2094 ITypeInfoImpl *ptiRet;
2096 TRACE_(typelib)("count=%u\n", count);
2098 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2099 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2100 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2102 /* this is where we are coming from */
2103 ptiRet->pTypeLib = pLibInfo;
2104 ptiRet->index=count;
2105 /* fill in the typeattr fields */
2107 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2108 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2109 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2110 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2111 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2112 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2113 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2114 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2115 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2116 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2117 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2118 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2119 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2120 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2121 MSFT_GetTdesc(pcx, tiBase.datatype1,
2122 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2124 /* FIXME: */
2125 /* IDLDESC idldescType; *//* never saw this one != zero */
2127 /* name, eventually add to a hash table */
2128 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2129 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2130 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2131 /* help info */
2132 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2133 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2134 ptiRet->dwHelpContext=tiBase.helpcontext;
2136 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2137 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2139 /* note: InfoType's Help file and HelpStringDll come from the containing
2140 * library. Further HelpString and Docstring appear to be the same thing :(
2142 /* functions */
2143 if(ptiRet->TypeAttr.cFuncs >0 )
2144 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2145 ptiRet->TypeAttr.cVars,
2146 tiBase.memoffset, & ptiRet->funclist);
2147 /* variables */
2148 if(ptiRet->TypeAttr.cVars >0 )
2149 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2150 ptiRet->TypeAttr.cVars,
2151 tiBase.memoffset, & ptiRet->varlist);
2152 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2153 switch(ptiRet->TypeAttr.typekind)
2155 case TKIND_COCLASS:
2156 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2157 tiBase.datatype1);
2158 break;
2159 case TKIND_DISPATCH:
2160 /* This is not -1 when the interface is a non-base dual interface or
2161 when a dispinterface wraps an interface ie the idl 'dispinterface x {interface y;};'.
2162 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2163 not this interface.
2166 if (tiBase.datatype1 != -1)
2168 ptiRet->impltypelist = TLB_Alloc(sizeof(TLBImplType));
2169 ptiRet->impltypelist->hRef = tiBase.datatype1;
2170 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2172 break;
2173 default:
2174 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2175 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2176 ptiRet->impltypelist->hRef = tiBase.datatype1;
2177 break;
2180 ptiRet->ctCustData=
2181 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2183 TRACE_(typelib)("%s guid: %s kind:%s\n",
2184 debugstr_w(ptiRet->Name),
2185 debugstr_guid(&ptiRet->TypeAttr.guid),
2186 typekind_desc[ptiRet->TypeAttr.typekind]);
2188 return ptiRet;
2191 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2192 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2193 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2194 * tradeoff here.
2196 static ITypeLibImpl *tlb_cache_first;
2197 static CRITICAL_SECTION cache_section;
2198 static CRITICAL_SECTION_DEBUG cache_section_debug =
2200 0, 0, &cache_section,
2201 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2202 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2204 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2207 /****************************************************************************
2208 * TLB_ReadTypeLib
2210 * find the type of the typelib file and map the typelib resource into
2211 * the memory
2213 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2214 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2215 static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2217 ITypeLibImpl *entry;
2218 int ret = TYPE_E_CANTLOADLIBRARY;
2219 INT index = 1;
2220 HINSTANCE hinstDLL;
2221 LPWSTR index_str, file = (LPWSTR)pszFileName;
2223 *ppTypeLib = NULL;
2225 index_str = strrchrW(pszFileName, '\\');
2226 if(index_str && *++index_str != '\0')
2228 LPWSTR end_ptr;
2229 long idx = strtolW(index_str, &end_ptr, 10);
2230 if(*end_ptr == '\0')
2232 int str_len = index_str - pszFileName - 1;
2233 index = idx;
2234 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
2235 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2236 file[str_len] = 0;
2240 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2242 if(strchrW(file, '\\'))
2244 lstrcpyW(pszPath, file);
2246 else
2248 int len = GetSystemDirectoryW(pszPath, cchPath);
2249 pszPath[len] = '\\';
2250 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2254 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file);
2256 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2258 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2259 EnterCriticalSection(&cache_section);
2260 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2262 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2264 TRACE("cache hit\n");
2265 *ppTypeLib = (ITypeLib2*)entry;
2266 ITypeLib_AddRef(*ppTypeLib);
2267 LeaveCriticalSection(&cache_section);
2268 return S_OK;
2271 LeaveCriticalSection(&cache_section);
2273 /* now actually load and parse the typelib */
2275 hinstDLL = LoadLibraryExW(pszPath, 0, DONT_RESOLVE_DLL_REFERENCES |
2276 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2278 if (hinstDLL)
2280 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2281 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2282 if (hrsrc)
2284 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2285 if (hGlobal)
2287 LPVOID pBase = LockResource(hGlobal);
2288 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2290 if (pBase)
2292 /* try to load as incore resource */
2293 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2294 if (dwSignature == MSFT_SIGNATURE)
2295 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2296 else if (dwSignature == SLTG_SIGNATURE)
2297 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2298 else
2299 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2301 FreeResource( hGlobal );
2304 FreeLibrary(hinstDLL);
2306 else
2308 HANDLE hFile = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2309 if (INVALID_HANDLE_VALUE != hFile)
2311 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2312 if (hMapping)
2314 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2315 if(pBase)
2317 /* retrieve file size */
2318 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2319 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2321 if (dwSignature == MSFT_SIGNATURE)
2322 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2323 else if (dwSignature == SLTG_SIGNATURE)
2324 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2326 UnmapViewOfFile(pBase);
2328 CloseHandle(hMapping);
2330 CloseHandle(hFile);
2334 if(*ppTypeLib) {
2335 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2337 TRACE("adding to cache\n");
2338 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2339 lstrcpyW(impl->path, pszPath);
2340 /* We should really canonicalise the path here. */
2341 impl->index = index;
2343 /* FIXME: check if it has added already in the meantime */
2344 EnterCriticalSection(&cache_section);
2345 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2346 impl->prev = NULL;
2347 tlb_cache_first = impl;
2348 LeaveCriticalSection(&cache_section);
2349 ret = S_OK;
2350 } else
2351 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2353 return ret;
2356 /*================== ITypeLib(2) Methods ===================================*/
2358 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2360 ITypeLibImpl* pTypeLibImpl;
2362 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2363 if (!pTypeLibImpl) return NULL;
2365 pTypeLibImpl->lpVtbl = &tlbvt;
2366 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2367 pTypeLibImpl->ref = 1;
2369 list_init(&pTypeLibImpl->ref_list);
2370 pTypeLibImpl->dispatch_href = -1;
2372 return pTypeLibImpl;
2375 /****************************************************************************
2376 * ITypeLib2_Constructor_MSFT
2378 * loading an MSFT typelib from an in-memory image
2380 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2382 TLBContext cx;
2383 long lPSegDir;
2384 MSFT_Header tlbHeader;
2385 MSFT_SegDir tlbSegDir;
2386 ITypeLibImpl * pTypeLibImpl;
2388 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2390 pTypeLibImpl = TypeLibImpl_Constructor();
2391 if (!pTypeLibImpl) return NULL;
2393 /* get pointer to beginning of typelib data */
2394 cx.pos = 0;
2395 cx.oStart=0;
2396 cx.mapping = pLib;
2397 cx.pLibInfo = pTypeLibImpl;
2398 cx.length = dwTLBLength;
2400 /* read header */
2401 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2402 TRACE_(typelib)("header:\n");
2403 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2404 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2405 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2406 return NULL;
2408 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2410 /* there is a small amount of information here until the next important
2411 * part:
2412 * the segment directory . Try to calculate the amount of data */
2413 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2415 /* now read the segment directory */
2416 TRACE("read segment directory (at %ld)\n",lPSegDir);
2417 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2418 cx.pTblDir = &tlbSegDir;
2420 /* just check two entries */
2421 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2423 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2424 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2425 return NULL;
2428 /* now fill our internal data */
2429 /* TLIBATTR fields */
2430 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2432 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2433 /* Windows seems to have zero here, is this correct? */
2434 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2435 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2436 else
2437 pTypeLibImpl->LibAttr.lcid = 0;
2439 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2440 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2441 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2442 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2444 /* name, eventually add to a hash table */
2445 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2447 /* help info */
2448 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2449 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2451 if( tlbHeader.varflags & HELPDLLFLAG)
2453 int offset;
2454 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2455 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2458 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2460 /* custom data */
2461 if(tlbHeader.CustomDataOffset >= 0)
2463 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2466 /* fill in typedescriptions */
2467 if(tlbSegDir.pTypdescTab.length > 0)
2469 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2470 INT16 td[4];
2471 pTypeLibImpl->ctTypeDesc = cTD;
2472 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2473 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2474 for(i=0; i<cTD; )
2476 /* FIXME: add several sanity checks here */
2477 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2478 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2480 /* FIXME: check safearray */
2481 if(td[3] < 0)
2482 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2483 else
2484 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2486 else if(td[0] == VT_CARRAY)
2488 /* array descr table here */
2489 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2491 else if(td[0] == VT_USERDEFINED)
2493 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2495 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2498 /* second time around to fill the array subscript info */
2499 for(i=0;i<cTD;i++)
2501 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2502 if(tlbSegDir.pArrayDescriptions.offset>0)
2504 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2505 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2507 if(td[1]<0)
2508 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2509 else
2510 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2512 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2514 for(j = 0; j<td[2]; j++)
2516 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2517 sizeof(INT), &cx, DO_NOT_SEEK);
2518 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2519 sizeof(INT), &cx, DO_NOT_SEEK);
2522 else
2524 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2525 ERR("didn't find array description data\n");
2530 /* imported type libs */
2531 if(tlbSegDir.pImpFiles.offset>0)
2533 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2534 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2535 UINT16 size;
2537 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2539 char *name;
2540 DWORD len;
2542 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2543 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2544 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2546 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2547 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2548 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2549 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2551 size >>= 2;
2552 name = TLB_Alloc(size+1);
2553 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2554 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2555 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2556 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2557 TLB_Free(name);
2559 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2560 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2562 ppImpLib = &(*ppImpLib)->next;
2566 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
2567 if(pTypeLibImpl->dispatch_href != -1)
2568 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
2570 /* type info's */
2571 if(tlbHeader.nrtypeinfos >= 0 )
2573 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2574 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2575 int i;
2577 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2579 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2581 ppTI = &((*ppTI)->next);
2582 (pTypeLibImpl->TypeInfoCount)++;
2586 TRACE("(%p)\n", pTypeLibImpl);
2587 return (ITypeLib2*) pTypeLibImpl;
2591 static BSTR TLB_MultiByteToBSTR(const char *ptr)
2593 DWORD len;
2594 WCHAR *nameW;
2595 BSTR ret;
2597 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2598 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2599 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2600 ret = SysAllocString(nameW);
2601 HeapFree(GetProcessHeap(), 0, nameW);
2602 return ret;
2605 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
2607 char b[3];
2608 int i;
2609 short s;
2611 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2612 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2613 return FALSE;
2616 guid->Data4[0] = s >> 8;
2617 guid->Data4[1] = s & 0xff;
2619 b[2] = '\0';
2620 for(i = 0; i < 6; i++) {
2621 memcpy(b, str + 24 + 2 * i, 2);
2622 guid->Data4[i + 2] = strtol(b, NULL, 16);
2624 return TRUE;
2627 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
2629 WORD bytelen;
2630 DWORD len;
2631 WCHAR *nameW;
2633 *pBstr = NULL;
2634 bytelen = *(const WORD*)ptr;
2635 if(bytelen == 0xffff) return 2;
2636 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2637 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2638 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2639 *pBstr = SysAllocStringLen(nameW, len);
2640 HeapFree(GetProcessHeap(), 0, nameW);
2641 return bytelen + 2;
2644 static WORD SLTG_ReadStringA(const char *ptr, char **str)
2646 WORD bytelen;
2648 *str = NULL;
2649 bytelen = *(const WORD*)ptr;
2650 if(bytelen == 0xffff) return 2;
2651 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2652 memcpy(*str, ptr + 2, bytelen);
2653 (*str)[bytelen] = '\0';
2654 return bytelen + 2;
2657 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2659 char *ptr = pLibBlk;
2660 WORD w;
2662 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2663 FIXME("libblk magic = %04x\n", w);
2664 return 0;
2667 ptr += 6;
2668 if((w = *(WORD*)ptr) != 0xffff) {
2669 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2670 ptr += w;
2672 ptr += 2;
2674 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2676 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2678 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2679 ptr += 4;
2681 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2682 ptr += 2;
2684 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2685 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2686 else
2687 pTypeLibImpl->LibAttr.lcid = 0;
2688 ptr += 2;
2690 ptr += 4; /* skip res12 */
2692 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2693 ptr += 2;
2695 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2696 ptr += 2;
2698 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2699 ptr += 2;
2701 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2702 ptr += sizeof(GUID);
2704 return ptr - (char*)pLibBlk;
2707 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
2708 typedef struct
2710 unsigned int num;
2711 HREFTYPE refs[1];
2712 } sltg_ref_lookup_t;
2714 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
2715 HREFTYPE *typelib_ref)
2717 if(typeinfo_ref < table->num)
2719 *typelib_ref = table->refs[typeinfo_ref];
2720 return S_OK;
2723 ERR("Unable to find reference\n");
2724 *typelib_ref = -1;
2725 return E_FAIL;
2728 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
2730 BOOL done = FALSE;
2732 while(!done) {
2733 if((*pType & 0xe00) == 0xe00) {
2734 pTD->vt = VT_PTR;
2735 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2736 sizeof(TYPEDESC));
2737 pTD = pTD->u.lptdesc;
2739 switch(*pType & 0x3f) {
2740 case VT_PTR:
2741 pTD->vt = VT_PTR;
2742 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2743 sizeof(TYPEDESC));
2744 pTD = pTD->u.lptdesc;
2745 break;
2747 case VT_USERDEFINED:
2748 pTD->vt = VT_USERDEFINED;
2749 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
2750 done = TRUE;
2751 break;
2753 case VT_CARRAY:
2755 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2756 array */
2758 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2760 pTD->vt = VT_CARRAY;
2761 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2762 sizeof(ARRAYDESC) +
2763 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2764 pTD->u.lpadesc->cDims = pSA->cDims;
2765 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2766 pSA->cDims * sizeof(SAFEARRAYBOUND));
2768 pTD = &pTD->u.lpadesc->tdescElem;
2769 break;
2772 case VT_SAFEARRAY:
2774 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2775 useful? */
2777 pType++;
2778 pTD->vt = VT_SAFEARRAY;
2779 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2780 sizeof(TYPEDESC));
2781 pTD = pTD->u.lptdesc;
2782 break;
2784 default:
2785 pTD->vt = *pType & 0x3f;
2786 done = TRUE;
2787 break;
2789 pType++;
2791 return pType;
2794 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
2795 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
2797 /* Handle [in/out] first */
2798 if((*pType & 0xc000) == 0xc000)
2799 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2800 else if(*pType & 0x8000)
2801 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2802 else if(*pType & 0x4000)
2803 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2804 else
2805 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2807 if(*pType & 0x2000)
2808 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2810 if(*pType & 0x80)
2811 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2813 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
2817 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
2818 char *pNameTable)
2820 int ref;
2821 char *name;
2822 TLBRefType *ref_type;
2823 sltg_ref_lookup_t *table;
2824 HREFTYPE typelib_ref;
2826 if(pRef->magic != SLTG_REF_MAGIC) {
2827 FIXME("Ref magic = %x\n", pRef->magic);
2828 return NULL;
2830 name = ( (char*)(&pRef->names) + pRef->number);
2832 table = HeapAlloc(GetProcessHeap(), 0, sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
2833 table->num = pRef->number >> 3;
2835 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
2837 /* We don't want the first href to be 0 */
2838 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
2840 for(ref = 0; ref < pRef->number >> 3; ref++) {
2841 char *refname;
2842 unsigned int lib_offs, type_num;
2844 ref_type = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref_type));
2846 name += SLTG_ReadStringA(name, &refname);
2847 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2848 FIXME("Can't sscanf ref\n");
2849 if(lib_offs != 0xffff) {
2850 TLBImpLib **import = &pTL->pImpLibs;
2852 while(*import) {
2853 if((*import)->offset == lib_offs)
2854 break;
2855 import = &(*import)->next;
2857 if(!*import) {
2858 char fname[MAX_PATH+1];
2859 int len;
2861 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2862 sizeof(**import));
2863 (*import)->offset = lib_offs;
2864 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2865 &(*import)->guid);
2866 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
2867 &(*import)->wVersionMajor,
2868 &(*import)->wVersionMinor,
2869 &(*import)->lcid, fname) != 4) {
2870 FIXME("can't sscanf ref %s\n",
2871 pNameTable + lib_offs + 40);
2873 len = strlen(fname);
2874 if(fname[len-1] != '#')
2875 FIXME("fname = %s\n", fname);
2876 fname[len-1] = '\0';
2877 (*import)->name = TLB_MultiByteToBSTR(fname);
2879 ref_type->pImpTLInfo = *import;
2881 /* Store a reference to IDispatch */
2882 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
2883 pTL->dispatch_href = typelib_ref;
2885 } else { /* internal ref */
2886 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
2888 ref_type->reference = typelib_ref;
2889 ref_type->index = type_num;
2891 HeapFree(GetProcessHeap(), 0, refname);
2892 list_add_tail(&pTL->ref_list, &ref_type->entry);
2894 table->refs[ref] = typelib_ref;
2895 typelib_ref += 4;
2897 if((BYTE)*name != SLTG_REF_MAGIC)
2898 FIXME("End of ref block magic = %x\n", *name);
2899 dump_TLBRefType(pTL);
2900 return table;
2903 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2904 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
2906 SLTG_ImplInfo *info;
2907 TLBImplType **ppImplType = &pTI->impltypelist;
2908 /* I don't really get this structure, usually it's 0x16 bytes
2909 long, but iuser.tlb contains some that are 0x18 bytes long.
2910 That's ok because we can use the next ptr to jump to the next
2911 one. But how do we know the length of the last one? The WORD
2912 at offs 0x8 might be the clue. For now I'm just assuming that
2913 the last one is the regular 0x16 bytes. */
2915 info = (SLTG_ImplInfo*)pBlk;
2916 while(1) {
2917 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2918 sizeof(**ppImplType));
2919 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef);
2920 (*ppImplType)->implflags = info->impltypeflags;
2921 pTI->TypeAttr.cImplTypes++;
2922 ppImplType = &(*ppImplType)->next;
2924 if(info->next == 0xffff)
2925 break;
2926 if(OneOnly)
2927 FIXME("Interface inheriting more than one interface\n");
2928 info = (SLTG_ImplInfo*)(pBlk + info->next);
2930 info++; /* see comment at top of function */
2931 return (char*)info;
2934 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
2935 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
2937 TLBVarDesc **ppVarDesc = &pTI->varlist;
2938 BSTR bstrPrevName = NULL;
2939 SLTG_Variable *pItem;
2940 unsigned short i;
2941 WORD *pType;
2942 char buf[300];
2944 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
2945 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
2947 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2948 sizeof(**ppVarDesc));
2949 (*ppVarDesc)->vardesc.memid = pItem->memid;
2951 if (pItem->magic != SLTG_VAR_MAGIC &&
2952 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
2953 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
2954 return;
2957 if (pItem->name == 0xfffe)
2958 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
2959 else
2960 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2962 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
2963 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
2965 if (pItem->flags & 0x40) {
2966 TRACE_(typelib)("VAR_DISPATCH\n");
2967 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
2969 else if (pItem->flags & 0x10) {
2970 TRACE_(typelib)("VAR_CONST\n");
2971 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2972 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2973 sizeof(VARIANT));
2974 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2975 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2976 *(INT*)(pBlk + pItem->byte_offs);
2978 else {
2979 TRACE_(typelib)("VAR_PERINSTANCE\n");
2980 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2981 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2984 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
2985 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
2987 if (pItem->flags & 0x80)
2988 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
2990 if(pItem->flags & 0x02)
2991 pType = &pItem->type;
2992 else
2993 pType = (WORD*)(pBlk + pItem->type);
2995 if (pItem->flags & ~0xd2)
2996 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xd2);
2998 SLTG_DoElem(pType, pBlk,
2999 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup);
3001 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3003 bstrPrevName = (*ppVarDesc)->Name;
3004 ppVarDesc = &((*ppVarDesc)->next);
3006 pTI->TypeAttr.cVars = cVars;
3009 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3010 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3012 SLTG_Function *pFunc;
3013 unsigned short i;
3014 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3016 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3017 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3019 int param;
3020 WORD *pType, *pArg;
3022 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3023 sizeof(**ppFuncDesc));
3025 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3026 case SLTG_FUNCTION_MAGIC:
3027 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3028 break;
3029 case SLTG_DISPATCH_FUNCTION_MAGIC:
3030 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3031 break;
3032 case SLTG_STATIC_FUNCTION_MAGIC:
3033 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3034 break;
3035 default:
3036 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3037 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
3038 *ppFuncDesc = NULL;
3039 return;
3041 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3043 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3044 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3045 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3046 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3047 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3048 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3050 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3051 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3053 if(pFunc->retnextopt & 0x80)
3054 pType = &pFunc->rettype;
3055 else
3056 pType = (WORD*)(pBlk + pFunc->rettype);
3058 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3060 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3061 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3062 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3063 (*ppFuncDesc)->pParamDesc =
3064 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3065 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3067 pArg = (WORD*)(pBlk + pFunc->arg_off);
3069 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3070 char *paramName = pNameTable + *pArg;
3071 BOOL HaveOffs;
3072 /* If arg type follows then paramName points to the 2nd
3073 letter of the name, else the next WORD is an offset to
3074 the arg type and paramName points to the first letter.
3075 So let's take one char off paramName and see if we're
3076 pointing at an alpha-numeric char. However if *pArg is
3077 0xffff or 0xfffe then the param has no name, the former
3078 meaning that the next WORD is the type, the latter
3079 meaning the the next WORD is an offset to the type. */
3081 HaveOffs = FALSE;
3082 if(*pArg == 0xffff)
3083 paramName = NULL;
3084 else if(*pArg == 0xfffe) {
3085 paramName = NULL;
3086 HaveOffs = TRUE;
3088 else if(paramName[-1] && !isalnum(paramName[-1]))
3089 HaveOffs = TRUE;
3091 pArg++;
3093 if(HaveOffs) { /* the next word is an offset to type */
3094 pType = (WORD*)(pBlk + *pArg);
3095 SLTG_DoElem(pType, pBlk,
3096 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3097 pArg++;
3098 } else {
3099 if(paramName)
3100 paramName--;
3101 pArg = SLTG_DoElem(pArg, pBlk,
3102 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3105 /* Are we an optional param ? */
3106 if((*ppFuncDesc)->funcdesc.cParams - param <=
3107 (*ppFuncDesc)->funcdesc.cParamsOpt)
3108 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3110 if(paramName) {
3111 (*ppFuncDesc)->pParamDesc[param].Name =
3112 TLB_MultiByteToBSTR(paramName);
3116 ppFuncDesc = &((*ppFuncDesc)->next);
3117 if(pFunc->next == 0xffff) break;
3119 pTI->TypeAttr.cFuncs = cFuncs;
3122 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3123 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3124 SLTG_TypeInfoTail *pTITail)
3126 char *pFirstItem, *pNextItem;
3127 sltg_ref_lookup_t *ref_lookup = NULL;
3129 if(pTIHeader->href_table != 0xffffffff) {
3130 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3131 pNameTable);
3134 pFirstItem = pNextItem = pBlk;
3136 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3137 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3139 HeapFree(GetProcessHeap(), 0, ref_lookup);
3143 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3144 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3145 const SLTG_TypeInfoTail *pTITail)
3147 char *pFirstItem, *pNextItem;
3148 sltg_ref_lookup_t *ref_lookup = NULL;
3150 if(pTIHeader->href_table != 0xffffffff) {
3151 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3152 pNameTable);
3155 pFirstItem = pNextItem = pBlk;
3157 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3158 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3161 if (pTITail->funcs_off != 0xffff)
3162 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3164 HeapFree(GetProcessHeap(), 0, ref_lookup);
3166 if (TRACE_ON(typelib))
3167 dump_TLBFuncDesc(pTI->funclist);
3170 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3171 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3172 const SLTG_TypeInfoTail *pTITail)
3174 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3177 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3178 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3179 const SLTG_TypeInfoTail *pTITail)
3181 WORD *pType;
3182 sltg_ref_lookup_t *ref_lookup = NULL;
3184 if (pTITail->simple_alias) {
3185 /* if simple alias, no more processing required */
3186 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3187 return;
3190 if(pTIHeader->href_table != 0xffffffff) {
3191 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3192 pNameTable);
3195 /* otherwise it is an offset to a type */
3196 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3198 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3200 HeapFree(GetProcessHeap(), 0, ref_lookup);
3203 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3204 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3205 const SLTG_TypeInfoTail *pTITail)
3207 sltg_ref_lookup_t *ref_lookup = NULL;
3208 if (pTIHeader->href_table != 0xffffffff)
3209 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3210 pNameTable);
3212 if (pTITail->vars_off != 0xffff)
3213 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3215 if (pTITail->funcs_off != 0xffff)
3216 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3218 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3219 * of dispinterface functons including the IDispatch ones, so
3220 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3221 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3223 HeapFree(GetProcessHeap(), 0, ref_lookup);
3224 if (TRACE_ON(typelib))
3225 dump_TLBFuncDesc(pTI->funclist);
3228 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3229 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3230 const SLTG_TypeInfoTail *pTITail)
3232 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3235 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3236 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3237 const SLTG_TypeInfoTail *pTITail)
3239 sltg_ref_lookup_t *ref_lookup = NULL;
3240 if (pTIHeader->href_table != 0xffffffff)
3241 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3242 pNameTable);
3244 if (pTITail->vars_off != 0xffff)
3245 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3247 if (pTITail->funcs_off != 0xffff)
3248 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3249 HeapFree(GetProcessHeap(), 0, ref_lookup);
3252 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3253 managable copy of it into this */
3254 typedef struct {
3255 WORD small_no;
3256 char *index_name;
3257 char *other_name;
3258 WORD res1a;
3259 WORD name_offs;
3260 WORD more_bytes;
3261 char *extra;
3262 WORD res20;
3263 DWORD helpcontext;
3264 WORD res26;
3265 GUID uuid;
3266 } SLTG_InternalOtherTypeInfo;
3268 /****************************************************************************
3269 * ITypeLib2_Constructor_SLTG
3271 * loading a SLTG typelib from an in-memory image
3273 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3275 ITypeLibImpl *pTypeLibImpl;
3276 SLTG_Header *pHeader;
3277 SLTG_BlkEntry *pBlkEntry;
3278 SLTG_Magic *pMagic;
3279 SLTG_Index *pIndex;
3280 SLTG_Pad9 *pPad9;
3281 LPVOID pBlk, pFirstBlk;
3282 SLTG_LibBlk *pLibBlk;
3283 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3284 char *pAfterOTIBlks = NULL;
3285 char *pNameTable, *ptr;
3286 int i;
3287 DWORD len, order;
3288 ITypeInfoImpl **ppTypeInfoImpl;
3290 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3293 pTypeLibImpl = TypeLibImpl_Constructor();
3294 if (!pTypeLibImpl) return NULL;
3296 pHeader = pLib;
3298 TRACE_(typelib)("header:\n");
3299 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3300 pHeader->nrOfFileBlks );
3301 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3302 FIXME("Header type magic 0x%08x not supported.\n",
3303 pHeader->SLTG_magic);
3304 return NULL;
3307 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3308 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3310 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3311 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3313 /* Next we have a magic block */
3314 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3316 /* Let's see if we're still in sync */
3317 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3318 sizeof(SLTG_COMPOBJ_MAGIC))) {
3319 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3320 return NULL;
3322 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3323 sizeof(SLTG_DIR_MAGIC))) {
3324 FIXME("dir magic = %s\n", pMagic->dir_magic);
3325 return NULL;
3328 pIndex = (SLTG_Index*)(pMagic+1);
3330 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3332 pFirstBlk = (LPVOID)(pPad9 + 1);
3334 /* We'll set up a ptr to the main library block, which is the last one. */
3336 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3337 pBlkEntry[order].next != 0;
3338 order = pBlkEntry[order].next - 1, i++) {
3339 pBlk = (char*)pBlk + pBlkEntry[order].len;
3341 pLibBlk = pBlk;
3343 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3345 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3346 interspersed */
3348 len += 0x40;
3350 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3352 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3353 sizeof(*pOtherTypeInfoBlks) *
3354 pTypeLibImpl->TypeInfoCount);
3357 ptr = (char*)pLibBlk + len;
3359 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3360 WORD w, extra;
3361 len = 0;
3363 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3365 w = *(WORD*)(ptr + 2);
3366 if(w != 0xffff) {
3367 len += w;
3368 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3369 w+1);
3370 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3371 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3373 w = *(WORD*)(ptr + 4 + len);
3374 if(w != 0xffff) {
3375 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3376 len += w;
3377 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3378 w+1);
3379 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3380 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3382 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3383 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3384 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3385 if(extra) {
3386 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3387 extra);
3388 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3389 len += extra;
3391 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3392 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3393 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3394 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3395 len += sizeof(SLTG_OtherTypeInfo);
3396 ptr += len;
3399 pAfterOTIBlks = ptr;
3401 /* Skip this WORD and get the next DWORD */
3402 len = *(DWORD*)(pAfterOTIBlks + 2);
3404 /* Now add this to pLibBLk look at what we're pointing at and
3405 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3406 dust and we should be pointing at the beginning of the name
3407 table */
3409 pNameTable = (char*)pLibBlk + len;
3411 switch(*(WORD*)pNameTable) {
3412 case 0xffff:
3413 break;
3414 case 0x0200:
3415 pNameTable += 0x20;
3416 break;
3417 default:
3418 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3419 break;
3422 pNameTable += 0x216;
3424 pNameTable += 2;
3426 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3428 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3431 /* Hopefully we now have enough ptrs set up to actually read in
3432 some TypeInfos. It's not clear which order to do them in, so
3433 I'll just follow the links along the BlkEntry chain and read
3434 them in the order in which they are in the file */
3436 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3438 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3439 pBlkEntry[order].next != 0;
3440 order = pBlkEntry[order].next - 1, i++) {
3442 SLTG_TypeInfoHeader *pTIHeader;
3443 SLTG_TypeInfoTail *pTITail;
3444 SLTG_MemberHeader *pMemHeader;
3446 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3447 pOtherTypeInfoBlks[i].index_name)) {
3448 FIXME("Index strings don't match\n");
3449 return NULL;
3452 pTIHeader = pBlk;
3453 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3454 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3455 return NULL;
3457 TRACE("pTIHeader->res06 = %x, pTIHeader->res0e = %x, pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3458 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3460 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3461 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3462 (*ppTypeInfoImpl)->index = i;
3463 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3464 pOtherTypeInfoBlks[i].name_offs +
3465 pNameTable);
3466 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3467 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3468 sizeof(GUID));
3469 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3470 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3471 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3472 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3473 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3475 if((pTIHeader->typeflags1 & 7) != 2)
3476 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3477 if(pTIHeader->typeflags3 != 2)
3478 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3480 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3481 debugstr_w((*ppTypeInfoImpl)->Name),
3482 typekind_desc[pTIHeader->typekind],
3483 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3484 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3486 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3488 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3490 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3491 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3492 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3494 switch(pTIHeader->typekind) {
3495 case TKIND_ENUM:
3496 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3497 pTIHeader, pTITail);
3498 break;
3500 case TKIND_RECORD:
3501 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3502 pTIHeader, pTITail);
3503 break;
3505 case TKIND_INTERFACE:
3506 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3507 pTIHeader, pTITail);
3508 break;
3510 case TKIND_COCLASS:
3511 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3512 pTIHeader, pTITail);
3513 break;
3515 case TKIND_ALIAS:
3516 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3517 pTIHeader, pTITail);
3518 break;
3520 case TKIND_DISPATCH:
3521 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3522 pTIHeader, pTITail);
3523 break;
3525 case TKIND_MODULE:
3526 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3527 pTIHeader, pTITail);
3528 break;
3530 default:
3531 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3532 break;
3536 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3537 but we've already set those */
3538 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3539 X(06);
3540 X(16);
3541 X(18);
3542 X(1a);
3543 X(1e);
3544 X(24);
3545 X(26);
3546 X(2a);
3547 X(2c);
3548 X(2e);
3549 X(30);
3550 X(32);
3551 X(34);
3553 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3554 pBlk = (char*)pBlk + pBlkEntry[order].len;
3557 if(i != pTypeLibImpl->TypeInfoCount) {
3558 FIXME("Somehow processed %d TypeInfos\n", i);
3559 return NULL;
3562 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3563 return (ITypeLib2*)pTypeLibImpl;
3566 /* ITypeLib::QueryInterface
3568 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3569 ITypeLib2 * iface,
3570 REFIID riid,
3571 VOID **ppvObject)
3573 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3575 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3577 *ppvObject=NULL;
3578 if(IsEqualIID(riid, &IID_IUnknown) ||
3579 IsEqualIID(riid,&IID_ITypeLib)||
3580 IsEqualIID(riid,&IID_ITypeLib2))
3582 *ppvObject = This;
3585 if(*ppvObject)
3587 ITypeLib2_AddRef(iface);
3588 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3589 return S_OK;
3591 TRACE("-- Interface: E_NOINTERFACE\n");
3592 return E_NOINTERFACE;
3595 /* ITypeLib::AddRef
3597 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3599 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3600 ULONG ref = InterlockedIncrement(&This->ref);
3602 TRACE("(%p)->ref was %u\n",This, ref - 1);
3604 return ref;
3607 /* ITypeLib::Release
3609 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3611 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3612 ULONG ref = InterlockedDecrement(&This->ref);
3614 TRACE("(%p)->(%u)\n",This, ref);
3616 if (!ref)
3618 TLBImpLib *pImpLib, *pImpLibNext;
3619 TLBCustData *pCustData, *pCustDataNext;
3620 TLBRefType *ref_type;
3621 void *cursor2;
3622 int i;
3624 /* remove cache entry */
3625 if(This->path)
3627 TRACE("removing from cache list\n");
3628 EnterCriticalSection(&cache_section);
3629 if (This->next) This->next->prev = This->prev;
3630 if (This->prev) This->prev->next = This->next;
3631 else tlb_cache_first = This->next;
3632 LeaveCriticalSection(&cache_section);
3633 HeapFree(GetProcessHeap(), 0, This->path);
3635 TRACE(" destroying ITypeLib(%p)\n",This);
3637 if (This->Name)
3639 SysFreeString(This->Name);
3640 This->Name = NULL;
3643 if (This->DocString)
3645 SysFreeString(This->DocString);
3646 This->DocString = NULL;
3649 if (This->HelpFile)
3651 SysFreeString(This->HelpFile);
3652 This->HelpFile = NULL;
3655 if (This->HelpStringDll)
3657 SysFreeString(This->HelpStringDll);
3658 This->HelpStringDll = NULL;
3661 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
3663 VariantClear(&pCustData->data);
3665 pCustDataNext = pCustData->next;
3666 TLB_Free(pCustData);
3669 for (i = 0; i < This->ctTypeDesc; i++)
3670 if (This->pTypeDesc[i].vt == VT_CARRAY)
3671 TLB_Free(This->pTypeDesc[i].u.lpadesc);
3673 TLB_Free(This->pTypeDesc);
3675 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
3677 if (pImpLib->pImpTypeLib)
3678 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
3679 TLB_Free(pImpLib->name);
3681 pImpLibNext = pImpLib->next;
3682 TLB_Free(pImpLib);
3685 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
3687 list_remove(&ref_type->entry);
3688 TLB_Free(ref_type);
3691 if (This->pTypeInfo) /* can be NULL */
3692 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3693 HeapFree(GetProcessHeap(),0,This);
3694 return 0;
3697 return ref;
3700 /* ITypeLib::GetTypeInfoCount
3702 * Returns the number of type descriptions in the type library
3704 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3706 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3707 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3708 return This->TypeInfoCount;
3711 /* ITypeLib::GetTypeInfo
3713 * retrieves the specified type description in the library.
3715 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3716 ITypeLib2 *iface,
3717 UINT index,
3718 ITypeInfo **ppTInfo)
3720 int i;
3722 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3723 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3725 TRACE("(%p)->(index=%d)\n", This, index);
3727 if (!ppTInfo) return E_INVALIDARG;
3729 /* search element n in list */
3730 for(i=0; i < index; i++)
3732 pTypeInfo = pTypeInfo->next;
3733 if (!pTypeInfo)
3735 TRACE("-- element not found\n");
3736 return TYPE_E_ELEMENTNOTFOUND;
3740 *ppTInfo = (ITypeInfo *) pTypeInfo;
3742 ITypeInfo_AddRef(*ppTInfo);
3743 TRACE("-- found (%p)\n",*ppTInfo);
3744 return S_OK;
3748 /* ITypeLibs::GetTypeInfoType
3750 * Retrieves the type of a type description.
3752 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3753 ITypeLib2 *iface,
3754 UINT index,
3755 TYPEKIND *pTKind)
3757 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3758 int i;
3759 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3761 if ((ITypeLib2_fnGetTypeInfoCount(iface) < index + 1) || (index < 0))
3762 return TYPE_E_ELEMENTNOTFOUND;
3764 TRACE("(%p) index %d\n", This, index);
3766 if(!pTKind) return E_INVALIDARG;
3768 /* search element n in list */
3769 for(i=0; i < index; i++)
3771 if(!pTInfo)
3773 TRACE("-- element not found\n");
3774 return TYPE_E_ELEMENTNOTFOUND;
3776 pTInfo = pTInfo->next;
3779 *pTKind = pTInfo->TypeAttr.typekind;
3780 TRACE("-- found Type (%d)\n", *pTKind);
3781 return S_OK;
3784 /* ITypeLib::GetTypeInfoOfGuid
3786 * Retrieves the type description that corresponds to the specified GUID.
3789 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3790 ITypeLib2 *iface,
3791 REFGUID guid,
3792 ITypeInfo **ppTInfo)
3794 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3795 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3797 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3799 if (!pTypeInfo)
3801 WARN("-- element not found\n");
3802 return TYPE_E_ELEMENTNOTFOUND;
3805 /* search linked list for guid */
3806 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3808 pTypeInfo = pTypeInfo->next;
3810 if (!pTypeInfo)
3812 /* end of list reached */
3813 WARN("-- element not found\n");
3814 return TYPE_E_ELEMENTNOTFOUND;
3818 TRACE("-- found (%p, %s)\n",
3819 pTypeInfo,
3820 debugstr_w(pTypeInfo->Name));
3822 *ppTInfo = (ITypeInfo*)pTypeInfo;
3823 ITypeInfo_AddRef(*ppTInfo);
3824 return S_OK;
3827 /* ITypeLib::GetLibAttr
3829 * Retrieves the structure that contains the library's attributes.
3832 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3833 ITypeLib2 *iface,
3834 LPTLIBATTR *ppTLibAttr)
3836 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3837 TRACE("(%p)\n",This);
3838 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3839 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3840 return S_OK;
3843 /* ITypeLib::GetTypeComp
3845 * Enables a client compiler to bind to a library's types, variables,
3846 * constants, and global functions.
3849 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3850 ITypeLib2 *iface,
3851 ITypeComp **ppTComp)
3853 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3855 TRACE("(%p)->(%p)\n",This,ppTComp);
3856 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3857 ITypeComp_AddRef(*ppTComp);
3859 return S_OK;
3862 /* ITypeLib::GetDocumentation
3864 * Retrieves the library's documentation string, the complete Help file name
3865 * and path, and the context identifier for the library Help topic in the Help
3866 * file.
3868 * On a successful return all non-null BSTR pointers will have been set,
3869 * possibly to NULL.
3871 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3872 ITypeLib2 *iface,
3873 INT index,
3874 BSTR *pBstrName,
3875 BSTR *pBstrDocString,
3876 DWORD *pdwHelpContext,
3877 BSTR *pBstrHelpFile)
3879 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3881 HRESULT result = E_INVALIDARG;
3883 ITypeInfo *pTInfo;
3886 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3887 This, index,
3888 pBstrName, pBstrDocString,
3889 pdwHelpContext, pBstrHelpFile);
3891 if(index<0)
3893 /* documentation for the typelib */
3894 if(pBstrName)
3896 if (This->Name)
3898 if(!(*pBstrName = SysAllocString(This->Name)))
3899 goto memerr1;
3901 else
3902 *pBstrName = NULL;
3904 if(pBstrDocString)
3906 if (This->DocString)
3908 if(!(*pBstrDocString = SysAllocString(This->DocString)))
3909 goto memerr2;
3911 else if (This->Name)
3913 if(!(*pBstrDocString = SysAllocString(This->Name)))
3914 goto memerr2;
3916 else
3917 *pBstrDocString = NULL;
3919 if(pdwHelpContext)
3921 *pdwHelpContext = This->dwHelpContext;
3923 if(pBstrHelpFile)
3925 if (This->HelpFile)
3927 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
3928 goto memerr3;
3930 else
3931 *pBstrHelpFile = NULL;
3934 result = S_OK;
3936 else
3938 /* for a typeinfo */
3939 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3941 if(SUCCEEDED(result))
3943 result = ITypeInfo_GetDocumentation(pTInfo,
3944 MEMBERID_NIL,
3945 pBstrName,
3946 pBstrDocString,
3947 pdwHelpContext, pBstrHelpFile);
3949 ITypeInfo_Release(pTInfo);
3952 return result;
3953 memerr3:
3954 if (pBstrDocString) SysFreeString (*pBstrDocString);
3955 memerr2:
3956 if (pBstrName) SysFreeString (*pBstrName);
3957 memerr1:
3958 return STG_E_INSUFFICIENTMEMORY;
3961 /* ITypeLib::IsName
3963 * Indicates whether a passed-in string contains the name of a type or member
3964 * described in the library.
3967 static HRESULT WINAPI ITypeLib2_fnIsName(
3968 ITypeLib2 *iface,
3969 LPOLESTR szNameBuf,
3970 ULONG lHashVal,
3971 BOOL *pfName)
3973 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3974 ITypeInfoImpl *pTInfo;
3975 TLBFuncDesc *pFInfo;
3976 TLBVarDesc *pVInfo;
3977 int i;
3978 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3980 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3981 pfName);
3983 *pfName=TRUE;
3984 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3985 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3986 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3987 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3988 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3989 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3990 goto ITypeLib2_fnIsName_exit;
3992 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3993 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3996 *pfName=FALSE;
3998 ITypeLib2_fnIsName_exit:
3999 TRACE("(%p)slow! search for %s: %s found!\n", This,
4000 debugstr_w(szNameBuf), *pfName?"NOT":"");
4002 return S_OK;
4005 /* ITypeLib::FindName
4007 * Finds occurrences of a type description in a type library. This may be used
4008 * to quickly verify that a name exists in a type library.
4011 static HRESULT WINAPI ITypeLib2_fnFindName(
4012 ITypeLib2 *iface,
4013 LPOLESTR szNameBuf,
4014 ULONG lHashVal,
4015 ITypeInfo **ppTInfo,
4016 MEMBERID *rgMemId,
4017 UINT16 *pcFound)
4019 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4020 ITypeInfoImpl *pTInfo;
4021 TLBFuncDesc *pFInfo;
4022 TLBVarDesc *pVInfo;
4023 int i,j = 0;
4024 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4026 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
4027 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4028 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4029 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4030 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
4031 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
4032 goto ITypeLib2_fnFindName_exit;
4035 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4036 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4037 continue;
4038 ITypeLib2_fnFindName_exit:
4039 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4040 ppTInfo[j]=(LPTYPEINFO)pTInfo;
4041 j++;
4043 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4044 This, *pcFound, debugstr_w(szNameBuf), j);
4046 *pcFound=j;
4048 return S_OK;
4051 /* ITypeLib::ReleaseTLibAttr
4053 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4056 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4057 ITypeLib2 *iface,
4058 TLIBATTR *pTLibAttr)
4060 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4061 TRACE("freeing (%p)\n",This);
4062 HeapFree(GetProcessHeap(),0,pTLibAttr);
4066 /* ITypeLib2::GetCustData
4068 * gets the custom data
4070 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4071 ITypeLib2 * iface,
4072 REFGUID guid,
4073 VARIANT *pVarVal)
4075 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4076 TLBCustData *pCData;
4078 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4080 if( IsEqualIID(guid, &pCData->guid)) break;
4083 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4085 if(pCData)
4087 VariantInit( pVarVal);
4088 VariantCopy( pVarVal, &pCData->data);
4089 return S_OK;
4091 return E_INVALIDARG; /* FIXME: correct? */
4094 /* ITypeLib2::GetLibStatistics
4096 * Returns statistics about a type library that are required for efficient
4097 * sizing of hash tables.
4100 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4101 ITypeLib2 * iface,
4102 ULONG *pcUniqueNames,
4103 ULONG *pcchUniqueNames)
4105 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4107 FIXME("(%p): stub!\n", This);
4109 if(pcUniqueNames) *pcUniqueNames=1;
4110 if(pcchUniqueNames) *pcchUniqueNames=1;
4111 return S_OK;
4114 /* ITypeLib2::GetDocumentation2
4116 * Retrieves the library's documentation string, the complete Help file name
4117 * and path, the localization context to use, and the context ID for the
4118 * library Help topic in the Help file.
4121 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4122 ITypeLib2 * iface,
4123 INT index,
4124 LCID lcid,
4125 BSTR *pbstrHelpString,
4126 DWORD *pdwHelpStringContext,
4127 BSTR *pbstrHelpStringDll)
4129 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4130 HRESULT result;
4131 ITypeInfo *pTInfo;
4133 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4135 /* the help string should be obtained from the helpstringdll,
4136 * using the _DLLGetDocumentation function, based on the supplied
4137 * lcid. Nice to do sometime...
4139 if(index<0)
4141 /* documentation for the typelib */
4142 if(pbstrHelpString)
4143 *pbstrHelpString=SysAllocString(This->DocString);
4144 if(pdwHelpStringContext)
4145 *pdwHelpStringContext=This->dwHelpContext;
4146 if(pbstrHelpStringDll)
4147 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4149 result = S_OK;
4151 else
4153 /* for a typeinfo */
4154 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4156 if(SUCCEEDED(result))
4158 ITypeInfo2 * pTInfo2;
4159 result = ITypeInfo_QueryInterface(pTInfo,
4160 &IID_ITypeInfo2,
4161 (LPVOID*) &pTInfo2);
4163 if(SUCCEEDED(result))
4165 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4166 MEMBERID_NIL,
4167 lcid,
4168 pbstrHelpString,
4169 pdwHelpStringContext,
4170 pbstrHelpStringDll);
4172 ITypeInfo2_Release(pTInfo2);
4175 ITypeInfo_Release(pTInfo);
4178 return result;
4181 /* ITypeLib2::GetAllCustData
4183 * Gets all custom data items for the library.
4186 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4187 ITypeLib2 * iface,
4188 CUSTDATA *pCustData)
4190 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4191 TLBCustData *pCData;
4192 int i;
4193 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4194 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4195 if(pCustData->prgCustData ){
4196 pCustData->cCustData=This->ctCustData;
4197 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4198 pCustData->prgCustData[i].guid=pCData->guid;
4199 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4201 }else{
4202 ERR(" OUT OF MEMORY!\n");
4203 return E_OUTOFMEMORY;
4205 return S_OK;
4208 static const ITypeLib2Vtbl tlbvt = {
4209 ITypeLib2_fnQueryInterface,
4210 ITypeLib2_fnAddRef,
4211 ITypeLib2_fnRelease,
4212 ITypeLib2_fnGetTypeInfoCount,
4213 ITypeLib2_fnGetTypeInfo,
4214 ITypeLib2_fnGetTypeInfoType,
4215 ITypeLib2_fnGetTypeInfoOfGuid,
4216 ITypeLib2_fnGetLibAttr,
4217 ITypeLib2_fnGetTypeComp,
4218 ITypeLib2_fnGetDocumentation,
4219 ITypeLib2_fnIsName,
4220 ITypeLib2_fnFindName,
4221 ITypeLib2_fnReleaseTLibAttr,
4223 ITypeLib2_fnGetCustData,
4224 ITypeLib2_fnGetLibStatistics,
4225 ITypeLib2_fnGetDocumentation2,
4226 ITypeLib2_fnGetAllCustData
4230 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4232 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4234 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4237 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4239 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4241 return ITypeLib2_AddRef((ITypeLib2 *)This);
4244 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4246 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4248 return ITypeLib2_Release((ITypeLib2 *)This);
4251 static HRESULT WINAPI ITypeLibComp_fnBind(
4252 ITypeComp * iface,
4253 OLECHAR * szName,
4254 ULONG lHash,
4255 WORD wFlags,
4256 ITypeInfo ** ppTInfo,
4257 DESCKIND * pDescKind,
4258 BINDPTR * pBindPtr)
4260 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4261 ITypeInfoImpl *pTypeInfo;
4263 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4265 *pDescKind = DESCKIND_NONE;
4266 pBindPtr->lptcomp = NULL;
4267 *ppTInfo = NULL;
4269 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4271 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4273 /* FIXME: check wFlags here? */
4274 /* FIXME: we should use a hash table to look this info up using lHash
4275 * instead of an O(n) search */
4276 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4277 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4279 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4281 *pDescKind = DESCKIND_TYPECOMP;
4282 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4283 ITypeComp_AddRef(pBindPtr->lptcomp);
4284 TRACE("module or enum: %s\n", debugstr_w(szName));
4285 return S_OK;
4289 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4290 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4292 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4293 HRESULT hr;
4295 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4296 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4298 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4299 return S_OK;
4303 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4304 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4306 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4307 HRESULT hr;
4308 ITypeInfo *subtypeinfo;
4309 BINDPTR subbindptr;
4310 DESCKIND subdesckind;
4312 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4313 &subtypeinfo, &subdesckind, &subbindptr);
4314 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4316 TYPEDESC tdesc_appobject =
4319 (TYPEDESC *)pTypeInfo->hreftype
4321 VT_USERDEFINED
4323 const VARDESC vardesc_appobject =
4325 -2, /* memid */
4326 NULL, /* lpstrSchema */
4328 0 /* oInst */
4331 /* ELEMDESC */
4333 /* TYPEDESC */
4335 &tdesc_appobject
4337 VT_PTR
4340 0, /* wVarFlags */
4341 VAR_STATIC /* varkind */
4344 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4346 /* cleanup things filled in by Bind call so we can put our
4347 * application object data in there instead */
4348 switch (subdesckind)
4350 case DESCKIND_FUNCDESC:
4351 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4352 break;
4353 case DESCKIND_VARDESC:
4354 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4355 break;
4356 default:
4357 break;
4359 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4361 if (pTypeInfo->hreftype == -1)
4362 FIXME("no hreftype for interface %p\n", pTypeInfo);
4364 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4365 if (FAILED(hr))
4366 return hr;
4368 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4369 *ppTInfo = (ITypeInfo *)pTypeInfo;
4370 ITypeInfo_AddRef(*ppTInfo);
4371 return S_OK;
4376 TRACE("name not found %s\n", debugstr_w(szName));
4377 return S_OK;
4380 static HRESULT WINAPI ITypeLibComp_fnBindType(
4381 ITypeComp * iface,
4382 OLECHAR * szName,
4383 ULONG lHash,
4384 ITypeInfo ** ppTInfo,
4385 ITypeComp ** ppTComp)
4387 FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4388 return E_NOTIMPL;
4391 static const ITypeCompVtbl tlbtcvt =
4394 ITypeLibComp_fnQueryInterface,
4395 ITypeLibComp_fnAddRef,
4396 ITypeLibComp_fnRelease,
4398 ITypeLibComp_fnBind,
4399 ITypeLibComp_fnBindType
4402 /*================== ITypeInfo(2) Methods ===================================*/
4403 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4405 ITypeInfoImpl * pTypeInfoImpl;
4407 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4408 if (pTypeInfoImpl)
4410 pTypeInfoImpl->lpVtbl = &tinfvt;
4411 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4412 pTypeInfoImpl->ref=1;
4413 pTypeInfoImpl->hreftype = -1;
4414 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4415 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4417 TRACE("(%p)\n", pTypeInfoImpl);
4418 return (ITypeInfo2*) pTypeInfoImpl;
4421 /* ITypeInfo::QueryInterface
4423 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4424 ITypeInfo2 *iface,
4425 REFIID riid,
4426 VOID **ppvObject)
4428 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4430 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4432 *ppvObject=NULL;
4433 if(IsEqualIID(riid, &IID_IUnknown) ||
4434 IsEqualIID(riid,&IID_ITypeInfo)||
4435 IsEqualIID(riid,&IID_ITypeInfo2))
4436 *ppvObject = This;
4438 if(*ppvObject){
4439 ITypeInfo_AddRef(iface);
4440 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4441 return S_OK;
4443 TRACE("-- Interface: E_NOINTERFACE\n");
4444 return E_NOINTERFACE;
4447 /* ITypeInfo::AddRef
4449 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4451 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4452 ULONG ref = InterlockedIncrement(&This->ref);
4454 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4456 TRACE("(%p)->ref is %u\n",This, ref);
4457 return ref;
4460 /* ITypeInfo::Release
4462 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4464 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4465 ULONG ref = InterlockedDecrement(&This->ref);
4467 TRACE("(%p)->(%u)\n",This, ref);
4469 if (ref) {
4470 /* We don't release ITypeLib when ref=0 because
4471 it means that function is called by ITypeLib2_Release */
4472 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4473 } else {
4474 TLBFuncDesc *pFInfo, *pFInfoNext;
4475 TLBVarDesc *pVInfo, *pVInfoNext;
4476 TLBImplType *pImpl, *pImplNext;
4477 TLBCustData *pCustData, *pCustDataNext;
4479 TRACE("destroying ITypeInfo(%p)\n",This);
4481 if (This->no_free_data)
4482 goto finish_free;
4484 if (This->Name)
4486 SysFreeString(This->Name);
4487 This->Name = 0;
4490 if (This->DocString)
4492 SysFreeString(This->DocString);
4493 This->DocString = 0;
4496 if (This->DllName)
4498 SysFreeString(This->DllName);
4499 This->DllName = 0;
4502 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4504 UINT i;
4505 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4507 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4508 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4510 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4511 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4513 SysFreeString(pFInfo->pParamDesc[i].Name);
4515 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4516 TLB_Free(pFInfo->pParamDesc);
4517 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
4519 VariantClear(&pCustData->data);
4521 pCustDataNext = pCustData->next;
4522 TLB_Free(pCustData);
4524 if (HIWORD(pFInfo->Entry) != 0 && pFInfo->Entry != (BSTR)-1)
4525 SysFreeString(pFInfo->Entry);
4526 SysFreeString(pFInfo->HelpString);
4527 SysFreeString(pFInfo->Name);
4529 pFInfoNext = pFInfo->next;
4530 TLB_Free(pFInfo);
4532 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
4534 if (pVInfo->vardesc.varkind == VAR_CONST)
4536 VariantClear(pVInfo->vardesc.u.lpvarValue);
4537 TLB_Free(pVInfo->vardesc.u.lpvarValue);
4539 SysFreeString(pVInfo->Name);
4540 pVInfoNext = pVInfo->next;
4541 TLB_Free(pVInfo);
4543 for(pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
4545 for (pCustData = pImpl->pCustData; pCustData; pCustData = pCustDataNext)
4547 VariantClear(&pCustData->data);
4549 pCustDataNext = pCustData->next;
4550 TLB_Free(pCustData);
4552 pImplNext = pImpl->next;
4553 TLB_Free(pImpl);
4555 TLB_Free(This->pCustData);
4557 finish_free:
4558 if (This->next)
4560 ITypeInfo_Release((ITypeInfo*)This->next);
4563 HeapFree(GetProcessHeap(),0,This);
4564 return 0;
4566 return ref;
4569 /* ITypeInfo::GetTypeAttr
4571 * Retrieves a TYPEATTR structure that contains the attributes of the type
4572 * description.
4575 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4576 LPTYPEATTR *ppTypeAttr)
4578 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4579 SIZE_T size;
4581 TRACE("(%p)\n",This);
4583 size = sizeof(**ppTypeAttr);
4584 if (This->TypeAttr.typekind == TKIND_ALIAS)
4585 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4587 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4588 if (!*ppTypeAttr)
4589 return E_OUTOFMEMORY;
4591 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4593 if (This->TypeAttr.typekind == TKIND_ALIAS)
4594 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4595 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4597 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4598 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4599 funcs */
4600 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4601 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4603 return S_OK;
4606 /* ITypeInfo::GetTypeComp
4608 * Retrieves the ITypeComp interface for the type description, which enables a
4609 * client compiler to bind to the type description's members.
4612 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4613 ITypeComp * *ppTComp)
4615 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4617 TRACE("(%p)->(%p)\n", This, ppTComp);
4619 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4620 ITypeComp_AddRef(*ppTComp);
4621 return S_OK;
4624 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4626 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4627 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4628 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4629 return size;
4632 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4634 memcpy(dest, src, sizeof(ELEMDESC));
4635 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4636 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4638 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4639 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4640 *buffer += sizeof(PARAMDESCEX);
4641 memcpy(pparamdescex_dest, pparamdescex_src, sizeof(PARAMDESCEX));
4642 VariantInit(&pparamdescex_dest->varDefaultValue);
4643 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4644 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4646 else
4647 dest->u.paramdesc.pparamdescex = NULL;
4648 return S_OK;
4651 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4653 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4654 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4657 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4659 FUNCDESC *dest;
4660 char *buffer;
4661 SIZE_T size = sizeof(*src);
4662 SHORT i;
4663 HRESULT hr;
4665 size += sizeof(*src->lprgscode) * src->cScodes;
4666 size += TLB_SizeElemDesc(&src->elemdescFunc);
4667 for (i = 0; i < src->cParams; i++)
4669 size += sizeof(ELEMDESC);
4670 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4673 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4674 if (!dest) return E_OUTOFMEMORY;
4676 memcpy(dest, src, sizeof(FUNCDESC));
4677 buffer = (char *)(dest + 1);
4679 dest->lprgscode = (SCODE *)buffer;
4680 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4681 buffer += sizeof(*src->lprgscode) * src->cScodes;
4683 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4684 if (FAILED(hr))
4686 SysFreeString((BSTR)dest);
4687 return hr;
4690 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4691 buffer += sizeof(ELEMDESC) * src->cParams;
4692 for (i = 0; i < src->cParams; i++)
4694 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4695 if (FAILED(hr))
4696 break;
4698 if (FAILED(hr))
4700 /* undo the above actions */
4701 for (i = i - 1; i >= 0; i--)
4702 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4703 TLB_FreeElemDesc(&dest->elemdescFunc);
4704 SysFreeString((BSTR)dest);
4705 return hr;
4708 /* special treatment for dispinterfaces: this makes functions appear
4709 * to return their [retval] value when it is really returning an
4710 * HRESULT */
4711 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4713 if (dest->cParams &&
4714 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4716 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4717 if (elemdesc->tdesc.vt != VT_PTR)
4719 ERR("elemdesc should have started with VT_PTR instead of:\n");
4720 if (ERR_ON(ole))
4721 dump_ELEMDESC(elemdesc);
4722 return E_UNEXPECTED;
4725 /* copy last parameter to the return value. we are using a flat
4726 * buffer so there is no danger of leaking memory in
4727 * elemdescFunc */
4728 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4730 /* remove the last parameter */
4731 dest->cParams--;
4733 else
4734 /* otherwise this function is made to appear to have no return
4735 * value */
4736 dest->elemdescFunc.tdesc.vt = VT_VOID;
4740 *dest_ptr = dest;
4741 return S_OK;
4744 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4746 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4747 const TLBFuncDesc *pFDesc;
4748 int i;
4750 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4753 if (pFDesc)
4755 *ppFuncDesc = &pFDesc->funcdesc;
4756 return S_OK;
4759 return TYPE_E_ELEMENTNOTFOUND;
4762 /* internal function to make the inherited interfaces' methods appear
4763 * part of the interface */
4764 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
4765 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
4767 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4768 HRESULT hr;
4769 UINT implemented_funcs = 0;
4771 if (funcs)
4772 *funcs = 0;
4773 else
4774 *hrefoffset = DISPATCH_HREF_OFFSET;
4776 if(This->impltypelist)
4778 ITypeInfo *pSubTypeInfo;
4779 UINT sub_funcs;
4781 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
4782 if (FAILED(hr))
4783 return hr;
4785 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
4786 index,
4787 ppFuncDesc,
4788 &sub_funcs, hrefoffset);
4789 implemented_funcs += sub_funcs;
4790 ITypeInfo_Release(pSubTypeInfo);
4791 if (SUCCEEDED(hr))
4792 return hr;
4793 *hrefoffset += DISPATCH_HREF_OFFSET;
4796 if (funcs)
4797 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
4798 else
4799 *hrefoffset = 0;
4801 if (index < implemented_funcs)
4802 return E_INVALIDARG;
4803 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
4804 ppFuncDesc);
4807 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
4809 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
4810 while (TRUE)
4812 switch (pTypeDesc->vt)
4814 case VT_USERDEFINED:
4815 pTypeDesc->u.hreftype += hrefoffset;
4816 return;
4817 case VT_PTR:
4818 case VT_SAFEARRAY:
4819 pTypeDesc = pTypeDesc->u.lptdesc;
4820 break;
4821 case VT_CARRAY:
4822 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
4823 break;
4824 default:
4825 return;
4830 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
4832 SHORT i;
4833 for (i = 0; i < pFuncDesc->cParams; i++)
4834 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
4835 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
4838 /* ITypeInfo::GetFuncDesc
4840 * Retrieves the FUNCDESC structure that contains information about a
4841 * specified function.
4844 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4845 LPFUNCDESC *ppFuncDesc)
4847 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4848 const FUNCDESC *internal_funcdesc;
4849 HRESULT hr;
4850 UINT hrefoffset = 0;
4852 TRACE("(%p) index %d\n", This, index);
4854 if (This->TypeAttr.typekind == TKIND_DISPATCH)
4855 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
4856 &internal_funcdesc, NULL,
4857 &hrefoffset);
4858 else
4859 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
4860 &internal_funcdesc);
4861 if (FAILED(hr))
4863 WARN("description for function %d not found\n", index);
4864 return hr;
4867 hr = TLB_AllocAndInitFuncDesc(
4868 internal_funcdesc,
4869 ppFuncDesc,
4870 This->TypeAttr.typekind == TKIND_DISPATCH);
4872 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
4873 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
4875 TRACE("-- 0x%08x\n", hr);
4876 return hr;
4879 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
4881 VARDESC *dest;
4882 char *buffer;
4883 SIZE_T size = sizeof(*src);
4884 HRESULT hr;
4886 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
4887 if (src->varkind == VAR_CONST)
4888 size += sizeof(VARIANT);
4889 size += TLB_SizeElemDesc(&src->elemdescVar);
4891 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
4892 if (!dest) return E_OUTOFMEMORY;
4894 *dest = *src;
4895 buffer = (char *)(dest + 1);
4896 if (src->lpstrSchema)
4898 int len;
4899 dest->lpstrSchema = (LPOLESTR)buffer;
4900 len = strlenW(src->lpstrSchema);
4901 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
4902 buffer += (len + 1) * sizeof(WCHAR);
4905 if (src->varkind == VAR_CONST)
4907 HRESULT hr;
4909 dest->u.lpvarValue = (VARIANT *)buffer;
4910 *dest->u.lpvarValue = *src->u.lpvarValue;
4911 buffer += sizeof(VARIANT);
4912 VariantInit(dest->u.lpvarValue);
4913 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
4914 if (FAILED(hr))
4916 SysFreeString((BSTR)dest_ptr);
4917 return hr;
4920 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
4921 if (FAILED(hr))
4923 if (src->varkind == VAR_CONST)
4924 VariantClear(dest->u.lpvarValue);
4925 SysFreeString((BSTR)dest);
4926 return hr;
4928 *dest_ptr = dest;
4929 return S_OK;
4932 /* ITypeInfo::GetVarDesc
4934 * Retrieves a VARDESC structure that describes the specified variable.
4937 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4938 LPVARDESC *ppVarDesc)
4940 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4941 int i;
4942 const TLBVarDesc *pVDesc;
4944 TRACE("(%p) index %d\n", This, index);
4946 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4949 if (pVDesc)
4950 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
4952 return E_INVALIDARG;
4955 /* ITypeInfo_GetNames
4957 * Retrieves the variable with the specified member ID (or the name of the
4958 * property or method and its parameters) that correspond to the specified
4959 * function ID.
4961 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4962 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4964 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4965 const TLBFuncDesc *pFDesc;
4966 const TLBVarDesc *pVDesc;
4967 int i;
4968 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
4969 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4970 if(pFDesc)
4972 /* function found, now return function and parameter names */
4973 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4975 if(!i)
4976 *rgBstrNames=SysAllocString(pFDesc->Name);
4977 else
4978 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4980 *pcNames=i;
4982 else
4984 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4985 if(pVDesc)
4987 *rgBstrNames=SysAllocString(pVDesc->Name);
4988 *pcNames=1;
4990 else
4992 if(This->impltypelist &&
4993 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4994 /* recursive search */
4995 ITypeInfo *pTInfo;
4996 HRESULT result;
4997 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4998 &pTInfo);
4999 if(SUCCEEDED(result))
5001 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5002 ITypeInfo_Release(pTInfo);
5003 return result;
5005 WARN("Could not search inherited interface!\n");
5007 else
5009 WARN("no names found\n");
5011 *pcNames=0;
5012 return TYPE_E_ELEMENTNOTFOUND;
5015 return S_OK;
5019 /* ITypeInfo::GetRefTypeOfImplType
5021 * If a type description describes a COM class, it retrieves the type
5022 * description of the implemented interface types. For an interface,
5023 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5024 * if any exist.
5027 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5028 ITypeInfo2 *iface,
5029 UINT index,
5030 HREFTYPE *pRefType)
5032 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5033 int i;
5034 HRESULT hr = S_OK;
5035 const TLBImplType *pImpl = This->impltypelist;
5037 TRACE("(%p) index %d\n", This, index);
5038 if (TRACE_ON(ole)) dump_TypeInfo(This);
5040 if(index==(UINT)-1)
5042 /* only valid on dual interfaces;
5043 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5045 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5047 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
5048 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
5050 *pRefType = -1;
5052 else
5054 hr = TYPE_E_ELEMENTNOTFOUND;
5057 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5059 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5060 *pRefType = This->pTypeLib->dispatch_href;
5062 else
5064 /* get element n from linked list */
5065 for(i=0; pImpl && i<index; i++)
5067 pImpl = pImpl->next;
5070 if (pImpl)
5071 *pRefType = pImpl->hRef;
5072 else
5073 hr = TYPE_E_ELEMENTNOTFOUND;
5076 if(TRACE_ON(ole))
5078 if(SUCCEEDED(hr))
5079 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5080 else
5081 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5084 return hr;
5087 /* ITypeInfo::GetImplTypeFlags
5089 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5090 * or base interface in a type description.
5092 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5093 UINT index, INT *pImplTypeFlags)
5095 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5096 int i;
5097 TLBImplType *pImpl;
5099 TRACE("(%p) index %d\n", This, index);
5100 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5101 i++, pImpl=pImpl->next)
5103 if(i==index && pImpl){
5104 *pImplTypeFlags=pImpl->implflags;
5105 return S_OK;
5107 *pImplTypeFlags=0;
5108 return TYPE_E_ELEMENTNOTFOUND;
5111 /* GetIDsOfNames
5112 * Maps between member names and member IDs, and parameter names and
5113 * parameter IDs.
5115 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5116 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5118 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5119 const TLBFuncDesc *pFDesc;
5120 const TLBVarDesc *pVDesc;
5121 HRESULT ret=S_OK;
5122 int i;
5124 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5125 cNames);
5127 /* init out parameters in case of failure */
5128 for (i = 0; i < cNames; i++)
5129 pMemId[i] = MEMBERID_NIL;
5131 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5132 int j;
5133 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5134 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5135 for(i=1; i < cNames; i++){
5136 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5137 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5138 break;
5139 if( j<pFDesc->funcdesc.cParams)
5140 pMemId[i]=j;
5141 else
5142 ret=DISP_E_UNKNOWNNAME;
5144 TRACE("-- 0x%08x\n", ret);
5145 return ret;
5148 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5149 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5150 if(cNames) *pMemId=pVDesc->vardesc.memid;
5151 return ret;
5154 /* not found, see if it can be found in an inherited interface */
5155 if(This->impltypelist) {
5156 /* recursive search */
5157 ITypeInfo *pTInfo;
5158 ret=ITypeInfo_GetRefTypeInfo(iface,
5159 This->impltypelist->hRef, &pTInfo);
5160 if(SUCCEEDED(ret)){
5161 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5162 ITypeInfo_Release(pTInfo);
5163 return ret;
5165 WARN("Could not search inherited interface!\n");
5166 } else
5167 WARN("no names found\n");
5168 return DISP_E_UNKNOWNNAME;
5171 /* ITypeInfo::Invoke
5173 * Invokes a method, or accesses a property of an object, that implements the
5174 * interface described by the type description.
5176 DWORD
5177 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5178 DWORD res;
5180 if (TRACE_ON(ole)) {
5181 int i;
5182 TRACE("Calling %p(",func);
5183 for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
5184 TRACE(")\n");
5187 switch (callconv) {
5188 case CC_STDCALL:
5190 switch (nrargs) {
5191 case 0:
5192 res = func();
5193 break;
5194 case 1:
5195 res = func(args[0]);
5196 break;
5197 case 2:
5198 res = func(args[0],args[1]);
5199 break;
5200 case 3:
5201 res = func(args[0],args[1],args[2]);
5202 break;
5203 case 4:
5204 res = func(args[0],args[1],args[2],args[3]);
5205 break;
5206 case 5:
5207 res = func(args[0],args[1],args[2],args[3],args[4]);
5208 break;
5209 case 6:
5210 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
5211 break;
5212 case 7:
5213 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
5214 break;
5215 case 8:
5216 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
5217 break;
5218 case 9:
5219 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
5220 break;
5221 case 10:
5222 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
5223 break;
5224 case 11:
5225 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
5226 break;
5227 case 12:
5228 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11]);
5229 break;
5230 case 13:
5231 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12]);
5232 break;
5233 case 14:
5234 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13]);
5235 break;
5236 case 15:
5237 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14]);
5238 break;
5239 case 16:
5240 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15]);
5241 break;
5242 case 17:
5243 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16]);
5244 break;
5245 case 18:
5246 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17]);
5247 break;
5248 case 19:
5249 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18]);
5250 break;
5251 case 20:
5252 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19]);
5253 break;
5254 case 21:
5255 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20]);
5256 break;
5257 case 22:
5258 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21]);
5259 break;
5260 case 23:
5261 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22]);
5262 break;
5263 case 24:
5264 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23]);
5265 break;
5266 case 25:
5267 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24]);
5268 break;
5269 case 26:
5270 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25]);
5271 break;
5272 case 27:
5273 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26]);
5274 break;
5275 case 28:
5276 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26],args[27]);
5277 break;
5278 case 29:
5279 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26],args[27],args[28]);
5280 break;
5281 case 30:
5282 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26],args[27],args[28],args[29]);
5283 break;
5284 default:
5285 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
5286 res = -1;
5287 break;
5289 break;
5290 default:
5291 FIXME("unsupported calling convention %d\n",callconv);
5292 res = -1;
5293 break;
5295 TRACE("returns %08x\n",res);
5296 return res;
5299 extern int _argsize(DWORD vt);
5301 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5303 HRESULT hr = S_OK;
5304 ITypeInfo *tinfo2 = NULL;
5305 TYPEATTR *tattr = NULL;
5307 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5308 if (hr)
5310 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5311 "hr = 0x%08x\n",
5312 tdesc->u.hreftype, hr);
5313 return hr;
5315 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5316 if (hr)
5318 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5319 ITypeInfo_Release(tinfo2);
5320 return hr;
5323 switch (tattr->typekind)
5325 case TKIND_ENUM:
5326 *vt |= VT_I4;
5327 break;
5329 case TKIND_ALIAS:
5330 tdesc = &tattr->tdescAlias;
5331 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5332 break;
5334 case TKIND_INTERFACE:
5335 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5336 *vt |= VT_DISPATCH;
5337 else
5338 *vt |= VT_UNKNOWN;
5339 break;
5341 case TKIND_DISPATCH:
5342 *vt |= VT_DISPATCH;
5343 break;
5345 case TKIND_COCLASS:
5346 *vt |= VT_DISPATCH;
5347 break;
5349 case TKIND_RECORD:
5350 FIXME("TKIND_RECORD unhandled.\n");
5351 hr = E_NOTIMPL;
5352 break;
5354 case TKIND_UNION:
5355 FIXME("TKIND_UNION unhandled.\n");
5356 hr = E_NOTIMPL;
5357 break;
5359 default:
5360 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5361 hr = E_NOTIMPL;
5362 break;
5364 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5365 ITypeInfo_Release(tinfo2);
5366 return hr;
5369 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5371 HRESULT hr = S_OK;
5373 /* enforce only one level of pointer indirection */
5374 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5376 tdesc = tdesc->u.lptdesc;
5378 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5379 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5380 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5381 if ((tdesc->vt == VT_USERDEFINED) ||
5382 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5384 VARTYPE vt_userdefined = 0;
5385 const TYPEDESC *tdesc_userdefined = tdesc;
5386 if (tdesc->vt == VT_PTR)
5388 vt_userdefined = VT_BYREF;
5389 tdesc_userdefined = tdesc->u.lptdesc;
5391 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5392 if ((hr == S_OK) &&
5393 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5394 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5396 *vt |= vt_userdefined;
5397 return S_OK;
5400 *vt = VT_BYREF;
5403 switch (tdesc->vt)
5405 case VT_HRESULT:
5406 *vt |= VT_ERROR;
5407 break;
5408 case VT_USERDEFINED:
5409 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5410 break;
5411 case VT_VOID:
5412 case VT_CARRAY:
5413 case VT_PTR:
5414 case VT_LPSTR:
5415 case VT_LPWSTR:
5416 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5417 hr = DISP_E_BADVARTYPE;
5418 break;
5419 case VT_SAFEARRAY:
5420 *vt |= VT_ARRAY;
5421 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5422 break;
5423 default:
5424 *vt |= tdesc->vt;
5425 break;
5427 return hr;
5430 /***********************************************************************
5431 * DispCallFunc (OLEAUT32.@)
5433 * Invokes a function of the specifed calling convention, passing the
5434 * specified arguments and returns the result.
5436 * PARAMS
5437 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5438 * oVft [I] The offset in the vtable. See notes.
5439 * cc [I] Calling convention of the function to call.
5440 * vtReturn [I] The return type of the function.
5441 * cActuals [I] Number of parameters.
5442 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5443 * prgpvarg [I] The arguments to pass.
5444 * pvargResult [O] The return value of the function. Can be NULL.
5446 * RETURNS
5447 * Success: S_OK.
5448 * Failure: HRESULT code.
5450 * NOTES
5451 * The HRESULT return value of this function is not affected by the return
5452 * value of the user supplied function, which is returned in pvargResult.
5454 * If pvInstance is NULL then a non-object function is to be called and oVft
5455 * is the address of the function to call.
5457 * The cc parameter can be one of the following values:
5458 *|CC_FASTCALL
5459 *|CC_CDECL
5460 *|CC_PASCAL
5461 *|CC_STDCALL
5462 *|CC_FPFASTCALL
5463 *|CC_SYSCALL
5464 *|CC_MPWCDECL
5465 *|CC_MPWPASCAL
5468 HRESULT WINAPI
5469 DispCallFunc(
5470 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5471 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5473 int i, argsize, argspos;
5474 DWORD *args;
5475 HRESULT hres;
5477 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5478 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5479 pvargResult, V_VT(pvargResult));
5481 argsize = 0;
5482 if (pvInstance)
5483 argsize++; /* for This pointer */
5485 for (i=0;i<cActuals;i++)
5487 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5488 dump_Variant(prgpvarg[i]);
5489 argsize += _argsize(prgvt[i]);
5491 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5493 argspos = 0;
5494 if (pvInstance)
5496 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5497 argspos++;
5500 for (i=0;i<cActuals;i++)
5502 VARIANT *arg = prgpvarg[i];
5503 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5504 if (prgvt[i] == VT_VARIANT)
5505 memcpy(&args[argspos], arg, _argsize(prgvt[i]) * sizeof(DWORD));
5506 else
5507 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5508 argspos += _argsize(prgvt[i]);
5511 if (pvInstance)
5513 FARPROC *vtable = *(FARPROC**)pvInstance;
5514 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5516 else
5517 /* if we aren't invoking an object then the function pointer is stored
5518 * in oVft */
5519 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5521 if (pvargResult && (vtReturn != VT_EMPTY))
5523 TRACE("Method returned 0x%08x\n",hres);
5524 V_VT(pvargResult) = vtReturn;
5525 V_UI4(pvargResult) = hres;
5528 HeapFree(GetProcessHeap(),0,args);
5529 return S_OK;
5532 #define INVBUF_ELEMENT_SIZE \
5533 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5534 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5535 ((VARIANTARG *)(buffer))
5536 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5537 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5538 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5539 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5540 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5541 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5543 static HRESULT WINAPI ITypeInfo_fnInvoke(
5544 ITypeInfo2 *iface,
5545 VOID *pIUnk,
5546 MEMBERID memid,
5547 UINT16 wFlags,
5548 DISPPARAMS *pDispParams,
5549 VARIANT *pVarResult,
5550 EXCEPINFO *pExcepInfo,
5551 UINT *pArgErr)
5553 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5554 int i;
5555 unsigned int var_index;
5556 TYPEKIND type_kind;
5557 HRESULT hres;
5558 const TLBFuncDesc *pFuncInfo;
5560 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
5561 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5564 if (!pDispParams)
5566 ERR("NULL pDispParams not allowed\n");
5567 return E_INVALIDARG;
5570 dump_DispParms(pDispParams);
5572 if (pDispParams->cNamedArgs > pDispParams->cArgs)
5574 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
5575 pDispParams->cNamedArgs, pDispParams->cArgs);
5576 return E_INVALIDARG;
5579 /* we do this instead of using GetFuncDesc since it will return a fake
5580 * FUNCDESC for dispinterfaces and we want the real function description */
5581 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5582 if ((memid == pFuncInfo->funcdesc.memid) &&
5583 (wFlags & pFuncInfo->funcdesc.invkind))
5584 break;
5586 if (pFuncInfo) {
5587 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5589 if (TRACE_ON(ole))
5591 TRACE("invoking:\n");
5592 dump_TLBFuncDescOne(pFuncInfo);
5595 switch (func_desc->funckind) {
5596 case FUNC_PUREVIRTUAL:
5597 case FUNC_VIRTUAL: {
5598 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
5599 VARIANT varresult;
5600 VARIANT retval; /* pointer for storing byref retvals in */
5601 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
5602 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
5603 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
5604 UINT cNamedArgs = pDispParams->cNamedArgs;
5605 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
5607 hres = S_OK;
5609 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
5611 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
5613 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
5614 hres = DISP_E_PARAMNOTFOUND;
5615 goto func_fail;
5617 /* ignore the DISPID_PROPERTYPUT named argument from now on */
5618 cNamedArgs--;
5619 rgdispidNamedArgs++;
5622 if (func_desc->cParamsOpt < 0 && cNamedArgs)
5624 ERR("functions with the vararg attribute do not support named arguments\n");
5625 hres = DISP_E_NONAMEDARGS;
5626 goto func_fail;
5629 for (i = 0; i < func_desc->cParams; i++)
5631 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5632 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
5633 if (FAILED(hres))
5634 goto func_fail;
5637 TRACE("changing args\n");
5638 for (i = 0; i < func_desc->cParams; i++)
5640 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5641 VARIANTARG *src_arg;
5643 if (cNamedArgs)
5645 USHORT j;
5646 src_arg = NULL;
5647 for (j = 0; j < cNamedArgs; j++)
5648 if (rgdispidNamedArgs[j] == i)
5650 src_arg = &pDispParams->rgvarg[j];
5651 break;
5654 else
5655 src_arg = i < pDispParams->cArgs ? &pDispParams->rgvarg[pDispParams->cArgs - 1 - i] : NULL;
5657 if (wParamFlags & PARAMFLAG_FRETVAL)
5659 /* under most conditions the caller is not allowed to
5660 * pass in a dispparam arg in the index of what would be
5661 * the retval parameter. however, there is an exception
5662 * where the extra parameter is used in an extra
5663 * IDispatch::Invoke below */
5664 if ((i < pDispParams->cArgs) &&
5665 ((func_desc->cParams != 1) || !pVarResult ||
5666 !(func_desc->invkind & INVOKE_PROPERTYGET)))
5668 hres = DISP_E_BADPARAMCOUNT;
5669 break;
5672 /* note: this check is placed so that if the caller passes
5673 * in a VARIANTARG for the retval we just ignore it, like
5674 * native does */
5675 if (i == func_desc->cParams - 1)
5677 VARIANTARG *arg;
5678 arg = prgpvarg[i] = &rgvarg[i];
5679 memset(arg, 0, sizeof(*arg));
5680 V_VT(arg) = rgvt[i];
5681 memset(&retval, 0, sizeof(retval));
5682 V_BYREF(arg) = &retval;
5684 else
5686 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
5687 hres = E_UNEXPECTED;
5688 break;
5691 else if (src_arg)
5693 dump_Variant(src_arg);
5695 if (rgvt[i] == VT_VARIANT)
5696 hres = VariantCopy(&rgvarg[i], src_arg);
5697 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
5699 if (rgvt[i] == V_VT(src_arg))
5700 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
5701 else
5703 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5704 hres = VariantCopy(&missing_arg[i], src_arg);
5705 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
5707 V_VT(&rgvarg[i]) = rgvt[i];
5709 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
5711 SAFEARRAY *a;
5712 SAFEARRAYBOUND bound;
5713 VARIANT *v;
5714 LONG j;
5715 bound.lLbound = 0;
5716 bound.cElements = pDispParams->cArgs-i;
5717 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
5719 ERR("SafeArrayCreate failed\n");
5720 break;
5722 hres = SafeArrayAccessData(a, (LPVOID)&v);
5723 if (hres != S_OK)
5725 ERR("SafeArrayAccessData failed with %x\n", hres);
5726 break;
5728 for (j = 0; j < bound.cElements; j++)
5729 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
5730 hres = SafeArrayUnaccessData(a);
5731 if (hres != S_OK)
5733 ERR("SafeArrayUnaccessData failed with %x\n", hres);
5734 break;
5736 V_ARRAY(&rgvarg[i]) = a;
5737 V_VT(&rgvarg[i]) = rgvt[i];
5739 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
5741 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5742 V_VT(&missing_arg[i]) = V_VT(src_arg);
5743 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
5744 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
5745 V_VT(&rgvarg[i]) = rgvt[i];
5747 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
5749 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
5750 V_VT(&rgvarg[i]) = rgvt[i];
5752 else
5754 /* FIXME: this doesn't work for VT_BYREF arguments if
5755 * they are not the same type as in the paramdesc */
5756 V_VT(&rgvarg[i]) = V_VT(src_arg);
5757 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
5758 V_VT(&rgvarg[i]) = rgvt[i];
5761 if (FAILED(hres))
5763 ERR("failed to convert param %d to %s%s from %s%s\n", i,
5764 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
5765 debugstr_VT(src_arg), debugstr_VF(src_arg));
5766 break;
5768 prgpvarg[i] = &rgvarg[i];
5770 else if (wParamFlags & PARAMFLAG_FOPT)
5772 VARIANTARG *arg;
5773 arg = prgpvarg[i] = &rgvarg[i];
5774 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5776 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
5777 if (FAILED(hres))
5778 break;
5780 else
5782 VARIANTARG *missing_arg;
5783 /* if the function wants a pointer to a variant then
5784 * set that up, otherwise just pass the VT_ERROR in
5785 * the argument by value */
5786 if (rgvt[i] & VT_BYREF)
5788 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
5789 V_VT(arg) = VT_VARIANT | VT_BYREF;
5790 V_VARIANTREF(arg) = missing_arg;
5792 else
5793 missing_arg = arg;
5794 V_VT(missing_arg) = VT_ERROR;
5795 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
5798 else
5800 hres = DISP_E_BADPARAMCOUNT;
5801 break;
5804 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5806 /* VT_VOID is a special case for return types, so it is not
5807 * handled in the general function */
5808 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
5809 V_VT(&varresult) = VT_EMPTY;
5810 else
5812 V_VT(&varresult) = 0;
5813 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
5814 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5817 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
5818 V_VT(&varresult), func_desc->cParams, rgvt,
5819 prgpvarg, &varresult);
5821 for (i = 0; i < func_desc->cParams; i++)
5823 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5824 if (wParamFlags & PARAMFLAG_FRETVAL)
5826 if (TRACE_ON(ole))
5828 TRACE("[retval] value: ");
5829 dump_Variant(prgpvarg[i]);
5832 if (pVarResult)
5834 VariantInit(pVarResult);
5835 /* deref return value */
5836 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
5839 /* free data stored in varresult. Note that
5840 * VariantClear doesn't do what we want because we are
5841 * working with byref types. */
5842 /* FIXME: clear safearrays, bstrs, records and
5843 * variants here too */
5844 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
5845 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
5847 if(*V_UNKNOWNREF(prgpvarg[i]))
5848 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
5850 break;
5852 else if (i < pDispParams->cArgs)
5854 if (wParamFlags & PARAMFLAG_FOUT)
5856 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5858 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
5859 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
5861 if (FAILED(hres))
5863 ERR("failed to convert param %d to vt %d\n", i,
5864 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
5865 break;
5868 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
5869 func_desc->cParamsOpt < 0 &&
5870 i == func_desc->cParams-1)
5872 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
5873 LONG j, ubound;
5874 VARIANT *v;
5875 hres = SafeArrayGetUBound(a, 1, &ubound);
5876 if (hres != S_OK)
5878 ERR("SafeArrayGetUBound failed with %x\n", hres);
5879 break;
5881 hres = SafeArrayAccessData(a, (LPVOID)&v);
5882 if (hres != S_OK)
5884 ERR("SafeArrayAccessData failed with %x\n", hres);
5885 break;
5887 for (j = 0; j <= ubound; j++)
5888 VariantClear(&v[j]);
5889 hres = SafeArrayUnaccessData(a);
5890 if (hres != S_OK)
5892 ERR("SafeArrayUnaccessData failed with %x\n", hres);
5893 break;
5896 VariantClear(&rgvarg[i]);
5898 else if (wParamFlags & PARAMFLAG_FOPT)
5900 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5901 VariantClear(&rgvarg[i]);
5905 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
5907 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
5908 hres = DISP_E_EXCEPTION;
5909 if (pExcepInfo)
5911 IErrorInfo *pErrorInfo;
5912 pExcepInfo->scode = V_ERROR(&varresult);
5913 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
5915 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
5916 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
5917 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
5918 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
5920 IErrorInfo_Release(pErrorInfo);
5924 if (V_VT(&varresult) != VT_ERROR)
5926 TRACE("varresult value: ");
5927 dump_Variant(&varresult);
5929 if (pVarResult)
5931 VariantClear(pVarResult);
5932 *pVarResult = varresult;
5934 else
5935 VariantClear(&varresult);
5938 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
5939 (func_desc->invkind & INVOKE_PROPERTYGET) &&
5940 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
5941 (pDispParams->cArgs != 0))
5943 if (V_VT(pVarResult) == VT_DISPATCH)
5945 IDispatch *pDispatch = V_DISPATCH(pVarResult);
5946 /* Note: not VariantClear; we still need the dispatch
5947 * pointer to be valid */
5948 VariantInit(pVarResult);
5949 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
5950 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
5951 pDispParams, pVarResult, pExcepInfo, pArgErr);
5952 IDispatch_Release(pDispatch);
5954 else
5956 VariantClear(pVarResult);
5957 hres = DISP_E_NOTACOLLECTION;
5961 func_fail:
5962 HeapFree(GetProcessHeap(), 0, buffer);
5963 break;
5965 case FUNC_DISPATCH: {
5966 IDispatch *disp;
5968 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5969 if (SUCCEEDED(hres)) {
5970 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5971 hres = IDispatch_Invoke(
5972 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
5973 pVarResult,pExcepInfo,pArgErr
5975 if (FAILED(hres))
5976 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
5977 IDispatch_Release(disp);
5978 } else
5979 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5980 break;
5982 default:
5983 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5984 hres = E_FAIL;
5985 break;
5988 TRACE("-- 0x%08x\n", hres);
5989 return hres;
5991 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5992 VARDESC *var_desc;
5994 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5995 if(FAILED(hres)) return hres;
5997 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5998 dump_VARDESC(var_desc);
5999 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6000 return E_NOTIMPL;
6003 /* not found, look for it in inherited interfaces */
6004 ITypeInfo2_GetTypeKind(iface, &type_kind);
6005 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6006 if(This->impltypelist) {
6007 /* recursive search */
6008 ITypeInfo *pTInfo;
6009 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6010 if(SUCCEEDED(hres)){
6011 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6012 ITypeInfo_Release(pTInfo);
6013 return hres;
6015 WARN("Could not search inherited interface!\n");
6018 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6019 return DISP_E_MEMBERNOTFOUND;
6022 /* ITypeInfo::GetDocumentation
6024 * Retrieves the documentation string, the complete Help file name and path,
6025 * and the context ID for the Help topic for a specified type description.
6027 * (Can be tested by the Visual Basic Editor in Word for instance.)
6029 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6030 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6031 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6033 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6034 const TLBFuncDesc *pFDesc;
6035 const TLBVarDesc *pVDesc;
6036 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6037 " HelpContext(%p) HelpFile(%p)\n",
6038 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6039 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6040 if(pBstrName)
6041 *pBstrName=SysAllocString(This->Name);
6042 if(pBstrDocString)
6043 *pBstrDocString=SysAllocString(This->DocString);
6044 if(pdwHelpContext)
6045 *pdwHelpContext=This->dwHelpContext;
6046 if(pBstrHelpFile)
6047 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6048 return S_OK;
6049 }else {/* for a member */
6050 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6051 if(pFDesc->funcdesc.memid==memid){
6052 if(pBstrName)
6053 *pBstrName = SysAllocString(pFDesc->Name);
6054 if(pBstrDocString)
6055 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6056 if(pdwHelpContext)
6057 *pdwHelpContext=pFDesc->helpcontext;
6058 return S_OK;
6060 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6061 if(pVDesc->vardesc.memid==memid){
6062 if(pBstrName)
6063 *pBstrName = SysAllocString(pVDesc->Name);
6064 if(pBstrDocString)
6065 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6066 if(pdwHelpContext)
6067 *pdwHelpContext=pVDesc->HelpContext;
6068 return S_OK;
6072 if(This->impltypelist &&
6073 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6074 /* recursive search */
6075 ITypeInfo *pTInfo;
6076 HRESULT result;
6077 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6078 &pTInfo);
6079 if(SUCCEEDED(result)) {
6080 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6081 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6082 ITypeInfo_Release(pTInfo);
6083 return result;
6085 WARN("Could not search inherited interface!\n");
6088 WARN("member %d not found\n", memid);
6089 return TYPE_E_ELEMENTNOTFOUND;
6092 /* ITypeInfo::GetDllEntry
6094 * Retrieves a description or specification of an entry point for a function
6095 * in a DLL.
6097 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6098 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6099 WORD *pwOrdinal)
6101 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6102 const TLBFuncDesc *pFDesc;
6104 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6106 if (pBstrDllName) *pBstrDllName = NULL;
6107 if (pBstrName) *pBstrName = NULL;
6108 if (pwOrdinal) *pwOrdinal = 0;
6110 if (This->TypeAttr.typekind != TKIND_MODULE)
6111 return TYPE_E_BADMODULEKIND;
6113 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6114 if(pFDesc->funcdesc.memid==memid){
6115 dump_TypeInfo(This);
6116 if (TRACE_ON(ole))
6117 dump_TLBFuncDescOne(pFDesc);
6119 if (pBstrDllName)
6120 *pBstrDllName = SysAllocString(This->DllName);
6122 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6123 if (pBstrName)
6124 *pBstrName = SysAllocString(pFDesc->Entry);
6125 if (pwOrdinal)
6126 *pwOrdinal = -1;
6127 return S_OK;
6129 if (pBstrName)
6130 *pBstrName = NULL;
6131 if (pwOrdinal)
6132 *pwOrdinal = (DWORD)pFDesc->Entry;
6133 return S_OK;
6135 return TYPE_E_ELEMENTNOTFOUND;
6138 /* internal function to make the inherited interfaces' methods appear
6139 * part of the interface */
6140 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6141 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6143 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6144 HRESULT hr;
6146 TRACE("%p, 0x%x\n", iface, *hRefType);
6148 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK))
6150 ITypeInfo *pSubTypeInfo;
6152 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
6153 if (FAILED(hr))
6154 return hr;
6156 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6157 hRefType, ppTInfo);
6158 ITypeInfo_Release(pSubTypeInfo);
6159 if (SUCCEEDED(hr))
6160 return hr;
6162 *hRefType -= DISPATCH_HREF_OFFSET;
6164 if (!(*hRefType & DISPATCH_HREF_MASK))
6165 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6166 else
6167 return E_FAIL;
6170 /* ITypeInfo::GetRefTypeInfo
6172 * If a type description references other type descriptions, it retrieves
6173 * the referenced type descriptions.
6175 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6176 ITypeInfo2 *iface,
6177 HREFTYPE hRefType,
6178 ITypeInfo **ppTInfo)
6180 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6181 HRESULT result = E_FAIL;
6183 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6185 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6186 ITypeInfo_AddRef(*ppTInfo);
6187 result = S_OK;
6189 else if (hRefType == -1 &&
6190 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6191 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6193 /* when we meet a DUAL dispinterface, we must create the interface
6194 * version of it.
6196 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
6199 /* the interface version contains the same information as the dispinterface
6200 * copy the contents of the structs.
6202 *pTypeInfoImpl = *This;
6203 pTypeInfoImpl->ref = 0;
6205 /* change the type to interface */
6206 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6208 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6210 /* we use data structures from This, so we need to keep a reference
6211 * to it to stop it being destroyed and signal to the new instance to
6212 * not free its data structures when it is destroyed */
6213 pTypeInfoImpl->no_free_data = TRUE;
6214 pTypeInfoImpl->next = This;
6215 ITypeInfo_AddRef((ITypeInfo*) This);
6217 ITypeInfo_AddRef(*ppTInfo);
6219 result = S_OK;
6221 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6222 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6223 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6225 HREFTYPE href_dispatch = hRefType;
6226 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6227 } else {
6228 TLBRefType *ref_type;
6229 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6231 if(ref_type->reference == hRefType)
6232 break;
6234 if(&ref_type->entry == &This->pTypeLib->ref_list)
6236 FIXME("Can't find pRefType for ref %x\n", hRefType);
6237 goto end;
6239 if(hRefType != -1) {
6240 ITypeLib *pTLib = NULL;
6242 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6243 UINT Index;
6244 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6245 } else {
6246 if(ref_type->pImpTLInfo->pImpTypeLib) {
6247 TRACE("typeinfo in imported typelib that is already loaded\n");
6248 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6249 ITypeLib2_AddRef((ITypeLib*) pTLib);
6250 result = S_OK;
6251 } else {
6252 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6253 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6254 ref_type->pImpTLInfo->wVersionMajor,
6255 ref_type->pImpTLInfo->wVersionMinor,
6256 ref_type->pImpTLInfo->lcid,
6257 &pTLib);
6259 if(!SUCCEEDED(result)) {
6260 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6261 result=LoadTypeLib(libnam, &pTLib);
6262 SysFreeString(libnam);
6264 if(SUCCEEDED(result)) {
6265 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6266 ITypeLib2_AddRef(pTLib);
6270 if(SUCCEEDED(result)) {
6271 if(ref_type->index == TLB_REF_USE_GUID)
6272 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6273 &ref_type->guid,
6274 ppTInfo);
6275 else
6276 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6277 ppTInfo);
6279 if (pTLib != NULL)
6280 ITypeLib2_Release(pTLib);
6284 end:
6285 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6286 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6287 return result;
6290 /* ITypeInfo::AddressOfMember
6292 * Retrieves the addresses of static functions or variables, such as those
6293 * defined in a DLL.
6295 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6296 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6298 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6299 HRESULT hr;
6300 BSTR dll, entry;
6301 WORD ordinal;
6302 HMODULE module;
6304 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6306 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6307 if (FAILED(hr))
6308 return hr;
6310 module = LoadLibraryW(dll);
6311 if (!module)
6313 ERR("couldn't load %s\n", debugstr_w(dll));
6314 SysFreeString(dll);
6315 if (entry) SysFreeString(entry);
6316 return STG_E_FILENOTFOUND;
6318 /* FIXME: store library somewhere where we can free it */
6320 if (entry)
6322 LPSTR entryA;
6323 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6324 entryA = HeapAlloc(GetProcessHeap(), 0, len);
6325 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6327 *ppv = GetProcAddress(module, entryA);
6328 if (!*ppv)
6329 ERR("function not found %s\n", debugstr_a(entryA));
6331 HeapFree(GetProcessHeap(), 0, entryA);
6333 else
6335 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6336 if (!*ppv)
6337 ERR("function not found %d\n", ordinal);
6340 SysFreeString(dll);
6341 if (entry) SysFreeString(entry);
6343 if (!*ppv)
6344 return TYPE_E_DLLFUNCTIONNOTFOUND;
6346 return S_OK;
6349 /* ITypeInfo::CreateInstance
6351 * Creates a new instance of a type that describes a component object class
6352 * (coclass).
6354 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6355 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6357 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6358 HRESULT hr;
6359 TYPEATTR *pTA;
6361 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6363 *ppvObj = NULL;
6365 if(pOuterUnk)
6367 WARN("Not able to aggregate\n");
6368 return CLASS_E_NOAGGREGATION;
6371 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6372 if(FAILED(hr)) return hr;
6374 if(pTA->typekind != TKIND_COCLASS)
6376 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6377 hr = E_INVALIDARG;
6378 goto end;
6381 hr = S_FALSE;
6382 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6384 IUnknown *pUnk;
6385 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6386 TRACE("GetActiveObject rets %08x\n", hr);
6387 if(hr == S_OK)
6389 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6390 IUnknown_Release(pUnk);
6394 if(hr != S_OK)
6395 hr = CoCreateInstance(&pTA->guid, NULL,
6396 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6397 riid, ppvObj);
6399 end:
6400 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6401 return hr;
6404 /* ITypeInfo::GetMops
6406 * Retrieves marshalling information.
6408 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6409 BSTR *pBstrMops)
6411 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6412 FIXME("(%p) stub!\n", This);
6413 return S_OK;
6416 /* ITypeInfo::GetContainingTypeLib
6418 * Retrieves the containing type library and the index of the type description
6419 * within that type library.
6421 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6422 ITypeLib * *ppTLib, UINT *pIndex)
6424 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6426 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6427 if (pIndex) {
6428 *pIndex=This->index;
6429 TRACE("returning pIndex=%d\n", *pIndex);
6432 if (ppTLib) {
6433 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6434 ITypeLib2_AddRef(*ppTLib);
6435 TRACE("returning ppTLib=%p\n", *ppTLib);
6438 return S_OK;
6441 /* ITypeInfo::ReleaseTypeAttr
6443 * Releases a TYPEATTR previously returned by GetTypeAttr.
6446 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6447 TYPEATTR* pTypeAttr)
6449 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6450 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6451 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6454 /* ITypeInfo::ReleaseFuncDesc
6456 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6458 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6459 ITypeInfo2 *iface,
6460 FUNCDESC *pFuncDesc)
6462 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6463 SHORT i;
6465 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6467 for (i = 0; i < pFuncDesc->cParams; i++)
6468 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6469 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6471 SysFreeString((BSTR)pFuncDesc);
6474 /* ITypeInfo::ReleaseVarDesc
6476 * Releases a VARDESC previously returned by GetVarDesc.
6478 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6479 VARDESC *pVarDesc)
6481 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6482 TRACE("(%p)->(%p)\n", This, pVarDesc);
6484 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6485 if (pVarDesc->varkind == VAR_CONST)
6486 VariantClear(pVarDesc->u.lpvarValue);
6487 SysFreeString((BSTR)pVarDesc);
6490 /* ITypeInfo2::GetTypeKind
6492 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6495 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6496 TYPEKIND *pTypeKind)
6498 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6499 *pTypeKind=This->TypeAttr.typekind;
6500 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6501 return S_OK;
6504 /* ITypeInfo2::GetTypeFlags
6506 * Returns the type flags without any allocations. This returns a DWORD type
6507 * flag, which expands the type flags without growing the TYPEATTR (type
6508 * attribute).
6511 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6513 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6514 *pTypeFlags=This->TypeAttr.wTypeFlags;
6515 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6516 return S_OK;
6519 /* ITypeInfo2::GetFuncIndexOfMemId
6520 * Binds to a specific member based on a known DISPID, where the member name
6521 * is not known (for example, when binding to a default member).
6524 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
6525 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
6527 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6528 const TLBFuncDesc *pFuncInfo;
6529 int i;
6530 HRESULT result;
6532 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
6533 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
6534 break;
6535 if(pFuncInfo) {
6536 *pFuncIndex = i;
6537 result = S_OK;
6538 } else
6539 result = TYPE_E_ELEMENTNOTFOUND;
6541 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
6542 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6543 return result;
6546 /* TypeInfo2::GetVarIndexOfMemId
6548 * Binds to a specific member based on a known DISPID, where the member name
6549 * is not known (for example, when binding to a default member).
6552 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
6553 MEMBERID memid, UINT *pVarIndex)
6555 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6556 TLBVarDesc *pVarInfo;
6557 int i;
6558 HRESULT result;
6559 for(i=0, pVarInfo=This->varlist; pVarInfo &&
6560 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
6562 if(pVarInfo) {
6563 *pVarIndex = i;
6564 result = S_OK;
6565 } else
6566 result = TYPE_E_ELEMENTNOTFOUND;
6568 TRACE("(%p) memid 0x%08x -> %s\n", This,
6569 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6570 return result;
6573 /* ITypeInfo2::GetCustData
6575 * Gets the custom data
6577 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
6578 ITypeInfo2 * iface,
6579 REFGUID guid,
6580 VARIANT *pVarVal)
6582 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6583 TLBCustData *pCData;
6585 for(pCData=This->pCustData; pCData; pCData = pCData->next)
6586 if( IsEqualIID(guid, &pCData->guid)) break;
6588 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6590 if(pCData)
6592 VariantInit( pVarVal);
6593 VariantCopy( pVarVal, &pCData->data);
6594 return S_OK;
6596 return E_INVALIDARG; /* FIXME: correct? */
6599 /* ITypeInfo2::GetFuncCustData
6601 * Gets the custom data
6603 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
6604 ITypeInfo2 * iface,
6605 UINT index,
6606 REFGUID guid,
6607 VARIANT *pVarVal)
6609 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6610 TLBCustData *pCData=NULL;
6611 TLBFuncDesc * pFDesc;
6612 int i;
6613 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6614 pFDesc=pFDesc->next);
6616 if(pFDesc)
6617 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
6618 if( IsEqualIID(guid, &pCData->guid)) break;
6620 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6622 if(pCData){
6623 VariantInit( pVarVal);
6624 VariantCopy( pVarVal, &pCData->data);
6625 return S_OK;
6627 return E_INVALIDARG; /* FIXME: correct? */
6630 /* ITypeInfo2::GetParamCustData
6632 * Gets the custom data
6634 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
6635 ITypeInfo2 * iface,
6636 UINT indexFunc,
6637 UINT indexParam,
6638 REFGUID guid,
6639 VARIANT *pVarVal)
6641 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6642 TLBCustData *pCData=NULL;
6643 TLBFuncDesc * pFDesc;
6644 int i;
6646 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
6648 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
6649 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
6650 pCData = pCData->next)
6651 if( IsEqualIID(guid, &pCData->guid)) break;
6653 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6655 if(pCData)
6657 VariantInit( pVarVal);
6658 VariantCopy( pVarVal, &pCData->data);
6659 return S_OK;
6661 return E_INVALIDARG; /* FIXME: correct? */
6664 /* ITypeInfo2::GetVarCustData
6666 * Gets the custom data
6668 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
6669 ITypeInfo2 * iface,
6670 UINT index,
6671 REFGUID guid,
6672 VARIANT *pVarVal)
6674 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6675 TLBCustData *pCData=NULL;
6676 TLBVarDesc * pVDesc;
6677 int i;
6679 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
6681 if(pVDesc)
6683 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
6685 if( IsEqualIID(guid, &pCData->guid)) break;
6689 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6691 if(pCData)
6693 VariantInit( pVarVal);
6694 VariantCopy( pVarVal, &pCData->data);
6695 return S_OK;
6697 return E_INVALIDARG; /* FIXME: correct? */
6700 /* ITypeInfo2::GetImplCustData
6702 * Gets the custom data
6704 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6705 ITypeInfo2 * iface,
6706 UINT index,
6707 REFGUID guid,
6708 VARIANT *pVarVal)
6710 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6711 TLBCustData *pCData=NULL;
6712 TLBImplType * pRDesc;
6713 int i;
6715 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6717 if(pRDesc)
6719 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6721 if( IsEqualIID(guid, &pCData->guid)) break;
6725 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6727 if(pCData)
6729 VariantInit( pVarVal);
6730 VariantCopy( pVarVal, &pCData->data);
6731 return S_OK;
6733 return E_INVALIDARG; /* FIXME: correct? */
6736 /* ITypeInfo2::GetDocumentation2
6738 * Retrieves the documentation string, the complete Help file name and path,
6739 * the localization context to use, and the context ID for the library Help
6740 * topic in the Help file.
6743 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6744 ITypeInfo2 * iface,
6745 MEMBERID memid,
6746 LCID lcid,
6747 BSTR *pbstrHelpString,
6748 DWORD *pdwHelpStringContext,
6749 BSTR *pbstrHelpStringDll)
6751 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6752 const TLBFuncDesc *pFDesc;
6753 const TLBVarDesc *pVDesc;
6754 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
6755 "HelpStringContext(%p) HelpStringDll(%p)\n",
6756 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6757 pbstrHelpStringDll );
6758 /* the help string should be obtained from the helpstringdll,
6759 * using the _DLLGetDocumentation function, based on the supplied
6760 * lcid. Nice to do sometime...
6762 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6763 if(pbstrHelpString)
6764 *pbstrHelpString=SysAllocString(This->Name);
6765 if(pdwHelpStringContext)
6766 *pdwHelpStringContext=This->dwHelpStringContext;
6767 if(pbstrHelpStringDll)
6768 *pbstrHelpStringDll=
6769 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6770 return S_OK;
6771 }else {/* for a member */
6772 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6773 if(pFDesc->funcdesc.memid==memid){
6774 if(pbstrHelpString)
6775 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6776 if(pdwHelpStringContext)
6777 *pdwHelpStringContext=pFDesc->HelpStringContext;
6778 if(pbstrHelpStringDll)
6779 *pbstrHelpStringDll=
6780 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6781 return S_OK;
6783 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6784 if(pVDesc->vardesc.memid==memid){
6785 if(pbstrHelpString)
6786 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6787 if(pdwHelpStringContext)
6788 *pdwHelpStringContext=pVDesc->HelpStringContext;
6789 if(pbstrHelpStringDll)
6790 *pbstrHelpStringDll=
6791 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6792 return S_OK;
6795 return TYPE_E_ELEMENTNOTFOUND;
6798 /* ITypeInfo2::GetAllCustData
6800 * Gets all custom data items for the Type info.
6803 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6804 ITypeInfo2 * iface,
6805 CUSTDATA *pCustData)
6807 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6808 TLBCustData *pCData;
6809 int i;
6811 TRACE("(%p) returning %d items\n", This, This->ctCustData);
6813 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6814 if(pCustData->prgCustData ){
6815 pCustData->cCustData=This->ctCustData;
6816 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
6817 pCustData->prgCustData[i].guid=pCData->guid;
6818 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
6820 }else{
6821 ERR(" OUT OF MEMORY!\n");
6822 return E_OUTOFMEMORY;
6824 return S_OK;
6827 /* ITypeInfo2::GetAllFuncCustData
6829 * Gets all custom data items for the specified Function
6832 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
6833 ITypeInfo2 * iface,
6834 UINT index,
6835 CUSTDATA *pCustData)
6837 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6838 TLBCustData *pCData;
6839 TLBFuncDesc * pFDesc;
6840 int i;
6841 TRACE("(%p) index %d\n", This, index);
6842 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6843 pFDesc=pFDesc->next)
6845 if(pFDesc){
6846 pCustData->prgCustData =
6847 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
6848 if(pCustData->prgCustData ){
6849 pCustData->cCustData=pFDesc->ctCustData;
6850 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
6851 pCData = pCData->next){
6852 pCustData->prgCustData[i].guid=pCData->guid;
6853 VariantCopy(& pCustData->prgCustData[i].varValue,
6854 & pCData->data);
6856 }else{
6857 ERR(" OUT OF MEMORY!\n");
6858 return E_OUTOFMEMORY;
6860 return S_OK;
6862 return TYPE_E_ELEMENTNOTFOUND;
6865 /* ITypeInfo2::GetAllParamCustData
6867 * Gets all custom data items for the Functions
6870 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
6871 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
6873 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6874 TLBCustData *pCData=NULL;
6875 TLBFuncDesc * pFDesc;
6876 int i;
6877 TRACE("(%p) index %d\n", This, indexFunc);
6878 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
6879 pFDesc=pFDesc->next)
6881 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
6882 pCustData->prgCustData =
6883 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
6884 sizeof(CUSTDATAITEM));
6885 if(pCustData->prgCustData ){
6886 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
6887 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
6888 pCData; i++, pCData = pCData->next){
6889 pCustData->prgCustData[i].guid=pCData->guid;
6890 VariantCopy(& pCustData->prgCustData[i].varValue,
6891 & pCData->data);
6893 }else{
6894 ERR(" OUT OF MEMORY!\n");
6895 return E_OUTOFMEMORY;
6897 return S_OK;
6899 return TYPE_E_ELEMENTNOTFOUND;
6902 /* ITypeInfo2::GetAllVarCustData
6904 * Gets all custom data items for the specified Variable
6907 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
6908 UINT index, CUSTDATA *pCustData)
6910 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6911 TLBCustData *pCData;
6912 TLBVarDesc * pVDesc;
6913 int i;
6914 TRACE("(%p) index %d\n", This, index);
6915 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
6916 pVDesc=pVDesc->next)
6918 if(pVDesc){
6919 pCustData->prgCustData =
6920 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
6921 if(pCustData->prgCustData ){
6922 pCustData->cCustData=pVDesc->ctCustData;
6923 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
6924 pCData = pCData->next){
6925 pCustData->prgCustData[i].guid=pCData->guid;
6926 VariantCopy(& pCustData->prgCustData[i].varValue,
6927 & pCData->data);
6929 }else{
6930 ERR(" OUT OF MEMORY!\n");
6931 return E_OUTOFMEMORY;
6933 return S_OK;
6935 return TYPE_E_ELEMENTNOTFOUND;
6938 /* ITypeInfo2::GetAllImplCustData
6940 * Gets all custom data items for the specified implementation type
6943 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
6944 ITypeInfo2 * iface,
6945 UINT index,
6946 CUSTDATA *pCustData)
6948 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6949 TLBCustData *pCData;
6950 TLBImplType * pRDesc;
6951 int i;
6952 TRACE("(%p) index %d\n", This, index);
6953 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
6954 pRDesc=pRDesc->next)
6956 if(pRDesc){
6957 pCustData->prgCustData =
6958 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
6959 if(pCustData->prgCustData ){
6960 pCustData->cCustData=pRDesc->ctCustData;
6961 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
6962 pCData = pCData->next){
6963 pCustData->prgCustData[i].guid=pCData->guid;
6964 VariantCopy(& pCustData->prgCustData[i].varValue,
6965 & pCData->data);
6967 }else{
6968 ERR(" OUT OF MEMORY!\n");
6969 return E_OUTOFMEMORY;
6971 return S_OK;
6973 return TYPE_E_ELEMENTNOTFOUND;
6976 static const ITypeInfo2Vtbl tinfvt =
6979 ITypeInfo_fnQueryInterface,
6980 ITypeInfo_fnAddRef,
6981 ITypeInfo_fnRelease,
6983 ITypeInfo_fnGetTypeAttr,
6984 ITypeInfo_fnGetTypeComp,
6985 ITypeInfo_fnGetFuncDesc,
6986 ITypeInfo_fnGetVarDesc,
6987 ITypeInfo_fnGetNames,
6988 ITypeInfo_fnGetRefTypeOfImplType,
6989 ITypeInfo_fnGetImplTypeFlags,
6990 ITypeInfo_fnGetIDsOfNames,
6991 ITypeInfo_fnInvoke,
6992 ITypeInfo_fnGetDocumentation,
6993 ITypeInfo_fnGetDllEntry,
6994 ITypeInfo_fnGetRefTypeInfo,
6995 ITypeInfo_fnAddressOfMember,
6996 ITypeInfo_fnCreateInstance,
6997 ITypeInfo_fnGetMops,
6998 ITypeInfo_fnGetContainingTypeLib,
6999 ITypeInfo_fnReleaseTypeAttr,
7000 ITypeInfo_fnReleaseFuncDesc,
7001 ITypeInfo_fnReleaseVarDesc,
7003 ITypeInfo2_fnGetTypeKind,
7004 ITypeInfo2_fnGetTypeFlags,
7005 ITypeInfo2_fnGetFuncIndexOfMemId,
7006 ITypeInfo2_fnGetVarIndexOfMemId,
7007 ITypeInfo2_fnGetCustData,
7008 ITypeInfo2_fnGetFuncCustData,
7009 ITypeInfo2_fnGetParamCustData,
7010 ITypeInfo2_fnGetVarCustData,
7011 ITypeInfo2_fnGetImplTypeCustData,
7012 ITypeInfo2_fnGetDocumentation2,
7013 ITypeInfo2_fnGetAllCustData,
7014 ITypeInfo2_fnGetAllFuncCustData,
7015 ITypeInfo2_fnGetAllParamCustData,
7016 ITypeInfo2_fnGetAllVarCustData,
7017 ITypeInfo2_fnGetAllImplTypeCustData,
7020 /******************************************************************************
7021 * CreateDispTypeInfo [OLEAUT32.31]
7023 * Build type information for an object so it can be called through an
7024 * IDispatch interface.
7026 * RETURNS
7027 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7028 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7030 * NOTES
7031 * This call allows an objects methods to be accessed through IDispatch, by
7032 * building an ITypeInfo object that IDispatch can use to call through.
7034 HRESULT WINAPI CreateDispTypeInfo(
7035 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7036 LCID lcid, /* [I] Locale Id */
7037 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7039 ITypeInfoImpl *pTIClass, *pTIIface;
7040 ITypeLibImpl *pTypeLibImpl;
7041 int param, func;
7042 TLBFuncDesc **ppFuncDesc;
7043 TLBRefType *ref;
7045 TRACE("\n");
7046 pTypeLibImpl = TypeLibImpl_Constructor();
7047 if (!pTypeLibImpl) return E_FAIL;
7049 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
7050 pTIIface->pTypeLib = pTypeLibImpl;
7051 pTIIface->index = 0;
7052 pTIIface->Name = NULL;
7053 pTIIface->dwHelpContext = -1;
7054 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7055 pTIIface->TypeAttr.lcid = lcid;
7056 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7057 pTIIface->TypeAttr.wMajorVerNum = 0;
7058 pTIIface->TypeAttr.wMinorVerNum = 0;
7059 pTIIface->TypeAttr.cbAlignment = 2;
7060 pTIIface->TypeAttr.cbSizeInstance = -1;
7061 pTIIface->TypeAttr.cbSizeVft = -1;
7062 pTIIface->TypeAttr.cFuncs = 0;
7063 pTIIface->TypeAttr.cImplTypes = 0;
7064 pTIIface->TypeAttr.cVars = 0;
7065 pTIIface->TypeAttr.wTypeFlags = 0;
7067 ppFuncDesc = &pTIIface->funclist;
7068 for(func = 0; func < pidata->cMembers; func++) {
7069 METHODDATA *md = pidata->pmethdata + func;
7070 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
7071 (*ppFuncDesc)->Name = SysAllocString(md->szName);
7072 (*ppFuncDesc)->funcdesc.memid = md->dispid;
7073 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
7074 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
7075 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
7076 (*ppFuncDesc)->funcdesc.callconv = md->cc;
7077 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
7078 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
7079 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
7080 (*ppFuncDesc)->funcdesc.cScodes = 0;
7081 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
7082 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7083 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7084 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7085 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7086 md->cArgs * sizeof(ELEMDESC));
7087 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7088 md->cArgs * sizeof(TLBParDesc));
7089 for(param = 0; param < md->cArgs; param++) {
7090 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7091 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7093 (*ppFuncDesc)->helpcontext = 0;
7094 (*ppFuncDesc)->HelpStringContext = 0;
7095 (*ppFuncDesc)->HelpString = NULL;
7096 (*ppFuncDesc)->Entry = NULL;
7097 (*ppFuncDesc)->ctCustData = 0;
7098 (*ppFuncDesc)->pCustData = NULL;
7099 (*ppFuncDesc)->next = NULL;
7100 pTIIface->TypeAttr.cFuncs++;
7101 ppFuncDesc = &(*ppFuncDesc)->next;
7104 dump_TypeInfo(pTIIface);
7106 pTypeLibImpl->pTypeInfo = pTIIface;
7107 pTypeLibImpl->TypeInfoCount++;
7109 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
7110 pTIClass->pTypeLib = pTypeLibImpl;
7111 pTIClass->index = 1;
7112 pTIClass->Name = NULL;
7113 pTIClass->dwHelpContext = -1;
7114 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7115 pTIClass->TypeAttr.lcid = lcid;
7116 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7117 pTIClass->TypeAttr.wMajorVerNum = 0;
7118 pTIClass->TypeAttr.wMinorVerNum = 0;
7119 pTIClass->TypeAttr.cbAlignment = 2;
7120 pTIClass->TypeAttr.cbSizeInstance = -1;
7121 pTIClass->TypeAttr.cbSizeVft = -1;
7122 pTIClass->TypeAttr.cFuncs = 0;
7123 pTIClass->TypeAttr.cImplTypes = 1;
7124 pTIClass->TypeAttr.cVars = 0;
7125 pTIClass->TypeAttr.wTypeFlags = 0;
7127 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
7128 pTIClass->impltypelist->hRef = 0;
7130 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
7131 ref->index = 0;
7132 ref->reference = 0;
7133 ref->pImpTLInfo = TLB_REF_INTERNAL;
7134 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7136 dump_TypeInfo(pTIClass);
7138 pTIIface->next = pTIClass;
7139 pTypeLibImpl->TypeInfoCount++;
7141 *pptinfo = (ITypeInfo*)pTIClass;
7143 ITypeInfo_AddRef(*pptinfo);
7144 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7146 return S_OK;
7150 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7152 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7154 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7157 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7159 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7161 return ITypeInfo_AddRef((ITypeInfo *)This);
7164 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7166 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7168 return ITypeInfo_Release((ITypeInfo *)This);
7171 static HRESULT WINAPI ITypeComp_fnBind(
7172 ITypeComp * iface,
7173 OLECHAR * szName,
7174 ULONG lHash,
7175 WORD wFlags,
7176 ITypeInfo ** ppTInfo,
7177 DESCKIND * pDescKind,
7178 BINDPTR * pBindPtr)
7180 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7181 const TLBFuncDesc *pFDesc;
7182 const TLBVarDesc *pVDesc;
7183 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7185 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7187 *pDescKind = DESCKIND_NONE;
7188 pBindPtr->lpfuncdesc = NULL;
7189 *ppTInfo = NULL;
7191 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
7192 if (!strcmpiW(pFDesc->Name, szName)) {
7193 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7194 break;
7195 else
7196 /* name found, but wrong flags */
7197 hr = TYPE_E_TYPEMISMATCH;
7200 if (pFDesc)
7202 HRESULT hr = TLB_AllocAndInitFuncDesc(
7203 &pFDesc->funcdesc,
7204 &pBindPtr->lpfuncdesc,
7205 This->TypeAttr.typekind == TKIND_DISPATCH);
7206 if (FAILED(hr))
7207 return hr;
7208 *pDescKind = DESCKIND_FUNCDESC;
7209 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7210 ITypeInfo_AddRef(*ppTInfo);
7211 return S_OK;
7212 } else {
7213 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7214 if (!strcmpiW(pVDesc->Name, szName)) {
7215 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7216 if (FAILED(hr))
7217 return hr;
7218 *pDescKind = DESCKIND_VARDESC;
7219 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7220 ITypeInfo_AddRef(*ppTInfo);
7221 return S_OK;
7225 /* FIXME: search each inherited interface, not just the first */
7226 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7227 /* recursive search */
7228 ITypeInfo *pTInfo;
7229 ITypeComp *pTComp;
7230 HRESULT hr;
7231 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7232 if (SUCCEEDED(hr))
7234 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7235 ITypeInfo_Release(pTInfo);
7237 if (SUCCEEDED(hr))
7239 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7240 ITypeComp_Release(pTComp);
7241 return hr;
7243 WARN("Could not search inherited interface!\n");
7245 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
7246 return hr;
7249 static HRESULT WINAPI ITypeComp_fnBindType(
7250 ITypeComp * iface,
7251 OLECHAR * szName,
7252 ULONG lHash,
7253 ITypeInfo ** ppTInfo,
7254 ITypeComp ** ppTComp)
7256 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7258 /* strange behaviour (does nothing) but like the
7259 * original */
7261 if (!ppTInfo || !ppTComp)
7262 return E_POINTER;
7264 *ppTInfo = NULL;
7265 *ppTComp = NULL;
7267 return S_OK;
7270 static const ITypeCompVtbl tcompvt =
7273 ITypeComp_fnQueryInterface,
7274 ITypeComp_fnAddRef,
7275 ITypeComp_fnRelease,
7277 ITypeComp_fnBind,
7278 ITypeComp_fnBindType