janitorial: Close COM after tests.
[wine.git] / dlls / oleaut32 / typelib.c
blob43aedc5a056e521643590d7ca2c289e67c461e3b
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 HRESULT 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 structures */
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 /* free custom data allocated by MSFT_CustData */
1425 static inline void TLB_FreeCustData(TLBCustData *pCustData)
1427 TLBCustData *pCustDataNext;
1428 for (; pCustData; pCustData = pCustDataNext)
1430 VariantClear(&pCustData->data);
1432 pCustDataNext = pCustData->next;
1433 TLB_Free(pCustData);
1437 /**********************************************************************
1439 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1441 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1443 return pcx->pos;
1446 static inline void MSFT_Seek(TLBContext *pcx, long where)
1448 if (where != DO_NOT_SEEK)
1450 where += pcx->oStart;
1451 if (where > pcx->length)
1453 /* FIXME */
1454 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1455 TLB_abort();
1457 pcx->pos = where;
1461 /* read function */
1462 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1464 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1465 pcx->pos, count, pcx->oStart, pcx->length, where);
1467 MSFT_Seek(pcx, where);
1468 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1469 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1470 pcx->pos += count;
1471 return count;
1474 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1475 long where )
1477 DWORD ret;
1479 ret = MSFT_Read(buffer, count, pcx, where);
1480 FromLEDWords(buffer, ret);
1482 return ret;
1485 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1486 long where )
1488 DWORD ret;
1490 ret = MSFT_Read(buffer, count, pcx, where);
1491 FromLEWords(buffer, ret);
1493 return ret;
1496 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1498 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1499 memset(pGuid,0, sizeof(GUID));
1500 return;
1502 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1503 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1504 pGuid->Data2 = FromLEWord(pGuid->Data2);
1505 pGuid->Data3 = FromLEWord(pGuid->Data3);
1506 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1509 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1511 MSFT_NameIntro niName;
1513 if (offset < 0)
1515 ERR_(typelib)("bad offset %d\n", offset);
1516 return -1;
1519 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1520 pcx->pTblDir->pNametab.offset+offset);
1522 return niName.hreftype;
1525 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1527 char * name;
1528 MSFT_NameIntro niName;
1529 int lengthInChars;
1530 BSTR bstrName = NULL;
1532 if (offset < 0)
1534 ERR_(typelib)("bad offset %d\n", offset);
1535 return NULL;
1537 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1538 pcx->pTblDir->pNametab.offset+offset);
1539 niName.namelen &= 0xFF; /* FIXME: correct ? */
1540 name=TLB_Alloc((niName.namelen & 0xff) +1);
1541 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1542 name[niName.namelen & 0xff]='\0';
1544 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1545 name, -1, NULL, 0);
1547 /* no invalid characters in string */
1548 if (lengthInChars)
1550 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1552 /* don't check for invalid character since this has been done previously */
1553 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1555 TLB_Free(name);
1557 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1558 return bstrName;
1561 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1563 char * string;
1564 INT16 length;
1565 int lengthInChars;
1566 BSTR bstr = NULL;
1568 if(offset<0) return NULL;
1569 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1570 if(length <= 0) return 0;
1571 string=TLB_Alloc(length +1);
1572 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1573 string[length]='\0';
1575 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1576 string, -1, NULL, 0);
1578 /* no invalid characters in string */
1579 if (lengthInChars)
1581 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1583 /* don't check for invalid character since this has been done previously */
1584 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1586 TLB_Free(string);
1588 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1589 return bstr;
1592 * read a value and fill a VARIANT structure
1594 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1596 int size;
1598 TRACE_(typelib)("\n");
1600 if(offset <0) { /* data are packed in here */
1601 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1602 V_I4(pVar) = offset & 0x3ffffff;
1603 return;
1605 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1606 pcx->pTblDir->pCustData.offset + offset );
1607 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1608 switch (V_VT(pVar)){
1609 case VT_EMPTY: /* FIXME: is this right? */
1610 case VT_NULL: /* FIXME: is this right? */
1611 case VT_I2 : /* this should not happen */
1612 case VT_I4 :
1613 case VT_R4 :
1614 case VT_ERROR :
1615 case VT_BOOL :
1616 case VT_I1 :
1617 case VT_UI1 :
1618 case VT_UI2 :
1619 case VT_UI4 :
1620 case VT_INT :
1621 case VT_UINT :
1622 case VT_VOID : /* FIXME: is this right? */
1623 case VT_HRESULT :
1624 size=4; break;
1625 case VT_R8 :
1626 case VT_CY :
1627 case VT_DATE :
1628 case VT_I8 :
1629 case VT_UI8 :
1630 case VT_DECIMAL : /* FIXME: is this right? */
1631 case VT_FILETIME :
1632 size=8;break;
1633 /* pointer types with known behaviour */
1634 case VT_BSTR :{
1635 char * ptr;
1636 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1637 if(size < 0) {
1638 char next;
1639 DWORD origPos = MSFT_Tell(pcx), nullPos;
1641 do {
1642 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1643 } while (next);
1644 nullPos = MSFT_Tell(pcx);
1645 size = nullPos - origPos;
1646 MSFT_Seek(pcx, origPos);
1648 ptr=TLB_Alloc(size);/* allocate temp buffer */
1649 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1650 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1651 /* FIXME: do we need a AtoW conversion here? */
1652 V_UNION(pVar, bstrVal[size])='\0';
1653 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1654 TLB_Free(ptr);
1656 size=-4; break;
1657 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1658 case VT_DISPATCH :
1659 case VT_VARIANT :
1660 case VT_UNKNOWN :
1661 case VT_PTR :
1662 case VT_SAFEARRAY :
1663 case VT_CARRAY :
1664 case VT_USERDEFINED :
1665 case VT_LPSTR :
1666 case VT_LPWSTR :
1667 case VT_BLOB :
1668 case VT_STREAM :
1669 case VT_STORAGE :
1670 case VT_STREAMED_OBJECT :
1671 case VT_STORED_OBJECT :
1672 case VT_BLOB_OBJECT :
1673 case VT_CF :
1674 case VT_CLSID :
1675 default:
1676 size=0;
1677 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1678 V_VT(pVar));
1681 if(size>0) /* (big|small) endian correct? */
1682 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1683 return;
1686 * create a linked list with custom data
1688 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1690 MSFT_CDGuid entry;
1691 TLBCustData* pNew;
1692 int count=0;
1694 TRACE_(typelib)("\n");
1696 while(offset >=0){
1697 count++;
1698 pNew=TLB_Alloc(sizeof(TLBCustData));
1699 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1700 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1701 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1702 /* add new custom data at head of the list */
1703 pNew->next=*ppCustData;
1704 *ppCustData=pNew;
1705 offset = entry.next;
1707 return count;
1710 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1711 ITypeInfoImpl *pTI)
1713 if(type <0)
1714 pTd->vt=type & VT_TYPEMASK;
1715 else
1716 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1718 if(pTd->vt == VT_USERDEFINED)
1719 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1721 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1724 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1726 /* resolve referenced type if any */
1727 while (lpTypeDesc)
1729 switch (lpTypeDesc->vt)
1731 case VT_PTR:
1732 lpTypeDesc = lpTypeDesc->u.lptdesc;
1733 break;
1735 case VT_CARRAY:
1736 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1737 break;
1739 case VT_USERDEFINED:
1740 MSFT_DoRefType(pcx, pTI->pTypeLib,
1741 lpTypeDesc->u.hreftype);
1743 lpTypeDesc = NULL;
1744 break;
1746 default:
1747 lpTypeDesc = NULL;
1752 static void
1753 MSFT_DoFuncs(TLBContext* pcx,
1754 ITypeInfoImpl* pTI,
1755 int cFuncs,
1756 int cVars,
1757 int offset,
1758 TLBFuncDesc** pptfd)
1761 * member information is stored in a data structure at offset
1762 * indicated by the memoffset field of the typeinfo structure
1763 * There are several distinctive parts.
1764 * The first part starts with a field that holds the total length
1765 * of this (first) part excluding this field. Then follow the records,
1766 * for each member there is one record.
1768 * The first entry is always the length of the record (including this
1769 * length word).
1770 * The rest of the record depends on the type of the member. If there is
1771 * a field indicating the member type (function, variable, interface, etc)
1772 * I have not found it yet. At this time we depend on the information
1773 * in the type info and the usual order how things are stored.
1775 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1776 * for each member;
1778 * Third is an equal sized array with file offsets to the name entry
1779 * of each member.
1781 * The fourth and last (?) part is an array with offsets to the records
1782 * in the first part of this file segment.
1785 int infolen, nameoffset, reclength, nrattributes, i;
1786 int recoffset = offset + sizeof(INT);
1788 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1789 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1790 TLBFuncDesc *ptfd_prev = NULL;
1792 TRACE_(typelib)("\n");
1794 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1796 for ( i = 0; i < cFuncs ; i++ )
1798 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1800 /* name, eventually add to a hash table */
1801 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1802 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1804 /* nameoffset is sometimes -1 on the second half of a propget/propput
1805 * pair of functions */
1806 if ((nameoffset == -1) && (i > 0))
1807 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1808 else
1809 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1811 /* read the function information record */
1812 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1814 reclength &= 0xffff;
1816 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1818 /* do the attributes */
1819 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1820 / sizeof(int);
1822 if ( nrattributes > 0 )
1824 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1826 if ( nrattributes > 1 )
1828 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1829 pFuncRec->OptAttr[1]) ;
1831 if ( nrattributes > 2 )
1833 if ( pFuncRec->FKCCIC & 0x2000 )
1835 if (HIWORD(pFuncRec->OptAttr[2]) != 0)
1836 ERR("ordinal 0x%08x invalid, HIWORD != 0\n", pFuncRec->OptAttr[2]);
1837 (*pptfd)->Entry = (BSTR)pFuncRec->OptAttr[2];
1839 else
1841 (*pptfd)->Entry = MSFT_ReadString(pcx,
1842 pFuncRec->OptAttr[2]);
1844 if( nrattributes > 5 )
1846 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1848 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1850 MSFT_CustData(pcx,
1851 pFuncRec->OptAttr[6],
1852 &(*pptfd)->pCustData);
1856 else
1858 (*pptfd)->Entry = (BSTR)-1;
1863 /* fill the FuncDesc Structure */
1864 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1865 offset + infolen + ( i + 1) * sizeof(INT));
1867 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1868 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1869 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1870 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1871 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1872 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1873 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1875 MSFT_GetTdesc(pcx,
1876 pFuncRec->DataType,
1877 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1878 pTI);
1879 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1881 /* do the parameters/arguments */
1882 if(pFuncRec->nrargs)
1884 int j = 0;
1885 MSFT_ParameterInfo paraminfo;
1887 (*pptfd)->funcdesc.lprgelemdescParam =
1888 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1890 (*pptfd)->pParamDesc =
1891 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1893 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1894 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1896 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1898 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1900 MSFT_GetTdesc(pcx,
1901 paraminfo.DataType,
1902 &elemdesc->tdesc,
1903 pTI);
1905 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1907 /* name */
1908 if (paraminfo.oName == -1)
1909 /* this occurs for [propput] or [propget] methods, so
1910 * we should just set the name of the parameter to the
1911 * name of the method. */
1912 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1913 else
1914 (*pptfd)->pParamDesc[j].Name =
1915 MSFT_ReadName( pcx, paraminfo.oName );
1916 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1918 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1920 /* default value */
1921 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1922 (pFuncRec->FKCCIC & 0x1000) )
1924 INT* pInt = (INT *)((char *)pFuncRec +
1925 reclength -
1926 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1928 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1930 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1931 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1933 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1934 pInt[j], pcx);
1936 else
1937 elemdesc->u.paramdesc.pparamdescex = NULL;
1938 /* custom info */
1939 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1941 MSFT_CustData(pcx,
1942 pFuncRec->OptAttr[7+j],
1943 &(*pptfd)->pParamDesc[j].pCustData);
1946 /* SEEK value = jump to offset,
1947 * from there jump to the end of record,
1948 * go back by (j-1) arguments
1950 MSFT_ReadLEDWords( &paraminfo ,
1951 sizeof(MSFT_ParameterInfo), pcx,
1952 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1953 * sizeof(MSFT_ParameterInfo)));
1957 /* scode is not used: archaic win16 stuff FIXME: right? */
1958 (*pptfd)->funcdesc.cScodes = 0 ;
1959 (*pptfd)->funcdesc.lprgscode = NULL ;
1961 ptfd_prev = *pptfd;
1962 pptfd = & ((*pptfd)->next);
1963 recoffset += reclength;
1965 HeapFree(GetProcessHeap(), 0, recbuf);
1968 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1969 int cVars, int offset, TLBVarDesc ** pptvd)
1971 int infolen, nameoffset, reclength;
1972 char recbuf[256];
1973 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1974 int i;
1975 int recoffset;
1977 TRACE_(typelib)("\n");
1979 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1980 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1981 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1982 recoffset += offset+sizeof(INT);
1983 for(i=0;i<cVars;i++){
1984 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1985 /* name, eventually add to a hash table */
1986 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1987 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
1988 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1989 /* read the variable information record */
1990 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1991 reclength &=0xff;
1992 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1993 /* Optional data */
1994 if(reclength >(6*sizeof(INT)) )
1995 (*pptvd)->HelpContext=pVarRec->HelpContext;
1996 if(reclength >(7*sizeof(INT)) )
1997 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1998 if(reclength >(8*sizeof(INT)) )
1999 if(reclength >(9*sizeof(INT)) )
2000 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
2001 /* fill the VarDesc Structure */
2002 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
2003 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2004 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
2005 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
2006 MSFT_GetTdesc(pcx, pVarRec->DataType,
2007 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
2008 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2009 if(pVarRec->VarKind == VAR_CONST ){
2010 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
2011 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
2012 pVarRec->OffsValue, pcx);
2013 } else
2014 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
2015 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
2016 pptvd=&((*pptvd)->next);
2017 recoffset += reclength;
2020 /* fill in data for a hreftype (offset). When the referenced type is contained
2021 * in the typelib, it's just an (file) offset in the type info base dir.
2022 * If comes from import, it's an offset+1 in the ImpInfo table
2023 * */
2024 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2025 int offset)
2027 TLBRefType *ref;
2029 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2031 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2033 if(ref->reference == offset) return;
2036 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
2037 list_add_tail(&pTL->ref_list, &ref->entry);
2039 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2040 /* external typelib */
2041 MSFT_ImpInfo impinfo;
2042 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2044 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2046 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2047 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2048 while (pImpLib){ /* search the known offsets of all import libraries */
2049 if(pImpLib->offset==impinfo.oImpFile) break;
2050 pImpLib=pImpLib->next;
2052 if(pImpLib){
2053 ref->reference = offset;
2054 ref->pImpTLInfo = pImpLib;
2055 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2056 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2057 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2058 ref->index = TLB_REF_USE_GUID;
2059 } else
2060 ref->index = impinfo.oGuid;
2061 }else{
2062 ERR("Cannot find a reference\n");
2063 ref->reference = -1;
2064 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2066 }else{
2067 /* in this typelib */
2068 ref->index = MSFT_HREFTYPE_INDEX(offset);
2069 ref->reference = offset;
2070 ref->pImpTLInfo = TLB_REF_INTERNAL;
2074 /* process Implemented Interfaces of a com class */
2075 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2076 int offset)
2078 int i;
2079 MSFT_RefRecord refrec;
2080 TLBImplType **ppImpl = &pTI->impltypelist;
2082 TRACE_(typelib)("\n");
2084 for(i=0;i<count;i++){
2085 if(offset<0) break; /* paranoia */
2086 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2087 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2088 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2089 (*ppImpl)->hRef = refrec.reftype;
2090 (*ppImpl)->implflags=refrec.flags;
2091 (*ppImpl)->ctCustData=
2092 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2093 offset=refrec.onext;
2094 ppImpl=&((*ppImpl)->next);
2098 * process a typeinfo record
2100 static ITypeInfoImpl * MSFT_DoTypeInfo(
2101 TLBContext *pcx,
2102 int count,
2103 ITypeLibImpl * pLibInfo)
2105 MSFT_TypeInfoBase tiBase;
2106 ITypeInfoImpl *ptiRet;
2108 TRACE_(typelib)("count=%u\n", count);
2110 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2111 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2112 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2114 /* this is where we are coming from */
2115 ptiRet->pTypeLib = pLibInfo;
2116 ptiRet->index=count;
2117 /* fill in the typeattr fields */
2119 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2120 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2121 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2122 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2123 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2124 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2125 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2126 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2127 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2128 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2129 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2130 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2131 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2132 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2133 MSFT_GetTdesc(pcx, tiBase.datatype1,
2134 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2136 /* FIXME: */
2137 /* IDLDESC idldescType; *//* never saw this one != zero */
2139 /* name, eventually add to a hash table */
2140 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2141 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2142 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2143 /* help info */
2144 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2145 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2146 ptiRet->dwHelpContext=tiBase.helpcontext;
2148 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2149 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2151 /* note: InfoType's Help file and HelpStringDll come from the containing
2152 * library. Further HelpString and Docstring appear to be the same thing :(
2154 /* functions */
2155 if(ptiRet->TypeAttr.cFuncs >0 )
2156 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2157 ptiRet->TypeAttr.cVars,
2158 tiBase.memoffset, & ptiRet->funclist);
2159 /* variables */
2160 if(ptiRet->TypeAttr.cVars >0 )
2161 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2162 ptiRet->TypeAttr.cVars,
2163 tiBase.memoffset, & ptiRet->varlist);
2164 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2165 switch(ptiRet->TypeAttr.typekind)
2167 case TKIND_COCLASS:
2168 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2169 tiBase.datatype1);
2170 break;
2171 case TKIND_DISPATCH:
2172 /* This is not -1 when the interface is a non-base dual interface or
2173 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2174 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2175 not this interface.
2178 if (tiBase.datatype1 != -1)
2180 ptiRet->impltypelist = TLB_Alloc(sizeof(TLBImplType));
2181 ptiRet->impltypelist->hRef = tiBase.datatype1;
2182 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2184 break;
2185 default:
2186 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2187 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2188 ptiRet->impltypelist->hRef = tiBase.datatype1;
2189 break;
2192 ptiRet->ctCustData=
2193 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2195 TRACE_(typelib)("%s guid: %s kind:%s\n",
2196 debugstr_w(ptiRet->Name),
2197 debugstr_guid(&ptiRet->TypeAttr.guid),
2198 typekind_desc[ptiRet->TypeAttr.typekind]);
2200 return ptiRet;
2203 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2204 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2205 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2206 * tradeoff here.
2208 static ITypeLibImpl *tlb_cache_first;
2209 static CRITICAL_SECTION cache_section;
2210 static CRITICAL_SECTION_DEBUG cache_section_debug =
2212 0, 0, &cache_section,
2213 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2214 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2216 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2219 typedef struct TLB_PEFile
2221 const IUnknownVtbl *lpvtbl;
2222 LONG refs;
2223 HMODULE dll;
2224 HRSRC typelib_resource;
2225 HGLOBAL typelib_global;
2226 LPVOID typelib_base;
2227 } TLB_PEFile;
2229 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2231 if (IsEqualIID(riid, &IID_IUnknown))
2233 *ppv = iface;
2234 IUnknown_AddRef(iface);
2235 return S_OK;
2237 *ppv = NULL;
2238 return E_NOINTERFACE;
2241 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2243 TLB_PEFile *This = (TLB_PEFile *)iface;
2244 return InterlockedIncrement(&This->refs);
2247 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2249 TLB_PEFile *This = (TLB_PEFile *)iface;
2250 ULONG refs = InterlockedDecrement(&This->refs);
2251 if (!refs)
2253 if (This->typelib_global)
2254 FreeResource(This->typelib_global);
2255 if (This->dll)
2256 FreeLibrary(This->dll);
2257 HeapFree(GetProcessHeap(), 0, This);
2259 return refs;
2262 static const IUnknownVtbl TLB_PEFile_Vtable =
2264 TLB_PEFile_QueryInterface,
2265 TLB_PEFile_AddRef,
2266 TLB_PEFile_Release
2269 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2271 TLB_PEFile *This;
2273 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2274 if (!This)
2275 return E_OUTOFMEMORY;
2277 This->lpvtbl = &TLB_PEFile_Vtable;
2278 This->refs = 1;
2279 This->dll = NULL;
2280 This->typelib_resource = NULL;
2281 This->typelib_global = NULL;
2282 This->typelib_base = NULL;
2284 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2285 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2287 if (This->dll)
2289 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2290 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2291 if (This->typelib_resource)
2293 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2294 if (This->typelib_global)
2296 This->typelib_base = LockResource(This->typelib_global);
2298 if (This->typelib_base)
2300 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2301 *ppBase = This->typelib_base;
2302 *ppFile = (IUnknown *)&This->lpvtbl;
2303 return S_OK;
2309 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2310 return TYPE_E_CANTLOADLIBRARY;
2314 typedef struct TLB_Mapping
2316 const IUnknownVtbl *lpvtbl;
2317 LONG refs;
2318 HANDLE file;
2319 HANDLE mapping;
2320 LPVOID typelib_base;
2321 } TLB_Mapping;
2323 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2325 if (IsEqualIID(riid, &IID_IUnknown))
2327 *ppv = iface;
2328 IUnknown_AddRef(iface);
2329 return S_OK;
2331 *ppv = NULL;
2332 return E_NOINTERFACE;
2335 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2337 TLB_Mapping *This = (TLB_Mapping *)iface;
2338 return InterlockedIncrement(&This->refs);
2341 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2343 TLB_Mapping *This = (TLB_Mapping *)iface;
2344 ULONG refs = InterlockedDecrement(&This->refs);
2345 if (!refs)
2347 if (This->typelib_base)
2348 UnmapViewOfFile(This->typelib_base);
2349 if (This->mapping)
2350 CloseHandle(This->mapping);
2351 if (This->file != INVALID_HANDLE_VALUE)
2352 CloseHandle(This->file);
2353 HeapFree(GetProcessHeap(), 0, This);
2355 return refs;
2358 static const IUnknownVtbl TLB_Mapping_Vtable =
2360 TLB_Mapping_QueryInterface,
2361 TLB_Mapping_AddRef,
2362 TLB_Mapping_Release
2365 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2367 TLB_Mapping *This;
2369 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2370 if (!This)
2371 return E_OUTOFMEMORY;
2373 This->lpvtbl = &TLB_Mapping_Vtable;
2374 This->refs = 1;
2375 This->file = INVALID_HANDLE_VALUE;
2376 This->mapping = NULL;
2377 This->typelib_base = NULL;
2379 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2380 if (INVALID_HANDLE_VALUE != This->file)
2382 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2383 if (This->mapping)
2385 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2386 if(This->typelib_base)
2388 /* retrieve file size */
2389 *pdwTLBLength = GetFileSize(This->file, NULL);
2390 *ppBase = This->typelib_base;
2391 *ppFile = (IUnknown *)&This->lpvtbl;
2392 return S_OK;
2397 IUnknown_Release((IUnknown *)&This->lpvtbl);
2398 return TYPE_E_CANTLOADLIBRARY;
2401 /****************************************************************************
2402 * TLB_ReadTypeLib
2404 * find the type of the typelib file and map the typelib resource into
2405 * the memory
2407 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2408 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2409 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2411 ITypeLibImpl *entry;
2412 HRESULT ret;
2413 INT index = 1;
2414 LPWSTR index_str, file = (LPWSTR)pszFileName;
2415 LPVOID pBase = NULL;
2416 DWORD dwTLBLength = 0;
2417 IUnknown *pFile = NULL;
2419 *ppTypeLib = NULL;
2421 index_str = strrchrW(pszFileName, '\\');
2422 if(index_str && *++index_str != '\0')
2424 LPWSTR end_ptr;
2425 long idx = strtolW(index_str, &end_ptr, 10);
2426 if(*end_ptr == '\0')
2428 int str_len = index_str - pszFileName - 1;
2429 index = idx;
2430 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
2431 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2432 file[str_len] = 0;
2436 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2438 if(strchrW(file, '\\'))
2440 lstrcpyW(pszPath, file);
2442 else
2444 int len = GetSystemDirectoryW(pszPath, cchPath);
2445 pszPath[len] = '\\';
2446 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2450 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file);
2452 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2454 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2455 EnterCriticalSection(&cache_section);
2456 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2458 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2460 TRACE("cache hit\n");
2461 *ppTypeLib = (ITypeLib2*)entry;
2462 ITypeLib_AddRef(*ppTypeLib);
2463 LeaveCriticalSection(&cache_section);
2464 return S_OK;
2467 LeaveCriticalSection(&cache_section);
2469 /* now actually load and parse the typelib */
2471 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2472 if (ret == TYPE_E_CANTLOADLIBRARY)
2473 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2474 if (SUCCEEDED(ret))
2476 if (dwTLBLength >= 4)
2478 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2479 if (dwSignature == MSFT_SIGNATURE)
2480 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2481 else if (dwSignature == SLTG_SIGNATURE)
2482 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2483 else
2485 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2486 ret = TYPE_E_CANTLOADLIBRARY;
2489 else
2490 ret = TYPE_E_CANTLOADLIBRARY;
2491 IUnknown_Release(pFile);
2494 if(*ppTypeLib) {
2495 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2497 TRACE("adding to cache\n");
2498 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2499 lstrcpyW(impl->path, pszPath);
2500 /* We should really canonicalise the path here. */
2501 impl->index = index;
2503 /* FIXME: check if it has added already in the meantime */
2504 EnterCriticalSection(&cache_section);
2505 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2506 impl->prev = NULL;
2507 tlb_cache_first = impl;
2508 LeaveCriticalSection(&cache_section);
2509 ret = S_OK;
2510 } else
2511 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2513 return ret;
2516 /*================== ITypeLib(2) Methods ===================================*/
2518 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2520 ITypeLibImpl* pTypeLibImpl;
2522 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2523 if (!pTypeLibImpl) return NULL;
2525 pTypeLibImpl->lpVtbl = &tlbvt;
2526 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2527 pTypeLibImpl->ref = 1;
2529 list_init(&pTypeLibImpl->ref_list);
2530 pTypeLibImpl->dispatch_href = -1;
2532 return pTypeLibImpl;
2535 /****************************************************************************
2536 * ITypeLib2_Constructor_MSFT
2538 * loading an MSFT typelib from an in-memory image
2540 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2542 TLBContext cx;
2543 long lPSegDir;
2544 MSFT_Header tlbHeader;
2545 MSFT_SegDir tlbSegDir;
2546 ITypeLibImpl * pTypeLibImpl;
2548 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2550 pTypeLibImpl = TypeLibImpl_Constructor();
2551 if (!pTypeLibImpl) return NULL;
2553 /* get pointer to beginning of typelib data */
2554 cx.pos = 0;
2555 cx.oStart=0;
2556 cx.mapping = pLib;
2557 cx.pLibInfo = pTypeLibImpl;
2558 cx.length = dwTLBLength;
2560 /* read header */
2561 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2562 TRACE_(typelib)("header:\n");
2563 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2564 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2565 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2566 return NULL;
2568 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2570 /* there is a small amount of information here until the next important
2571 * part:
2572 * the segment directory . Try to calculate the amount of data */
2573 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2575 /* now read the segment directory */
2576 TRACE("read segment directory (at %ld)\n",lPSegDir);
2577 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2578 cx.pTblDir = &tlbSegDir;
2580 /* just check two entries */
2581 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2583 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2584 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2585 return NULL;
2588 /* now fill our internal data */
2589 /* TLIBATTR fields */
2590 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2592 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2593 /* Windows seems to have zero here, is this correct? */
2594 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2595 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2596 else
2597 pTypeLibImpl->LibAttr.lcid = 0;
2599 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2600 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2601 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2602 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2604 /* name, eventually add to a hash table */
2605 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2607 /* help info */
2608 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2609 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2611 if( tlbHeader.varflags & HELPDLLFLAG)
2613 int offset;
2614 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2615 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2618 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2620 /* custom data */
2621 if(tlbHeader.CustomDataOffset >= 0)
2623 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2626 /* fill in type descriptions */
2627 if(tlbSegDir.pTypdescTab.length > 0)
2629 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2630 INT16 td[4];
2631 pTypeLibImpl->ctTypeDesc = cTD;
2632 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2633 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2634 for(i=0; i<cTD; )
2636 /* FIXME: add several sanity checks here */
2637 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2638 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2640 /* FIXME: check safearray */
2641 if(td[3] < 0)
2642 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2643 else
2644 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2646 else if(td[0] == VT_CARRAY)
2648 /* array descr table here */
2649 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2651 else if(td[0] == VT_USERDEFINED)
2653 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2655 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2658 /* second time around to fill the array subscript info */
2659 for(i=0;i<cTD;i++)
2661 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2662 if(tlbSegDir.pArrayDescriptions.offset>0)
2664 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2665 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2667 if(td[1]<0)
2668 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2669 else
2670 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2672 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2674 for(j = 0; j<td[2]; j++)
2676 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2677 sizeof(INT), &cx, DO_NOT_SEEK);
2678 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2679 sizeof(INT), &cx, DO_NOT_SEEK);
2682 else
2684 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2685 ERR("didn't find array description data\n");
2690 /* imported type libs */
2691 if(tlbSegDir.pImpFiles.offset>0)
2693 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2694 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2695 UINT16 size;
2697 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2699 char *name;
2700 DWORD len;
2702 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2703 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2704 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2706 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2707 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2708 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2709 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2711 size >>= 2;
2712 name = TLB_Alloc(size+1);
2713 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2714 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2715 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2716 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2717 TLB_Free(name);
2719 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2720 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2722 ppImpLib = &(*ppImpLib)->next;
2726 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
2727 if(pTypeLibImpl->dispatch_href != -1)
2728 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
2730 /* type info's */
2731 if(tlbHeader.nrtypeinfos >= 0 )
2733 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2734 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2735 int i;
2737 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
2739 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2741 ppTI = &((*ppTI)->next);
2742 (pTypeLibImpl->TypeInfoCount)++;
2746 TRACE("(%p)\n", pTypeLibImpl);
2747 return (ITypeLib2*) pTypeLibImpl;
2751 static BSTR TLB_MultiByteToBSTR(const char *ptr)
2753 DWORD len;
2754 WCHAR *nameW;
2755 BSTR ret;
2757 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2758 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2759 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2760 ret = SysAllocString(nameW);
2761 HeapFree(GetProcessHeap(), 0, nameW);
2762 return ret;
2765 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
2767 char b[3];
2768 int i;
2769 short s;
2771 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2772 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2773 return FALSE;
2776 guid->Data4[0] = s >> 8;
2777 guid->Data4[1] = s & 0xff;
2779 b[2] = '\0';
2780 for(i = 0; i < 6; i++) {
2781 memcpy(b, str + 24 + 2 * i, 2);
2782 guid->Data4[i + 2] = strtol(b, NULL, 16);
2784 return TRUE;
2787 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
2789 WORD bytelen;
2790 DWORD len;
2791 WCHAR *nameW;
2793 *pBstr = NULL;
2794 bytelen = *(const WORD*)ptr;
2795 if(bytelen == 0xffff) return 2;
2796 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2797 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2798 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2799 *pBstr = SysAllocStringLen(nameW, len);
2800 HeapFree(GetProcessHeap(), 0, nameW);
2801 return bytelen + 2;
2804 static WORD SLTG_ReadStringA(const char *ptr, char **str)
2806 WORD bytelen;
2808 *str = NULL;
2809 bytelen = *(const WORD*)ptr;
2810 if(bytelen == 0xffff) return 2;
2811 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2812 memcpy(*str, ptr + 2, bytelen);
2813 (*str)[bytelen] = '\0';
2814 return bytelen + 2;
2817 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2819 char *ptr = pLibBlk;
2820 WORD w;
2822 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2823 FIXME("libblk magic = %04x\n", w);
2824 return 0;
2827 ptr += 6;
2828 if((w = *(WORD*)ptr) != 0xffff) {
2829 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2830 ptr += w;
2832 ptr += 2;
2834 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2836 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2838 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2839 ptr += 4;
2841 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2842 ptr += 2;
2844 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2845 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2846 else
2847 pTypeLibImpl->LibAttr.lcid = 0;
2848 ptr += 2;
2850 ptr += 4; /* skip res12 */
2852 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2853 ptr += 2;
2855 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2856 ptr += 2;
2858 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2859 ptr += 2;
2861 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2862 ptr += sizeof(GUID);
2864 return ptr - (char*)pLibBlk;
2867 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
2868 typedef struct
2870 unsigned int num;
2871 HREFTYPE refs[1];
2872 } sltg_ref_lookup_t;
2874 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
2875 HREFTYPE *typelib_ref)
2877 if(typeinfo_ref < table->num)
2879 *typelib_ref = table->refs[typeinfo_ref];
2880 return S_OK;
2883 ERR("Unable to find reference\n");
2884 *typelib_ref = -1;
2885 return E_FAIL;
2888 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
2890 BOOL done = FALSE;
2892 while(!done) {
2893 if((*pType & 0xe00) == 0xe00) {
2894 pTD->vt = VT_PTR;
2895 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2896 sizeof(TYPEDESC));
2897 pTD = pTD->u.lptdesc;
2899 switch(*pType & 0x3f) {
2900 case VT_PTR:
2901 pTD->vt = VT_PTR;
2902 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2903 sizeof(TYPEDESC));
2904 pTD = pTD->u.lptdesc;
2905 break;
2907 case VT_USERDEFINED:
2908 pTD->vt = VT_USERDEFINED;
2909 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
2910 done = TRUE;
2911 break;
2913 case VT_CARRAY:
2915 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2916 array */
2918 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2920 pTD->vt = VT_CARRAY;
2921 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2922 sizeof(ARRAYDESC) +
2923 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2924 pTD->u.lpadesc->cDims = pSA->cDims;
2925 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2926 pSA->cDims * sizeof(SAFEARRAYBOUND));
2928 pTD = &pTD->u.lpadesc->tdescElem;
2929 break;
2932 case VT_SAFEARRAY:
2934 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2935 useful? */
2937 pType++;
2938 pTD->vt = VT_SAFEARRAY;
2939 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2940 sizeof(TYPEDESC));
2941 pTD = pTD->u.lptdesc;
2942 break;
2944 default:
2945 pTD->vt = *pType & 0x3f;
2946 done = TRUE;
2947 break;
2949 pType++;
2951 return pType;
2954 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
2955 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
2957 /* Handle [in/out] first */
2958 if((*pType & 0xc000) == 0xc000)
2959 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2960 else if(*pType & 0x8000)
2961 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2962 else if(*pType & 0x4000)
2963 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2964 else
2965 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2967 if(*pType & 0x2000)
2968 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2970 if(*pType & 0x80)
2971 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2973 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
2977 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
2978 char *pNameTable)
2980 int ref;
2981 char *name;
2982 TLBRefType *ref_type;
2983 sltg_ref_lookup_t *table;
2984 HREFTYPE typelib_ref;
2986 if(pRef->magic != SLTG_REF_MAGIC) {
2987 FIXME("Ref magic = %x\n", pRef->magic);
2988 return NULL;
2990 name = ( (char*)(&pRef->names) + pRef->number);
2992 table = HeapAlloc(GetProcessHeap(), 0, sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
2993 table->num = pRef->number >> 3;
2995 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
2997 /* We don't want the first href to be 0 */
2998 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3000 for(ref = 0; ref < pRef->number >> 3; ref++) {
3001 char *refname;
3002 unsigned int lib_offs, type_num;
3004 ref_type = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref_type));
3006 name += SLTG_ReadStringA(name, &refname);
3007 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3008 FIXME("Can't sscanf ref\n");
3009 if(lib_offs != 0xffff) {
3010 TLBImpLib **import = &pTL->pImpLibs;
3012 while(*import) {
3013 if((*import)->offset == lib_offs)
3014 break;
3015 import = &(*import)->next;
3017 if(!*import) {
3018 char fname[MAX_PATH+1];
3019 int len;
3021 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3022 sizeof(**import));
3023 (*import)->offset = lib_offs;
3024 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3025 &(*import)->guid);
3026 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3027 &(*import)->wVersionMajor,
3028 &(*import)->wVersionMinor,
3029 &(*import)->lcid, fname) != 4) {
3030 FIXME("can't sscanf ref %s\n",
3031 pNameTable + lib_offs + 40);
3033 len = strlen(fname);
3034 if(fname[len-1] != '#')
3035 FIXME("fname = %s\n", fname);
3036 fname[len-1] = '\0';
3037 (*import)->name = TLB_MultiByteToBSTR(fname);
3039 ref_type->pImpTLInfo = *import;
3041 /* Store a reference to IDispatch */
3042 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
3043 pTL->dispatch_href = typelib_ref;
3045 } else { /* internal ref */
3046 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3048 ref_type->reference = typelib_ref;
3049 ref_type->index = type_num;
3051 HeapFree(GetProcessHeap(), 0, refname);
3052 list_add_tail(&pTL->ref_list, &ref_type->entry);
3054 table->refs[ref] = typelib_ref;
3055 typelib_ref += 4;
3057 if((BYTE)*name != SLTG_REF_MAGIC)
3058 FIXME("End of ref block magic = %x\n", *name);
3059 dump_TLBRefType(pTL);
3060 return table;
3063 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3064 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3066 SLTG_ImplInfo *info;
3067 TLBImplType **ppImplType = &pTI->impltypelist;
3068 /* I don't really get this structure, usually it's 0x16 bytes
3069 long, but iuser.tlb contains some that are 0x18 bytes long.
3070 That's ok because we can use the next ptr to jump to the next
3071 one. But how do we know the length of the last one? The WORD
3072 at offs 0x8 might be the clue. For now I'm just assuming that
3073 the last one is the regular 0x16 bytes. */
3075 info = (SLTG_ImplInfo*)pBlk;
3076 while(1) {
3077 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3078 sizeof(**ppImplType));
3079 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef);
3080 (*ppImplType)->implflags = info->impltypeflags;
3081 pTI->TypeAttr.cImplTypes++;
3082 ppImplType = &(*ppImplType)->next;
3084 if(info->next == 0xffff)
3085 break;
3086 if(OneOnly)
3087 FIXME("Interface inheriting more than one interface\n");
3088 info = (SLTG_ImplInfo*)(pBlk + info->next);
3090 info++; /* see comment at top of function */
3091 return (char*)info;
3094 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3095 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3097 TLBVarDesc **ppVarDesc = &pTI->varlist;
3098 BSTR bstrPrevName = NULL;
3099 SLTG_Variable *pItem;
3100 unsigned short i;
3101 WORD *pType;
3102 char buf[300];
3104 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3105 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
3107 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3108 sizeof(**ppVarDesc));
3109 (*ppVarDesc)->vardesc.memid = pItem->memid;
3111 if (pItem->magic != SLTG_VAR_MAGIC &&
3112 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3113 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3114 return;
3117 if (pItem->name == 0xfffe)
3118 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
3119 else
3120 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3122 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3123 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3125 if (pItem->flags & 0x40) {
3126 TRACE_(typelib)("VAR_DISPATCH\n");
3127 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
3129 else if (pItem->flags & 0x10) {
3130 TRACE_(typelib)("VAR_CONST\n");
3131 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3132 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3133 sizeof(VARIANT));
3134 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3135 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
3136 *(INT*)(pBlk + pItem->byte_offs);
3138 else {
3139 TRACE_(typelib)("VAR_PERINSTANCE\n");
3140 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3141 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3144 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3145 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
3147 if (pItem->flags & 0x80)
3148 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3150 if(pItem->flags & 0x02)
3151 pType = &pItem->type;
3152 else
3153 pType = (WORD*)(pBlk + pItem->type);
3155 if (pItem->flags & ~0xd2)
3156 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xd2);
3158 SLTG_DoElem(pType, pBlk,
3159 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup);
3161 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3163 bstrPrevName = (*ppVarDesc)->Name;
3164 ppVarDesc = &((*ppVarDesc)->next);
3166 pTI->TypeAttr.cVars = cVars;
3169 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3170 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3172 SLTG_Function *pFunc;
3173 unsigned short i;
3174 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3176 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3177 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3179 int param;
3180 WORD *pType, *pArg;
3182 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3183 sizeof(**ppFuncDesc));
3185 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3186 case SLTG_FUNCTION_MAGIC:
3187 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3188 break;
3189 case SLTG_DISPATCH_FUNCTION_MAGIC:
3190 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3191 break;
3192 case SLTG_STATIC_FUNCTION_MAGIC:
3193 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3194 break;
3195 default:
3196 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3197 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
3198 *ppFuncDesc = NULL;
3199 return;
3201 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3203 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3204 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3205 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3206 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3207 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3208 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3210 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3211 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3213 if(pFunc->retnextopt & 0x80)
3214 pType = &pFunc->rettype;
3215 else
3216 pType = (WORD*)(pBlk + pFunc->rettype);
3218 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3220 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3221 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3222 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3223 (*ppFuncDesc)->pParamDesc =
3224 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3225 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3227 pArg = (WORD*)(pBlk + pFunc->arg_off);
3229 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3230 char *paramName = pNameTable + *pArg;
3231 BOOL HaveOffs;
3232 /* If arg type follows then paramName points to the 2nd
3233 letter of the name, else the next WORD is an offset to
3234 the arg type and paramName points to the first letter.
3235 So let's take one char off paramName and see if we're
3236 pointing at an alpha-numeric char. However if *pArg is
3237 0xffff or 0xfffe then the param has no name, the former
3238 meaning that the next WORD is the type, the latter
3239 meaning that the next WORD is an offset to the type. */
3241 HaveOffs = FALSE;
3242 if(*pArg == 0xffff)
3243 paramName = NULL;
3244 else if(*pArg == 0xfffe) {
3245 paramName = NULL;
3246 HaveOffs = TRUE;
3248 else if(paramName[-1] && !isalnum(paramName[-1]))
3249 HaveOffs = TRUE;
3251 pArg++;
3253 if(HaveOffs) { /* the next word is an offset to type */
3254 pType = (WORD*)(pBlk + *pArg);
3255 SLTG_DoElem(pType, pBlk,
3256 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3257 pArg++;
3258 } else {
3259 if(paramName)
3260 paramName--;
3261 pArg = SLTG_DoElem(pArg, pBlk,
3262 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3265 /* Are we an optional param ? */
3266 if((*ppFuncDesc)->funcdesc.cParams - param <=
3267 (*ppFuncDesc)->funcdesc.cParamsOpt)
3268 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3270 if(paramName) {
3271 (*ppFuncDesc)->pParamDesc[param].Name =
3272 TLB_MultiByteToBSTR(paramName);
3276 ppFuncDesc = &((*ppFuncDesc)->next);
3277 if(pFunc->next == 0xffff) break;
3279 pTI->TypeAttr.cFuncs = cFuncs;
3282 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3283 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3284 SLTG_TypeInfoTail *pTITail)
3286 char *pFirstItem;
3287 sltg_ref_lookup_t *ref_lookup = NULL;
3289 if(pTIHeader->href_table != 0xffffffff) {
3290 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3291 pNameTable);
3294 pFirstItem = pBlk;
3296 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3297 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3299 HeapFree(GetProcessHeap(), 0, ref_lookup);
3303 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3304 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3305 const SLTG_TypeInfoTail *pTITail)
3307 char *pFirstItem;
3308 sltg_ref_lookup_t *ref_lookup = NULL;
3310 if(pTIHeader->href_table != 0xffffffff) {
3311 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3312 pNameTable);
3315 pFirstItem = pBlk;
3317 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3318 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3321 if (pTITail->funcs_off != 0xffff)
3322 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3324 HeapFree(GetProcessHeap(), 0, ref_lookup);
3326 if (TRACE_ON(typelib))
3327 dump_TLBFuncDesc(pTI->funclist);
3330 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3331 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3332 const SLTG_TypeInfoTail *pTITail)
3334 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3337 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3338 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3339 const SLTG_TypeInfoTail *pTITail)
3341 WORD *pType;
3342 sltg_ref_lookup_t *ref_lookup = NULL;
3344 if (pTITail->simple_alias) {
3345 /* if simple alias, no more processing required */
3346 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3347 return;
3350 if(pTIHeader->href_table != 0xffffffff) {
3351 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3352 pNameTable);
3355 /* otherwise it is an offset to a type */
3356 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3358 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3360 HeapFree(GetProcessHeap(), 0, ref_lookup);
3363 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3364 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3365 const SLTG_TypeInfoTail *pTITail)
3367 sltg_ref_lookup_t *ref_lookup = NULL;
3368 if (pTIHeader->href_table != 0xffffffff)
3369 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3370 pNameTable);
3372 if (pTITail->vars_off != 0xffff)
3373 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3375 if (pTITail->funcs_off != 0xffff)
3376 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3378 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3379 * of dispinterface functions including the IDispatch ones, so
3380 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3381 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3383 HeapFree(GetProcessHeap(), 0, ref_lookup);
3384 if (TRACE_ON(typelib))
3385 dump_TLBFuncDesc(pTI->funclist);
3388 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3389 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3390 const SLTG_TypeInfoTail *pTITail)
3392 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3395 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3396 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3397 const SLTG_TypeInfoTail *pTITail)
3399 sltg_ref_lookup_t *ref_lookup = NULL;
3400 if (pTIHeader->href_table != 0xffffffff)
3401 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3402 pNameTable);
3404 if (pTITail->vars_off != 0xffff)
3405 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3407 if (pTITail->funcs_off != 0xffff)
3408 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3409 HeapFree(GetProcessHeap(), 0, ref_lookup);
3412 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3413 managable copy of it into this */
3414 typedef struct {
3415 WORD small_no;
3416 char *index_name;
3417 char *other_name;
3418 WORD res1a;
3419 WORD name_offs;
3420 WORD more_bytes;
3421 char *extra;
3422 WORD res20;
3423 DWORD helpcontext;
3424 WORD res26;
3425 GUID uuid;
3426 } SLTG_InternalOtherTypeInfo;
3428 /****************************************************************************
3429 * ITypeLib2_Constructor_SLTG
3431 * loading a SLTG typelib from an in-memory image
3433 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3435 ITypeLibImpl *pTypeLibImpl;
3436 SLTG_Header *pHeader;
3437 SLTG_BlkEntry *pBlkEntry;
3438 SLTG_Magic *pMagic;
3439 SLTG_Index *pIndex;
3440 SLTG_Pad9 *pPad9;
3441 LPVOID pBlk, pFirstBlk;
3442 SLTG_LibBlk *pLibBlk;
3443 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3444 char *pAfterOTIBlks = NULL;
3445 char *pNameTable, *ptr;
3446 int i;
3447 DWORD len, order;
3448 ITypeInfoImpl **ppTypeInfoImpl;
3450 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3453 pTypeLibImpl = TypeLibImpl_Constructor();
3454 if (!pTypeLibImpl) return NULL;
3456 pHeader = pLib;
3458 TRACE_(typelib)("header:\n");
3459 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3460 pHeader->nrOfFileBlks );
3461 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3462 FIXME("Header type magic 0x%08x not supported.\n",
3463 pHeader->SLTG_magic);
3464 return NULL;
3467 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3468 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3470 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3471 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3473 /* Next we have a magic block */
3474 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3476 /* Let's see if we're still in sync */
3477 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3478 sizeof(SLTG_COMPOBJ_MAGIC))) {
3479 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3480 return NULL;
3482 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3483 sizeof(SLTG_DIR_MAGIC))) {
3484 FIXME("dir magic = %s\n", pMagic->dir_magic);
3485 return NULL;
3488 pIndex = (SLTG_Index*)(pMagic+1);
3490 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3492 pFirstBlk = (LPVOID)(pPad9 + 1);
3494 /* We'll set up a ptr to the main library block, which is the last one. */
3496 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3497 pBlkEntry[order].next != 0;
3498 order = pBlkEntry[order].next - 1, i++) {
3499 pBlk = (char*)pBlk + pBlkEntry[order].len;
3501 pLibBlk = pBlk;
3503 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3505 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3506 interspersed */
3508 len += 0x40;
3510 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3512 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3513 sizeof(*pOtherTypeInfoBlks) *
3514 pTypeLibImpl->TypeInfoCount);
3517 ptr = (char*)pLibBlk + len;
3519 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3520 WORD w, extra;
3521 len = 0;
3523 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3525 w = *(WORD*)(ptr + 2);
3526 if(w != 0xffff) {
3527 len += w;
3528 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3529 w+1);
3530 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3531 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3533 w = *(WORD*)(ptr + 4 + len);
3534 if(w != 0xffff) {
3535 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3536 len += w;
3537 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3538 w+1);
3539 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3540 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3542 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3543 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3544 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3545 if(extra) {
3546 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3547 extra);
3548 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3549 len += extra;
3551 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3552 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3553 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3554 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3555 len += sizeof(SLTG_OtherTypeInfo);
3556 ptr += len;
3559 pAfterOTIBlks = ptr;
3561 /* Skip this WORD and get the next DWORD */
3562 len = *(DWORD*)(pAfterOTIBlks + 2);
3564 /* Now add this to pLibBLk look at what we're pointing at and
3565 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3566 dust and we should be pointing at the beginning of the name
3567 table */
3569 pNameTable = (char*)pLibBlk + len;
3571 switch(*(WORD*)pNameTable) {
3572 case 0xffff:
3573 break;
3574 case 0x0200:
3575 pNameTable += 0x20;
3576 break;
3577 default:
3578 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3579 break;
3582 pNameTable += 0x216;
3584 pNameTable += 2;
3586 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3588 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3591 /* Hopefully we now have enough ptrs set up to actually read in
3592 some TypeInfos. It's not clear which order to do them in, so
3593 I'll just follow the links along the BlkEntry chain and read
3594 them in the order in which they are in the file */
3596 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3598 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3599 pBlkEntry[order].next != 0;
3600 order = pBlkEntry[order].next - 1, i++) {
3602 SLTG_TypeInfoHeader *pTIHeader;
3603 SLTG_TypeInfoTail *pTITail;
3604 SLTG_MemberHeader *pMemHeader;
3606 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3607 pOtherTypeInfoBlks[i].index_name)) {
3608 FIXME("Index strings don't match\n");
3609 return NULL;
3612 pTIHeader = pBlk;
3613 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3614 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3615 return NULL;
3617 TRACE("pTIHeader->res06 = %x, pTIHeader->res0e = %x, pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3618 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3620 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3621 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3622 (*ppTypeInfoImpl)->index = i;
3623 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3624 pOtherTypeInfoBlks[i].name_offs +
3625 pNameTable);
3626 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3627 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
3628 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3629 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3630 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3631 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3632 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3634 if((pTIHeader->typeflags1 & 7) != 2)
3635 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3636 if(pTIHeader->typeflags3 != 2)
3637 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3639 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3640 debugstr_w((*ppTypeInfoImpl)->Name),
3641 typekind_desc[pTIHeader->typekind],
3642 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3643 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3645 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3647 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3649 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3650 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3651 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3653 switch(pTIHeader->typekind) {
3654 case TKIND_ENUM:
3655 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3656 pTIHeader, pTITail);
3657 break;
3659 case TKIND_RECORD:
3660 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3661 pTIHeader, pTITail);
3662 break;
3664 case TKIND_INTERFACE:
3665 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3666 pTIHeader, pTITail);
3667 break;
3669 case TKIND_COCLASS:
3670 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3671 pTIHeader, pTITail);
3672 break;
3674 case TKIND_ALIAS:
3675 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3676 pTIHeader, pTITail);
3677 break;
3679 case TKIND_DISPATCH:
3680 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3681 pTIHeader, pTITail);
3682 break;
3684 case TKIND_MODULE:
3685 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3686 pTIHeader, pTITail);
3687 break;
3689 default:
3690 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3691 break;
3695 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3696 but we've already set those */
3697 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3698 X(06);
3699 X(16);
3700 X(18);
3701 X(1a);
3702 X(1e);
3703 X(24);
3704 X(26);
3705 X(2a);
3706 X(2c);
3707 X(2e);
3708 X(30);
3709 X(32);
3710 X(34);
3712 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3713 pBlk = (char*)pBlk + pBlkEntry[order].len;
3716 if(i != pTypeLibImpl->TypeInfoCount) {
3717 FIXME("Somehow processed %d TypeInfos\n", i);
3718 return NULL;
3721 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3722 return (ITypeLib2*)pTypeLibImpl;
3725 /* ITypeLib::QueryInterface
3727 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3728 ITypeLib2 * iface,
3729 REFIID riid,
3730 VOID **ppvObject)
3732 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3734 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3736 *ppvObject=NULL;
3737 if(IsEqualIID(riid, &IID_IUnknown) ||
3738 IsEqualIID(riid,&IID_ITypeLib)||
3739 IsEqualIID(riid,&IID_ITypeLib2))
3741 *ppvObject = This;
3744 if(*ppvObject)
3746 ITypeLib2_AddRef(iface);
3747 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3748 return S_OK;
3750 TRACE("-- Interface: E_NOINTERFACE\n");
3751 return E_NOINTERFACE;
3754 /* ITypeLib::AddRef
3756 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3758 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3759 ULONG ref = InterlockedIncrement(&This->ref);
3761 TRACE("(%p)->ref was %u\n",This, ref - 1);
3763 return ref;
3766 /* ITypeLib::Release
3768 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3770 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3771 ULONG ref = InterlockedDecrement(&This->ref);
3773 TRACE("(%p)->(%u)\n",This, ref);
3775 if (!ref)
3777 TLBImpLib *pImpLib, *pImpLibNext;
3778 TLBCustData *pCustData, *pCustDataNext;
3779 TLBRefType *ref_type;
3780 void *cursor2;
3781 int i;
3783 /* remove cache entry */
3784 if(This->path)
3786 TRACE("removing from cache list\n");
3787 EnterCriticalSection(&cache_section);
3788 if (This->next) This->next->prev = This->prev;
3789 if (This->prev) This->prev->next = This->next;
3790 else tlb_cache_first = This->next;
3791 LeaveCriticalSection(&cache_section);
3792 HeapFree(GetProcessHeap(), 0, This->path);
3794 TRACE(" destroying ITypeLib(%p)\n",This);
3796 if (This->Name)
3798 SysFreeString(This->Name);
3799 This->Name = NULL;
3802 if (This->DocString)
3804 SysFreeString(This->DocString);
3805 This->DocString = NULL;
3808 if (This->HelpFile)
3810 SysFreeString(This->HelpFile);
3811 This->HelpFile = NULL;
3814 if (This->HelpStringDll)
3816 SysFreeString(This->HelpStringDll);
3817 This->HelpStringDll = NULL;
3820 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
3822 VariantClear(&pCustData->data);
3824 pCustDataNext = pCustData->next;
3825 TLB_Free(pCustData);
3828 for (i = 0; i < This->ctTypeDesc; i++)
3829 if (This->pTypeDesc[i].vt == VT_CARRAY)
3830 TLB_Free(This->pTypeDesc[i].u.lpadesc);
3832 TLB_Free(This->pTypeDesc);
3834 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
3836 if (pImpLib->pImpTypeLib)
3837 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
3838 TLB_Free(pImpLib->name);
3840 pImpLibNext = pImpLib->next;
3841 TLB_Free(pImpLib);
3844 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
3846 list_remove(&ref_type->entry);
3847 TLB_Free(ref_type);
3850 if (This->pTypeInfo) /* can be NULL */
3851 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3852 HeapFree(GetProcessHeap(),0,This);
3853 return 0;
3856 return ref;
3859 /* ITypeLib::GetTypeInfoCount
3861 * Returns the number of type descriptions in the type library
3863 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3865 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3866 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3867 return This->TypeInfoCount;
3870 /* ITypeLib::GetTypeInfo
3872 * retrieves the specified type description in the library.
3874 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3875 ITypeLib2 *iface,
3876 UINT index,
3877 ITypeInfo **ppTInfo)
3879 int i;
3881 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3882 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3884 TRACE("(%p)->(index=%d)\n", This, index);
3886 if (!ppTInfo) return E_INVALIDARG;
3888 /* search element n in list */
3889 for(i=0; i < index; i++)
3891 pTypeInfo = pTypeInfo->next;
3892 if (!pTypeInfo)
3894 TRACE("-- element not found\n");
3895 return TYPE_E_ELEMENTNOTFOUND;
3899 *ppTInfo = (ITypeInfo *) pTypeInfo;
3901 ITypeInfo_AddRef(*ppTInfo);
3902 TRACE("-- found (%p)\n",*ppTInfo);
3903 return S_OK;
3907 /* ITypeLibs::GetTypeInfoType
3909 * Retrieves the type of a type description.
3911 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3912 ITypeLib2 *iface,
3913 UINT index,
3914 TYPEKIND *pTKind)
3916 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3917 int i;
3918 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3920 if (ITypeLib2_fnGetTypeInfoCount(iface) < index + 1)
3921 return TYPE_E_ELEMENTNOTFOUND;
3923 TRACE("(%p) index %d\n", This, index);
3925 if(!pTKind) return E_INVALIDARG;
3927 /* search element n in list */
3928 for(i=0; i < index; i++)
3930 if(!pTInfo)
3932 TRACE("-- element not found\n");
3933 return TYPE_E_ELEMENTNOTFOUND;
3935 pTInfo = pTInfo->next;
3938 *pTKind = pTInfo->TypeAttr.typekind;
3939 TRACE("-- found Type (%d)\n", *pTKind);
3940 return S_OK;
3943 /* ITypeLib::GetTypeInfoOfGuid
3945 * Retrieves the type description that corresponds to the specified GUID.
3948 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3949 ITypeLib2 *iface,
3950 REFGUID guid,
3951 ITypeInfo **ppTInfo)
3953 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3954 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3956 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3958 if (!pTypeInfo)
3960 WARN("-- element not found\n");
3961 return TYPE_E_ELEMENTNOTFOUND;
3964 /* search linked list for guid */
3965 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3967 pTypeInfo = pTypeInfo->next;
3969 if (!pTypeInfo)
3971 /* end of list reached */
3972 WARN("-- element not found\n");
3973 return TYPE_E_ELEMENTNOTFOUND;
3977 TRACE("-- found (%p, %s)\n",
3978 pTypeInfo,
3979 debugstr_w(pTypeInfo->Name));
3981 *ppTInfo = (ITypeInfo*)pTypeInfo;
3982 ITypeInfo_AddRef(*ppTInfo);
3983 return S_OK;
3986 /* ITypeLib::GetLibAttr
3988 * Retrieves the structure that contains the library's attributes.
3991 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3992 ITypeLib2 *iface,
3993 LPTLIBATTR *ppTLibAttr)
3995 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3996 TRACE("(%p)\n",This);
3997 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3998 **ppTLibAttr = This->LibAttr;
3999 return S_OK;
4002 /* ITypeLib::GetTypeComp
4004 * Enables a client compiler to bind to a library's types, variables,
4005 * constants, and global functions.
4008 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4009 ITypeLib2 *iface,
4010 ITypeComp **ppTComp)
4012 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4014 TRACE("(%p)->(%p)\n",This,ppTComp);
4015 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4016 ITypeComp_AddRef(*ppTComp);
4018 return S_OK;
4021 /* ITypeLib::GetDocumentation
4023 * Retrieves the library's documentation string, the complete Help file name
4024 * and path, and the context identifier for the library Help topic in the Help
4025 * file.
4027 * On a successful return all non-null BSTR pointers will have been set,
4028 * possibly to NULL.
4030 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4031 ITypeLib2 *iface,
4032 INT index,
4033 BSTR *pBstrName,
4034 BSTR *pBstrDocString,
4035 DWORD *pdwHelpContext,
4036 BSTR *pBstrHelpFile)
4038 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4040 HRESULT result = E_INVALIDARG;
4042 ITypeInfo *pTInfo;
4045 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4046 This, index,
4047 pBstrName, pBstrDocString,
4048 pdwHelpContext, pBstrHelpFile);
4050 if(index<0)
4052 /* documentation for the typelib */
4053 if(pBstrName)
4055 if (This->Name)
4057 if(!(*pBstrName = SysAllocString(This->Name)))
4058 goto memerr1;
4060 else
4061 *pBstrName = NULL;
4063 if(pBstrDocString)
4065 if (This->DocString)
4067 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4068 goto memerr2;
4070 else if (This->Name)
4072 if(!(*pBstrDocString = SysAllocString(This->Name)))
4073 goto memerr2;
4075 else
4076 *pBstrDocString = NULL;
4078 if(pdwHelpContext)
4080 *pdwHelpContext = This->dwHelpContext;
4082 if(pBstrHelpFile)
4084 if (This->HelpFile)
4086 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4087 goto memerr3;
4089 else
4090 *pBstrHelpFile = NULL;
4093 result = S_OK;
4095 else
4097 /* for a typeinfo */
4098 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4100 if(SUCCEEDED(result))
4102 result = ITypeInfo_GetDocumentation(pTInfo,
4103 MEMBERID_NIL,
4104 pBstrName,
4105 pBstrDocString,
4106 pdwHelpContext, pBstrHelpFile);
4108 ITypeInfo_Release(pTInfo);
4111 return result;
4112 memerr3:
4113 if (pBstrDocString) SysFreeString (*pBstrDocString);
4114 memerr2:
4115 if (pBstrName) SysFreeString (*pBstrName);
4116 memerr1:
4117 return STG_E_INSUFFICIENTMEMORY;
4120 /* ITypeLib::IsName
4122 * Indicates whether a passed-in string contains the name of a type or member
4123 * described in the library.
4126 static HRESULT WINAPI ITypeLib2_fnIsName(
4127 ITypeLib2 *iface,
4128 LPOLESTR szNameBuf,
4129 ULONG lHashVal,
4130 BOOL *pfName)
4132 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4133 ITypeInfoImpl *pTInfo;
4134 TLBFuncDesc *pFInfo;
4135 TLBVarDesc *pVInfo;
4136 int i;
4137 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4139 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4140 pfName);
4142 *pfName=TRUE;
4143 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
4144 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4145 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4146 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4147 for(i=0;i<pFInfo->funcdesc.cParams;i++)
4148 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
4149 goto ITypeLib2_fnIsName_exit;
4151 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4152 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4155 *pfName=FALSE;
4157 ITypeLib2_fnIsName_exit:
4158 TRACE("(%p)slow! search for %s: %s found!\n", This,
4159 debugstr_w(szNameBuf), *pfName?"NOT":"");
4161 return S_OK;
4164 /* ITypeLib::FindName
4166 * Finds occurrences of a type description in a type library. This may be used
4167 * to quickly verify that a name exists in a type library.
4170 static HRESULT WINAPI ITypeLib2_fnFindName(
4171 ITypeLib2 *iface,
4172 LPOLESTR szNameBuf,
4173 ULONG lHashVal,
4174 ITypeInfo **ppTInfo,
4175 MEMBERID *rgMemId,
4176 UINT16 *pcFound)
4178 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4179 ITypeInfoImpl *pTInfo;
4180 TLBFuncDesc *pFInfo;
4181 TLBVarDesc *pVInfo;
4182 int i,j = 0;
4183 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4185 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
4186 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4187 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4188 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4189 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
4190 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
4191 goto ITypeLib2_fnFindName_exit;
4194 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4195 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4196 continue;
4197 ITypeLib2_fnFindName_exit:
4198 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4199 ppTInfo[j]=(LPTYPEINFO)pTInfo;
4200 j++;
4202 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4203 This, *pcFound, debugstr_w(szNameBuf), j);
4205 *pcFound=j;
4207 return S_OK;
4210 /* ITypeLib::ReleaseTLibAttr
4212 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4215 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4216 ITypeLib2 *iface,
4217 TLIBATTR *pTLibAttr)
4219 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4220 TRACE("freeing (%p)\n",This);
4221 HeapFree(GetProcessHeap(),0,pTLibAttr);
4225 /* ITypeLib2::GetCustData
4227 * gets the custom data
4229 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4230 ITypeLib2 * iface,
4231 REFGUID guid,
4232 VARIANT *pVarVal)
4234 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4235 TLBCustData *pCData;
4237 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4239 if( IsEqualIID(guid, &pCData->guid)) break;
4242 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4244 if(pCData)
4246 VariantInit( pVarVal);
4247 VariantCopy( pVarVal, &pCData->data);
4248 return S_OK;
4250 return E_INVALIDARG; /* FIXME: correct? */
4253 /* ITypeLib2::GetLibStatistics
4255 * Returns statistics about a type library that are required for efficient
4256 * sizing of hash tables.
4259 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4260 ITypeLib2 * iface,
4261 ULONG *pcUniqueNames,
4262 ULONG *pcchUniqueNames)
4264 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4266 FIXME("(%p): stub!\n", This);
4268 if(pcUniqueNames) *pcUniqueNames=1;
4269 if(pcchUniqueNames) *pcchUniqueNames=1;
4270 return S_OK;
4273 /* ITypeLib2::GetDocumentation2
4275 * Retrieves the library's documentation string, the complete Help file name
4276 * and path, the localization context to use, and the context ID for the
4277 * library Help topic in the Help file.
4280 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4281 ITypeLib2 * iface,
4282 INT index,
4283 LCID lcid,
4284 BSTR *pbstrHelpString,
4285 DWORD *pdwHelpStringContext,
4286 BSTR *pbstrHelpStringDll)
4288 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4289 HRESULT result;
4290 ITypeInfo *pTInfo;
4292 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4294 /* the help string should be obtained from the helpstringdll,
4295 * using the _DLLGetDocumentation function, based on the supplied
4296 * lcid. Nice to do sometime...
4298 if(index<0)
4300 /* documentation for the typelib */
4301 if(pbstrHelpString)
4302 *pbstrHelpString=SysAllocString(This->DocString);
4303 if(pdwHelpStringContext)
4304 *pdwHelpStringContext=This->dwHelpContext;
4305 if(pbstrHelpStringDll)
4306 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4308 result = S_OK;
4310 else
4312 /* for a typeinfo */
4313 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4315 if(SUCCEEDED(result))
4317 ITypeInfo2 * pTInfo2;
4318 result = ITypeInfo_QueryInterface(pTInfo,
4319 &IID_ITypeInfo2,
4320 (LPVOID*) &pTInfo2);
4322 if(SUCCEEDED(result))
4324 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4325 MEMBERID_NIL,
4326 lcid,
4327 pbstrHelpString,
4328 pdwHelpStringContext,
4329 pbstrHelpStringDll);
4331 ITypeInfo2_Release(pTInfo2);
4334 ITypeInfo_Release(pTInfo);
4337 return result;
4340 /* ITypeLib2::GetAllCustData
4342 * Gets all custom data items for the library.
4345 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4346 ITypeLib2 * iface,
4347 CUSTDATA *pCustData)
4349 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4350 TLBCustData *pCData;
4351 int i;
4352 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4353 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4354 if(pCustData->prgCustData ){
4355 pCustData->cCustData=This->ctCustData;
4356 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4357 pCustData->prgCustData[i].guid=pCData->guid;
4358 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4360 }else{
4361 ERR(" OUT OF MEMORY!\n");
4362 return E_OUTOFMEMORY;
4364 return S_OK;
4367 static const ITypeLib2Vtbl tlbvt = {
4368 ITypeLib2_fnQueryInterface,
4369 ITypeLib2_fnAddRef,
4370 ITypeLib2_fnRelease,
4371 ITypeLib2_fnGetTypeInfoCount,
4372 ITypeLib2_fnGetTypeInfo,
4373 ITypeLib2_fnGetTypeInfoType,
4374 ITypeLib2_fnGetTypeInfoOfGuid,
4375 ITypeLib2_fnGetLibAttr,
4376 ITypeLib2_fnGetTypeComp,
4377 ITypeLib2_fnGetDocumentation,
4378 ITypeLib2_fnIsName,
4379 ITypeLib2_fnFindName,
4380 ITypeLib2_fnReleaseTLibAttr,
4382 ITypeLib2_fnGetCustData,
4383 ITypeLib2_fnGetLibStatistics,
4384 ITypeLib2_fnGetDocumentation2,
4385 ITypeLib2_fnGetAllCustData
4389 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4391 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4393 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4396 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4398 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4400 return ITypeLib2_AddRef((ITypeLib2 *)This);
4403 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4405 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4407 return ITypeLib2_Release((ITypeLib2 *)This);
4410 static HRESULT WINAPI ITypeLibComp_fnBind(
4411 ITypeComp * iface,
4412 OLECHAR * szName,
4413 ULONG lHash,
4414 WORD wFlags,
4415 ITypeInfo ** ppTInfo,
4416 DESCKIND * pDescKind,
4417 BINDPTR * pBindPtr)
4419 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4420 ITypeInfoImpl *pTypeInfo;
4422 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4424 *pDescKind = DESCKIND_NONE;
4425 pBindPtr->lptcomp = NULL;
4426 *ppTInfo = NULL;
4428 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4430 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4432 /* FIXME: check wFlags here? */
4433 /* FIXME: we should use a hash table to look this info up using lHash
4434 * instead of an O(n) search */
4435 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4436 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4438 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4440 *pDescKind = DESCKIND_TYPECOMP;
4441 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4442 ITypeComp_AddRef(pBindPtr->lptcomp);
4443 TRACE("module or enum: %s\n", debugstr_w(szName));
4444 return S_OK;
4448 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4449 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4451 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4452 HRESULT hr;
4454 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4455 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4457 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4458 return S_OK;
4462 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4463 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4465 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4466 HRESULT hr;
4467 ITypeInfo *subtypeinfo;
4468 BINDPTR subbindptr;
4469 DESCKIND subdesckind;
4471 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4472 &subtypeinfo, &subdesckind, &subbindptr);
4473 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4475 TYPEDESC tdesc_appobject =
4478 (TYPEDESC *)pTypeInfo->hreftype
4480 VT_USERDEFINED
4482 const VARDESC vardesc_appobject =
4484 -2, /* memid */
4485 NULL, /* lpstrSchema */
4487 0 /* oInst */
4490 /* ELEMDESC */
4492 /* TYPEDESC */
4494 &tdesc_appobject
4496 VT_PTR
4499 0, /* wVarFlags */
4500 VAR_STATIC /* varkind */
4503 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4505 /* cleanup things filled in by Bind call so we can put our
4506 * application object data in there instead */
4507 switch (subdesckind)
4509 case DESCKIND_FUNCDESC:
4510 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4511 break;
4512 case DESCKIND_VARDESC:
4513 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4514 break;
4515 default:
4516 break;
4518 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4520 if (pTypeInfo->hreftype == -1)
4521 FIXME("no hreftype for interface %p\n", pTypeInfo);
4523 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4524 if (FAILED(hr))
4525 return hr;
4527 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4528 *ppTInfo = (ITypeInfo *)pTypeInfo;
4529 ITypeInfo_AddRef(*ppTInfo);
4530 return S_OK;
4535 TRACE("name not found %s\n", debugstr_w(szName));
4536 return S_OK;
4539 static HRESULT WINAPI ITypeLibComp_fnBindType(
4540 ITypeComp * iface,
4541 OLECHAR * szName,
4542 ULONG lHash,
4543 ITypeInfo ** ppTInfo,
4544 ITypeComp ** ppTComp)
4546 FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4547 return E_NOTIMPL;
4550 static const ITypeCompVtbl tlbtcvt =
4553 ITypeLibComp_fnQueryInterface,
4554 ITypeLibComp_fnAddRef,
4555 ITypeLibComp_fnRelease,
4557 ITypeLibComp_fnBind,
4558 ITypeLibComp_fnBindType
4561 /*================== ITypeInfo(2) Methods ===================================*/
4562 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4564 ITypeInfoImpl * pTypeInfoImpl;
4566 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4567 if (pTypeInfoImpl)
4569 pTypeInfoImpl->lpVtbl = &tinfvt;
4570 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4571 pTypeInfoImpl->ref=1;
4572 pTypeInfoImpl->hreftype = -1;
4573 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4574 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4576 TRACE("(%p)\n", pTypeInfoImpl);
4577 return (ITypeInfo2*) pTypeInfoImpl;
4580 /* ITypeInfo::QueryInterface
4582 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4583 ITypeInfo2 *iface,
4584 REFIID riid,
4585 VOID **ppvObject)
4587 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4589 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4591 *ppvObject=NULL;
4592 if(IsEqualIID(riid, &IID_IUnknown) ||
4593 IsEqualIID(riid,&IID_ITypeInfo)||
4594 IsEqualIID(riid,&IID_ITypeInfo2))
4595 *ppvObject = This;
4597 if(*ppvObject){
4598 ITypeInfo_AddRef(iface);
4599 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4600 return S_OK;
4602 TRACE("-- Interface: E_NOINTERFACE\n");
4603 return E_NOINTERFACE;
4606 /* ITypeInfo::AddRef
4608 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4610 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4611 ULONG ref = InterlockedIncrement(&This->ref);
4613 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4615 TRACE("(%p)->ref is %u\n",This, ref);
4616 return ref;
4619 /* ITypeInfo::Release
4621 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4623 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4624 ULONG ref = InterlockedDecrement(&This->ref);
4626 TRACE("(%p)->(%u)\n",This, ref);
4628 if (ref) {
4629 /* We don't release ITypeLib when ref=0 because
4630 it means that function is called by ITypeLib2_Release */
4631 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4632 } else {
4633 TLBFuncDesc *pFInfo, *pFInfoNext;
4634 TLBVarDesc *pVInfo, *pVInfoNext;
4635 TLBImplType *pImpl, *pImplNext;
4637 TRACE("destroying ITypeInfo(%p)\n",This);
4639 if (This->no_free_data)
4640 goto finish_free;
4642 if (This->Name)
4644 SysFreeString(This->Name);
4645 This->Name = 0;
4648 if (This->DocString)
4650 SysFreeString(This->DocString);
4651 This->DocString = 0;
4654 if (This->DllName)
4656 SysFreeString(This->DllName);
4657 This->DllName = 0;
4660 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4662 UINT i;
4663 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4665 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4666 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4668 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4669 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4671 SysFreeString(pFInfo->pParamDesc[i].Name);
4673 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4674 TLB_Free(pFInfo->pParamDesc);
4675 TLB_FreeCustData(pFInfo->pCustData);
4676 if (HIWORD(pFInfo->Entry) != 0 && pFInfo->Entry != (BSTR)-1)
4677 SysFreeString(pFInfo->Entry);
4678 SysFreeString(pFInfo->HelpString);
4679 SysFreeString(pFInfo->Name);
4681 pFInfoNext = pFInfo->next;
4682 TLB_Free(pFInfo);
4684 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
4686 if (pVInfo->vardesc.varkind == VAR_CONST)
4688 VariantClear(pVInfo->vardesc.u.lpvarValue);
4689 TLB_Free(pVInfo->vardesc.u.lpvarValue);
4691 TLB_FreeCustData(pVInfo->pCustData);
4692 SysFreeString(pVInfo->Name);
4693 pVInfoNext = pVInfo->next;
4694 TLB_Free(pVInfo);
4696 for(pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
4698 TLB_FreeCustData(pImpl->pCustData);
4699 pImplNext = pImpl->next;
4700 TLB_Free(pImpl);
4702 TLB_FreeCustData(This->pCustData);
4704 finish_free:
4705 if (This->next)
4707 ITypeInfo_Release((ITypeInfo*)This->next);
4710 HeapFree(GetProcessHeap(),0,This);
4711 return 0;
4713 return ref;
4716 /* ITypeInfo::GetTypeAttr
4718 * Retrieves a TYPEATTR structure that contains the attributes of the type
4719 * description.
4722 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4723 LPTYPEATTR *ppTypeAttr)
4725 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4726 SIZE_T size;
4728 TRACE("(%p)\n",This);
4730 size = sizeof(**ppTypeAttr);
4731 if (This->TypeAttr.typekind == TKIND_ALIAS)
4732 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4734 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4735 if (!*ppTypeAttr)
4736 return E_OUTOFMEMORY;
4738 **ppTypeAttr = This->TypeAttr;
4740 if (This->TypeAttr.typekind == TKIND_ALIAS)
4741 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4742 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4744 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4745 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4746 funcs */
4747 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4748 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4750 return S_OK;
4753 /* ITypeInfo::GetTypeComp
4755 * Retrieves the ITypeComp interface for the type description, which enables a
4756 * client compiler to bind to the type description's members.
4759 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4760 ITypeComp * *ppTComp)
4762 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4764 TRACE("(%p)->(%p)\n", This, ppTComp);
4766 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4767 ITypeComp_AddRef(*ppTComp);
4768 return S_OK;
4771 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4773 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4774 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4775 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4776 return size;
4779 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4781 *dest = *src;
4782 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4783 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4785 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4786 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4787 *buffer += sizeof(PARAMDESCEX);
4788 *pparamdescex_dest = *pparamdescex_src;
4789 VariantInit(&pparamdescex_dest->varDefaultValue);
4790 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4791 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4793 else
4794 dest->u.paramdesc.pparamdescex = NULL;
4795 return S_OK;
4798 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4800 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4801 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4804 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4806 FUNCDESC *dest;
4807 char *buffer;
4808 SIZE_T size = sizeof(*src);
4809 SHORT i;
4810 HRESULT hr;
4812 size += sizeof(*src->lprgscode) * src->cScodes;
4813 size += TLB_SizeElemDesc(&src->elemdescFunc);
4814 for (i = 0; i < src->cParams; i++)
4816 size += sizeof(ELEMDESC);
4817 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4820 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4821 if (!dest) return E_OUTOFMEMORY;
4823 *dest = *src;
4824 if (dispinterface) /* overwrite funckind */
4825 dest->funckind = FUNC_DISPATCH;
4826 buffer = (char *)(dest + 1);
4828 dest->lprgscode = (SCODE *)buffer;
4829 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4830 buffer += sizeof(*src->lprgscode) * src->cScodes;
4832 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4833 if (FAILED(hr))
4835 SysFreeString((BSTR)dest);
4836 return hr;
4839 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4840 buffer += sizeof(ELEMDESC) * src->cParams;
4841 for (i = 0; i < src->cParams; i++)
4843 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4844 if (FAILED(hr))
4845 break;
4847 if (FAILED(hr))
4849 /* undo the above actions */
4850 for (i = i - 1; i >= 0; i--)
4851 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4852 TLB_FreeElemDesc(&dest->elemdescFunc);
4853 SysFreeString((BSTR)dest);
4854 return hr;
4857 /* special treatment for dispinterfaces: this makes functions appear
4858 * to return their [retval] value when it is really returning an
4859 * HRESULT */
4860 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4862 if (dest->cParams &&
4863 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4865 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4866 if (elemdesc->tdesc.vt != VT_PTR)
4868 ERR("elemdesc should have started with VT_PTR instead of:\n");
4869 if (ERR_ON(ole))
4870 dump_ELEMDESC(elemdesc);
4871 return E_UNEXPECTED;
4874 /* copy last parameter to the return value. we are using a flat
4875 * buffer so there is no danger of leaking memory in
4876 * elemdescFunc */
4877 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4879 /* remove the last parameter */
4880 dest->cParams--;
4882 else
4883 /* otherwise this function is made to appear to have no return
4884 * value */
4885 dest->elemdescFunc.tdesc.vt = VT_VOID;
4889 *dest_ptr = dest;
4890 return S_OK;
4893 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4895 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4896 const TLBFuncDesc *pFDesc;
4897 int i;
4899 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4902 if (pFDesc)
4904 *ppFuncDesc = &pFDesc->funcdesc;
4905 return S_OK;
4908 return TYPE_E_ELEMENTNOTFOUND;
4911 /* internal function to make the inherited interfaces' methods appear
4912 * part of the interface */
4913 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
4914 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
4916 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4917 HRESULT hr;
4918 UINT implemented_funcs = 0;
4920 if (funcs)
4921 *funcs = 0;
4922 else
4923 *hrefoffset = DISPATCH_HREF_OFFSET;
4925 if(This->impltypelist)
4927 ITypeInfo *pSubTypeInfo;
4928 UINT sub_funcs;
4930 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
4931 if (FAILED(hr))
4932 return hr;
4934 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
4935 index,
4936 ppFuncDesc,
4937 &sub_funcs, hrefoffset);
4938 implemented_funcs += sub_funcs;
4939 ITypeInfo_Release(pSubTypeInfo);
4940 if (SUCCEEDED(hr))
4941 return hr;
4942 *hrefoffset += DISPATCH_HREF_OFFSET;
4945 if (funcs)
4946 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
4947 else
4948 *hrefoffset = 0;
4950 if (index < implemented_funcs)
4951 return E_INVALIDARG;
4952 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
4953 ppFuncDesc);
4956 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
4958 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
4959 while (TRUE)
4961 switch (pTypeDesc->vt)
4963 case VT_USERDEFINED:
4964 pTypeDesc->u.hreftype += hrefoffset;
4965 return;
4966 case VT_PTR:
4967 case VT_SAFEARRAY:
4968 pTypeDesc = pTypeDesc->u.lptdesc;
4969 break;
4970 case VT_CARRAY:
4971 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
4972 break;
4973 default:
4974 return;
4979 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
4981 SHORT i;
4982 for (i = 0; i < pFuncDesc->cParams; i++)
4983 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
4984 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
4987 /* ITypeInfo::GetFuncDesc
4989 * Retrieves the FUNCDESC structure that contains information about a
4990 * specified function.
4993 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4994 LPFUNCDESC *ppFuncDesc)
4996 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4997 const FUNCDESC *internal_funcdesc;
4998 HRESULT hr;
4999 UINT hrefoffset = 0;
5001 TRACE("(%p) index %d\n", This, index);
5003 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5004 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5005 &internal_funcdesc, NULL,
5006 &hrefoffset);
5007 else
5008 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5009 &internal_funcdesc);
5010 if (FAILED(hr))
5012 WARN("description for function %d not found\n", index);
5013 return hr;
5016 hr = TLB_AllocAndInitFuncDesc(
5017 internal_funcdesc,
5018 ppFuncDesc,
5019 This->TypeAttr.typekind == TKIND_DISPATCH);
5021 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5022 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5024 TRACE("-- 0x%08x\n", hr);
5025 return hr;
5028 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5030 VARDESC *dest;
5031 char *buffer;
5032 SIZE_T size = sizeof(*src);
5033 HRESULT hr;
5035 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5036 if (src->varkind == VAR_CONST)
5037 size += sizeof(VARIANT);
5038 size += TLB_SizeElemDesc(&src->elemdescVar);
5040 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5041 if (!dest) return E_OUTOFMEMORY;
5043 *dest = *src;
5044 buffer = (char *)(dest + 1);
5045 if (src->lpstrSchema)
5047 int len;
5048 dest->lpstrSchema = (LPOLESTR)buffer;
5049 len = strlenW(src->lpstrSchema);
5050 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5051 buffer += (len + 1) * sizeof(WCHAR);
5054 if (src->varkind == VAR_CONST)
5056 HRESULT hr;
5058 dest->u.lpvarValue = (VARIANT *)buffer;
5059 *dest->u.lpvarValue = *src->u.lpvarValue;
5060 buffer += sizeof(VARIANT);
5061 VariantInit(dest->u.lpvarValue);
5062 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5063 if (FAILED(hr))
5065 SysFreeString((BSTR)dest_ptr);
5066 return hr;
5069 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5070 if (FAILED(hr))
5072 if (src->varkind == VAR_CONST)
5073 VariantClear(dest->u.lpvarValue);
5074 SysFreeString((BSTR)dest);
5075 return hr;
5077 *dest_ptr = dest;
5078 return S_OK;
5081 /* ITypeInfo::GetVarDesc
5083 * Retrieves a VARDESC structure that describes the specified variable.
5086 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5087 LPVARDESC *ppVarDesc)
5089 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5090 int i;
5091 const TLBVarDesc *pVDesc;
5093 TRACE("(%p) index %d\n", This, index);
5095 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
5098 if (pVDesc)
5099 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5101 return E_INVALIDARG;
5104 /* ITypeInfo_GetNames
5106 * Retrieves the variable with the specified member ID (or the name of the
5107 * property or method and its parameters) that correspond to the specified
5108 * function ID.
5110 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5111 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5113 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5114 const TLBFuncDesc *pFDesc;
5115 const TLBVarDesc *pVDesc;
5116 int i;
5117 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5118 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
5119 if(pFDesc)
5121 /* function found, now return function and parameter names */
5122 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5124 if(!i)
5125 *rgBstrNames=SysAllocString(pFDesc->Name);
5126 else
5127 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5129 *pcNames=i;
5131 else
5133 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
5134 if(pVDesc)
5136 *rgBstrNames=SysAllocString(pVDesc->Name);
5137 *pcNames=1;
5139 else
5141 if(This->impltypelist &&
5142 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5143 /* recursive search */
5144 ITypeInfo *pTInfo;
5145 HRESULT result;
5146 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5147 &pTInfo);
5148 if(SUCCEEDED(result))
5150 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5151 ITypeInfo_Release(pTInfo);
5152 return result;
5154 WARN("Could not search inherited interface!\n");
5156 else
5158 WARN("no names found\n");
5160 *pcNames=0;
5161 return TYPE_E_ELEMENTNOTFOUND;
5164 return S_OK;
5168 /* ITypeInfo::GetRefTypeOfImplType
5170 * If a type description describes a COM class, it retrieves the type
5171 * description of the implemented interface types. For an interface,
5172 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5173 * if any exist.
5176 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5177 ITypeInfo2 *iface,
5178 UINT index,
5179 HREFTYPE *pRefType)
5181 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5182 int i;
5183 HRESULT hr = S_OK;
5184 const TLBImplType *pImpl = This->impltypelist;
5186 TRACE("(%p) index %d\n", This, index);
5187 if (TRACE_ON(ole)) dump_TypeInfo(This);
5189 if(index==(UINT)-1)
5191 /* only valid on dual interfaces;
5192 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5194 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5196 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
5197 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
5199 *pRefType = -1;
5201 else
5203 hr = TYPE_E_ELEMENTNOTFOUND;
5206 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5208 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5209 *pRefType = This->pTypeLib->dispatch_href;
5211 else
5213 /* get element n from linked list */
5214 for(i=0; pImpl && i<index; i++)
5216 pImpl = pImpl->next;
5219 if (pImpl)
5220 *pRefType = pImpl->hRef;
5221 else
5222 hr = TYPE_E_ELEMENTNOTFOUND;
5225 if(TRACE_ON(ole))
5227 if(SUCCEEDED(hr))
5228 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5229 else
5230 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5233 return hr;
5236 /* ITypeInfo::GetImplTypeFlags
5238 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5239 * or base interface in a type description.
5241 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5242 UINT index, INT *pImplTypeFlags)
5244 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5245 int i;
5246 TLBImplType *pImpl;
5248 TRACE("(%p) index %d\n", This, index);
5249 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5250 i++, pImpl=pImpl->next)
5252 if(i==index && pImpl){
5253 *pImplTypeFlags=pImpl->implflags;
5254 return S_OK;
5256 *pImplTypeFlags=0;
5257 return TYPE_E_ELEMENTNOTFOUND;
5260 /* GetIDsOfNames
5261 * Maps between member names and member IDs, and parameter names and
5262 * parameter IDs.
5264 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5265 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5267 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5268 const TLBFuncDesc *pFDesc;
5269 const TLBVarDesc *pVDesc;
5270 HRESULT ret=S_OK;
5271 int i;
5273 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5274 cNames);
5276 /* init out parameters in case of failure */
5277 for (i = 0; i < cNames; i++)
5278 pMemId[i] = MEMBERID_NIL;
5280 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5281 int j;
5282 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5283 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5284 for(i=1; i < cNames; i++){
5285 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5286 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5287 break;
5288 if( j<pFDesc->funcdesc.cParams)
5289 pMemId[i]=j;
5290 else
5291 ret=DISP_E_UNKNOWNNAME;
5293 TRACE("-- 0x%08x\n", ret);
5294 return ret;
5297 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5298 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5299 if(cNames) *pMemId=pVDesc->vardesc.memid;
5300 return ret;
5303 /* not found, see if it can be found in an inherited interface */
5304 if(This->impltypelist) {
5305 /* recursive search */
5306 ITypeInfo *pTInfo;
5307 ret=ITypeInfo_GetRefTypeInfo(iface,
5308 This->impltypelist->hRef, &pTInfo);
5309 if(SUCCEEDED(ret)){
5310 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5311 ITypeInfo_Release(pTInfo);
5312 return ret;
5314 WARN("Could not search inherited interface!\n");
5315 } else
5316 WARN("no names found\n");
5317 return DISP_E_UNKNOWNNAME;
5320 /* ITypeInfo::Invoke
5322 * Invokes a method, or accesses a property of an object, that implements the
5323 * interface described by the type description.
5325 DWORD
5326 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5327 DWORD res;
5329 if (TRACE_ON(ole)) {
5330 int i;
5331 TRACE("Calling %p(",func);
5332 for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
5333 TRACE(")\n");
5336 switch (callconv) {
5337 case CC_STDCALL:
5339 switch (nrargs) {
5340 case 0:
5341 res = func();
5342 break;
5343 case 1:
5344 res = func(args[0]);
5345 break;
5346 case 2:
5347 res = func(args[0],args[1]);
5348 break;
5349 case 3:
5350 res = func(args[0],args[1],args[2]);
5351 break;
5352 case 4:
5353 res = func(args[0],args[1],args[2],args[3]);
5354 break;
5355 case 5:
5356 res = func(args[0],args[1],args[2],args[3],args[4]);
5357 break;
5358 case 6:
5359 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
5360 break;
5361 case 7:
5362 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
5363 break;
5364 case 8:
5365 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
5366 break;
5367 case 9:
5368 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
5369 break;
5370 case 10:
5371 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
5372 break;
5373 case 11:
5374 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
5375 break;
5376 case 12:
5377 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]);
5378 break;
5379 case 13:
5380 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]);
5381 break;
5382 case 14:
5383 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]);
5384 break;
5385 case 15:
5386 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]);
5387 break;
5388 case 16:
5389 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]);
5390 break;
5391 case 17:
5392 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]);
5393 break;
5394 case 18:
5395 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]);
5396 break;
5397 case 19:
5398 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]);
5399 break;
5400 case 20:
5401 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]);
5402 break;
5403 case 21:
5404 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]);
5405 break;
5406 case 22:
5407 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]);
5408 break;
5409 case 23:
5410 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]);
5411 break;
5412 case 24:
5413 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]);
5414 break;
5415 case 25:
5416 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]);
5417 break;
5418 case 26:
5419 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]);
5420 break;
5421 case 27:
5422 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]);
5423 break;
5424 case 28:
5425 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]);
5426 break;
5427 case 29:
5428 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]);
5429 break;
5430 case 30:
5431 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]);
5432 break;
5433 default:
5434 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
5435 res = -1;
5436 break;
5438 break;
5439 default:
5440 FIXME("unsupported calling convention %d\n",callconv);
5441 res = -1;
5442 break;
5444 TRACE("returns %08x\n",res);
5445 return res;
5448 extern int _argsize(DWORD vt);
5450 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5452 HRESULT hr = S_OK;
5453 ITypeInfo *tinfo2 = NULL;
5454 TYPEATTR *tattr = NULL;
5456 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5457 if (hr)
5459 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5460 "hr = 0x%08x\n",
5461 tdesc->u.hreftype, hr);
5462 return hr;
5464 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5465 if (hr)
5467 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5468 ITypeInfo_Release(tinfo2);
5469 return hr;
5472 switch (tattr->typekind)
5474 case TKIND_ENUM:
5475 *vt |= VT_I4;
5476 break;
5478 case TKIND_ALIAS:
5479 tdesc = &tattr->tdescAlias;
5480 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5481 break;
5483 case TKIND_INTERFACE:
5484 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5485 *vt |= VT_DISPATCH;
5486 else
5487 *vt |= VT_UNKNOWN;
5488 break;
5490 case TKIND_DISPATCH:
5491 *vt |= VT_DISPATCH;
5492 break;
5494 case TKIND_COCLASS:
5495 *vt |= VT_DISPATCH;
5496 break;
5498 case TKIND_RECORD:
5499 FIXME("TKIND_RECORD unhandled.\n");
5500 hr = E_NOTIMPL;
5501 break;
5503 case TKIND_UNION:
5504 FIXME("TKIND_UNION unhandled.\n");
5505 hr = E_NOTIMPL;
5506 break;
5508 default:
5509 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5510 hr = E_NOTIMPL;
5511 break;
5513 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5514 ITypeInfo_Release(tinfo2);
5515 return hr;
5518 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5520 HRESULT hr = S_OK;
5522 /* enforce only one level of pointer indirection */
5523 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5525 tdesc = tdesc->u.lptdesc;
5527 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5528 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5529 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5530 if ((tdesc->vt == VT_USERDEFINED) ||
5531 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5533 VARTYPE vt_userdefined = 0;
5534 const TYPEDESC *tdesc_userdefined = tdesc;
5535 if (tdesc->vt == VT_PTR)
5537 vt_userdefined = VT_BYREF;
5538 tdesc_userdefined = tdesc->u.lptdesc;
5540 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5541 if ((hr == S_OK) &&
5542 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5543 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5545 *vt |= vt_userdefined;
5546 return S_OK;
5549 *vt = VT_BYREF;
5552 switch (tdesc->vt)
5554 case VT_HRESULT:
5555 *vt |= VT_ERROR;
5556 break;
5557 case VT_USERDEFINED:
5558 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5559 break;
5560 case VT_VOID:
5561 case VT_CARRAY:
5562 case VT_PTR:
5563 case VT_LPSTR:
5564 case VT_LPWSTR:
5565 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5566 hr = DISP_E_BADVARTYPE;
5567 break;
5568 case VT_SAFEARRAY:
5569 *vt |= VT_ARRAY;
5570 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5571 break;
5572 default:
5573 *vt |= tdesc->vt;
5574 break;
5576 return hr;
5579 /***********************************************************************
5580 * DispCallFunc (OLEAUT32.@)
5582 * Invokes a function of the specified calling convention, passing the
5583 * specified arguments and returns the result.
5585 * PARAMS
5586 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5587 * oVft [I] The offset in the vtable. See notes.
5588 * cc [I] Calling convention of the function to call.
5589 * vtReturn [I] The return type of the function.
5590 * cActuals [I] Number of parameters.
5591 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5592 * prgpvarg [I] The arguments to pass.
5593 * pvargResult [O] The return value of the function. Can be NULL.
5595 * RETURNS
5596 * Success: S_OK.
5597 * Failure: HRESULT code.
5599 * NOTES
5600 * The HRESULT return value of this function is not affected by the return
5601 * value of the user supplied function, which is returned in pvargResult.
5603 * If pvInstance is NULL then a non-object function is to be called and oVft
5604 * is the address of the function to call.
5606 * The cc parameter can be one of the following values:
5607 *|CC_FASTCALL
5608 *|CC_CDECL
5609 *|CC_PASCAL
5610 *|CC_STDCALL
5611 *|CC_FPFASTCALL
5612 *|CC_SYSCALL
5613 *|CC_MPWCDECL
5614 *|CC_MPWPASCAL
5617 HRESULT WINAPI
5618 DispCallFunc(
5619 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5620 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5622 int i, argsize, argspos;
5623 DWORD *args;
5624 HRESULT hres;
5626 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5627 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5628 pvargResult, V_VT(pvargResult));
5630 argsize = 0;
5631 if (pvInstance)
5632 argsize++; /* for This pointer */
5634 for (i=0;i<cActuals;i++)
5636 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5637 dump_Variant(prgpvarg[i]);
5638 argsize += _argsize(prgvt[i]);
5640 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5642 argspos = 0;
5643 if (pvInstance)
5645 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5646 argspos++;
5649 for (i=0;i<cActuals;i++)
5651 VARIANT *arg = prgpvarg[i];
5652 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5653 if (prgvt[i] == VT_VARIANT)
5654 memcpy(&args[argspos], arg, _argsize(prgvt[i]) * sizeof(DWORD));
5655 else
5656 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5657 argspos += _argsize(prgvt[i]);
5660 if (pvInstance)
5662 FARPROC *vtable = *(FARPROC**)pvInstance;
5663 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5665 else
5666 /* if we aren't invoking an object then the function pointer is stored
5667 * in oVft */
5668 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5670 if (pvargResult && (vtReturn != VT_EMPTY))
5672 TRACE("Method returned 0x%08x\n",hres);
5673 V_VT(pvargResult) = vtReturn;
5674 V_UI4(pvargResult) = hres;
5677 HeapFree(GetProcessHeap(),0,args);
5678 return S_OK;
5681 #define INVBUF_ELEMENT_SIZE \
5682 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5683 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5684 ((VARIANTARG *)(buffer))
5685 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5686 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5687 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5688 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5689 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5690 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5692 static HRESULT WINAPI ITypeInfo_fnInvoke(
5693 ITypeInfo2 *iface,
5694 VOID *pIUnk,
5695 MEMBERID memid,
5696 UINT16 wFlags,
5697 DISPPARAMS *pDispParams,
5698 VARIANT *pVarResult,
5699 EXCEPINFO *pExcepInfo,
5700 UINT *pArgErr)
5702 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5703 int i;
5704 unsigned int var_index;
5705 TYPEKIND type_kind;
5706 HRESULT hres;
5707 const TLBFuncDesc *pFuncInfo;
5709 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
5710 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5713 if (!pDispParams)
5715 ERR("NULL pDispParams not allowed\n");
5716 return E_INVALIDARG;
5719 dump_DispParms(pDispParams);
5721 if (pDispParams->cNamedArgs > pDispParams->cArgs)
5723 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
5724 pDispParams->cNamedArgs, pDispParams->cArgs);
5725 return E_INVALIDARG;
5728 /* we do this instead of using GetFuncDesc since it will return a fake
5729 * FUNCDESC for dispinterfaces and we want the real function description */
5730 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5731 if ((memid == pFuncInfo->funcdesc.memid) &&
5732 (wFlags & pFuncInfo->funcdesc.invkind))
5733 break;
5735 if (pFuncInfo) {
5736 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5738 if (TRACE_ON(ole))
5740 TRACE("invoking:\n");
5741 dump_TLBFuncDescOne(pFuncInfo);
5744 switch (func_desc->funckind) {
5745 case FUNC_PUREVIRTUAL:
5746 case FUNC_VIRTUAL: {
5747 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
5748 VARIANT varresult;
5749 VARIANT retval; /* pointer for storing byref retvals in */
5750 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
5751 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
5752 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
5753 UINT cNamedArgs = pDispParams->cNamedArgs;
5754 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
5756 hres = S_OK;
5758 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
5760 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
5762 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
5763 hres = DISP_E_PARAMNOTFOUND;
5764 goto func_fail;
5766 /* ignore the DISPID_PROPERTYPUT named argument from now on */
5767 cNamedArgs--;
5768 rgdispidNamedArgs++;
5771 if (func_desc->cParamsOpt < 0 && cNamedArgs)
5773 ERR("functions with the vararg attribute do not support named arguments\n");
5774 hres = DISP_E_NONAMEDARGS;
5775 goto func_fail;
5778 for (i = 0; i < func_desc->cParams; i++)
5780 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5781 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
5782 if (FAILED(hres))
5783 goto func_fail;
5786 TRACE("changing args\n");
5787 for (i = 0; i < func_desc->cParams; i++)
5789 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5790 VARIANTARG *src_arg;
5792 if (cNamedArgs)
5794 USHORT j;
5795 src_arg = NULL;
5796 for (j = 0; j < cNamedArgs; j++)
5797 if (rgdispidNamedArgs[j] == i)
5799 src_arg = &pDispParams->rgvarg[j];
5800 break;
5803 else
5804 src_arg = i < pDispParams->cArgs ? &pDispParams->rgvarg[pDispParams->cArgs - 1 - i] : NULL;
5806 if (wParamFlags & PARAMFLAG_FRETVAL)
5808 /* under most conditions the caller is not allowed to
5809 * pass in a dispparam arg in the index of what would be
5810 * the retval parameter. however, there is an exception
5811 * where the extra parameter is used in an extra
5812 * IDispatch::Invoke below */
5813 if ((i < pDispParams->cArgs) &&
5814 ((func_desc->cParams != 1) || !pVarResult ||
5815 !(func_desc->invkind & INVOKE_PROPERTYGET)))
5817 hres = DISP_E_BADPARAMCOUNT;
5818 break;
5821 /* note: this check is placed so that if the caller passes
5822 * in a VARIANTARG for the retval we just ignore it, like
5823 * native does */
5824 if (i == func_desc->cParams - 1)
5826 VARIANTARG *arg;
5827 arg = prgpvarg[i] = &rgvarg[i];
5828 memset(arg, 0, sizeof(*arg));
5829 V_VT(arg) = rgvt[i];
5830 memset(&retval, 0, sizeof(retval));
5831 V_BYREF(arg) = &retval;
5833 else
5835 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
5836 hres = E_UNEXPECTED;
5837 break;
5840 else if (src_arg)
5842 dump_Variant(src_arg);
5844 if (rgvt[i] == VT_VARIANT)
5845 hres = VariantCopy(&rgvarg[i], src_arg);
5846 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
5848 if (rgvt[i] == V_VT(src_arg))
5849 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
5850 else
5852 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5853 hres = VariantCopy(&missing_arg[i], src_arg);
5854 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
5856 V_VT(&rgvarg[i]) = rgvt[i];
5858 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
5860 SAFEARRAY *a;
5861 SAFEARRAYBOUND bound;
5862 VARIANT *v;
5863 LONG j;
5864 bound.lLbound = 0;
5865 bound.cElements = pDispParams->cArgs-i;
5866 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
5868 ERR("SafeArrayCreate failed\n");
5869 break;
5871 hres = SafeArrayAccessData(a, (LPVOID)&v);
5872 if (hres != S_OK)
5874 ERR("SafeArrayAccessData failed with %x\n", hres);
5875 break;
5877 for (j = 0; j < bound.cElements; j++)
5878 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
5879 hres = SafeArrayUnaccessData(a);
5880 if (hres != S_OK)
5882 ERR("SafeArrayUnaccessData failed with %x\n", hres);
5883 break;
5885 V_ARRAY(&rgvarg[i]) = a;
5886 V_VT(&rgvarg[i]) = rgvt[i];
5888 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
5890 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5891 V_VT(&missing_arg[i]) = V_VT(src_arg);
5892 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
5893 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
5894 V_VT(&rgvarg[i]) = rgvt[i];
5896 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
5898 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
5899 V_VT(&rgvarg[i]) = rgvt[i];
5901 else
5903 /* FIXME: this doesn't work for VT_BYREF arguments if
5904 * they are not the same type as in the paramdesc */
5905 V_VT(&rgvarg[i]) = V_VT(src_arg);
5906 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
5907 V_VT(&rgvarg[i]) = rgvt[i];
5910 if (FAILED(hres))
5912 ERR("failed to convert param %d to %s%s from %s%s\n", i,
5913 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
5914 debugstr_VT(src_arg), debugstr_VF(src_arg));
5915 break;
5917 prgpvarg[i] = &rgvarg[i];
5919 else if (wParamFlags & PARAMFLAG_FOPT)
5921 VARIANTARG *arg;
5922 arg = prgpvarg[i] = &rgvarg[i];
5923 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5925 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
5926 if (FAILED(hres))
5927 break;
5929 else
5931 VARIANTARG *missing_arg;
5932 /* if the function wants a pointer to a variant then
5933 * set that up, otherwise just pass the VT_ERROR in
5934 * the argument by value */
5935 if (rgvt[i] & VT_BYREF)
5937 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
5938 V_VT(arg) = VT_VARIANT | VT_BYREF;
5939 V_VARIANTREF(arg) = missing_arg;
5941 else
5942 missing_arg = arg;
5943 V_VT(missing_arg) = VT_ERROR;
5944 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
5947 else
5949 hres = DISP_E_BADPARAMCOUNT;
5950 break;
5953 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5955 /* VT_VOID is a special case for return types, so it is not
5956 * handled in the general function */
5957 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
5958 V_VT(&varresult) = VT_EMPTY;
5959 else
5961 V_VT(&varresult) = 0;
5962 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
5963 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5966 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
5967 V_VT(&varresult), func_desc->cParams, rgvt,
5968 prgpvarg, &varresult);
5970 for (i = 0; i < func_desc->cParams; i++)
5972 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5973 if (wParamFlags & PARAMFLAG_FRETVAL)
5975 if (TRACE_ON(ole))
5977 TRACE("[retval] value: ");
5978 dump_Variant(prgpvarg[i]);
5981 if (pVarResult)
5983 VariantInit(pVarResult);
5984 /* deref return value */
5985 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
5988 /* free data stored in varresult. Note that
5989 * VariantClear doesn't do what we want because we are
5990 * working with byref types. */
5991 /* FIXME: clear safearrays, bstrs, records and
5992 * variants here too */
5993 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
5994 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
5996 if(*V_UNKNOWNREF(prgpvarg[i]))
5997 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
5999 break;
6001 else if (i < pDispParams->cArgs)
6003 if (wParamFlags & PARAMFLAG_FOUT)
6005 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
6007 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
6008 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6010 if (FAILED(hres))
6012 ERR("failed to convert param %d to vt %d\n", i,
6013 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
6014 break;
6017 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6018 func_desc->cParamsOpt < 0 &&
6019 i == func_desc->cParams-1)
6021 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6022 LONG j, ubound;
6023 VARIANT *v;
6024 hres = SafeArrayGetUBound(a, 1, &ubound);
6025 if (hres != S_OK)
6027 ERR("SafeArrayGetUBound failed with %x\n", hres);
6028 break;
6030 hres = SafeArrayAccessData(a, (LPVOID)&v);
6031 if (hres != S_OK)
6033 ERR("SafeArrayAccessData failed with %x\n", hres);
6034 break;
6036 for (j = 0; j <= ubound; j++)
6037 VariantClear(&v[j]);
6038 hres = SafeArrayUnaccessData(a);
6039 if (hres != S_OK)
6041 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6042 break;
6045 VariantClear(&rgvarg[i]);
6047 else if (wParamFlags & PARAMFLAG_FOPT)
6049 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6050 VariantClear(&rgvarg[i]);
6054 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6056 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6057 hres = DISP_E_EXCEPTION;
6058 if (pExcepInfo)
6060 IErrorInfo *pErrorInfo;
6061 pExcepInfo->scode = V_ERROR(&varresult);
6062 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6064 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6065 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6066 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6067 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6069 IErrorInfo_Release(pErrorInfo);
6073 if (V_VT(&varresult) != VT_ERROR)
6075 TRACE("varresult value: ");
6076 dump_Variant(&varresult);
6078 if (pVarResult)
6080 VariantClear(pVarResult);
6081 *pVarResult = varresult;
6083 else
6084 VariantClear(&varresult);
6087 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6088 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6089 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6090 (pDispParams->cArgs != 0))
6092 if (V_VT(pVarResult) == VT_DISPATCH)
6094 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6095 /* Note: not VariantClear; we still need the dispatch
6096 * pointer to be valid */
6097 VariantInit(pVarResult);
6098 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6099 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6100 pDispParams, pVarResult, pExcepInfo, pArgErr);
6101 IDispatch_Release(pDispatch);
6103 else
6105 VariantClear(pVarResult);
6106 hres = DISP_E_NOTACOLLECTION;
6110 func_fail:
6111 HeapFree(GetProcessHeap(), 0, buffer);
6112 break;
6114 case FUNC_DISPATCH: {
6115 IDispatch *disp;
6117 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6118 if (SUCCEEDED(hres)) {
6119 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6120 hres = IDispatch_Invoke(
6121 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6122 pVarResult,pExcepInfo,pArgErr
6124 if (FAILED(hres))
6125 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6126 IDispatch_Release(disp);
6127 } else
6128 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6129 break;
6131 default:
6132 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6133 hres = E_FAIL;
6134 break;
6137 TRACE("-- 0x%08x\n", hres);
6138 return hres;
6140 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6141 VARDESC *var_desc;
6143 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6144 if(FAILED(hres)) return hres;
6146 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6147 dump_VARDESC(var_desc);
6148 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6149 return E_NOTIMPL;
6152 /* not found, look for it in inherited interfaces */
6153 ITypeInfo2_GetTypeKind(iface, &type_kind);
6154 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6155 if(This->impltypelist) {
6156 /* recursive search */
6157 ITypeInfo *pTInfo;
6158 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6159 if(SUCCEEDED(hres)){
6160 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6161 ITypeInfo_Release(pTInfo);
6162 return hres;
6164 WARN("Could not search inherited interface!\n");
6167 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6168 return DISP_E_MEMBERNOTFOUND;
6171 /* ITypeInfo::GetDocumentation
6173 * Retrieves the documentation string, the complete Help file name and path,
6174 * and the context ID for the Help topic for a specified type description.
6176 * (Can be tested by the Visual Basic Editor in Word for instance.)
6178 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6179 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6180 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6182 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6183 const TLBFuncDesc *pFDesc;
6184 const TLBVarDesc *pVDesc;
6185 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6186 " HelpContext(%p) HelpFile(%p)\n",
6187 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6188 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6189 if(pBstrName)
6190 *pBstrName=SysAllocString(This->Name);
6191 if(pBstrDocString)
6192 *pBstrDocString=SysAllocString(This->DocString);
6193 if(pdwHelpContext)
6194 *pdwHelpContext=This->dwHelpContext;
6195 if(pBstrHelpFile)
6196 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6197 return S_OK;
6198 }else {/* for a member */
6199 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6200 if(pFDesc->funcdesc.memid==memid){
6201 if(pBstrName)
6202 *pBstrName = SysAllocString(pFDesc->Name);
6203 if(pBstrDocString)
6204 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6205 if(pdwHelpContext)
6206 *pdwHelpContext=pFDesc->helpcontext;
6207 return S_OK;
6209 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6210 if(pVDesc->vardesc.memid==memid){
6211 if(pBstrName)
6212 *pBstrName = SysAllocString(pVDesc->Name);
6213 if(pBstrDocString)
6214 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6215 if(pdwHelpContext)
6216 *pdwHelpContext=pVDesc->HelpContext;
6217 return S_OK;
6221 if(This->impltypelist &&
6222 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6223 /* recursive search */
6224 ITypeInfo *pTInfo;
6225 HRESULT result;
6226 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6227 &pTInfo);
6228 if(SUCCEEDED(result)) {
6229 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6230 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6231 ITypeInfo_Release(pTInfo);
6232 return result;
6234 WARN("Could not search inherited interface!\n");
6237 WARN("member %d not found\n", memid);
6238 return TYPE_E_ELEMENTNOTFOUND;
6241 /* ITypeInfo::GetDllEntry
6243 * Retrieves a description or specification of an entry point for a function
6244 * in a DLL.
6246 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6247 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6248 WORD *pwOrdinal)
6250 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6251 const TLBFuncDesc *pFDesc;
6253 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6255 if (pBstrDllName) *pBstrDllName = NULL;
6256 if (pBstrName) *pBstrName = NULL;
6257 if (pwOrdinal) *pwOrdinal = 0;
6259 if (This->TypeAttr.typekind != TKIND_MODULE)
6260 return TYPE_E_BADMODULEKIND;
6262 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6263 if(pFDesc->funcdesc.memid==memid){
6264 dump_TypeInfo(This);
6265 if (TRACE_ON(ole))
6266 dump_TLBFuncDescOne(pFDesc);
6268 if (pBstrDllName)
6269 *pBstrDllName = SysAllocString(This->DllName);
6271 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6272 if (pBstrName)
6273 *pBstrName = SysAllocString(pFDesc->Entry);
6274 if (pwOrdinal)
6275 *pwOrdinal = -1;
6276 return S_OK;
6278 if (pBstrName)
6279 *pBstrName = NULL;
6280 if (pwOrdinal)
6281 *pwOrdinal = (DWORD)pFDesc->Entry;
6282 return S_OK;
6284 return TYPE_E_ELEMENTNOTFOUND;
6287 /* internal function to make the inherited interfaces' methods appear
6288 * part of the interface */
6289 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6290 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6292 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6293 HRESULT hr;
6295 TRACE("%p, 0x%x\n", iface, *hRefType);
6297 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK))
6299 ITypeInfo *pSubTypeInfo;
6301 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
6302 if (FAILED(hr))
6303 return hr;
6305 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6306 hRefType, ppTInfo);
6307 ITypeInfo_Release(pSubTypeInfo);
6308 if (SUCCEEDED(hr))
6309 return hr;
6311 *hRefType -= DISPATCH_HREF_OFFSET;
6313 if (!(*hRefType & DISPATCH_HREF_MASK))
6314 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6315 else
6316 return E_FAIL;
6319 /* ITypeInfo::GetRefTypeInfo
6321 * If a type description references other type descriptions, it retrieves
6322 * the referenced type descriptions.
6324 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6325 ITypeInfo2 *iface,
6326 HREFTYPE hRefType,
6327 ITypeInfo **ppTInfo)
6329 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6330 HRESULT result = E_FAIL;
6332 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6334 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6335 ITypeInfo_AddRef(*ppTInfo);
6336 result = S_OK;
6338 else if (hRefType == -1 &&
6339 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6340 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6342 /* when we meet a DUAL dispinterface, we must create the interface
6343 * version of it.
6345 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
6348 /* the interface version contains the same information as the dispinterface
6349 * copy the contents of the structs.
6351 *pTypeInfoImpl = *This;
6352 pTypeInfoImpl->ref = 0;
6354 /* change the type to interface */
6355 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6357 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6359 /* we use data structures from This, so we need to keep a reference
6360 * to it to stop it being destroyed and signal to the new instance to
6361 * not free its data structures when it is destroyed */
6362 pTypeInfoImpl->no_free_data = TRUE;
6363 pTypeInfoImpl->next = This;
6364 ITypeInfo_AddRef((ITypeInfo*) This);
6366 ITypeInfo_AddRef(*ppTInfo);
6368 result = S_OK;
6370 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6371 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6372 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6374 HREFTYPE href_dispatch = hRefType;
6375 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6376 } else {
6377 TLBRefType *ref_type;
6378 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6380 if(ref_type->reference == hRefType)
6381 break;
6383 if(&ref_type->entry == &This->pTypeLib->ref_list)
6385 FIXME("Can't find pRefType for ref %x\n", hRefType);
6386 goto end;
6388 if(hRefType != -1) {
6389 ITypeLib *pTLib = NULL;
6391 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6392 UINT Index;
6393 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6394 } else {
6395 if(ref_type->pImpTLInfo->pImpTypeLib) {
6396 TRACE("typeinfo in imported typelib that is already loaded\n");
6397 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6398 ITypeLib2_AddRef(pTLib);
6399 result = S_OK;
6400 } else {
6401 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6402 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6403 ref_type->pImpTLInfo->wVersionMajor,
6404 ref_type->pImpTLInfo->wVersionMinor,
6405 ref_type->pImpTLInfo->lcid,
6406 &pTLib);
6408 if(!SUCCEEDED(result)) {
6409 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6410 result=LoadTypeLib(libnam, &pTLib);
6411 SysFreeString(libnam);
6413 if(SUCCEEDED(result)) {
6414 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6415 ITypeLib2_AddRef(pTLib);
6419 if(SUCCEEDED(result)) {
6420 if(ref_type->index == TLB_REF_USE_GUID)
6421 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6422 &ref_type->guid,
6423 ppTInfo);
6424 else
6425 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6426 ppTInfo);
6428 if (pTLib != NULL)
6429 ITypeLib2_Release(pTLib);
6433 end:
6434 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6435 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6436 return result;
6439 /* ITypeInfo::AddressOfMember
6441 * Retrieves the addresses of static functions or variables, such as those
6442 * defined in a DLL.
6444 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6445 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6447 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6448 HRESULT hr;
6449 BSTR dll, entry;
6450 WORD ordinal;
6451 HMODULE module;
6453 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6455 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6456 if (FAILED(hr))
6457 return hr;
6459 module = LoadLibraryW(dll);
6460 if (!module)
6462 ERR("couldn't load %s\n", debugstr_w(dll));
6463 SysFreeString(dll);
6464 if (entry) SysFreeString(entry);
6465 return STG_E_FILENOTFOUND;
6467 /* FIXME: store library somewhere where we can free it */
6469 if (entry)
6471 LPSTR entryA;
6472 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6473 entryA = HeapAlloc(GetProcessHeap(), 0, len);
6474 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6476 *ppv = GetProcAddress(module, entryA);
6477 if (!*ppv)
6478 ERR("function not found %s\n", debugstr_a(entryA));
6480 HeapFree(GetProcessHeap(), 0, entryA);
6482 else
6484 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6485 if (!*ppv)
6486 ERR("function not found %d\n", ordinal);
6489 SysFreeString(dll);
6490 if (entry) SysFreeString(entry);
6492 if (!*ppv)
6493 return TYPE_E_DLLFUNCTIONNOTFOUND;
6495 return S_OK;
6498 /* ITypeInfo::CreateInstance
6500 * Creates a new instance of a type that describes a component object class
6501 * (coclass).
6503 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6504 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6506 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6507 HRESULT hr;
6508 TYPEATTR *pTA;
6510 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6512 *ppvObj = NULL;
6514 if(pOuterUnk)
6516 WARN("Not able to aggregate\n");
6517 return CLASS_E_NOAGGREGATION;
6520 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6521 if(FAILED(hr)) return hr;
6523 if(pTA->typekind != TKIND_COCLASS)
6525 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6526 hr = E_INVALIDARG;
6527 goto end;
6530 hr = S_FALSE;
6531 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6533 IUnknown *pUnk;
6534 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6535 TRACE("GetActiveObject rets %08x\n", hr);
6536 if(hr == S_OK)
6538 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6539 IUnknown_Release(pUnk);
6543 if(hr != S_OK)
6544 hr = CoCreateInstance(&pTA->guid, NULL,
6545 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6546 riid, ppvObj);
6548 end:
6549 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6550 return hr;
6553 /* ITypeInfo::GetMops
6555 * Retrieves marshalling information.
6557 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6558 BSTR *pBstrMops)
6560 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6561 FIXME("(%p) stub!\n", This);
6562 return S_OK;
6565 /* ITypeInfo::GetContainingTypeLib
6567 * Retrieves the containing type library and the index of the type description
6568 * within that type library.
6570 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6571 ITypeLib * *ppTLib, UINT *pIndex)
6573 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6575 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6576 if (pIndex) {
6577 *pIndex=This->index;
6578 TRACE("returning pIndex=%d\n", *pIndex);
6581 if (ppTLib) {
6582 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6583 ITypeLib2_AddRef(*ppTLib);
6584 TRACE("returning ppTLib=%p\n", *ppTLib);
6587 return S_OK;
6590 /* ITypeInfo::ReleaseTypeAttr
6592 * Releases a TYPEATTR previously returned by GetTypeAttr.
6595 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6596 TYPEATTR* pTypeAttr)
6598 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6599 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6600 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6603 /* ITypeInfo::ReleaseFuncDesc
6605 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6607 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6608 ITypeInfo2 *iface,
6609 FUNCDESC *pFuncDesc)
6611 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6612 SHORT i;
6614 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6616 for (i = 0; i < pFuncDesc->cParams; i++)
6617 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6618 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6620 SysFreeString((BSTR)pFuncDesc);
6623 /* ITypeInfo::ReleaseVarDesc
6625 * Releases a VARDESC previously returned by GetVarDesc.
6627 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6628 VARDESC *pVarDesc)
6630 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6631 TRACE("(%p)->(%p)\n", This, pVarDesc);
6633 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6634 if (pVarDesc->varkind == VAR_CONST)
6635 VariantClear(pVarDesc->u.lpvarValue);
6636 SysFreeString((BSTR)pVarDesc);
6639 /* ITypeInfo2::GetTypeKind
6641 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6644 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6645 TYPEKIND *pTypeKind)
6647 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6648 *pTypeKind=This->TypeAttr.typekind;
6649 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6650 return S_OK;
6653 /* ITypeInfo2::GetTypeFlags
6655 * Returns the type flags without any allocations. This returns a DWORD type
6656 * flag, which expands the type flags without growing the TYPEATTR (type
6657 * attribute).
6660 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6662 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6663 *pTypeFlags=This->TypeAttr.wTypeFlags;
6664 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6665 return S_OK;
6668 /* ITypeInfo2::GetFuncIndexOfMemId
6669 * Binds to a specific member based on a known DISPID, where the member name
6670 * is not known (for example, when binding to a default member).
6673 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
6674 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
6676 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6677 const TLBFuncDesc *pFuncInfo;
6678 int i;
6679 HRESULT result;
6681 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
6682 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
6683 break;
6684 if(pFuncInfo) {
6685 *pFuncIndex = i;
6686 result = S_OK;
6687 } else
6688 result = TYPE_E_ELEMENTNOTFOUND;
6690 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
6691 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6692 return result;
6695 /* TypeInfo2::GetVarIndexOfMemId
6697 * Binds to a specific member based on a known DISPID, where the member name
6698 * is not known (for example, when binding to a default member).
6701 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
6702 MEMBERID memid, UINT *pVarIndex)
6704 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6705 TLBVarDesc *pVarInfo;
6706 int i;
6707 HRESULT result;
6708 for(i=0, pVarInfo=This->varlist; pVarInfo &&
6709 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
6711 if(pVarInfo) {
6712 *pVarIndex = i;
6713 result = S_OK;
6714 } else
6715 result = TYPE_E_ELEMENTNOTFOUND;
6717 TRACE("(%p) memid 0x%08x -> %s\n", This,
6718 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6719 return result;
6722 /* ITypeInfo2::GetCustData
6724 * Gets the custom data
6726 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
6727 ITypeInfo2 * iface,
6728 REFGUID guid,
6729 VARIANT *pVarVal)
6731 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6732 TLBCustData *pCData;
6734 for(pCData=This->pCustData; pCData; pCData = pCData->next)
6735 if( IsEqualIID(guid, &pCData->guid)) break;
6737 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6739 if(pCData)
6741 VariantInit( pVarVal);
6742 VariantCopy( pVarVal, &pCData->data);
6743 return S_OK;
6745 return E_INVALIDARG; /* FIXME: correct? */
6748 /* ITypeInfo2::GetFuncCustData
6750 * Gets the custom data
6752 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
6753 ITypeInfo2 * iface,
6754 UINT index,
6755 REFGUID guid,
6756 VARIANT *pVarVal)
6758 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6759 TLBCustData *pCData=NULL;
6760 TLBFuncDesc * pFDesc;
6761 int i;
6762 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6763 pFDesc=pFDesc->next);
6765 if(pFDesc)
6766 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
6767 if( IsEqualIID(guid, &pCData->guid)) break;
6769 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6771 if(pCData){
6772 VariantInit( pVarVal);
6773 VariantCopy( pVarVal, &pCData->data);
6774 return S_OK;
6776 return E_INVALIDARG; /* FIXME: correct? */
6779 /* ITypeInfo2::GetParamCustData
6781 * Gets the custom data
6783 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
6784 ITypeInfo2 * iface,
6785 UINT indexFunc,
6786 UINT indexParam,
6787 REFGUID guid,
6788 VARIANT *pVarVal)
6790 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6791 TLBCustData *pCData=NULL;
6792 TLBFuncDesc * pFDesc;
6793 int i;
6795 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
6797 if(pFDesc && indexParam<pFDesc->funcdesc.cParams)
6798 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
6799 pCData = pCData->next)
6800 if( IsEqualIID(guid, &pCData->guid)) break;
6802 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6804 if(pCData)
6806 VariantInit( pVarVal);
6807 VariantCopy( pVarVal, &pCData->data);
6808 return S_OK;
6810 return E_INVALIDARG; /* FIXME: correct? */
6813 /* ITypeInfo2::GetVarCustData
6815 * Gets the custom data
6817 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
6818 ITypeInfo2 * iface,
6819 UINT index,
6820 REFGUID guid,
6821 VARIANT *pVarVal)
6823 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6824 TLBCustData *pCData=NULL;
6825 TLBVarDesc * pVDesc;
6826 int i;
6828 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
6830 if(pVDesc)
6832 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
6834 if( IsEqualIID(guid, &pCData->guid)) break;
6838 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6840 if(pCData)
6842 VariantInit( pVarVal);
6843 VariantCopy( pVarVal, &pCData->data);
6844 return S_OK;
6846 return E_INVALIDARG; /* FIXME: correct? */
6849 /* ITypeInfo2::GetImplCustData
6851 * Gets the custom data
6853 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6854 ITypeInfo2 * iface,
6855 UINT index,
6856 REFGUID guid,
6857 VARIANT *pVarVal)
6859 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6860 TLBCustData *pCData=NULL;
6861 TLBImplType * pRDesc;
6862 int i;
6864 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6866 if(pRDesc)
6868 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6870 if( IsEqualIID(guid, &pCData->guid)) break;
6874 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6876 if(pCData)
6878 VariantInit( pVarVal);
6879 VariantCopy( pVarVal, &pCData->data);
6880 return S_OK;
6882 return E_INVALIDARG; /* FIXME: correct? */
6885 /* ITypeInfo2::GetDocumentation2
6887 * Retrieves the documentation string, the complete Help file name and path,
6888 * the localization context to use, and the context ID for the library Help
6889 * topic in the Help file.
6892 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6893 ITypeInfo2 * iface,
6894 MEMBERID memid,
6895 LCID lcid,
6896 BSTR *pbstrHelpString,
6897 DWORD *pdwHelpStringContext,
6898 BSTR *pbstrHelpStringDll)
6900 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6901 const TLBFuncDesc *pFDesc;
6902 const TLBVarDesc *pVDesc;
6903 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
6904 "HelpStringContext(%p) HelpStringDll(%p)\n",
6905 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6906 pbstrHelpStringDll );
6907 /* the help string should be obtained from the helpstringdll,
6908 * using the _DLLGetDocumentation function, based on the supplied
6909 * lcid. Nice to do sometime...
6911 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6912 if(pbstrHelpString)
6913 *pbstrHelpString=SysAllocString(This->Name);
6914 if(pdwHelpStringContext)
6915 *pdwHelpStringContext=This->dwHelpStringContext;
6916 if(pbstrHelpStringDll)
6917 *pbstrHelpStringDll=
6918 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6919 return S_OK;
6920 }else {/* for a member */
6921 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6922 if(pFDesc->funcdesc.memid==memid){
6923 if(pbstrHelpString)
6924 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6925 if(pdwHelpStringContext)
6926 *pdwHelpStringContext=pFDesc->HelpStringContext;
6927 if(pbstrHelpStringDll)
6928 *pbstrHelpStringDll=
6929 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6930 return S_OK;
6932 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6933 if(pVDesc->vardesc.memid==memid){
6934 if(pbstrHelpString)
6935 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6936 if(pdwHelpStringContext)
6937 *pdwHelpStringContext=pVDesc->HelpStringContext;
6938 if(pbstrHelpStringDll)
6939 *pbstrHelpStringDll=
6940 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6941 return S_OK;
6944 return TYPE_E_ELEMENTNOTFOUND;
6947 /* ITypeInfo2::GetAllCustData
6949 * Gets all custom data items for the Type info.
6952 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6953 ITypeInfo2 * iface,
6954 CUSTDATA *pCustData)
6956 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6957 TLBCustData *pCData;
6958 int i;
6960 TRACE("(%p) returning %d items\n", This, This->ctCustData);
6962 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6963 if(pCustData->prgCustData ){
6964 pCustData->cCustData=This->ctCustData;
6965 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
6966 pCustData->prgCustData[i].guid=pCData->guid;
6967 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
6969 }else{
6970 ERR(" OUT OF MEMORY!\n");
6971 return E_OUTOFMEMORY;
6973 return S_OK;
6976 /* ITypeInfo2::GetAllFuncCustData
6978 * Gets all custom data items for the specified Function
6981 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
6982 ITypeInfo2 * iface,
6983 UINT index,
6984 CUSTDATA *pCustData)
6986 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6987 TLBCustData *pCData;
6988 TLBFuncDesc * pFDesc;
6989 int i;
6990 TRACE("(%p) index %d\n", This, index);
6991 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6992 pFDesc=pFDesc->next)
6994 if(pFDesc){
6995 pCustData->prgCustData =
6996 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
6997 if(pCustData->prgCustData ){
6998 pCustData->cCustData=pFDesc->ctCustData;
6999 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
7000 pCData = pCData->next){
7001 pCustData->prgCustData[i].guid=pCData->guid;
7002 VariantCopy(& pCustData->prgCustData[i].varValue,
7003 & pCData->data);
7005 }else{
7006 ERR(" OUT OF MEMORY!\n");
7007 return E_OUTOFMEMORY;
7009 return S_OK;
7011 return TYPE_E_ELEMENTNOTFOUND;
7014 /* ITypeInfo2::GetAllParamCustData
7016 * Gets all custom data items for the Functions
7019 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7020 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7022 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7023 TLBCustData *pCData=NULL;
7024 TLBFuncDesc * pFDesc;
7025 int i;
7026 TRACE("(%p) index %d\n", This, indexFunc);
7027 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
7028 pFDesc=pFDesc->next)
7030 if(pFDesc && indexParam<pFDesc->funcdesc.cParams){
7031 pCustData->prgCustData =
7032 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
7033 sizeof(CUSTDATAITEM));
7034 if(pCustData->prgCustData ){
7035 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
7036 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
7037 pCData; i++, pCData = pCData->next){
7038 pCustData->prgCustData[i].guid=pCData->guid;
7039 VariantCopy(& pCustData->prgCustData[i].varValue,
7040 & pCData->data);
7042 }else{
7043 ERR(" OUT OF MEMORY!\n");
7044 return E_OUTOFMEMORY;
7046 return S_OK;
7048 return TYPE_E_ELEMENTNOTFOUND;
7051 /* ITypeInfo2::GetAllVarCustData
7053 * Gets all custom data items for the specified Variable
7056 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7057 UINT index, CUSTDATA *pCustData)
7059 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7060 TLBCustData *pCData;
7061 TLBVarDesc * pVDesc;
7062 int i;
7063 TRACE("(%p) index %d\n", This, index);
7064 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
7065 pVDesc=pVDesc->next)
7067 if(pVDesc){
7068 pCustData->prgCustData =
7069 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
7070 if(pCustData->prgCustData ){
7071 pCustData->cCustData=pVDesc->ctCustData;
7072 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
7073 pCData = pCData->next){
7074 pCustData->prgCustData[i].guid=pCData->guid;
7075 VariantCopy(& pCustData->prgCustData[i].varValue,
7076 & pCData->data);
7078 }else{
7079 ERR(" OUT OF MEMORY!\n");
7080 return E_OUTOFMEMORY;
7082 return S_OK;
7084 return TYPE_E_ELEMENTNOTFOUND;
7087 /* ITypeInfo2::GetAllImplCustData
7089 * Gets all custom data items for the specified implementation type
7092 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7093 ITypeInfo2 * iface,
7094 UINT index,
7095 CUSTDATA *pCustData)
7097 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7098 TLBCustData *pCData;
7099 TLBImplType * pRDesc;
7100 int i;
7101 TRACE("(%p) index %d\n", This, index);
7102 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
7103 pRDesc=pRDesc->next)
7105 if(pRDesc){
7106 pCustData->prgCustData =
7107 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
7108 if(pCustData->prgCustData ){
7109 pCustData->cCustData=pRDesc->ctCustData;
7110 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
7111 pCData = pCData->next){
7112 pCustData->prgCustData[i].guid=pCData->guid;
7113 VariantCopy(& pCustData->prgCustData[i].varValue,
7114 & pCData->data);
7116 }else{
7117 ERR(" OUT OF MEMORY!\n");
7118 return E_OUTOFMEMORY;
7120 return S_OK;
7122 return TYPE_E_ELEMENTNOTFOUND;
7125 static const ITypeInfo2Vtbl tinfvt =
7128 ITypeInfo_fnQueryInterface,
7129 ITypeInfo_fnAddRef,
7130 ITypeInfo_fnRelease,
7132 ITypeInfo_fnGetTypeAttr,
7133 ITypeInfo_fnGetTypeComp,
7134 ITypeInfo_fnGetFuncDesc,
7135 ITypeInfo_fnGetVarDesc,
7136 ITypeInfo_fnGetNames,
7137 ITypeInfo_fnGetRefTypeOfImplType,
7138 ITypeInfo_fnGetImplTypeFlags,
7139 ITypeInfo_fnGetIDsOfNames,
7140 ITypeInfo_fnInvoke,
7141 ITypeInfo_fnGetDocumentation,
7142 ITypeInfo_fnGetDllEntry,
7143 ITypeInfo_fnGetRefTypeInfo,
7144 ITypeInfo_fnAddressOfMember,
7145 ITypeInfo_fnCreateInstance,
7146 ITypeInfo_fnGetMops,
7147 ITypeInfo_fnGetContainingTypeLib,
7148 ITypeInfo_fnReleaseTypeAttr,
7149 ITypeInfo_fnReleaseFuncDesc,
7150 ITypeInfo_fnReleaseVarDesc,
7152 ITypeInfo2_fnGetTypeKind,
7153 ITypeInfo2_fnGetTypeFlags,
7154 ITypeInfo2_fnGetFuncIndexOfMemId,
7155 ITypeInfo2_fnGetVarIndexOfMemId,
7156 ITypeInfo2_fnGetCustData,
7157 ITypeInfo2_fnGetFuncCustData,
7158 ITypeInfo2_fnGetParamCustData,
7159 ITypeInfo2_fnGetVarCustData,
7160 ITypeInfo2_fnGetImplTypeCustData,
7161 ITypeInfo2_fnGetDocumentation2,
7162 ITypeInfo2_fnGetAllCustData,
7163 ITypeInfo2_fnGetAllFuncCustData,
7164 ITypeInfo2_fnGetAllParamCustData,
7165 ITypeInfo2_fnGetAllVarCustData,
7166 ITypeInfo2_fnGetAllImplTypeCustData,
7169 /******************************************************************************
7170 * CreateDispTypeInfo [OLEAUT32.31]
7172 * Build type information for an object so it can be called through an
7173 * IDispatch interface.
7175 * RETURNS
7176 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7177 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7179 * NOTES
7180 * This call allows an objects methods to be accessed through IDispatch, by
7181 * building an ITypeInfo object that IDispatch can use to call through.
7183 HRESULT WINAPI CreateDispTypeInfo(
7184 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7185 LCID lcid, /* [I] Locale Id */
7186 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7188 ITypeInfoImpl *pTIClass, *pTIIface;
7189 ITypeLibImpl *pTypeLibImpl;
7190 int param, func;
7191 TLBFuncDesc **ppFuncDesc;
7192 TLBRefType *ref;
7194 TRACE("\n");
7195 pTypeLibImpl = TypeLibImpl_Constructor();
7196 if (!pTypeLibImpl) return E_FAIL;
7198 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
7199 pTIIface->pTypeLib = pTypeLibImpl;
7200 pTIIface->index = 0;
7201 pTIIface->Name = NULL;
7202 pTIIface->dwHelpContext = -1;
7203 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7204 pTIIface->TypeAttr.lcid = lcid;
7205 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7206 pTIIface->TypeAttr.wMajorVerNum = 0;
7207 pTIIface->TypeAttr.wMinorVerNum = 0;
7208 pTIIface->TypeAttr.cbAlignment = 2;
7209 pTIIface->TypeAttr.cbSizeInstance = -1;
7210 pTIIface->TypeAttr.cbSizeVft = -1;
7211 pTIIface->TypeAttr.cFuncs = 0;
7212 pTIIface->TypeAttr.cImplTypes = 0;
7213 pTIIface->TypeAttr.cVars = 0;
7214 pTIIface->TypeAttr.wTypeFlags = 0;
7216 ppFuncDesc = &pTIIface->funclist;
7217 for(func = 0; func < pidata->cMembers; func++) {
7218 METHODDATA *md = pidata->pmethdata + func;
7219 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
7220 (*ppFuncDesc)->Name = SysAllocString(md->szName);
7221 (*ppFuncDesc)->funcdesc.memid = md->dispid;
7222 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
7223 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
7224 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
7225 (*ppFuncDesc)->funcdesc.callconv = md->cc;
7226 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
7227 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
7228 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
7229 (*ppFuncDesc)->funcdesc.cScodes = 0;
7230 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
7231 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7232 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7233 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7234 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7235 md->cArgs * sizeof(ELEMDESC));
7236 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7237 md->cArgs * sizeof(TLBParDesc));
7238 for(param = 0; param < md->cArgs; param++) {
7239 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7240 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7242 (*ppFuncDesc)->helpcontext = 0;
7243 (*ppFuncDesc)->HelpStringContext = 0;
7244 (*ppFuncDesc)->HelpString = NULL;
7245 (*ppFuncDesc)->Entry = NULL;
7246 (*ppFuncDesc)->ctCustData = 0;
7247 (*ppFuncDesc)->pCustData = NULL;
7248 (*ppFuncDesc)->next = NULL;
7249 pTIIface->TypeAttr.cFuncs++;
7250 ppFuncDesc = &(*ppFuncDesc)->next;
7253 dump_TypeInfo(pTIIface);
7255 pTypeLibImpl->pTypeInfo = pTIIface;
7256 pTypeLibImpl->TypeInfoCount++;
7258 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
7259 pTIClass->pTypeLib = pTypeLibImpl;
7260 pTIClass->index = 1;
7261 pTIClass->Name = NULL;
7262 pTIClass->dwHelpContext = -1;
7263 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7264 pTIClass->TypeAttr.lcid = lcid;
7265 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7266 pTIClass->TypeAttr.wMajorVerNum = 0;
7267 pTIClass->TypeAttr.wMinorVerNum = 0;
7268 pTIClass->TypeAttr.cbAlignment = 2;
7269 pTIClass->TypeAttr.cbSizeInstance = -1;
7270 pTIClass->TypeAttr.cbSizeVft = -1;
7271 pTIClass->TypeAttr.cFuncs = 0;
7272 pTIClass->TypeAttr.cImplTypes = 1;
7273 pTIClass->TypeAttr.cVars = 0;
7274 pTIClass->TypeAttr.wTypeFlags = 0;
7276 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
7277 pTIClass->impltypelist->hRef = 0;
7279 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
7280 ref->index = 0;
7281 ref->reference = 0;
7282 ref->pImpTLInfo = TLB_REF_INTERNAL;
7283 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7285 dump_TypeInfo(pTIClass);
7287 pTIIface->next = pTIClass;
7288 pTypeLibImpl->TypeInfoCount++;
7290 *pptinfo = (ITypeInfo*)pTIClass;
7292 ITypeInfo_AddRef(*pptinfo);
7293 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7295 return S_OK;
7299 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7301 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7303 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7306 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7308 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7310 return ITypeInfo_AddRef((ITypeInfo *)This);
7313 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7315 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7317 return ITypeInfo_Release((ITypeInfo *)This);
7320 static HRESULT WINAPI ITypeComp_fnBind(
7321 ITypeComp * iface,
7322 OLECHAR * szName,
7323 ULONG lHash,
7324 WORD wFlags,
7325 ITypeInfo ** ppTInfo,
7326 DESCKIND * pDescKind,
7327 BINDPTR * pBindPtr)
7329 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7330 const TLBFuncDesc *pFDesc;
7331 const TLBVarDesc *pVDesc;
7332 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7334 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7336 *pDescKind = DESCKIND_NONE;
7337 pBindPtr->lpfuncdesc = NULL;
7338 *ppTInfo = NULL;
7340 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
7341 if (!strcmpiW(pFDesc->Name, szName)) {
7342 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7343 break;
7344 else
7345 /* name found, but wrong flags */
7346 hr = TYPE_E_TYPEMISMATCH;
7349 if (pFDesc)
7351 HRESULT hr = TLB_AllocAndInitFuncDesc(
7352 &pFDesc->funcdesc,
7353 &pBindPtr->lpfuncdesc,
7354 This->TypeAttr.typekind == TKIND_DISPATCH);
7355 if (FAILED(hr))
7356 return hr;
7357 *pDescKind = DESCKIND_FUNCDESC;
7358 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7359 ITypeInfo_AddRef(*ppTInfo);
7360 return S_OK;
7361 } else {
7362 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7363 if (!strcmpiW(pVDesc->Name, szName)) {
7364 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7365 if (FAILED(hr))
7366 return hr;
7367 *pDescKind = DESCKIND_VARDESC;
7368 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7369 ITypeInfo_AddRef(*ppTInfo);
7370 return S_OK;
7374 /* FIXME: search each inherited interface, not just the first */
7375 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7376 /* recursive search */
7377 ITypeInfo *pTInfo;
7378 ITypeComp *pTComp;
7379 HRESULT hr;
7380 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7381 if (SUCCEEDED(hr))
7383 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7384 ITypeInfo_Release(pTInfo);
7386 if (SUCCEEDED(hr))
7388 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7389 ITypeComp_Release(pTComp);
7390 return hr;
7392 WARN("Could not search inherited interface!\n");
7394 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
7395 return hr;
7398 static HRESULT WINAPI ITypeComp_fnBindType(
7399 ITypeComp * iface,
7400 OLECHAR * szName,
7401 ULONG lHash,
7402 ITypeInfo ** ppTInfo,
7403 ITypeComp ** ppTComp)
7405 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7407 /* strange behaviour (does nothing) but like the
7408 * original */
7410 if (!ppTInfo || !ppTComp)
7411 return E_POINTER;
7413 *ppTInfo = NULL;
7414 *ppTComp = NULL;
7416 return S_OK;
7419 static const ITypeCompVtbl tcompvt =
7422 ITypeComp_fnQueryInterface,
7423 ITypeComp_fnAddRef,
7424 ITypeComp_fnRelease,
7426 ITypeComp_fnBind,
7427 ITypeComp_fnBindType