richedit: Fixed object leaks generated by context creation & destruction.
[wine.git] / dlls / oleaut32 / typelib.c
blob59b4d96166c86d8e879745ef2b538bdf76669f0f
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 structurees */
1002 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1003 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1004 int index; /* index in this typelib; */
1005 HREFTYPE hreftype; /* hreftype for app object binding */
1006 /* type libs seem to store the doc strings in ascii
1007 * so why should we do it in unicode?
1009 BSTR Name;
1010 BSTR DocString;
1011 BSTR DllName;
1012 unsigned long dwHelpContext;
1013 unsigned long dwHelpStringContext;
1015 /* functions */
1016 TLBFuncDesc * funclist; /* linked list with function descriptions */
1018 /* variables */
1019 TLBVarDesc * varlist; /* linked list with variable descriptions */
1021 /* Implemented Interfaces */
1022 TLBImplType * impltypelist;
1024 int ctCustData;
1025 TLBCustData * pCustData; /* linked list to cust data; */
1026 struct tagITypeInfoImpl * next;
1027 } ITypeInfoImpl;
1029 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1031 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1034 static const ITypeInfo2Vtbl tinfvt;
1035 static const ITypeCompVtbl tcompvt;
1037 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
1039 typedef struct tagTLBContext
1041 unsigned int oStart; /* start of TLB in file */
1042 unsigned int pos; /* current pos */
1043 unsigned int length; /* total length */
1044 void *mapping; /* memory mapping */
1045 MSFT_SegDir * pTblDir;
1046 ITypeLibImpl* pLibInfo;
1047 } TLBContext;
1050 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1053 debug
1055 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1056 if (pTD->vt & VT_RESERVED)
1057 szVarType += strlen(strcpy(szVarType, "reserved | "));
1058 if (pTD->vt & VT_BYREF)
1059 szVarType += strlen(strcpy(szVarType, "ref to "));
1060 if (pTD->vt & VT_ARRAY)
1061 szVarType += strlen(strcpy(szVarType, "array of "));
1062 if (pTD->vt & VT_VECTOR)
1063 szVarType += strlen(strcpy(szVarType, "vector of "));
1064 switch(pTD->vt & VT_TYPEMASK) {
1065 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1066 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1067 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1068 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1069 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1070 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1071 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1072 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1073 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1074 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1075 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1076 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1077 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1078 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1079 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1080 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1081 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1082 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1083 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1084 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1085 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1086 pTD->u.hreftype); break;
1087 case VT_PTR: sprintf(szVarType, "ptr to ");
1088 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1089 break;
1090 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1091 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1092 break;
1093 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1094 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1095 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1096 break;
1098 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1102 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1103 char buf[200];
1104 USHORT flags = edesc->u.paramdesc.wParamFlags;
1105 dump_TypeDesc(&edesc->tdesc,buf);
1106 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1107 MESSAGE("\t\tu.paramdesc.wParamFlags");
1108 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1109 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1110 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1111 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1112 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1113 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1114 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1115 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1116 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1118 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1119 int i;
1120 MESSAGE("memid is %08x\n",funcdesc->memid);
1121 for (i=0;i<funcdesc->cParams;i++) {
1122 MESSAGE("Param %d:\n",i);
1123 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1125 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1126 switch (funcdesc->funckind) {
1127 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1128 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1129 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1130 case FUNC_STATIC: MESSAGE("static");break;
1131 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1132 default: MESSAGE("unknown");break;
1134 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1135 switch (funcdesc->invkind) {
1136 case INVOKE_FUNC: MESSAGE("func");break;
1137 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1138 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1139 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1141 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1142 switch (funcdesc->callconv) {
1143 case CC_CDECL: MESSAGE("cdecl");break;
1144 case CC_PASCAL: MESSAGE("pascal");break;
1145 case CC_STDCALL: MESSAGE("stdcall");break;
1146 case CC_SYSCALL: MESSAGE("syscall");break;
1147 default:break;
1149 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1150 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1151 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1153 MESSAGE("\telemdescFunc (return value type):\n");
1154 dump_ELEMDESC(&funcdesc->elemdescFunc);
1157 static const char * const typekind_desc[] =
1159 "TKIND_ENUM",
1160 "TKIND_RECORD",
1161 "TKIND_MODULE",
1162 "TKIND_INTERFACE",
1163 "TKIND_DISPATCH",
1164 "TKIND_COCLASS",
1165 "TKIND_ALIAS",
1166 "TKIND_UNION",
1167 "TKIND_MAX"
1170 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1172 int i;
1173 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1174 for (i=0;i<pfd->funcdesc.cParams;i++)
1175 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1178 dump_FUNCDESC(&(pfd->funcdesc));
1180 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1181 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1183 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1185 while (pfd)
1187 dump_TLBFuncDescOne(pfd);
1188 pfd = pfd->next;
1191 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1193 while (pvd)
1195 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1196 pvd = pvd->next;
1200 static void dump_TLBImpLib(const TLBImpLib *import)
1202 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1203 debugstr_w(import->name));
1204 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1205 import->wVersionMinor, import->lcid, import->offset);
1208 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1210 TLBRefType *ref;
1212 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1214 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1215 if(ref->index == -1)
1216 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1217 else
1218 TRACE_(typelib)("type no: %d\n", ref->index);
1220 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1222 TRACE_(typelib)("in lib\n");
1223 dump_TLBImpLib(ref->pImpTLInfo);
1228 static void dump_TLBImplType(const TLBImplType * impl)
1230 while (impl) {
1231 TRACE_(typelib)(
1232 "implementing/inheriting interface hRef = %x implflags %x\n",
1233 impl->hRef, impl->implflags);
1234 impl = impl->next;
1238 static void dump_Variant(const VARIANT * pvar)
1240 SYSTEMTIME st;
1242 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1244 if (pvar)
1246 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1247 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1249 TRACE(",%p", V_BYREF(pvar));
1251 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1253 TRACE(",%p", V_ARRAY(pvar));
1255 else switch (V_TYPE(pvar))
1257 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1258 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1259 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1260 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1261 case VT_INT:
1262 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1263 case VT_UINT:
1264 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1265 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1266 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1267 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1268 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1269 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1270 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1271 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1272 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1273 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1274 V_CY(pvar).s.Lo); break;
1275 case VT_DATE:
1276 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1277 TRACE(",<invalid>");
1278 else
1279 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1280 st.wHour, st.wMinute, st.wSecond);
1281 break;
1282 case VT_ERROR:
1283 case VT_VOID:
1284 case VT_USERDEFINED:
1285 case VT_EMPTY:
1286 case VT_NULL: break;
1287 default: TRACE(",?"); break;
1290 TRACE("}\n");
1293 static void dump_DispParms(const DISPPARAMS * pdp)
1295 int index;
1297 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1299 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1301 TRACE("named args:\n");
1302 for (index = 0; index < pdp->cNamedArgs; index++)
1303 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1306 if (pdp->cArgs && pdp->rgvarg)
1308 TRACE("args:\n");
1309 for (index = 0; index < pdp->cArgs; index++)
1310 dump_Variant( &pdp->rgvarg[index] );
1314 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1316 TRACE("%p ref=%u\n", pty, pty->ref);
1317 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1318 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1319 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1320 TRACE("fct:%u var:%u impl:%u\n",
1321 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1322 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1323 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1324 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1325 if (TRACE_ON(ole))
1326 dump_TLBFuncDesc(pty->funclist);
1327 dump_TLBVarDesc(pty->varlist);
1328 dump_TLBImplType(pty->impltypelist);
1331 static void dump_VARDESC(const VARDESC *v)
1333 MESSAGE("memid %d\n",v->memid);
1334 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1335 MESSAGE("oInst %d\n",v->u.oInst);
1336 dump_ELEMDESC(&(v->elemdescVar));
1337 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1338 MESSAGE("varkind %d\n",v->varkind);
1341 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1343 /* VT_LPWSTR is largest type that */
1344 /* may appear in type description*/
1345 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1346 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1347 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1348 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1349 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1350 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1351 {{0},30},{{0},31}
1354 static void TLB_abort(void)
1356 DebugBreak();
1358 static void * TLB_Alloc(unsigned size)
1360 void * ret;
1361 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1362 /* FIXME */
1363 ERR("cannot allocate memory\n");
1365 return ret;
1368 static void TLB_Free(void * ptr)
1370 HeapFree(GetProcessHeap(), 0, ptr);
1373 /* returns the size required for a deep copy of a typedesc into a
1374 * flat buffer */
1375 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1377 SIZE_T size = 0;
1379 if (alloc_initial_space)
1380 size += sizeof(TYPEDESC);
1382 switch (tdesc->vt)
1384 case VT_PTR:
1385 case VT_SAFEARRAY:
1386 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1387 break;
1388 case VT_CARRAY:
1389 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1390 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1391 break;
1393 return size;
1396 /* deep copy a typedesc into a flat buffer */
1397 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1399 if (!dest)
1401 dest = buffer;
1402 buffer = (char *)buffer + sizeof(TYPEDESC);
1405 *dest = *src;
1407 switch (src->vt)
1409 case VT_PTR:
1410 case VT_SAFEARRAY:
1411 dest->u.lptdesc = buffer;
1412 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1413 break;
1414 case VT_CARRAY:
1415 dest->u.lpadesc = buffer;
1416 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1417 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1418 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1419 break;
1421 return buffer;
1424 /* 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 int j;
2028 TLBRefType *ref;
2030 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2032 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2034 if(ref->reference == offset) return;
2037 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
2038 list_add_tail(&pTL->ref_list, &ref->entry);
2040 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2041 /* external typelib */
2042 MSFT_ImpInfo impinfo;
2043 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2045 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2047 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2048 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2049 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
2050 if(pImpLib->offset==impinfo.oImpFile) break;
2051 pImpLib=pImpLib->next;
2053 if(pImpLib){
2054 ref->reference = offset;
2055 ref->pImpTLInfo = pImpLib;
2056 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2057 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2058 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2059 ref->index = TLB_REF_USE_GUID;
2060 } else
2061 ref->index = impinfo.oGuid;
2062 }else{
2063 ERR("Cannot find a reference\n");
2064 ref->reference = -1;
2065 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2067 }else{
2068 /* in this typelib */
2069 ref->index = MSFT_HREFTYPE_INDEX(offset);
2070 ref->reference = offset;
2071 ref->pImpTLInfo = TLB_REF_INTERNAL;
2075 /* process Implemented Interfaces of a com class */
2076 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2077 int offset)
2079 int i;
2080 MSFT_RefRecord refrec;
2081 TLBImplType **ppImpl = &pTI->impltypelist;
2083 TRACE_(typelib)("\n");
2085 for(i=0;i<count;i++){
2086 if(offset<0) break; /* paranoia */
2087 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2088 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2089 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2090 (*ppImpl)->hRef = refrec.reftype;
2091 (*ppImpl)->implflags=refrec.flags;
2092 (*ppImpl)->ctCustData=
2093 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2094 offset=refrec.onext;
2095 ppImpl=&((*ppImpl)->next);
2099 * process a typeinfo record
2101 static ITypeInfoImpl * MSFT_DoTypeInfo(
2102 TLBContext *pcx,
2103 int count,
2104 ITypeLibImpl * pLibInfo)
2106 MSFT_TypeInfoBase tiBase;
2107 ITypeInfoImpl *ptiRet;
2109 TRACE_(typelib)("count=%u\n", count);
2111 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2112 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2113 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2115 /* this is where we are coming from */
2116 ptiRet->pTypeLib = pLibInfo;
2117 ptiRet->index=count;
2118 /* fill in the typeattr fields */
2120 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2121 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2122 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2123 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2124 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2125 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2126 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2127 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2128 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2129 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2130 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2131 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2132 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2133 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2134 MSFT_GetTdesc(pcx, tiBase.datatype1,
2135 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2137 /* FIXME: */
2138 /* IDLDESC idldescType; *//* never saw this one != zero */
2140 /* name, eventually add to a hash table */
2141 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2142 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2143 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2144 /* help info */
2145 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2146 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2147 ptiRet->dwHelpContext=tiBase.helpcontext;
2149 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2150 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2152 /* note: InfoType's Help file and HelpStringDll come from the containing
2153 * library. Further HelpString and Docstring appear to be the same thing :(
2155 /* functions */
2156 if(ptiRet->TypeAttr.cFuncs >0 )
2157 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2158 ptiRet->TypeAttr.cVars,
2159 tiBase.memoffset, & ptiRet->funclist);
2160 /* variables */
2161 if(ptiRet->TypeAttr.cVars >0 )
2162 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2163 ptiRet->TypeAttr.cVars,
2164 tiBase.memoffset, & ptiRet->varlist);
2165 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2166 switch(ptiRet->TypeAttr.typekind)
2168 case TKIND_COCLASS:
2169 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2170 tiBase.datatype1);
2171 break;
2172 case TKIND_DISPATCH:
2173 /* This is not -1 when the interface is a non-base dual interface or
2174 when a dispinterface wraps an interface ie the idl 'dispinterface x {interface y;};'.
2175 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2176 not this interface.
2179 if (tiBase.datatype1 != -1)
2181 ptiRet->impltypelist = TLB_Alloc(sizeof(TLBImplType));
2182 ptiRet->impltypelist->hRef = tiBase.datatype1;
2183 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2185 break;
2186 default:
2187 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2188 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2189 ptiRet->impltypelist->hRef = tiBase.datatype1;
2190 break;
2193 ptiRet->ctCustData=
2194 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2196 TRACE_(typelib)("%s guid: %s kind:%s\n",
2197 debugstr_w(ptiRet->Name),
2198 debugstr_guid(&ptiRet->TypeAttr.guid),
2199 typekind_desc[ptiRet->TypeAttr.typekind]);
2201 return ptiRet;
2204 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2205 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2206 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2207 * tradeoff here.
2209 static ITypeLibImpl *tlb_cache_first;
2210 static CRITICAL_SECTION cache_section;
2211 static CRITICAL_SECTION_DEBUG cache_section_debug =
2213 0, 0, &cache_section,
2214 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2215 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2217 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2220 typedef struct TLB_PEFile
2222 const IUnknownVtbl *lpvtbl;
2223 LONG refs;
2224 HMODULE dll;
2225 HRSRC typelib_resource;
2226 HGLOBAL typelib_global;
2227 LPVOID typelib_base;
2228 } TLB_PEFile;
2230 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2232 if (IsEqualIID(riid, &IID_IUnknown))
2234 *ppv = iface;
2235 IUnknown_AddRef(iface);
2236 return S_OK;
2238 *ppv = NULL;
2239 return E_NOINTERFACE;
2242 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2244 TLB_PEFile *This = (TLB_PEFile *)iface;
2245 return InterlockedIncrement(&This->refs);
2248 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2250 TLB_PEFile *This = (TLB_PEFile *)iface;
2251 ULONG refs = InterlockedDecrement(&This->refs);
2252 if (!refs)
2254 if (This->typelib_global)
2255 FreeResource(This->typelib_global);
2256 if (This->dll)
2257 FreeLibrary(This->dll);
2258 HeapFree(GetProcessHeap(), 0, This);
2260 return refs;
2263 static const IUnknownVtbl TLB_PEFile_Vtable =
2265 TLB_PEFile_QueryInterface,
2266 TLB_PEFile_AddRef,
2267 TLB_PEFile_Release
2270 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2272 TLB_PEFile *This;
2274 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2275 if (!This)
2276 return E_OUTOFMEMORY;
2278 This->lpvtbl = &TLB_PEFile_Vtable;
2279 This->refs = 1;
2280 This->dll = NULL;
2281 This->typelib_resource = NULL;
2282 This->typelib_global = NULL;
2283 This->typelib_base = NULL;
2285 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2286 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2288 if (This->dll)
2290 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2291 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2292 if (This->typelib_resource)
2294 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2295 if (This->typelib_global)
2297 This->typelib_base = LockResource(This->typelib_global);
2299 if (This->typelib_base)
2301 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2302 *ppBase = This->typelib_base;
2303 *ppFile = (IUnknown *)&This->lpvtbl;
2304 return S_OK;
2310 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2311 return TYPE_E_CANTLOADLIBRARY;
2315 typedef struct TLB_Mapping
2317 const IUnknownVtbl *lpvtbl;
2318 LONG refs;
2319 HANDLE file;
2320 HANDLE mapping;
2321 LPVOID typelib_base;
2322 } TLB_Mapping;
2324 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2326 if (IsEqualIID(riid, &IID_IUnknown))
2328 *ppv = iface;
2329 IUnknown_AddRef(iface);
2330 return S_OK;
2332 *ppv = NULL;
2333 return E_NOINTERFACE;
2336 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2338 TLB_Mapping *This = (TLB_Mapping *)iface;
2339 return InterlockedIncrement(&This->refs);
2342 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2344 TLB_Mapping *This = (TLB_Mapping *)iface;
2345 ULONG refs = InterlockedDecrement(&This->refs);
2346 if (!refs)
2348 if (This->typelib_base)
2349 UnmapViewOfFile(This->typelib_base);
2350 if (This->mapping)
2351 CloseHandle(This->mapping);
2352 if (This->file != INVALID_HANDLE_VALUE)
2353 CloseHandle(This->file);
2354 HeapFree(GetProcessHeap(), 0, This);
2356 return refs;
2359 static const IUnknownVtbl TLB_Mapping_Vtable =
2361 TLB_Mapping_QueryInterface,
2362 TLB_Mapping_AddRef,
2363 TLB_Mapping_Release
2366 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2368 TLB_Mapping *This;
2370 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2371 if (!This)
2372 return E_OUTOFMEMORY;
2374 This->lpvtbl = &TLB_Mapping_Vtable;
2375 This->refs = 1;
2376 This->file = INVALID_HANDLE_VALUE;
2377 This->mapping = NULL;
2378 This->typelib_base = NULL;
2380 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2381 if (INVALID_HANDLE_VALUE != This->file)
2383 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2384 if (This->mapping)
2386 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2387 if(This->typelib_base)
2389 /* retrieve file size */
2390 *pdwTLBLength = GetFileSize(This->file, NULL);
2391 *ppBase = This->typelib_base;
2392 *ppFile = (IUnknown *)&This->lpvtbl;
2393 return S_OK;
2398 IUnknown_Release((IUnknown *)&This->lpvtbl);
2399 return TYPE_E_CANTLOADLIBRARY;
2402 /****************************************************************************
2403 * TLB_ReadTypeLib
2405 * find the type of the typelib file and map the typelib resource into
2406 * the memory
2408 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2409 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2410 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2412 ITypeLibImpl *entry;
2413 HRESULT ret;
2414 INT index = 1;
2415 LPWSTR index_str, file = (LPWSTR)pszFileName;
2416 LPVOID pBase = NULL;
2417 DWORD dwTLBLength = 0;
2418 IUnknown *pFile = NULL;
2420 *ppTypeLib = NULL;
2422 index_str = strrchrW(pszFileName, '\\');
2423 if(index_str && *++index_str != '\0')
2425 LPWSTR end_ptr;
2426 long idx = strtolW(index_str, &end_ptr, 10);
2427 if(*end_ptr == '\0')
2429 int str_len = index_str - pszFileName - 1;
2430 index = idx;
2431 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
2432 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2433 file[str_len] = 0;
2437 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2439 if(strchrW(file, '\\'))
2441 lstrcpyW(pszPath, file);
2443 else
2445 int len = GetSystemDirectoryW(pszPath, cchPath);
2446 pszPath[len] = '\\';
2447 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2451 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file);
2453 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2455 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2456 EnterCriticalSection(&cache_section);
2457 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2459 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2461 TRACE("cache hit\n");
2462 *ppTypeLib = (ITypeLib2*)entry;
2463 ITypeLib_AddRef(*ppTypeLib);
2464 LeaveCriticalSection(&cache_section);
2465 return S_OK;
2468 LeaveCriticalSection(&cache_section);
2470 /* now actually load and parse the typelib */
2472 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2473 if (ret == TYPE_E_CANTLOADLIBRARY)
2474 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2475 if (SUCCEEDED(ret))
2477 if (dwTLBLength >= 4)
2479 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2480 if (dwSignature == MSFT_SIGNATURE)
2481 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2482 else if (dwSignature == SLTG_SIGNATURE)
2483 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2484 else
2486 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2487 ret = TYPE_E_CANTLOADLIBRARY;
2490 else
2491 ret = TYPE_E_CANTLOADLIBRARY;
2492 IUnknown_Release(pFile);
2495 if(*ppTypeLib) {
2496 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2498 TRACE("adding to cache\n");
2499 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2500 lstrcpyW(impl->path, pszPath);
2501 /* We should really canonicalise the path here. */
2502 impl->index = index;
2504 /* FIXME: check if it has added already in the meantime */
2505 EnterCriticalSection(&cache_section);
2506 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2507 impl->prev = NULL;
2508 tlb_cache_first = impl;
2509 LeaveCriticalSection(&cache_section);
2510 ret = S_OK;
2511 } else
2512 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2514 return ret;
2517 /*================== ITypeLib(2) Methods ===================================*/
2519 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2521 ITypeLibImpl* pTypeLibImpl;
2523 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2524 if (!pTypeLibImpl) return NULL;
2526 pTypeLibImpl->lpVtbl = &tlbvt;
2527 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2528 pTypeLibImpl->ref = 1;
2530 list_init(&pTypeLibImpl->ref_list);
2531 pTypeLibImpl->dispatch_href = -1;
2533 return pTypeLibImpl;
2536 /****************************************************************************
2537 * ITypeLib2_Constructor_MSFT
2539 * loading an MSFT typelib from an in-memory image
2541 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2543 TLBContext cx;
2544 long lPSegDir;
2545 MSFT_Header tlbHeader;
2546 MSFT_SegDir tlbSegDir;
2547 ITypeLibImpl * pTypeLibImpl;
2549 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2551 pTypeLibImpl = TypeLibImpl_Constructor();
2552 if (!pTypeLibImpl) return NULL;
2554 /* get pointer to beginning of typelib data */
2555 cx.pos = 0;
2556 cx.oStart=0;
2557 cx.mapping = pLib;
2558 cx.pLibInfo = pTypeLibImpl;
2559 cx.length = dwTLBLength;
2561 /* read header */
2562 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2563 TRACE_(typelib)("header:\n");
2564 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2565 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2566 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2567 return NULL;
2569 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2571 /* there is a small amount of information here until the next important
2572 * part:
2573 * the segment directory . Try to calculate the amount of data */
2574 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2576 /* now read the segment directory */
2577 TRACE("read segment directory (at %ld)\n",lPSegDir);
2578 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2579 cx.pTblDir = &tlbSegDir;
2581 /* just check two entries */
2582 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2584 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2585 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2586 return NULL;
2589 /* now fill our internal data */
2590 /* TLIBATTR fields */
2591 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2593 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2594 /* Windows seems to have zero here, is this correct? */
2595 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2596 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2597 else
2598 pTypeLibImpl->LibAttr.lcid = 0;
2600 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2601 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2602 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2603 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2605 /* name, eventually add to a hash table */
2606 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2608 /* help info */
2609 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2610 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2612 if( tlbHeader.varflags & HELPDLLFLAG)
2614 int offset;
2615 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2616 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2619 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2621 /* custom data */
2622 if(tlbHeader.CustomDataOffset >= 0)
2624 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2627 /* fill in typedescriptions */
2628 if(tlbSegDir.pTypdescTab.length > 0)
2630 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2631 INT16 td[4];
2632 pTypeLibImpl->ctTypeDesc = cTD;
2633 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2634 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2635 for(i=0; i<cTD; )
2637 /* FIXME: add several sanity checks here */
2638 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2639 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2641 /* FIXME: check safearray */
2642 if(td[3] < 0)
2643 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2644 else
2645 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2647 else if(td[0] == VT_CARRAY)
2649 /* array descr table here */
2650 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2652 else if(td[0] == VT_USERDEFINED)
2654 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2656 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2659 /* second time around to fill the array subscript info */
2660 for(i=0;i<cTD;i++)
2662 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2663 if(tlbSegDir.pArrayDescriptions.offset>0)
2665 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2666 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2668 if(td[1]<0)
2669 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2670 else
2671 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2673 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2675 for(j = 0; j<td[2]; j++)
2677 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2678 sizeof(INT), &cx, DO_NOT_SEEK);
2679 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2680 sizeof(INT), &cx, DO_NOT_SEEK);
2683 else
2685 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2686 ERR("didn't find array description data\n");
2691 /* imported type libs */
2692 if(tlbSegDir.pImpFiles.offset>0)
2694 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2695 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2696 UINT16 size;
2698 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2700 char *name;
2701 DWORD len;
2703 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2704 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2705 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2707 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2708 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2709 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2710 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2712 size >>= 2;
2713 name = TLB_Alloc(size+1);
2714 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2715 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2716 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2717 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2718 TLB_Free(name);
2720 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2721 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2723 ppImpLib = &(*ppImpLib)->next;
2727 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
2728 if(pTypeLibImpl->dispatch_href != -1)
2729 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
2731 /* type info's */
2732 if(tlbHeader.nrtypeinfos >= 0 )
2734 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2735 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2736 int i;
2738 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
2740 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2742 ppTI = &((*ppTI)->next);
2743 (pTypeLibImpl->TypeInfoCount)++;
2747 TRACE("(%p)\n", pTypeLibImpl);
2748 return (ITypeLib2*) pTypeLibImpl;
2752 static BSTR TLB_MultiByteToBSTR(const char *ptr)
2754 DWORD len;
2755 WCHAR *nameW;
2756 BSTR ret;
2758 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2759 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2760 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2761 ret = SysAllocString(nameW);
2762 HeapFree(GetProcessHeap(), 0, nameW);
2763 return ret;
2766 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
2768 char b[3];
2769 int i;
2770 short s;
2772 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2773 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2774 return FALSE;
2777 guid->Data4[0] = s >> 8;
2778 guid->Data4[1] = s & 0xff;
2780 b[2] = '\0';
2781 for(i = 0; i < 6; i++) {
2782 memcpy(b, str + 24 + 2 * i, 2);
2783 guid->Data4[i + 2] = strtol(b, NULL, 16);
2785 return TRUE;
2788 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
2790 WORD bytelen;
2791 DWORD len;
2792 WCHAR *nameW;
2794 *pBstr = NULL;
2795 bytelen = *(const WORD*)ptr;
2796 if(bytelen == 0xffff) return 2;
2797 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2798 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2799 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2800 *pBstr = SysAllocStringLen(nameW, len);
2801 HeapFree(GetProcessHeap(), 0, nameW);
2802 return bytelen + 2;
2805 static WORD SLTG_ReadStringA(const char *ptr, char **str)
2807 WORD bytelen;
2809 *str = NULL;
2810 bytelen = *(const WORD*)ptr;
2811 if(bytelen == 0xffff) return 2;
2812 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2813 memcpy(*str, ptr + 2, bytelen);
2814 (*str)[bytelen] = '\0';
2815 return bytelen + 2;
2818 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2820 char *ptr = pLibBlk;
2821 WORD w;
2823 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2824 FIXME("libblk magic = %04x\n", w);
2825 return 0;
2828 ptr += 6;
2829 if((w = *(WORD*)ptr) != 0xffff) {
2830 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2831 ptr += w;
2833 ptr += 2;
2835 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2837 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2839 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2840 ptr += 4;
2842 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2843 ptr += 2;
2845 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2846 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2847 else
2848 pTypeLibImpl->LibAttr.lcid = 0;
2849 ptr += 2;
2851 ptr += 4; /* skip res12 */
2853 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2854 ptr += 2;
2856 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2857 ptr += 2;
2859 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2860 ptr += 2;
2862 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2863 ptr += sizeof(GUID);
2865 return ptr - (char*)pLibBlk;
2868 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
2869 typedef struct
2871 unsigned int num;
2872 HREFTYPE refs[1];
2873 } sltg_ref_lookup_t;
2875 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
2876 HREFTYPE *typelib_ref)
2878 if(typeinfo_ref < table->num)
2880 *typelib_ref = table->refs[typeinfo_ref];
2881 return S_OK;
2884 ERR("Unable to find reference\n");
2885 *typelib_ref = -1;
2886 return E_FAIL;
2889 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
2891 BOOL done = FALSE;
2893 while(!done) {
2894 if((*pType & 0xe00) == 0xe00) {
2895 pTD->vt = VT_PTR;
2896 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2897 sizeof(TYPEDESC));
2898 pTD = pTD->u.lptdesc;
2900 switch(*pType & 0x3f) {
2901 case VT_PTR:
2902 pTD->vt = VT_PTR;
2903 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2904 sizeof(TYPEDESC));
2905 pTD = pTD->u.lptdesc;
2906 break;
2908 case VT_USERDEFINED:
2909 pTD->vt = VT_USERDEFINED;
2910 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
2911 done = TRUE;
2912 break;
2914 case VT_CARRAY:
2916 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2917 array */
2919 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2921 pTD->vt = VT_CARRAY;
2922 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2923 sizeof(ARRAYDESC) +
2924 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2925 pTD->u.lpadesc->cDims = pSA->cDims;
2926 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2927 pSA->cDims * sizeof(SAFEARRAYBOUND));
2929 pTD = &pTD->u.lpadesc->tdescElem;
2930 break;
2933 case VT_SAFEARRAY:
2935 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2936 useful? */
2938 pType++;
2939 pTD->vt = VT_SAFEARRAY;
2940 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2941 sizeof(TYPEDESC));
2942 pTD = pTD->u.lptdesc;
2943 break;
2945 default:
2946 pTD->vt = *pType & 0x3f;
2947 done = TRUE;
2948 break;
2950 pType++;
2952 return pType;
2955 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
2956 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
2958 /* Handle [in/out] first */
2959 if((*pType & 0xc000) == 0xc000)
2960 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2961 else if(*pType & 0x8000)
2962 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2963 else if(*pType & 0x4000)
2964 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2965 else
2966 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2968 if(*pType & 0x2000)
2969 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2971 if(*pType & 0x80)
2972 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2974 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
2978 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
2979 char *pNameTable)
2981 int ref;
2982 char *name;
2983 TLBRefType *ref_type;
2984 sltg_ref_lookup_t *table;
2985 HREFTYPE typelib_ref;
2987 if(pRef->magic != SLTG_REF_MAGIC) {
2988 FIXME("Ref magic = %x\n", pRef->magic);
2989 return NULL;
2991 name = ( (char*)(&pRef->names) + pRef->number);
2993 table = HeapAlloc(GetProcessHeap(), 0, sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
2994 table->num = pRef->number >> 3;
2996 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
2998 /* We don't want the first href to be 0 */
2999 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3001 for(ref = 0; ref < pRef->number >> 3; ref++) {
3002 char *refname;
3003 unsigned int lib_offs, type_num;
3005 ref_type = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref_type));
3007 name += SLTG_ReadStringA(name, &refname);
3008 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3009 FIXME("Can't sscanf ref\n");
3010 if(lib_offs != 0xffff) {
3011 TLBImpLib **import = &pTL->pImpLibs;
3013 while(*import) {
3014 if((*import)->offset == lib_offs)
3015 break;
3016 import = &(*import)->next;
3018 if(!*import) {
3019 char fname[MAX_PATH+1];
3020 int len;
3022 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3023 sizeof(**import));
3024 (*import)->offset = lib_offs;
3025 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3026 &(*import)->guid);
3027 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3028 &(*import)->wVersionMajor,
3029 &(*import)->wVersionMinor,
3030 &(*import)->lcid, fname) != 4) {
3031 FIXME("can't sscanf ref %s\n",
3032 pNameTable + lib_offs + 40);
3034 len = strlen(fname);
3035 if(fname[len-1] != '#')
3036 FIXME("fname = %s\n", fname);
3037 fname[len-1] = '\0';
3038 (*import)->name = TLB_MultiByteToBSTR(fname);
3040 ref_type->pImpTLInfo = *import;
3042 /* Store a reference to IDispatch */
3043 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
3044 pTL->dispatch_href = typelib_ref;
3046 } else { /* internal ref */
3047 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3049 ref_type->reference = typelib_ref;
3050 ref_type->index = type_num;
3052 HeapFree(GetProcessHeap(), 0, refname);
3053 list_add_tail(&pTL->ref_list, &ref_type->entry);
3055 table->refs[ref] = typelib_ref;
3056 typelib_ref += 4;
3058 if((BYTE)*name != SLTG_REF_MAGIC)
3059 FIXME("End of ref block magic = %x\n", *name);
3060 dump_TLBRefType(pTL);
3061 return table;
3064 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3065 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3067 SLTG_ImplInfo *info;
3068 TLBImplType **ppImplType = &pTI->impltypelist;
3069 /* I don't really get this structure, usually it's 0x16 bytes
3070 long, but iuser.tlb contains some that are 0x18 bytes long.
3071 That's ok because we can use the next ptr to jump to the next
3072 one. But how do we know the length of the last one? The WORD
3073 at offs 0x8 might be the clue. For now I'm just assuming that
3074 the last one is the regular 0x16 bytes. */
3076 info = (SLTG_ImplInfo*)pBlk;
3077 while(1) {
3078 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3079 sizeof(**ppImplType));
3080 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef);
3081 (*ppImplType)->implflags = info->impltypeflags;
3082 pTI->TypeAttr.cImplTypes++;
3083 ppImplType = &(*ppImplType)->next;
3085 if(info->next == 0xffff)
3086 break;
3087 if(OneOnly)
3088 FIXME("Interface inheriting more than one interface\n");
3089 info = (SLTG_ImplInfo*)(pBlk + info->next);
3091 info++; /* see comment at top of function */
3092 return (char*)info;
3095 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3096 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3098 TLBVarDesc **ppVarDesc = &pTI->varlist;
3099 BSTR bstrPrevName = NULL;
3100 SLTG_Variable *pItem;
3101 unsigned short i;
3102 WORD *pType;
3103 char buf[300];
3105 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3106 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
3108 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3109 sizeof(**ppVarDesc));
3110 (*ppVarDesc)->vardesc.memid = pItem->memid;
3112 if (pItem->magic != SLTG_VAR_MAGIC &&
3113 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3114 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3115 return;
3118 if (pItem->name == 0xfffe)
3119 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
3120 else
3121 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3123 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3124 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3126 if (pItem->flags & 0x40) {
3127 TRACE_(typelib)("VAR_DISPATCH\n");
3128 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
3130 else if (pItem->flags & 0x10) {
3131 TRACE_(typelib)("VAR_CONST\n");
3132 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3133 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3134 sizeof(VARIANT));
3135 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3136 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
3137 *(INT*)(pBlk + pItem->byte_offs);
3139 else {
3140 TRACE_(typelib)("VAR_PERINSTANCE\n");
3141 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3142 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3145 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3146 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
3148 if (pItem->flags & 0x80)
3149 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3151 if(pItem->flags & 0x02)
3152 pType = &pItem->type;
3153 else
3154 pType = (WORD*)(pBlk + pItem->type);
3156 if (pItem->flags & ~0xd2)
3157 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xd2);
3159 SLTG_DoElem(pType, pBlk,
3160 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup);
3162 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3164 bstrPrevName = (*ppVarDesc)->Name;
3165 ppVarDesc = &((*ppVarDesc)->next);
3167 pTI->TypeAttr.cVars = cVars;
3170 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3171 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3173 SLTG_Function *pFunc;
3174 unsigned short i;
3175 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3177 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3178 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3180 int param;
3181 WORD *pType, *pArg;
3183 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3184 sizeof(**ppFuncDesc));
3186 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3187 case SLTG_FUNCTION_MAGIC:
3188 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3189 break;
3190 case SLTG_DISPATCH_FUNCTION_MAGIC:
3191 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3192 break;
3193 case SLTG_STATIC_FUNCTION_MAGIC:
3194 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3195 break;
3196 default:
3197 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3198 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
3199 *ppFuncDesc = NULL;
3200 return;
3202 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3204 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3205 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3206 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3207 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3208 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3209 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3211 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3212 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3214 if(pFunc->retnextopt & 0x80)
3215 pType = &pFunc->rettype;
3216 else
3217 pType = (WORD*)(pBlk + pFunc->rettype);
3219 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3221 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3222 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3223 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3224 (*ppFuncDesc)->pParamDesc =
3225 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3226 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3228 pArg = (WORD*)(pBlk + pFunc->arg_off);
3230 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3231 char *paramName = pNameTable + *pArg;
3232 BOOL HaveOffs;
3233 /* If arg type follows then paramName points to the 2nd
3234 letter of the name, else the next WORD is an offset to
3235 the arg type and paramName points to the first letter.
3236 So let's take one char off paramName and see if we're
3237 pointing at an alpha-numeric char. However if *pArg is
3238 0xffff or 0xfffe then the param has no name, the former
3239 meaning that the next WORD is the type, the latter
3240 meaning that the next WORD is an offset to the type. */
3242 HaveOffs = FALSE;
3243 if(*pArg == 0xffff)
3244 paramName = NULL;
3245 else if(*pArg == 0xfffe) {
3246 paramName = NULL;
3247 HaveOffs = TRUE;
3249 else if(paramName[-1] && !isalnum(paramName[-1]))
3250 HaveOffs = TRUE;
3252 pArg++;
3254 if(HaveOffs) { /* the next word is an offset to type */
3255 pType = (WORD*)(pBlk + *pArg);
3256 SLTG_DoElem(pType, pBlk,
3257 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3258 pArg++;
3259 } else {
3260 if(paramName)
3261 paramName--;
3262 pArg = SLTG_DoElem(pArg, pBlk,
3263 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3266 /* Are we an optional param ? */
3267 if((*ppFuncDesc)->funcdesc.cParams - param <=
3268 (*ppFuncDesc)->funcdesc.cParamsOpt)
3269 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3271 if(paramName) {
3272 (*ppFuncDesc)->pParamDesc[param].Name =
3273 TLB_MultiByteToBSTR(paramName);
3277 ppFuncDesc = &((*ppFuncDesc)->next);
3278 if(pFunc->next == 0xffff) break;
3280 pTI->TypeAttr.cFuncs = cFuncs;
3283 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3284 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3285 SLTG_TypeInfoTail *pTITail)
3287 char *pFirstItem, *pNextItem;
3288 sltg_ref_lookup_t *ref_lookup = NULL;
3290 if(pTIHeader->href_table != 0xffffffff) {
3291 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3292 pNameTable);
3295 pFirstItem = pNextItem = pBlk;
3297 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3298 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3300 HeapFree(GetProcessHeap(), 0, ref_lookup);
3304 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3305 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3306 const SLTG_TypeInfoTail *pTITail)
3308 char *pFirstItem, *pNextItem;
3309 sltg_ref_lookup_t *ref_lookup = NULL;
3311 if(pTIHeader->href_table != 0xffffffff) {
3312 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3313 pNameTable);
3316 pFirstItem = pNextItem = pBlk;
3318 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3319 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3322 if (pTITail->funcs_off != 0xffff)
3323 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3325 HeapFree(GetProcessHeap(), 0, ref_lookup);
3327 if (TRACE_ON(typelib))
3328 dump_TLBFuncDesc(pTI->funclist);
3331 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3332 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3333 const SLTG_TypeInfoTail *pTITail)
3335 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3338 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3339 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3340 const SLTG_TypeInfoTail *pTITail)
3342 WORD *pType;
3343 sltg_ref_lookup_t *ref_lookup = NULL;
3345 if (pTITail->simple_alias) {
3346 /* if simple alias, no more processing required */
3347 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3348 return;
3351 if(pTIHeader->href_table != 0xffffffff) {
3352 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3353 pNameTable);
3356 /* otherwise it is an offset to a type */
3357 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3359 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3361 HeapFree(GetProcessHeap(), 0, ref_lookup);
3364 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3365 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3366 const SLTG_TypeInfoTail *pTITail)
3368 sltg_ref_lookup_t *ref_lookup = NULL;
3369 if (pTIHeader->href_table != 0xffffffff)
3370 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3371 pNameTable);
3373 if (pTITail->vars_off != 0xffff)
3374 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3376 if (pTITail->funcs_off != 0xffff)
3377 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3379 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3380 * of dispinterface functons including the IDispatch ones, so
3381 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3382 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3384 HeapFree(GetProcessHeap(), 0, ref_lookup);
3385 if (TRACE_ON(typelib))
3386 dump_TLBFuncDesc(pTI->funclist);
3389 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3390 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3391 const SLTG_TypeInfoTail *pTITail)
3393 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3396 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3397 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3398 const SLTG_TypeInfoTail *pTITail)
3400 sltg_ref_lookup_t *ref_lookup = NULL;
3401 if (pTIHeader->href_table != 0xffffffff)
3402 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3403 pNameTable);
3405 if (pTITail->vars_off != 0xffff)
3406 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3408 if (pTITail->funcs_off != 0xffff)
3409 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3410 HeapFree(GetProcessHeap(), 0, ref_lookup);
3413 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3414 managable copy of it into this */
3415 typedef struct {
3416 WORD small_no;
3417 char *index_name;
3418 char *other_name;
3419 WORD res1a;
3420 WORD name_offs;
3421 WORD more_bytes;
3422 char *extra;
3423 WORD res20;
3424 DWORD helpcontext;
3425 WORD res26;
3426 GUID uuid;
3427 } SLTG_InternalOtherTypeInfo;
3429 /****************************************************************************
3430 * ITypeLib2_Constructor_SLTG
3432 * loading a SLTG typelib from an in-memory image
3434 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3436 ITypeLibImpl *pTypeLibImpl;
3437 SLTG_Header *pHeader;
3438 SLTG_BlkEntry *pBlkEntry;
3439 SLTG_Magic *pMagic;
3440 SLTG_Index *pIndex;
3441 SLTG_Pad9 *pPad9;
3442 LPVOID pBlk, pFirstBlk;
3443 SLTG_LibBlk *pLibBlk;
3444 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3445 char *pAfterOTIBlks = NULL;
3446 char *pNameTable, *ptr;
3447 int i;
3448 DWORD len, order;
3449 ITypeInfoImpl **ppTypeInfoImpl;
3451 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3454 pTypeLibImpl = TypeLibImpl_Constructor();
3455 if (!pTypeLibImpl) return NULL;
3457 pHeader = pLib;
3459 TRACE_(typelib)("header:\n");
3460 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3461 pHeader->nrOfFileBlks );
3462 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3463 FIXME("Header type magic 0x%08x not supported.\n",
3464 pHeader->SLTG_magic);
3465 return NULL;
3468 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3469 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3471 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3472 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3474 /* Next we have a magic block */
3475 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3477 /* Let's see if we're still in sync */
3478 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3479 sizeof(SLTG_COMPOBJ_MAGIC))) {
3480 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3481 return NULL;
3483 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3484 sizeof(SLTG_DIR_MAGIC))) {
3485 FIXME("dir magic = %s\n", pMagic->dir_magic);
3486 return NULL;
3489 pIndex = (SLTG_Index*)(pMagic+1);
3491 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3493 pFirstBlk = (LPVOID)(pPad9 + 1);
3495 /* We'll set up a ptr to the main library block, which is the last one. */
3497 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3498 pBlkEntry[order].next != 0;
3499 order = pBlkEntry[order].next - 1, i++) {
3500 pBlk = (char*)pBlk + pBlkEntry[order].len;
3502 pLibBlk = pBlk;
3504 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3506 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3507 interspersed */
3509 len += 0x40;
3511 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3513 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3514 sizeof(*pOtherTypeInfoBlks) *
3515 pTypeLibImpl->TypeInfoCount);
3518 ptr = (char*)pLibBlk + len;
3520 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3521 WORD w, extra;
3522 len = 0;
3524 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3526 w = *(WORD*)(ptr + 2);
3527 if(w != 0xffff) {
3528 len += w;
3529 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3530 w+1);
3531 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3532 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3534 w = *(WORD*)(ptr + 4 + len);
3535 if(w != 0xffff) {
3536 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3537 len += w;
3538 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3539 w+1);
3540 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3541 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3543 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3544 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3545 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3546 if(extra) {
3547 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3548 extra);
3549 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3550 len += extra;
3552 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3553 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3554 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3555 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3556 len += sizeof(SLTG_OtherTypeInfo);
3557 ptr += len;
3560 pAfterOTIBlks = ptr;
3562 /* Skip this WORD and get the next DWORD */
3563 len = *(DWORD*)(pAfterOTIBlks + 2);
3565 /* Now add this to pLibBLk look at what we're pointing at and
3566 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3567 dust and we should be pointing at the beginning of the name
3568 table */
3570 pNameTable = (char*)pLibBlk + len;
3572 switch(*(WORD*)pNameTable) {
3573 case 0xffff:
3574 break;
3575 case 0x0200:
3576 pNameTable += 0x20;
3577 break;
3578 default:
3579 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3580 break;
3583 pNameTable += 0x216;
3585 pNameTable += 2;
3587 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3589 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3592 /* Hopefully we now have enough ptrs set up to actually read in
3593 some TypeInfos. It's not clear which order to do them in, so
3594 I'll just follow the links along the BlkEntry chain and read
3595 them in the order in which they are in the file */
3597 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3599 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3600 pBlkEntry[order].next != 0;
3601 order = pBlkEntry[order].next - 1, i++) {
3603 SLTG_TypeInfoHeader *pTIHeader;
3604 SLTG_TypeInfoTail *pTITail;
3605 SLTG_MemberHeader *pMemHeader;
3607 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3608 pOtherTypeInfoBlks[i].index_name)) {
3609 FIXME("Index strings don't match\n");
3610 return NULL;
3613 pTIHeader = pBlk;
3614 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3615 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3616 return NULL;
3618 TRACE("pTIHeader->res06 = %x, pTIHeader->res0e = %x, pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3619 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3621 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3622 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3623 (*ppTypeInfoImpl)->index = i;
3624 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3625 pOtherTypeInfoBlks[i].name_offs +
3626 pNameTable);
3627 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3628 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
3629 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3630 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3631 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3632 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3633 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3635 if((pTIHeader->typeflags1 & 7) != 2)
3636 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3637 if(pTIHeader->typeflags3 != 2)
3638 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3640 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3641 debugstr_w((*ppTypeInfoImpl)->Name),
3642 typekind_desc[pTIHeader->typekind],
3643 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3644 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3646 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3648 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3650 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3651 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3652 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3654 switch(pTIHeader->typekind) {
3655 case TKIND_ENUM:
3656 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3657 pTIHeader, pTITail);
3658 break;
3660 case TKIND_RECORD:
3661 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3662 pTIHeader, pTITail);
3663 break;
3665 case TKIND_INTERFACE:
3666 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3667 pTIHeader, pTITail);
3668 break;
3670 case TKIND_COCLASS:
3671 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3672 pTIHeader, pTITail);
3673 break;
3675 case TKIND_ALIAS:
3676 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3677 pTIHeader, pTITail);
3678 break;
3680 case TKIND_DISPATCH:
3681 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3682 pTIHeader, pTITail);
3683 break;
3685 case TKIND_MODULE:
3686 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3687 pTIHeader, pTITail);
3688 break;
3690 default:
3691 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3692 break;
3696 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3697 but we've already set those */
3698 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3699 X(06);
3700 X(16);
3701 X(18);
3702 X(1a);
3703 X(1e);
3704 X(24);
3705 X(26);
3706 X(2a);
3707 X(2c);
3708 X(2e);
3709 X(30);
3710 X(32);
3711 X(34);
3713 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3714 pBlk = (char*)pBlk + pBlkEntry[order].len;
3717 if(i != pTypeLibImpl->TypeInfoCount) {
3718 FIXME("Somehow processed %d TypeInfos\n", i);
3719 return NULL;
3722 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3723 return (ITypeLib2*)pTypeLibImpl;
3726 /* ITypeLib::QueryInterface
3728 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3729 ITypeLib2 * iface,
3730 REFIID riid,
3731 VOID **ppvObject)
3733 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3735 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3737 *ppvObject=NULL;
3738 if(IsEqualIID(riid, &IID_IUnknown) ||
3739 IsEqualIID(riid,&IID_ITypeLib)||
3740 IsEqualIID(riid,&IID_ITypeLib2))
3742 *ppvObject = This;
3745 if(*ppvObject)
3747 ITypeLib2_AddRef(iface);
3748 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3749 return S_OK;
3751 TRACE("-- Interface: E_NOINTERFACE\n");
3752 return E_NOINTERFACE;
3755 /* ITypeLib::AddRef
3757 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3759 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3760 ULONG ref = InterlockedIncrement(&This->ref);
3762 TRACE("(%p)->ref was %u\n",This, ref - 1);
3764 return ref;
3767 /* ITypeLib::Release
3769 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3771 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3772 ULONG ref = InterlockedDecrement(&This->ref);
3774 TRACE("(%p)->(%u)\n",This, ref);
3776 if (!ref)
3778 TLBImpLib *pImpLib, *pImpLibNext;
3779 TLBCustData *pCustData, *pCustDataNext;
3780 TLBRefType *ref_type;
3781 void *cursor2;
3782 int i;
3784 /* remove cache entry */
3785 if(This->path)
3787 TRACE("removing from cache list\n");
3788 EnterCriticalSection(&cache_section);
3789 if (This->next) This->next->prev = This->prev;
3790 if (This->prev) This->prev->next = This->next;
3791 else tlb_cache_first = This->next;
3792 LeaveCriticalSection(&cache_section);
3793 HeapFree(GetProcessHeap(), 0, This->path);
3795 TRACE(" destroying ITypeLib(%p)\n",This);
3797 if (This->Name)
3799 SysFreeString(This->Name);
3800 This->Name = NULL;
3803 if (This->DocString)
3805 SysFreeString(This->DocString);
3806 This->DocString = NULL;
3809 if (This->HelpFile)
3811 SysFreeString(This->HelpFile);
3812 This->HelpFile = NULL;
3815 if (This->HelpStringDll)
3817 SysFreeString(This->HelpStringDll);
3818 This->HelpStringDll = NULL;
3821 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
3823 VariantClear(&pCustData->data);
3825 pCustDataNext = pCustData->next;
3826 TLB_Free(pCustData);
3829 for (i = 0; i < This->ctTypeDesc; i++)
3830 if (This->pTypeDesc[i].vt == VT_CARRAY)
3831 TLB_Free(This->pTypeDesc[i].u.lpadesc);
3833 TLB_Free(This->pTypeDesc);
3835 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
3837 if (pImpLib->pImpTypeLib)
3838 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
3839 TLB_Free(pImpLib->name);
3841 pImpLibNext = pImpLib->next;
3842 TLB_Free(pImpLib);
3845 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
3847 list_remove(&ref_type->entry);
3848 TLB_Free(ref_type);
3851 if (This->pTypeInfo) /* can be NULL */
3852 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3853 HeapFree(GetProcessHeap(),0,This);
3854 return 0;
3857 return ref;
3860 /* ITypeLib::GetTypeInfoCount
3862 * Returns the number of type descriptions in the type library
3864 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3866 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3867 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3868 return This->TypeInfoCount;
3871 /* ITypeLib::GetTypeInfo
3873 * retrieves the specified type description in the library.
3875 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3876 ITypeLib2 *iface,
3877 UINT index,
3878 ITypeInfo **ppTInfo)
3880 int i;
3882 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3883 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3885 TRACE("(%p)->(index=%d)\n", This, index);
3887 if (!ppTInfo) return E_INVALIDARG;
3889 /* search element n in list */
3890 for(i=0; i < index; i++)
3892 pTypeInfo = pTypeInfo->next;
3893 if (!pTypeInfo)
3895 TRACE("-- element not found\n");
3896 return TYPE_E_ELEMENTNOTFOUND;
3900 *ppTInfo = (ITypeInfo *) pTypeInfo;
3902 ITypeInfo_AddRef(*ppTInfo);
3903 TRACE("-- found (%p)\n",*ppTInfo);
3904 return S_OK;
3908 /* ITypeLibs::GetTypeInfoType
3910 * Retrieves the type of a type description.
3912 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3913 ITypeLib2 *iface,
3914 UINT index,
3915 TYPEKIND *pTKind)
3917 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3918 int i;
3919 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3921 if (ITypeLib2_fnGetTypeInfoCount(iface) < index + 1)
3922 return TYPE_E_ELEMENTNOTFOUND;
3924 TRACE("(%p) index %d\n", This, index);
3926 if(!pTKind) return E_INVALIDARG;
3928 /* search element n in list */
3929 for(i=0; i < index; i++)
3931 if(!pTInfo)
3933 TRACE("-- element not found\n");
3934 return TYPE_E_ELEMENTNOTFOUND;
3936 pTInfo = pTInfo->next;
3939 *pTKind = pTInfo->TypeAttr.typekind;
3940 TRACE("-- found Type (%d)\n", *pTKind);
3941 return S_OK;
3944 /* ITypeLib::GetTypeInfoOfGuid
3946 * Retrieves the type description that corresponds to the specified GUID.
3949 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3950 ITypeLib2 *iface,
3951 REFGUID guid,
3952 ITypeInfo **ppTInfo)
3954 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3955 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3957 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3959 if (!pTypeInfo)
3961 WARN("-- element not found\n");
3962 return TYPE_E_ELEMENTNOTFOUND;
3965 /* search linked list for guid */
3966 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3968 pTypeInfo = pTypeInfo->next;
3970 if (!pTypeInfo)
3972 /* end of list reached */
3973 WARN("-- element not found\n");
3974 return TYPE_E_ELEMENTNOTFOUND;
3978 TRACE("-- found (%p, %s)\n",
3979 pTypeInfo,
3980 debugstr_w(pTypeInfo->Name));
3982 *ppTInfo = (ITypeInfo*)pTypeInfo;
3983 ITypeInfo_AddRef(*ppTInfo);
3984 return S_OK;
3987 /* ITypeLib::GetLibAttr
3989 * Retrieves the structure that contains the library's attributes.
3992 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3993 ITypeLib2 *iface,
3994 LPTLIBATTR *ppTLibAttr)
3996 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3997 TRACE("(%p)\n",This);
3998 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3999 **ppTLibAttr = This->LibAttr;
4000 return S_OK;
4003 /* ITypeLib::GetTypeComp
4005 * Enables a client compiler to bind to a library's types, variables,
4006 * constants, and global functions.
4009 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4010 ITypeLib2 *iface,
4011 ITypeComp **ppTComp)
4013 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4015 TRACE("(%p)->(%p)\n",This,ppTComp);
4016 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4017 ITypeComp_AddRef(*ppTComp);
4019 return S_OK;
4022 /* ITypeLib::GetDocumentation
4024 * Retrieves the library's documentation string, the complete Help file name
4025 * and path, and the context identifier for the library Help topic in the Help
4026 * file.
4028 * On a successful return all non-null BSTR pointers will have been set,
4029 * possibly to NULL.
4031 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4032 ITypeLib2 *iface,
4033 INT index,
4034 BSTR *pBstrName,
4035 BSTR *pBstrDocString,
4036 DWORD *pdwHelpContext,
4037 BSTR *pBstrHelpFile)
4039 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4041 HRESULT result = E_INVALIDARG;
4043 ITypeInfo *pTInfo;
4046 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4047 This, index,
4048 pBstrName, pBstrDocString,
4049 pdwHelpContext, pBstrHelpFile);
4051 if(index<0)
4053 /* documentation for the typelib */
4054 if(pBstrName)
4056 if (This->Name)
4058 if(!(*pBstrName = SysAllocString(This->Name)))
4059 goto memerr1;
4061 else
4062 *pBstrName = NULL;
4064 if(pBstrDocString)
4066 if (This->DocString)
4068 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4069 goto memerr2;
4071 else if (This->Name)
4073 if(!(*pBstrDocString = SysAllocString(This->Name)))
4074 goto memerr2;
4076 else
4077 *pBstrDocString = NULL;
4079 if(pdwHelpContext)
4081 *pdwHelpContext = This->dwHelpContext;
4083 if(pBstrHelpFile)
4085 if (This->HelpFile)
4087 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4088 goto memerr3;
4090 else
4091 *pBstrHelpFile = NULL;
4094 result = S_OK;
4096 else
4098 /* for a typeinfo */
4099 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4101 if(SUCCEEDED(result))
4103 result = ITypeInfo_GetDocumentation(pTInfo,
4104 MEMBERID_NIL,
4105 pBstrName,
4106 pBstrDocString,
4107 pdwHelpContext, pBstrHelpFile);
4109 ITypeInfo_Release(pTInfo);
4112 return result;
4113 memerr3:
4114 if (pBstrDocString) SysFreeString (*pBstrDocString);
4115 memerr2:
4116 if (pBstrName) SysFreeString (*pBstrName);
4117 memerr1:
4118 return STG_E_INSUFFICIENTMEMORY;
4121 /* ITypeLib::IsName
4123 * Indicates whether a passed-in string contains the name of a type or member
4124 * described in the library.
4127 static HRESULT WINAPI ITypeLib2_fnIsName(
4128 ITypeLib2 *iface,
4129 LPOLESTR szNameBuf,
4130 ULONG lHashVal,
4131 BOOL *pfName)
4133 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4134 ITypeInfoImpl *pTInfo;
4135 TLBFuncDesc *pFInfo;
4136 TLBVarDesc *pVInfo;
4137 int i;
4138 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4140 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4141 pfName);
4143 *pfName=TRUE;
4144 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
4145 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4146 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4147 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4148 for(i=0;i<pFInfo->funcdesc.cParams;i++)
4149 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
4150 goto ITypeLib2_fnIsName_exit;
4152 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4153 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4156 *pfName=FALSE;
4158 ITypeLib2_fnIsName_exit:
4159 TRACE("(%p)slow! search for %s: %s found!\n", This,
4160 debugstr_w(szNameBuf), *pfName?"NOT":"");
4162 return S_OK;
4165 /* ITypeLib::FindName
4167 * Finds occurrences of a type description in a type library. This may be used
4168 * to quickly verify that a name exists in a type library.
4171 static HRESULT WINAPI ITypeLib2_fnFindName(
4172 ITypeLib2 *iface,
4173 LPOLESTR szNameBuf,
4174 ULONG lHashVal,
4175 ITypeInfo **ppTInfo,
4176 MEMBERID *rgMemId,
4177 UINT16 *pcFound)
4179 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4180 ITypeInfoImpl *pTInfo;
4181 TLBFuncDesc *pFInfo;
4182 TLBVarDesc *pVInfo;
4183 int i,j = 0;
4184 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4186 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
4187 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4188 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4189 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4190 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
4191 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
4192 goto ITypeLib2_fnFindName_exit;
4195 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4196 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4197 continue;
4198 ITypeLib2_fnFindName_exit:
4199 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4200 ppTInfo[j]=(LPTYPEINFO)pTInfo;
4201 j++;
4203 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4204 This, *pcFound, debugstr_w(szNameBuf), j);
4206 *pcFound=j;
4208 return S_OK;
4211 /* ITypeLib::ReleaseTLibAttr
4213 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4216 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4217 ITypeLib2 *iface,
4218 TLIBATTR *pTLibAttr)
4220 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4221 TRACE("freeing (%p)\n",This);
4222 HeapFree(GetProcessHeap(),0,pTLibAttr);
4226 /* ITypeLib2::GetCustData
4228 * gets the custom data
4230 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4231 ITypeLib2 * iface,
4232 REFGUID guid,
4233 VARIANT *pVarVal)
4235 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4236 TLBCustData *pCData;
4238 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4240 if( IsEqualIID(guid, &pCData->guid)) break;
4243 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4245 if(pCData)
4247 VariantInit( pVarVal);
4248 VariantCopy( pVarVal, &pCData->data);
4249 return S_OK;
4251 return E_INVALIDARG; /* FIXME: correct? */
4254 /* ITypeLib2::GetLibStatistics
4256 * Returns statistics about a type library that are required for efficient
4257 * sizing of hash tables.
4260 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4261 ITypeLib2 * iface,
4262 ULONG *pcUniqueNames,
4263 ULONG *pcchUniqueNames)
4265 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4267 FIXME("(%p): stub!\n", This);
4269 if(pcUniqueNames) *pcUniqueNames=1;
4270 if(pcchUniqueNames) *pcchUniqueNames=1;
4271 return S_OK;
4274 /* ITypeLib2::GetDocumentation2
4276 * Retrieves the library's documentation string, the complete Help file name
4277 * and path, the localization context to use, and the context ID for the
4278 * library Help topic in the Help file.
4281 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4282 ITypeLib2 * iface,
4283 INT index,
4284 LCID lcid,
4285 BSTR *pbstrHelpString,
4286 DWORD *pdwHelpStringContext,
4287 BSTR *pbstrHelpStringDll)
4289 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4290 HRESULT result;
4291 ITypeInfo *pTInfo;
4293 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4295 /* the help string should be obtained from the helpstringdll,
4296 * using the _DLLGetDocumentation function, based on the supplied
4297 * lcid. Nice to do sometime...
4299 if(index<0)
4301 /* documentation for the typelib */
4302 if(pbstrHelpString)
4303 *pbstrHelpString=SysAllocString(This->DocString);
4304 if(pdwHelpStringContext)
4305 *pdwHelpStringContext=This->dwHelpContext;
4306 if(pbstrHelpStringDll)
4307 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4309 result = S_OK;
4311 else
4313 /* for a typeinfo */
4314 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4316 if(SUCCEEDED(result))
4318 ITypeInfo2 * pTInfo2;
4319 result = ITypeInfo_QueryInterface(pTInfo,
4320 &IID_ITypeInfo2,
4321 (LPVOID*) &pTInfo2);
4323 if(SUCCEEDED(result))
4325 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4326 MEMBERID_NIL,
4327 lcid,
4328 pbstrHelpString,
4329 pdwHelpStringContext,
4330 pbstrHelpStringDll);
4332 ITypeInfo2_Release(pTInfo2);
4335 ITypeInfo_Release(pTInfo);
4338 return result;
4341 /* ITypeLib2::GetAllCustData
4343 * Gets all custom data items for the library.
4346 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4347 ITypeLib2 * iface,
4348 CUSTDATA *pCustData)
4350 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4351 TLBCustData *pCData;
4352 int i;
4353 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4354 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4355 if(pCustData->prgCustData ){
4356 pCustData->cCustData=This->ctCustData;
4357 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4358 pCustData->prgCustData[i].guid=pCData->guid;
4359 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4361 }else{
4362 ERR(" OUT OF MEMORY!\n");
4363 return E_OUTOFMEMORY;
4365 return S_OK;
4368 static const ITypeLib2Vtbl tlbvt = {
4369 ITypeLib2_fnQueryInterface,
4370 ITypeLib2_fnAddRef,
4371 ITypeLib2_fnRelease,
4372 ITypeLib2_fnGetTypeInfoCount,
4373 ITypeLib2_fnGetTypeInfo,
4374 ITypeLib2_fnGetTypeInfoType,
4375 ITypeLib2_fnGetTypeInfoOfGuid,
4376 ITypeLib2_fnGetLibAttr,
4377 ITypeLib2_fnGetTypeComp,
4378 ITypeLib2_fnGetDocumentation,
4379 ITypeLib2_fnIsName,
4380 ITypeLib2_fnFindName,
4381 ITypeLib2_fnReleaseTLibAttr,
4383 ITypeLib2_fnGetCustData,
4384 ITypeLib2_fnGetLibStatistics,
4385 ITypeLib2_fnGetDocumentation2,
4386 ITypeLib2_fnGetAllCustData
4390 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4392 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4394 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4397 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4399 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4401 return ITypeLib2_AddRef((ITypeLib2 *)This);
4404 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4406 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4408 return ITypeLib2_Release((ITypeLib2 *)This);
4411 static HRESULT WINAPI ITypeLibComp_fnBind(
4412 ITypeComp * iface,
4413 OLECHAR * szName,
4414 ULONG lHash,
4415 WORD wFlags,
4416 ITypeInfo ** ppTInfo,
4417 DESCKIND * pDescKind,
4418 BINDPTR * pBindPtr)
4420 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4421 ITypeInfoImpl *pTypeInfo;
4423 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4425 *pDescKind = DESCKIND_NONE;
4426 pBindPtr->lptcomp = NULL;
4427 *ppTInfo = NULL;
4429 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4431 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4433 /* FIXME: check wFlags here? */
4434 /* FIXME: we should use a hash table to look this info up using lHash
4435 * instead of an O(n) search */
4436 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4437 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4439 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4441 *pDescKind = DESCKIND_TYPECOMP;
4442 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4443 ITypeComp_AddRef(pBindPtr->lptcomp);
4444 TRACE("module or enum: %s\n", debugstr_w(szName));
4445 return S_OK;
4449 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4450 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4452 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4453 HRESULT hr;
4455 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4456 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4458 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4459 return S_OK;
4463 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4464 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4466 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4467 HRESULT hr;
4468 ITypeInfo *subtypeinfo;
4469 BINDPTR subbindptr;
4470 DESCKIND subdesckind;
4472 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4473 &subtypeinfo, &subdesckind, &subbindptr);
4474 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4476 TYPEDESC tdesc_appobject =
4479 (TYPEDESC *)pTypeInfo->hreftype
4481 VT_USERDEFINED
4483 const VARDESC vardesc_appobject =
4485 -2, /* memid */
4486 NULL, /* lpstrSchema */
4488 0 /* oInst */
4491 /* ELEMDESC */
4493 /* TYPEDESC */
4495 &tdesc_appobject
4497 VT_PTR
4500 0, /* wVarFlags */
4501 VAR_STATIC /* varkind */
4504 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4506 /* cleanup things filled in by Bind call so we can put our
4507 * application object data in there instead */
4508 switch (subdesckind)
4510 case DESCKIND_FUNCDESC:
4511 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4512 break;
4513 case DESCKIND_VARDESC:
4514 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4515 break;
4516 default:
4517 break;
4519 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4521 if (pTypeInfo->hreftype == -1)
4522 FIXME("no hreftype for interface %p\n", pTypeInfo);
4524 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4525 if (FAILED(hr))
4526 return hr;
4528 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4529 *ppTInfo = (ITypeInfo *)pTypeInfo;
4530 ITypeInfo_AddRef(*ppTInfo);
4531 return S_OK;
4536 TRACE("name not found %s\n", debugstr_w(szName));
4537 return S_OK;
4540 static HRESULT WINAPI ITypeLibComp_fnBindType(
4541 ITypeComp * iface,
4542 OLECHAR * szName,
4543 ULONG lHash,
4544 ITypeInfo ** ppTInfo,
4545 ITypeComp ** ppTComp)
4547 FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4548 return E_NOTIMPL;
4551 static const ITypeCompVtbl tlbtcvt =
4554 ITypeLibComp_fnQueryInterface,
4555 ITypeLibComp_fnAddRef,
4556 ITypeLibComp_fnRelease,
4558 ITypeLibComp_fnBind,
4559 ITypeLibComp_fnBindType
4562 /*================== ITypeInfo(2) Methods ===================================*/
4563 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4565 ITypeInfoImpl * pTypeInfoImpl;
4567 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4568 if (pTypeInfoImpl)
4570 pTypeInfoImpl->lpVtbl = &tinfvt;
4571 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4572 pTypeInfoImpl->ref=1;
4573 pTypeInfoImpl->hreftype = -1;
4574 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4575 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4577 TRACE("(%p)\n", pTypeInfoImpl);
4578 return (ITypeInfo2*) pTypeInfoImpl;
4581 /* ITypeInfo::QueryInterface
4583 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4584 ITypeInfo2 *iface,
4585 REFIID riid,
4586 VOID **ppvObject)
4588 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4590 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4592 *ppvObject=NULL;
4593 if(IsEqualIID(riid, &IID_IUnknown) ||
4594 IsEqualIID(riid,&IID_ITypeInfo)||
4595 IsEqualIID(riid,&IID_ITypeInfo2))
4596 *ppvObject = This;
4598 if(*ppvObject){
4599 ITypeInfo_AddRef(iface);
4600 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4601 return S_OK;
4603 TRACE("-- Interface: E_NOINTERFACE\n");
4604 return E_NOINTERFACE;
4607 /* ITypeInfo::AddRef
4609 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4611 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4612 ULONG ref = InterlockedIncrement(&This->ref);
4614 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4616 TRACE("(%p)->ref is %u\n",This, ref);
4617 return ref;
4620 /* ITypeInfo::Release
4622 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4624 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4625 ULONG ref = InterlockedDecrement(&This->ref);
4627 TRACE("(%p)->(%u)\n",This, ref);
4629 if (ref) {
4630 /* We don't release ITypeLib when ref=0 because
4631 it means that function is called by ITypeLib2_Release */
4632 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4633 } else {
4634 TLBFuncDesc *pFInfo, *pFInfoNext;
4635 TLBVarDesc *pVInfo, *pVInfoNext;
4636 TLBImplType *pImpl, *pImplNext;
4638 TRACE("destroying ITypeInfo(%p)\n",This);
4640 if (This->no_free_data)
4641 goto finish_free;
4643 if (This->Name)
4645 SysFreeString(This->Name);
4646 This->Name = 0;
4649 if (This->DocString)
4651 SysFreeString(This->DocString);
4652 This->DocString = 0;
4655 if (This->DllName)
4657 SysFreeString(This->DllName);
4658 This->DllName = 0;
4661 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4663 UINT i;
4664 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4666 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4667 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4669 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4670 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4672 SysFreeString(pFInfo->pParamDesc[i].Name);
4674 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4675 TLB_Free(pFInfo->pParamDesc);
4676 TLB_FreeCustData(pFInfo->pCustData);
4677 if (HIWORD(pFInfo->Entry) != 0 && pFInfo->Entry != (BSTR)-1)
4678 SysFreeString(pFInfo->Entry);
4679 SysFreeString(pFInfo->HelpString);
4680 SysFreeString(pFInfo->Name);
4682 pFInfoNext = pFInfo->next;
4683 TLB_Free(pFInfo);
4685 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
4687 if (pVInfo->vardesc.varkind == VAR_CONST)
4689 VariantClear(pVInfo->vardesc.u.lpvarValue);
4690 TLB_Free(pVInfo->vardesc.u.lpvarValue);
4692 TLB_FreeCustData(pVInfo->pCustData);
4693 SysFreeString(pVInfo->Name);
4694 pVInfoNext = pVInfo->next;
4695 TLB_Free(pVInfo);
4697 for(pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
4699 TLB_FreeCustData(pImpl->pCustData);
4700 pImplNext = pImpl->next;
4701 TLB_Free(pImpl);
4703 TLB_FreeCustData(This->pCustData);
4705 finish_free:
4706 if (This->next)
4708 ITypeInfo_Release((ITypeInfo*)This->next);
4711 HeapFree(GetProcessHeap(),0,This);
4712 return 0;
4714 return ref;
4717 /* ITypeInfo::GetTypeAttr
4719 * Retrieves a TYPEATTR structure that contains the attributes of the type
4720 * description.
4723 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4724 LPTYPEATTR *ppTypeAttr)
4726 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4727 SIZE_T size;
4729 TRACE("(%p)\n",This);
4731 size = sizeof(**ppTypeAttr);
4732 if (This->TypeAttr.typekind == TKIND_ALIAS)
4733 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4735 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4736 if (!*ppTypeAttr)
4737 return E_OUTOFMEMORY;
4739 **ppTypeAttr = This->TypeAttr;
4741 if (This->TypeAttr.typekind == TKIND_ALIAS)
4742 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4743 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4745 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4746 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4747 funcs */
4748 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4749 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4751 return S_OK;
4754 /* ITypeInfo::GetTypeComp
4756 * Retrieves the ITypeComp interface for the type description, which enables a
4757 * client compiler to bind to the type description's members.
4760 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4761 ITypeComp * *ppTComp)
4763 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4765 TRACE("(%p)->(%p)\n", This, ppTComp);
4767 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4768 ITypeComp_AddRef(*ppTComp);
4769 return S_OK;
4772 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4774 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4775 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4776 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4777 return size;
4780 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4782 *dest = *src;
4783 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4784 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4786 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4787 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4788 *buffer += sizeof(PARAMDESCEX);
4789 *pparamdescex_dest = *pparamdescex_src;
4790 VariantInit(&pparamdescex_dest->varDefaultValue);
4791 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4792 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4794 else
4795 dest->u.paramdesc.pparamdescex = NULL;
4796 return S_OK;
4799 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4801 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4802 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4805 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4807 FUNCDESC *dest;
4808 char *buffer;
4809 SIZE_T size = sizeof(*src);
4810 SHORT i;
4811 HRESULT hr;
4813 size += sizeof(*src->lprgscode) * src->cScodes;
4814 size += TLB_SizeElemDesc(&src->elemdescFunc);
4815 for (i = 0; i < src->cParams; i++)
4817 size += sizeof(ELEMDESC);
4818 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4821 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4822 if (!dest) return E_OUTOFMEMORY;
4824 *dest = *src;
4825 if (dispinterface) /* overwrite funckind */
4826 dest->funckind = FUNC_DISPATCH;
4827 buffer = (char *)(dest + 1);
4829 dest->lprgscode = (SCODE *)buffer;
4830 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4831 buffer += sizeof(*src->lprgscode) * src->cScodes;
4833 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4834 if (FAILED(hr))
4836 SysFreeString((BSTR)dest);
4837 return hr;
4840 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4841 buffer += sizeof(ELEMDESC) * src->cParams;
4842 for (i = 0; i < src->cParams; i++)
4844 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4845 if (FAILED(hr))
4846 break;
4848 if (FAILED(hr))
4850 /* undo the above actions */
4851 for (i = i - 1; i >= 0; i--)
4852 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4853 TLB_FreeElemDesc(&dest->elemdescFunc);
4854 SysFreeString((BSTR)dest);
4855 return hr;
4858 /* special treatment for dispinterfaces: this makes functions appear
4859 * to return their [retval] value when it is really returning an
4860 * HRESULT */
4861 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4863 if (dest->cParams &&
4864 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4866 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4867 if (elemdesc->tdesc.vt != VT_PTR)
4869 ERR("elemdesc should have started with VT_PTR instead of:\n");
4870 if (ERR_ON(ole))
4871 dump_ELEMDESC(elemdesc);
4872 return E_UNEXPECTED;
4875 /* copy last parameter to the return value. we are using a flat
4876 * buffer so there is no danger of leaking memory in
4877 * elemdescFunc */
4878 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4880 /* remove the last parameter */
4881 dest->cParams--;
4883 else
4884 /* otherwise this function is made to appear to have no return
4885 * value */
4886 dest->elemdescFunc.tdesc.vt = VT_VOID;
4890 *dest_ptr = dest;
4891 return S_OK;
4894 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4896 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4897 const TLBFuncDesc *pFDesc;
4898 int i;
4900 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4903 if (pFDesc)
4905 *ppFuncDesc = &pFDesc->funcdesc;
4906 return S_OK;
4909 return TYPE_E_ELEMENTNOTFOUND;
4912 /* internal function to make the inherited interfaces' methods appear
4913 * part of the interface */
4914 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
4915 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
4917 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4918 HRESULT hr;
4919 UINT implemented_funcs = 0;
4921 if (funcs)
4922 *funcs = 0;
4923 else
4924 *hrefoffset = DISPATCH_HREF_OFFSET;
4926 if(This->impltypelist)
4928 ITypeInfo *pSubTypeInfo;
4929 UINT sub_funcs;
4931 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
4932 if (FAILED(hr))
4933 return hr;
4935 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
4936 index,
4937 ppFuncDesc,
4938 &sub_funcs, hrefoffset);
4939 implemented_funcs += sub_funcs;
4940 ITypeInfo_Release(pSubTypeInfo);
4941 if (SUCCEEDED(hr))
4942 return hr;
4943 *hrefoffset += DISPATCH_HREF_OFFSET;
4946 if (funcs)
4947 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
4948 else
4949 *hrefoffset = 0;
4951 if (index < implemented_funcs)
4952 return E_INVALIDARG;
4953 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
4954 ppFuncDesc);
4957 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
4959 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
4960 while (TRUE)
4962 switch (pTypeDesc->vt)
4964 case VT_USERDEFINED:
4965 pTypeDesc->u.hreftype += hrefoffset;
4966 return;
4967 case VT_PTR:
4968 case VT_SAFEARRAY:
4969 pTypeDesc = pTypeDesc->u.lptdesc;
4970 break;
4971 case VT_CARRAY:
4972 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
4973 break;
4974 default:
4975 return;
4980 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
4982 SHORT i;
4983 for (i = 0; i < pFuncDesc->cParams; i++)
4984 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
4985 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
4988 /* ITypeInfo::GetFuncDesc
4990 * Retrieves the FUNCDESC structure that contains information about a
4991 * specified function.
4994 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4995 LPFUNCDESC *ppFuncDesc)
4997 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4998 const FUNCDESC *internal_funcdesc;
4999 HRESULT hr;
5000 UINT hrefoffset = 0;
5002 TRACE("(%p) index %d\n", This, index);
5004 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5005 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5006 &internal_funcdesc, NULL,
5007 &hrefoffset);
5008 else
5009 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5010 &internal_funcdesc);
5011 if (FAILED(hr))
5013 WARN("description for function %d not found\n", index);
5014 return hr;
5017 hr = TLB_AllocAndInitFuncDesc(
5018 internal_funcdesc,
5019 ppFuncDesc,
5020 This->TypeAttr.typekind == TKIND_DISPATCH);
5022 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5023 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5025 TRACE("-- 0x%08x\n", hr);
5026 return hr;
5029 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5031 VARDESC *dest;
5032 char *buffer;
5033 SIZE_T size = sizeof(*src);
5034 HRESULT hr;
5036 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5037 if (src->varkind == VAR_CONST)
5038 size += sizeof(VARIANT);
5039 size += TLB_SizeElemDesc(&src->elemdescVar);
5041 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5042 if (!dest) return E_OUTOFMEMORY;
5044 *dest = *src;
5045 buffer = (char *)(dest + 1);
5046 if (src->lpstrSchema)
5048 int len;
5049 dest->lpstrSchema = (LPOLESTR)buffer;
5050 len = strlenW(src->lpstrSchema);
5051 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5052 buffer += (len + 1) * sizeof(WCHAR);
5055 if (src->varkind == VAR_CONST)
5057 HRESULT hr;
5059 dest->u.lpvarValue = (VARIANT *)buffer;
5060 *dest->u.lpvarValue = *src->u.lpvarValue;
5061 buffer += sizeof(VARIANT);
5062 VariantInit(dest->u.lpvarValue);
5063 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5064 if (FAILED(hr))
5066 SysFreeString((BSTR)dest_ptr);
5067 return hr;
5070 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5071 if (FAILED(hr))
5073 if (src->varkind == VAR_CONST)
5074 VariantClear(dest->u.lpvarValue);
5075 SysFreeString((BSTR)dest);
5076 return hr;
5078 *dest_ptr = dest;
5079 return S_OK;
5082 /* ITypeInfo::GetVarDesc
5084 * Retrieves a VARDESC structure that describes the specified variable.
5087 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5088 LPVARDESC *ppVarDesc)
5090 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5091 int i;
5092 const TLBVarDesc *pVDesc;
5094 TRACE("(%p) index %d\n", This, index);
5096 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
5099 if (pVDesc)
5100 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5102 return E_INVALIDARG;
5105 /* ITypeInfo_GetNames
5107 * Retrieves the variable with the specified member ID (or the name of the
5108 * property or method and its parameters) that correspond to the specified
5109 * function ID.
5111 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5112 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5114 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5115 const TLBFuncDesc *pFDesc;
5116 const TLBVarDesc *pVDesc;
5117 int i;
5118 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5119 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
5120 if(pFDesc)
5122 /* function found, now return function and parameter names */
5123 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5125 if(!i)
5126 *rgBstrNames=SysAllocString(pFDesc->Name);
5127 else
5128 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5130 *pcNames=i;
5132 else
5134 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
5135 if(pVDesc)
5137 *rgBstrNames=SysAllocString(pVDesc->Name);
5138 *pcNames=1;
5140 else
5142 if(This->impltypelist &&
5143 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5144 /* recursive search */
5145 ITypeInfo *pTInfo;
5146 HRESULT result;
5147 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5148 &pTInfo);
5149 if(SUCCEEDED(result))
5151 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5152 ITypeInfo_Release(pTInfo);
5153 return result;
5155 WARN("Could not search inherited interface!\n");
5157 else
5159 WARN("no names found\n");
5161 *pcNames=0;
5162 return TYPE_E_ELEMENTNOTFOUND;
5165 return S_OK;
5169 /* ITypeInfo::GetRefTypeOfImplType
5171 * If a type description describes a COM class, it retrieves the type
5172 * description of the implemented interface types. For an interface,
5173 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5174 * if any exist.
5177 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5178 ITypeInfo2 *iface,
5179 UINT index,
5180 HREFTYPE *pRefType)
5182 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5183 int i;
5184 HRESULT hr = S_OK;
5185 const TLBImplType *pImpl = This->impltypelist;
5187 TRACE("(%p) index %d\n", This, index);
5188 if (TRACE_ON(ole)) dump_TypeInfo(This);
5190 if(index==(UINT)-1)
5192 /* only valid on dual interfaces;
5193 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5195 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5197 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
5198 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
5200 *pRefType = -1;
5202 else
5204 hr = TYPE_E_ELEMENTNOTFOUND;
5207 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5209 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5210 *pRefType = This->pTypeLib->dispatch_href;
5212 else
5214 /* get element n from linked list */
5215 for(i=0; pImpl && i<index; i++)
5217 pImpl = pImpl->next;
5220 if (pImpl)
5221 *pRefType = pImpl->hRef;
5222 else
5223 hr = TYPE_E_ELEMENTNOTFOUND;
5226 if(TRACE_ON(ole))
5228 if(SUCCEEDED(hr))
5229 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5230 else
5231 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5234 return hr;
5237 /* ITypeInfo::GetImplTypeFlags
5239 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5240 * or base interface in a type description.
5242 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5243 UINT index, INT *pImplTypeFlags)
5245 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5246 int i;
5247 TLBImplType *pImpl;
5249 TRACE("(%p) index %d\n", This, index);
5250 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5251 i++, pImpl=pImpl->next)
5253 if(i==index && pImpl){
5254 *pImplTypeFlags=pImpl->implflags;
5255 return S_OK;
5257 *pImplTypeFlags=0;
5258 return TYPE_E_ELEMENTNOTFOUND;
5261 /* GetIDsOfNames
5262 * Maps between member names and member IDs, and parameter names and
5263 * parameter IDs.
5265 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5266 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5268 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5269 const TLBFuncDesc *pFDesc;
5270 const TLBVarDesc *pVDesc;
5271 HRESULT ret=S_OK;
5272 int i;
5274 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5275 cNames);
5277 /* init out parameters in case of failure */
5278 for (i = 0; i < cNames; i++)
5279 pMemId[i] = MEMBERID_NIL;
5281 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5282 int j;
5283 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5284 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5285 for(i=1; i < cNames; i++){
5286 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5287 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5288 break;
5289 if( j<pFDesc->funcdesc.cParams)
5290 pMemId[i]=j;
5291 else
5292 ret=DISP_E_UNKNOWNNAME;
5294 TRACE("-- 0x%08x\n", ret);
5295 return ret;
5298 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5299 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5300 if(cNames) *pMemId=pVDesc->vardesc.memid;
5301 return ret;
5304 /* not found, see if it can be found in an inherited interface */
5305 if(This->impltypelist) {
5306 /* recursive search */
5307 ITypeInfo *pTInfo;
5308 ret=ITypeInfo_GetRefTypeInfo(iface,
5309 This->impltypelist->hRef, &pTInfo);
5310 if(SUCCEEDED(ret)){
5311 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5312 ITypeInfo_Release(pTInfo);
5313 return ret;
5315 WARN("Could not search inherited interface!\n");
5316 } else
5317 WARN("no names found\n");
5318 return DISP_E_UNKNOWNNAME;
5321 /* ITypeInfo::Invoke
5323 * Invokes a method, or accesses a property of an object, that implements the
5324 * interface described by the type description.
5326 DWORD
5327 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5328 DWORD res;
5330 if (TRACE_ON(ole)) {
5331 int i;
5332 TRACE("Calling %p(",func);
5333 for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
5334 TRACE(")\n");
5337 switch (callconv) {
5338 case CC_STDCALL:
5340 switch (nrargs) {
5341 case 0:
5342 res = func();
5343 break;
5344 case 1:
5345 res = func(args[0]);
5346 break;
5347 case 2:
5348 res = func(args[0],args[1]);
5349 break;
5350 case 3:
5351 res = func(args[0],args[1],args[2]);
5352 break;
5353 case 4:
5354 res = func(args[0],args[1],args[2],args[3]);
5355 break;
5356 case 5:
5357 res = func(args[0],args[1],args[2],args[3],args[4]);
5358 break;
5359 case 6:
5360 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
5361 break;
5362 case 7:
5363 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
5364 break;
5365 case 8:
5366 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
5367 break;
5368 case 9:
5369 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
5370 break;
5371 case 10:
5372 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
5373 break;
5374 case 11:
5375 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
5376 break;
5377 case 12:
5378 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]);
5379 break;
5380 case 13:
5381 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]);
5382 break;
5383 case 14:
5384 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]);
5385 break;
5386 case 15:
5387 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]);
5388 break;
5389 case 16:
5390 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]);
5391 break;
5392 case 17:
5393 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]);
5394 break;
5395 case 18:
5396 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]);
5397 break;
5398 case 19:
5399 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]);
5400 break;
5401 case 20:
5402 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]);
5403 break;
5404 case 21:
5405 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]);
5406 break;
5407 case 22:
5408 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]);
5409 break;
5410 case 23:
5411 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]);
5412 break;
5413 case 24:
5414 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]);
5415 break;
5416 case 25:
5417 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]);
5418 break;
5419 case 26:
5420 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]);
5421 break;
5422 case 27:
5423 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]);
5424 break;
5425 case 28:
5426 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]);
5427 break;
5428 case 29:
5429 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]);
5430 break;
5431 case 30:
5432 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]);
5433 break;
5434 default:
5435 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
5436 res = -1;
5437 break;
5439 break;
5440 default:
5441 FIXME("unsupported calling convention %d\n",callconv);
5442 res = -1;
5443 break;
5445 TRACE("returns %08x\n",res);
5446 return res;
5449 extern int _argsize(DWORD vt);
5451 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5453 HRESULT hr = S_OK;
5454 ITypeInfo *tinfo2 = NULL;
5455 TYPEATTR *tattr = NULL;
5457 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5458 if (hr)
5460 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5461 "hr = 0x%08x\n",
5462 tdesc->u.hreftype, hr);
5463 return hr;
5465 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5466 if (hr)
5468 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5469 ITypeInfo_Release(tinfo2);
5470 return hr;
5473 switch (tattr->typekind)
5475 case TKIND_ENUM:
5476 *vt |= VT_I4;
5477 break;
5479 case TKIND_ALIAS:
5480 tdesc = &tattr->tdescAlias;
5481 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5482 break;
5484 case TKIND_INTERFACE:
5485 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5486 *vt |= VT_DISPATCH;
5487 else
5488 *vt |= VT_UNKNOWN;
5489 break;
5491 case TKIND_DISPATCH:
5492 *vt |= VT_DISPATCH;
5493 break;
5495 case TKIND_COCLASS:
5496 *vt |= VT_DISPATCH;
5497 break;
5499 case TKIND_RECORD:
5500 FIXME("TKIND_RECORD unhandled.\n");
5501 hr = E_NOTIMPL;
5502 break;
5504 case TKIND_UNION:
5505 FIXME("TKIND_UNION unhandled.\n");
5506 hr = E_NOTIMPL;
5507 break;
5509 default:
5510 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5511 hr = E_NOTIMPL;
5512 break;
5514 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5515 ITypeInfo_Release(tinfo2);
5516 return hr;
5519 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5521 HRESULT hr = S_OK;
5523 /* enforce only one level of pointer indirection */
5524 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5526 tdesc = tdesc->u.lptdesc;
5528 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5529 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5530 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5531 if ((tdesc->vt == VT_USERDEFINED) ||
5532 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5534 VARTYPE vt_userdefined = 0;
5535 const TYPEDESC *tdesc_userdefined = tdesc;
5536 if (tdesc->vt == VT_PTR)
5538 vt_userdefined = VT_BYREF;
5539 tdesc_userdefined = tdesc->u.lptdesc;
5541 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5542 if ((hr == S_OK) &&
5543 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5544 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5546 *vt |= vt_userdefined;
5547 return S_OK;
5550 *vt = VT_BYREF;
5553 switch (tdesc->vt)
5555 case VT_HRESULT:
5556 *vt |= VT_ERROR;
5557 break;
5558 case VT_USERDEFINED:
5559 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5560 break;
5561 case VT_VOID:
5562 case VT_CARRAY:
5563 case VT_PTR:
5564 case VT_LPSTR:
5565 case VT_LPWSTR:
5566 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5567 hr = DISP_E_BADVARTYPE;
5568 break;
5569 case VT_SAFEARRAY:
5570 *vt |= VT_ARRAY;
5571 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5572 break;
5573 default:
5574 *vt |= tdesc->vt;
5575 break;
5577 return hr;
5580 /***********************************************************************
5581 * DispCallFunc (OLEAUT32.@)
5583 * Invokes a function of the specifed calling convention, passing the
5584 * specified arguments and returns the result.
5586 * PARAMS
5587 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5588 * oVft [I] The offset in the vtable. See notes.
5589 * cc [I] Calling convention of the function to call.
5590 * vtReturn [I] The return type of the function.
5591 * cActuals [I] Number of parameters.
5592 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5593 * prgpvarg [I] The arguments to pass.
5594 * pvargResult [O] The return value of the function. Can be NULL.
5596 * RETURNS
5597 * Success: S_OK.
5598 * Failure: HRESULT code.
5600 * NOTES
5601 * The HRESULT return value of this function is not affected by the return
5602 * value of the user supplied function, which is returned in pvargResult.
5604 * If pvInstance is NULL then a non-object function is to be called and oVft
5605 * is the address of the function to call.
5607 * The cc parameter can be one of the following values:
5608 *|CC_FASTCALL
5609 *|CC_CDECL
5610 *|CC_PASCAL
5611 *|CC_STDCALL
5612 *|CC_FPFASTCALL
5613 *|CC_SYSCALL
5614 *|CC_MPWCDECL
5615 *|CC_MPWPASCAL
5618 HRESULT WINAPI
5619 DispCallFunc(
5620 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5621 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5623 int i, argsize, argspos;
5624 DWORD *args;
5625 HRESULT hres;
5627 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5628 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5629 pvargResult, V_VT(pvargResult));
5631 argsize = 0;
5632 if (pvInstance)
5633 argsize++; /* for This pointer */
5635 for (i=0;i<cActuals;i++)
5637 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5638 dump_Variant(prgpvarg[i]);
5639 argsize += _argsize(prgvt[i]);
5641 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5643 argspos = 0;
5644 if (pvInstance)
5646 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5647 argspos++;
5650 for (i=0;i<cActuals;i++)
5652 VARIANT *arg = prgpvarg[i];
5653 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5654 if (prgvt[i] == VT_VARIANT)
5655 memcpy(&args[argspos], arg, _argsize(prgvt[i]) * sizeof(DWORD));
5656 else
5657 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5658 argspos += _argsize(prgvt[i]);
5661 if (pvInstance)
5663 FARPROC *vtable = *(FARPROC**)pvInstance;
5664 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5666 else
5667 /* if we aren't invoking an object then the function pointer is stored
5668 * in oVft */
5669 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5671 if (pvargResult && (vtReturn != VT_EMPTY))
5673 TRACE("Method returned 0x%08x\n",hres);
5674 V_VT(pvargResult) = vtReturn;
5675 V_UI4(pvargResult) = hres;
5678 HeapFree(GetProcessHeap(),0,args);
5679 return S_OK;
5682 #define INVBUF_ELEMENT_SIZE \
5683 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5684 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5685 ((VARIANTARG *)(buffer))
5686 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5687 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5688 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5689 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5690 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5691 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5693 static HRESULT WINAPI ITypeInfo_fnInvoke(
5694 ITypeInfo2 *iface,
5695 VOID *pIUnk,
5696 MEMBERID memid,
5697 UINT16 wFlags,
5698 DISPPARAMS *pDispParams,
5699 VARIANT *pVarResult,
5700 EXCEPINFO *pExcepInfo,
5701 UINT *pArgErr)
5703 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5704 int i;
5705 unsigned int var_index;
5706 TYPEKIND type_kind;
5707 HRESULT hres;
5708 const TLBFuncDesc *pFuncInfo;
5710 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
5711 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5714 if (!pDispParams)
5716 ERR("NULL pDispParams not allowed\n");
5717 return E_INVALIDARG;
5720 dump_DispParms(pDispParams);
5722 if (pDispParams->cNamedArgs > pDispParams->cArgs)
5724 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
5725 pDispParams->cNamedArgs, pDispParams->cArgs);
5726 return E_INVALIDARG;
5729 /* we do this instead of using GetFuncDesc since it will return a fake
5730 * FUNCDESC for dispinterfaces and we want the real function description */
5731 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5732 if ((memid == pFuncInfo->funcdesc.memid) &&
5733 (wFlags & pFuncInfo->funcdesc.invkind))
5734 break;
5736 if (pFuncInfo) {
5737 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5739 if (TRACE_ON(ole))
5741 TRACE("invoking:\n");
5742 dump_TLBFuncDescOne(pFuncInfo);
5745 switch (func_desc->funckind) {
5746 case FUNC_PUREVIRTUAL:
5747 case FUNC_VIRTUAL: {
5748 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
5749 VARIANT varresult;
5750 VARIANT retval; /* pointer for storing byref retvals in */
5751 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
5752 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
5753 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
5754 UINT cNamedArgs = pDispParams->cNamedArgs;
5755 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
5757 hres = S_OK;
5759 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
5761 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
5763 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
5764 hres = DISP_E_PARAMNOTFOUND;
5765 goto func_fail;
5767 /* ignore the DISPID_PROPERTYPUT named argument from now on */
5768 cNamedArgs--;
5769 rgdispidNamedArgs++;
5772 if (func_desc->cParamsOpt < 0 && cNamedArgs)
5774 ERR("functions with the vararg attribute do not support named arguments\n");
5775 hres = DISP_E_NONAMEDARGS;
5776 goto func_fail;
5779 for (i = 0; i < func_desc->cParams; i++)
5781 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5782 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
5783 if (FAILED(hres))
5784 goto func_fail;
5787 TRACE("changing args\n");
5788 for (i = 0; i < func_desc->cParams; i++)
5790 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5791 VARIANTARG *src_arg;
5793 if (cNamedArgs)
5795 USHORT j;
5796 src_arg = NULL;
5797 for (j = 0; j < cNamedArgs; j++)
5798 if (rgdispidNamedArgs[j] == i)
5800 src_arg = &pDispParams->rgvarg[j];
5801 break;
5804 else
5805 src_arg = i < pDispParams->cArgs ? &pDispParams->rgvarg[pDispParams->cArgs - 1 - i] : NULL;
5807 if (wParamFlags & PARAMFLAG_FRETVAL)
5809 /* under most conditions the caller is not allowed to
5810 * pass in a dispparam arg in the index of what would be
5811 * the retval parameter. however, there is an exception
5812 * where the extra parameter is used in an extra
5813 * IDispatch::Invoke below */
5814 if ((i < pDispParams->cArgs) &&
5815 ((func_desc->cParams != 1) || !pVarResult ||
5816 !(func_desc->invkind & INVOKE_PROPERTYGET)))
5818 hres = DISP_E_BADPARAMCOUNT;
5819 break;
5822 /* note: this check is placed so that if the caller passes
5823 * in a VARIANTARG for the retval we just ignore it, like
5824 * native does */
5825 if (i == func_desc->cParams - 1)
5827 VARIANTARG *arg;
5828 arg = prgpvarg[i] = &rgvarg[i];
5829 memset(arg, 0, sizeof(*arg));
5830 V_VT(arg) = rgvt[i];
5831 memset(&retval, 0, sizeof(retval));
5832 V_BYREF(arg) = &retval;
5834 else
5836 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
5837 hres = E_UNEXPECTED;
5838 break;
5841 else if (src_arg)
5843 dump_Variant(src_arg);
5845 if (rgvt[i] == VT_VARIANT)
5846 hres = VariantCopy(&rgvarg[i], src_arg);
5847 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
5849 if (rgvt[i] == V_VT(src_arg))
5850 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
5851 else
5853 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5854 hres = VariantCopy(&missing_arg[i], src_arg);
5855 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
5857 V_VT(&rgvarg[i]) = rgvt[i];
5859 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
5861 SAFEARRAY *a;
5862 SAFEARRAYBOUND bound;
5863 VARIANT *v;
5864 LONG j;
5865 bound.lLbound = 0;
5866 bound.cElements = pDispParams->cArgs-i;
5867 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
5869 ERR("SafeArrayCreate failed\n");
5870 break;
5872 hres = SafeArrayAccessData(a, (LPVOID)&v);
5873 if (hres != S_OK)
5875 ERR("SafeArrayAccessData failed with %x\n", hres);
5876 break;
5878 for (j = 0; j < bound.cElements; j++)
5879 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
5880 hres = SafeArrayUnaccessData(a);
5881 if (hres != S_OK)
5883 ERR("SafeArrayUnaccessData failed with %x\n", hres);
5884 break;
5886 V_ARRAY(&rgvarg[i]) = a;
5887 V_VT(&rgvarg[i]) = rgvt[i];
5889 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
5891 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5892 V_VT(&missing_arg[i]) = V_VT(src_arg);
5893 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
5894 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
5895 V_VT(&rgvarg[i]) = rgvt[i];
5897 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
5899 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
5900 V_VT(&rgvarg[i]) = rgvt[i];
5902 else
5904 /* FIXME: this doesn't work for VT_BYREF arguments if
5905 * they are not the same type as in the paramdesc */
5906 V_VT(&rgvarg[i]) = V_VT(src_arg);
5907 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
5908 V_VT(&rgvarg[i]) = rgvt[i];
5911 if (FAILED(hres))
5913 ERR("failed to convert param %d to %s%s from %s%s\n", i,
5914 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
5915 debugstr_VT(src_arg), debugstr_VF(src_arg));
5916 break;
5918 prgpvarg[i] = &rgvarg[i];
5920 else if (wParamFlags & PARAMFLAG_FOPT)
5922 VARIANTARG *arg;
5923 arg = prgpvarg[i] = &rgvarg[i];
5924 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5926 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
5927 if (FAILED(hres))
5928 break;
5930 else
5932 VARIANTARG *missing_arg;
5933 /* if the function wants a pointer to a variant then
5934 * set that up, otherwise just pass the VT_ERROR in
5935 * the argument by value */
5936 if (rgvt[i] & VT_BYREF)
5938 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
5939 V_VT(arg) = VT_VARIANT | VT_BYREF;
5940 V_VARIANTREF(arg) = missing_arg;
5942 else
5943 missing_arg = arg;
5944 V_VT(missing_arg) = VT_ERROR;
5945 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
5948 else
5950 hres = DISP_E_BADPARAMCOUNT;
5951 break;
5954 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5956 /* VT_VOID is a special case for return types, so it is not
5957 * handled in the general function */
5958 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
5959 V_VT(&varresult) = VT_EMPTY;
5960 else
5962 V_VT(&varresult) = 0;
5963 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
5964 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5967 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
5968 V_VT(&varresult), func_desc->cParams, rgvt,
5969 prgpvarg, &varresult);
5971 for (i = 0; i < func_desc->cParams; i++)
5973 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5974 if (wParamFlags & PARAMFLAG_FRETVAL)
5976 if (TRACE_ON(ole))
5978 TRACE("[retval] value: ");
5979 dump_Variant(prgpvarg[i]);
5982 if (pVarResult)
5984 VariantInit(pVarResult);
5985 /* deref return value */
5986 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
5989 /* free data stored in varresult. Note that
5990 * VariantClear doesn't do what we want because we are
5991 * working with byref types. */
5992 /* FIXME: clear safearrays, bstrs, records and
5993 * variants here too */
5994 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
5995 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
5997 if(*V_UNKNOWNREF(prgpvarg[i]))
5998 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
6000 break;
6002 else if (i < pDispParams->cArgs)
6004 if (wParamFlags & PARAMFLAG_FOUT)
6006 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
6008 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
6009 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6011 if (FAILED(hres))
6013 ERR("failed to convert param %d to vt %d\n", i,
6014 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
6015 break;
6018 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6019 func_desc->cParamsOpt < 0 &&
6020 i == func_desc->cParams-1)
6022 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6023 LONG j, ubound;
6024 VARIANT *v;
6025 hres = SafeArrayGetUBound(a, 1, &ubound);
6026 if (hres != S_OK)
6028 ERR("SafeArrayGetUBound failed with %x\n", hres);
6029 break;
6031 hres = SafeArrayAccessData(a, (LPVOID)&v);
6032 if (hres != S_OK)
6034 ERR("SafeArrayAccessData failed with %x\n", hres);
6035 break;
6037 for (j = 0; j <= ubound; j++)
6038 VariantClear(&v[j]);
6039 hres = SafeArrayUnaccessData(a);
6040 if (hres != S_OK)
6042 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6043 break;
6046 VariantClear(&rgvarg[i]);
6048 else if (wParamFlags & PARAMFLAG_FOPT)
6050 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6051 VariantClear(&rgvarg[i]);
6055 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6057 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6058 hres = DISP_E_EXCEPTION;
6059 if (pExcepInfo)
6061 IErrorInfo *pErrorInfo;
6062 pExcepInfo->scode = V_ERROR(&varresult);
6063 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6065 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6066 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6067 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6068 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6070 IErrorInfo_Release(pErrorInfo);
6074 if (V_VT(&varresult) != VT_ERROR)
6076 TRACE("varresult value: ");
6077 dump_Variant(&varresult);
6079 if (pVarResult)
6081 VariantClear(pVarResult);
6082 *pVarResult = varresult;
6084 else
6085 VariantClear(&varresult);
6088 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6089 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6090 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6091 (pDispParams->cArgs != 0))
6093 if (V_VT(pVarResult) == VT_DISPATCH)
6095 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6096 /* Note: not VariantClear; we still need the dispatch
6097 * pointer to be valid */
6098 VariantInit(pVarResult);
6099 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6100 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6101 pDispParams, pVarResult, pExcepInfo, pArgErr);
6102 IDispatch_Release(pDispatch);
6104 else
6106 VariantClear(pVarResult);
6107 hres = DISP_E_NOTACOLLECTION;
6111 func_fail:
6112 HeapFree(GetProcessHeap(), 0, buffer);
6113 break;
6115 case FUNC_DISPATCH: {
6116 IDispatch *disp;
6118 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6119 if (SUCCEEDED(hres)) {
6120 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6121 hres = IDispatch_Invoke(
6122 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6123 pVarResult,pExcepInfo,pArgErr
6125 if (FAILED(hres))
6126 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6127 IDispatch_Release(disp);
6128 } else
6129 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6130 break;
6132 default:
6133 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6134 hres = E_FAIL;
6135 break;
6138 TRACE("-- 0x%08x\n", hres);
6139 return hres;
6141 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6142 VARDESC *var_desc;
6144 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6145 if(FAILED(hres)) return hres;
6147 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6148 dump_VARDESC(var_desc);
6149 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6150 return E_NOTIMPL;
6153 /* not found, look for it in inherited interfaces */
6154 ITypeInfo2_GetTypeKind(iface, &type_kind);
6155 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6156 if(This->impltypelist) {
6157 /* recursive search */
6158 ITypeInfo *pTInfo;
6159 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6160 if(SUCCEEDED(hres)){
6161 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6162 ITypeInfo_Release(pTInfo);
6163 return hres;
6165 WARN("Could not search inherited interface!\n");
6168 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6169 return DISP_E_MEMBERNOTFOUND;
6172 /* ITypeInfo::GetDocumentation
6174 * Retrieves the documentation string, the complete Help file name and path,
6175 * and the context ID for the Help topic for a specified type description.
6177 * (Can be tested by the Visual Basic Editor in Word for instance.)
6179 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6180 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6181 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6183 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6184 const TLBFuncDesc *pFDesc;
6185 const TLBVarDesc *pVDesc;
6186 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6187 " HelpContext(%p) HelpFile(%p)\n",
6188 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6189 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6190 if(pBstrName)
6191 *pBstrName=SysAllocString(This->Name);
6192 if(pBstrDocString)
6193 *pBstrDocString=SysAllocString(This->DocString);
6194 if(pdwHelpContext)
6195 *pdwHelpContext=This->dwHelpContext;
6196 if(pBstrHelpFile)
6197 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6198 return S_OK;
6199 }else {/* for a member */
6200 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6201 if(pFDesc->funcdesc.memid==memid){
6202 if(pBstrName)
6203 *pBstrName = SysAllocString(pFDesc->Name);
6204 if(pBstrDocString)
6205 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6206 if(pdwHelpContext)
6207 *pdwHelpContext=pFDesc->helpcontext;
6208 return S_OK;
6210 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6211 if(pVDesc->vardesc.memid==memid){
6212 if(pBstrName)
6213 *pBstrName = SysAllocString(pVDesc->Name);
6214 if(pBstrDocString)
6215 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6216 if(pdwHelpContext)
6217 *pdwHelpContext=pVDesc->HelpContext;
6218 return S_OK;
6222 if(This->impltypelist &&
6223 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6224 /* recursive search */
6225 ITypeInfo *pTInfo;
6226 HRESULT result;
6227 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6228 &pTInfo);
6229 if(SUCCEEDED(result)) {
6230 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6231 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6232 ITypeInfo_Release(pTInfo);
6233 return result;
6235 WARN("Could not search inherited interface!\n");
6238 WARN("member %d not found\n", memid);
6239 return TYPE_E_ELEMENTNOTFOUND;
6242 /* ITypeInfo::GetDllEntry
6244 * Retrieves a description or specification of an entry point for a function
6245 * in a DLL.
6247 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6248 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6249 WORD *pwOrdinal)
6251 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6252 const TLBFuncDesc *pFDesc;
6254 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6256 if (pBstrDllName) *pBstrDllName = NULL;
6257 if (pBstrName) *pBstrName = NULL;
6258 if (pwOrdinal) *pwOrdinal = 0;
6260 if (This->TypeAttr.typekind != TKIND_MODULE)
6261 return TYPE_E_BADMODULEKIND;
6263 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6264 if(pFDesc->funcdesc.memid==memid){
6265 dump_TypeInfo(This);
6266 if (TRACE_ON(ole))
6267 dump_TLBFuncDescOne(pFDesc);
6269 if (pBstrDllName)
6270 *pBstrDllName = SysAllocString(This->DllName);
6272 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6273 if (pBstrName)
6274 *pBstrName = SysAllocString(pFDesc->Entry);
6275 if (pwOrdinal)
6276 *pwOrdinal = -1;
6277 return S_OK;
6279 if (pBstrName)
6280 *pBstrName = NULL;
6281 if (pwOrdinal)
6282 *pwOrdinal = (DWORD)pFDesc->Entry;
6283 return S_OK;
6285 return TYPE_E_ELEMENTNOTFOUND;
6288 /* internal function to make the inherited interfaces' methods appear
6289 * part of the interface */
6290 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6291 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6293 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6294 HRESULT hr;
6296 TRACE("%p, 0x%x\n", iface, *hRefType);
6298 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK))
6300 ITypeInfo *pSubTypeInfo;
6302 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
6303 if (FAILED(hr))
6304 return hr;
6306 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6307 hRefType, ppTInfo);
6308 ITypeInfo_Release(pSubTypeInfo);
6309 if (SUCCEEDED(hr))
6310 return hr;
6312 *hRefType -= DISPATCH_HREF_OFFSET;
6314 if (!(*hRefType & DISPATCH_HREF_MASK))
6315 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6316 else
6317 return E_FAIL;
6320 /* ITypeInfo::GetRefTypeInfo
6322 * If a type description references other type descriptions, it retrieves
6323 * the referenced type descriptions.
6325 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6326 ITypeInfo2 *iface,
6327 HREFTYPE hRefType,
6328 ITypeInfo **ppTInfo)
6330 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6331 HRESULT result = E_FAIL;
6333 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6335 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6336 ITypeInfo_AddRef(*ppTInfo);
6337 result = S_OK;
6339 else if (hRefType == -1 &&
6340 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6341 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6343 /* when we meet a DUAL dispinterface, we must create the interface
6344 * version of it.
6346 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
6349 /* the interface version contains the same information as the dispinterface
6350 * copy the contents of the structs.
6352 *pTypeInfoImpl = *This;
6353 pTypeInfoImpl->ref = 0;
6355 /* change the type to interface */
6356 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6358 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6360 /* we use data structures from This, so we need to keep a reference
6361 * to it to stop it being destroyed and signal to the new instance to
6362 * not free its data structures when it is destroyed */
6363 pTypeInfoImpl->no_free_data = TRUE;
6364 pTypeInfoImpl->next = This;
6365 ITypeInfo_AddRef((ITypeInfo*) This);
6367 ITypeInfo_AddRef(*ppTInfo);
6369 result = S_OK;
6371 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6372 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6373 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6375 HREFTYPE href_dispatch = hRefType;
6376 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6377 } else {
6378 TLBRefType *ref_type;
6379 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6381 if(ref_type->reference == hRefType)
6382 break;
6384 if(&ref_type->entry == &This->pTypeLib->ref_list)
6386 FIXME("Can't find pRefType for ref %x\n", hRefType);
6387 goto end;
6389 if(hRefType != -1) {
6390 ITypeLib *pTLib = NULL;
6392 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6393 UINT Index;
6394 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6395 } else {
6396 if(ref_type->pImpTLInfo->pImpTypeLib) {
6397 TRACE("typeinfo in imported typelib that is already loaded\n");
6398 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6399 ITypeLib2_AddRef(pTLib);
6400 result = S_OK;
6401 } else {
6402 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6403 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6404 ref_type->pImpTLInfo->wVersionMajor,
6405 ref_type->pImpTLInfo->wVersionMinor,
6406 ref_type->pImpTLInfo->lcid,
6407 &pTLib);
6409 if(!SUCCEEDED(result)) {
6410 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6411 result=LoadTypeLib(libnam, &pTLib);
6412 SysFreeString(libnam);
6414 if(SUCCEEDED(result)) {
6415 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6416 ITypeLib2_AddRef(pTLib);
6420 if(SUCCEEDED(result)) {
6421 if(ref_type->index == TLB_REF_USE_GUID)
6422 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6423 &ref_type->guid,
6424 ppTInfo);
6425 else
6426 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6427 ppTInfo);
6429 if (pTLib != NULL)
6430 ITypeLib2_Release(pTLib);
6434 end:
6435 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6436 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6437 return result;
6440 /* ITypeInfo::AddressOfMember
6442 * Retrieves the addresses of static functions or variables, such as those
6443 * defined in a DLL.
6445 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6446 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6448 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6449 HRESULT hr;
6450 BSTR dll, entry;
6451 WORD ordinal;
6452 HMODULE module;
6454 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6456 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6457 if (FAILED(hr))
6458 return hr;
6460 module = LoadLibraryW(dll);
6461 if (!module)
6463 ERR("couldn't load %s\n", debugstr_w(dll));
6464 SysFreeString(dll);
6465 if (entry) SysFreeString(entry);
6466 return STG_E_FILENOTFOUND;
6468 /* FIXME: store library somewhere where we can free it */
6470 if (entry)
6472 LPSTR entryA;
6473 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6474 entryA = HeapAlloc(GetProcessHeap(), 0, len);
6475 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6477 *ppv = GetProcAddress(module, entryA);
6478 if (!*ppv)
6479 ERR("function not found %s\n", debugstr_a(entryA));
6481 HeapFree(GetProcessHeap(), 0, entryA);
6483 else
6485 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6486 if (!*ppv)
6487 ERR("function not found %d\n", ordinal);
6490 SysFreeString(dll);
6491 if (entry) SysFreeString(entry);
6493 if (!*ppv)
6494 return TYPE_E_DLLFUNCTIONNOTFOUND;
6496 return S_OK;
6499 /* ITypeInfo::CreateInstance
6501 * Creates a new instance of a type that describes a component object class
6502 * (coclass).
6504 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6505 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6507 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6508 HRESULT hr;
6509 TYPEATTR *pTA;
6511 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6513 *ppvObj = NULL;
6515 if(pOuterUnk)
6517 WARN("Not able to aggregate\n");
6518 return CLASS_E_NOAGGREGATION;
6521 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6522 if(FAILED(hr)) return hr;
6524 if(pTA->typekind != TKIND_COCLASS)
6526 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6527 hr = E_INVALIDARG;
6528 goto end;
6531 hr = S_FALSE;
6532 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6534 IUnknown *pUnk;
6535 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6536 TRACE("GetActiveObject rets %08x\n", hr);
6537 if(hr == S_OK)
6539 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6540 IUnknown_Release(pUnk);
6544 if(hr != S_OK)
6545 hr = CoCreateInstance(&pTA->guid, NULL,
6546 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6547 riid, ppvObj);
6549 end:
6550 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6551 return hr;
6554 /* ITypeInfo::GetMops
6556 * Retrieves marshalling information.
6558 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6559 BSTR *pBstrMops)
6561 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6562 FIXME("(%p) stub!\n", This);
6563 return S_OK;
6566 /* ITypeInfo::GetContainingTypeLib
6568 * Retrieves the containing type library and the index of the type description
6569 * within that type library.
6571 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6572 ITypeLib * *ppTLib, UINT *pIndex)
6574 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6576 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6577 if (pIndex) {
6578 *pIndex=This->index;
6579 TRACE("returning pIndex=%d\n", *pIndex);
6582 if (ppTLib) {
6583 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6584 ITypeLib2_AddRef(*ppTLib);
6585 TRACE("returning ppTLib=%p\n", *ppTLib);
6588 return S_OK;
6591 /* ITypeInfo::ReleaseTypeAttr
6593 * Releases a TYPEATTR previously returned by GetTypeAttr.
6596 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6597 TYPEATTR* pTypeAttr)
6599 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6600 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6601 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6604 /* ITypeInfo::ReleaseFuncDesc
6606 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6608 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6609 ITypeInfo2 *iface,
6610 FUNCDESC *pFuncDesc)
6612 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6613 SHORT i;
6615 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6617 for (i = 0; i < pFuncDesc->cParams; i++)
6618 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6619 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6621 SysFreeString((BSTR)pFuncDesc);
6624 /* ITypeInfo::ReleaseVarDesc
6626 * Releases a VARDESC previously returned by GetVarDesc.
6628 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6629 VARDESC *pVarDesc)
6631 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6632 TRACE("(%p)->(%p)\n", This, pVarDesc);
6634 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6635 if (pVarDesc->varkind == VAR_CONST)
6636 VariantClear(pVarDesc->u.lpvarValue);
6637 SysFreeString((BSTR)pVarDesc);
6640 /* ITypeInfo2::GetTypeKind
6642 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6645 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6646 TYPEKIND *pTypeKind)
6648 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6649 *pTypeKind=This->TypeAttr.typekind;
6650 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6651 return S_OK;
6654 /* ITypeInfo2::GetTypeFlags
6656 * Returns the type flags without any allocations. This returns a DWORD type
6657 * flag, which expands the type flags without growing the TYPEATTR (type
6658 * attribute).
6661 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6663 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6664 *pTypeFlags=This->TypeAttr.wTypeFlags;
6665 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6666 return S_OK;
6669 /* ITypeInfo2::GetFuncIndexOfMemId
6670 * Binds to a specific member based on a known DISPID, where the member name
6671 * is not known (for example, when binding to a default member).
6674 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
6675 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
6677 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6678 const TLBFuncDesc *pFuncInfo;
6679 int i;
6680 HRESULT result;
6682 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
6683 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
6684 break;
6685 if(pFuncInfo) {
6686 *pFuncIndex = i;
6687 result = S_OK;
6688 } else
6689 result = TYPE_E_ELEMENTNOTFOUND;
6691 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
6692 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6693 return result;
6696 /* TypeInfo2::GetVarIndexOfMemId
6698 * Binds to a specific member based on a known DISPID, where the member name
6699 * is not known (for example, when binding to a default member).
6702 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
6703 MEMBERID memid, UINT *pVarIndex)
6705 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6706 TLBVarDesc *pVarInfo;
6707 int i;
6708 HRESULT result;
6709 for(i=0, pVarInfo=This->varlist; pVarInfo &&
6710 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
6712 if(pVarInfo) {
6713 *pVarIndex = i;
6714 result = S_OK;
6715 } else
6716 result = TYPE_E_ELEMENTNOTFOUND;
6718 TRACE("(%p) memid 0x%08x -> %s\n", This,
6719 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6720 return result;
6723 /* ITypeInfo2::GetCustData
6725 * Gets the custom data
6727 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
6728 ITypeInfo2 * iface,
6729 REFGUID guid,
6730 VARIANT *pVarVal)
6732 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6733 TLBCustData *pCData;
6735 for(pCData=This->pCustData; pCData; pCData = pCData->next)
6736 if( IsEqualIID(guid, &pCData->guid)) break;
6738 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6740 if(pCData)
6742 VariantInit( pVarVal);
6743 VariantCopy( pVarVal, &pCData->data);
6744 return S_OK;
6746 return E_INVALIDARG; /* FIXME: correct? */
6749 /* ITypeInfo2::GetFuncCustData
6751 * Gets the custom data
6753 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
6754 ITypeInfo2 * iface,
6755 UINT index,
6756 REFGUID guid,
6757 VARIANT *pVarVal)
6759 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6760 TLBCustData *pCData=NULL;
6761 TLBFuncDesc * pFDesc;
6762 int i;
6763 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6764 pFDesc=pFDesc->next);
6766 if(pFDesc)
6767 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
6768 if( IsEqualIID(guid, &pCData->guid)) break;
6770 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6772 if(pCData){
6773 VariantInit( pVarVal);
6774 VariantCopy( pVarVal, &pCData->data);
6775 return S_OK;
6777 return E_INVALIDARG; /* FIXME: correct? */
6780 /* ITypeInfo2::GetParamCustData
6782 * Gets the custom data
6784 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
6785 ITypeInfo2 * iface,
6786 UINT indexFunc,
6787 UINT indexParam,
6788 REFGUID guid,
6789 VARIANT *pVarVal)
6791 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6792 TLBCustData *pCData=NULL;
6793 TLBFuncDesc * pFDesc;
6794 int i;
6796 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
6798 if(pFDesc && indexParam<pFDesc->funcdesc.cParams)
6799 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
6800 pCData = pCData->next)
6801 if( IsEqualIID(guid, &pCData->guid)) break;
6803 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6805 if(pCData)
6807 VariantInit( pVarVal);
6808 VariantCopy( pVarVal, &pCData->data);
6809 return S_OK;
6811 return E_INVALIDARG; /* FIXME: correct? */
6814 /* ITypeInfo2::GetVarCustData
6816 * Gets the custom data
6818 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
6819 ITypeInfo2 * iface,
6820 UINT index,
6821 REFGUID guid,
6822 VARIANT *pVarVal)
6824 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6825 TLBCustData *pCData=NULL;
6826 TLBVarDesc * pVDesc;
6827 int i;
6829 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
6831 if(pVDesc)
6833 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
6835 if( IsEqualIID(guid, &pCData->guid)) break;
6839 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6841 if(pCData)
6843 VariantInit( pVarVal);
6844 VariantCopy( pVarVal, &pCData->data);
6845 return S_OK;
6847 return E_INVALIDARG; /* FIXME: correct? */
6850 /* ITypeInfo2::GetImplCustData
6852 * Gets the custom data
6854 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6855 ITypeInfo2 * iface,
6856 UINT index,
6857 REFGUID guid,
6858 VARIANT *pVarVal)
6860 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6861 TLBCustData *pCData=NULL;
6862 TLBImplType * pRDesc;
6863 int i;
6865 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6867 if(pRDesc)
6869 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6871 if( IsEqualIID(guid, &pCData->guid)) break;
6875 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6877 if(pCData)
6879 VariantInit( pVarVal);
6880 VariantCopy( pVarVal, &pCData->data);
6881 return S_OK;
6883 return E_INVALIDARG; /* FIXME: correct? */
6886 /* ITypeInfo2::GetDocumentation2
6888 * Retrieves the documentation string, the complete Help file name and path,
6889 * the localization context to use, and the context ID for the library Help
6890 * topic in the Help file.
6893 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6894 ITypeInfo2 * iface,
6895 MEMBERID memid,
6896 LCID lcid,
6897 BSTR *pbstrHelpString,
6898 DWORD *pdwHelpStringContext,
6899 BSTR *pbstrHelpStringDll)
6901 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6902 const TLBFuncDesc *pFDesc;
6903 const TLBVarDesc *pVDesc;
6904 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
6905 "HelpStringContext(%p) HelpStringDll(%p)\n",
6906 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6907 pbstrHelpStringDll );
6908 /* the help string should be obtained from the helpstringdll,
6909 * using the _DLLGetDocumentation function, based on the supplied
6910 * lcid. Nice to do sometime...
6912 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6913 if(pbstrHelpString)
6914 *pbstrHelpString=SysAllocString(This->Name);
6915 if(pdwHelpStringContext)
6916 *pdwHelpStringContext=This->dwHelpStringContext;
6917 if(pbstrHelpStringDll)
6918 *pbstrHelpStringDll=
6919 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6920 return S_OK;
6921 }else {/* for a member */
6922 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6923 if(pFDesc->funcdesc.memid==memid){
6924 if(pbstrHelpString)
6925 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6926 if(pdwHelpStringContext)
6927 *pdwHelpStringContext=pFDesc->HelpStringContext;
6928 if(pbstrHelpStringDll)
6929 *pbstrHelpStringDll=
6930 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6931 return S_OK;
6933 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6934 if(pVDesc->vardesc.memid==memid){
6935 if(pbstrHelpString)
6936 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6937 if(pdwHelpStringContext)
6938 *pdwHelpStringContext=pVDesc->HelpStringContext;
6939 if(pbstrHelpStringDll)
6940 *pbstrHelpStringDll=
6941 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6942 return S_OK;
6945 return TYPE_E_ELEMENTNOTFOUND;
6948 /* ITypeInfo2::GetAllCustData
6950 * Gets all custom data items for the Type info.
6953 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6954 ITypeInfo2 * iface,
6955 CUSTDATA *pCustData)
6957 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6958 TLBCustData *pCData;
6959 int i;
6961 TRACE("(%p) returning %d items\n", This, This->ctCustData);
6963 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6964 if(pCustData->prgCustData ){
6965 pCustData->cCustData=This->ctCustData;
6966 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
6967 pCustData->prgCustData[i].guid=pCData->guid;
6968 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
6970 }else{
6971 ERR(" OUT OF MEMORY!\n");
6972 return E_OUTOFMEMORY;
6974 return S_OK;
6977 /* ITypeInfo2::GetAllFuncCustData
6979 * Gets all custom data items for the specified Function
6982 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
6983 ITypeInfo2 * iface,
6984 UINT index,
6985 CUSTDATA *pCustData)
6987 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6988 TLBCustData *pCData;
6989 TLBFuncDesc * pFDesc;
6990 int i;
6991 TRACE("(%p) index %d\n", This, index);
6992 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6993 pFDesc=pFDesc->next)
6995 if(pFDesc){
6996 pCustData->prgCustData =
6997 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
6998 if(pCustData->prgCustData ){
6999 pCustData->cCustData=pFDesc->ctCustData;
7000 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
7001 pCData = pCData->next){
7002 pCustData->prgCustData[i].guid=pCData->guid;
7003 VariantCopy(& pCustData->prgCustData[i].varValue,
7004 & pCData->data);
7006 }else{
7007 ERR(" OUT OF MEMORY!\n");
7008 return E_OUTOFMEMORY;
7010 return S_OK;
7012 return TYPE_E_ELEMENTNOTFOUND;
7015 /* ITypeInfo2::GetAllParamCustData
7017 * Gets all custom data items for the Functions
7020 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7021 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7023 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7024 TLBCustData *pCData=NULL;
7025 TLBFuncDesc * pFDesc;
7026 int i;
7027 TRACE("(%p) index %d\n", This, indexFunc);
7028 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
7029 pFDesc=pFDesc->next)
7031 if(pFDesc && indexParam<pFDesc->funcdesc.cParams){
7032 pCustData->prgCustData =
7033 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
7034 sizeof(CUSTDATAITEM));
7035 if(pCustData->prgCustData ){
7036 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
7037 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
7038 pCData; i++, pCData = pCData->next){
7039 pCustData->prgCustData[i].guid=pCData->guid;
7040 VariantCopy(& pCustData->prgCustData[i].varValue,
7041 & pCData->data);
7043 }else{
7044 ERR(" OUT OF MEMORY!\n");
7045 return E_OUTOFMEMORY;
7047 return S_OK;
7049 return TYPE_E_ELEMENTNOTFOUND;
7052 /* ITypeInfo2::GetAllVarCustData
7054 * Gets all custom data items for the specified Variable
7057 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7058 UINT index, CUSTDATA *pCustData)
7060 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7061 TLBCustData *pCData;
7062 TLBVarDesc * pVDesc;
7063 int i;
7064 TRACE("(%p) index %d\n", This, index);
7065 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
7066 pVDesc=pVDesc->next)
7068 if(pVDesc){
7069 pCustData->prgCustData =
7070 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
7071 if(pCustData->prgCustData ){
7072 pCustData->cCustData=pVDesc->ctCustData;
7073 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
7074 pCData = pCData->next){
7075 pCustData->prgCustData[i].guid=pCData->guid;
7076 VariantCopy(& pCustData->prgCustData[i].varValue,
7077 & pCData->data);
7079 }else{
7080 ERR(" OUT OF MEMORY!\n");
7081 return E_OUTOFMEMORY;
7083 return S_OK;
7085 return TYPE_E_ELEMENTNOTFOUND;
7088 /* ITypeInfo2::GetAllImplCustData
7090 * Gets all custom data items for the specified implementation type
7093 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7094 ITypeInfo2 * iface,
7095 UINT index,
7096 CUSTDATA *pCustData)
7098 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7099 TLBCustData *pCData;
7100 TLBImplType * pRDesc;
7101 int i;
7102 TRACE("(%p) index %d\n", This, index);
7103 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
7104 pRDesc=pRDesc->next)
7106 if(pRDesc){
7107 pCustData->prgCustData =
7108 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
7109 if(pCustData->prgCustData ){
7110 pCustData->cCustData=pRDesc->ctCustData;
7111 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
7112 pCData = pCData->next){
7113 pCustData->prgCustData[i].guid=pCData->guid;
7114 VariantCopy(& pCustData->prgCustData[i].varValue,
7115 & pCData->data);
7117 }else{
7118 ERR(" OUT OF MEMORY!\n");
7119 return E_OUTOFMEMORY;
7121 return S_OK;
7123 return TYPE_E_ELEMENTNOTFOUND;
7126 static const ITypeInfo2Vtbl tinfvt =
7129 ITypeInfo_fnQueryInterface,
7130 ITypeInfo_fnAddRef,
7131 ITypeInfo_fnRelease,
7133 ITypeInfo_fnGetTypeAttr,
7134 ITypeInfo_fnGetTypeComp,
7135 ITypeInfo_fnGetFuncDesc,
7136 ITypeInfo_fnGetVarDesc,
7137 ITypeInfo_fnGetNames,
7138 ITypeInfo_fnGetRefTypeOfImplType,
7139 ITypeInfo_fnGetImplTypeFlags,
7140 ITypeInfo_fnGetIDsOfNames,
7141 ITypeInfo_fnInvoke,
7142 ITypeInfo_fnGetDocumentation,
7143 ITypeInfo_fnGetDllEntry,
7144 ITypeInfo_fnGetRefTypeInfo,
7145 ITypeInfo_fnAddressOfMember,
7146 ITypeInfo_fnCreateInstance,
7147 ITypeInfo_fnGetMops,
7148 ITypeInfo_fnGetContainingTypeLib,
7149 ITypeInfo_fnReleaseTypeAttr,
7150 ITypeInfo_fnReleaseFuncDesc,
7151 ITypeInfo_fnReleaseVarDesc,
7153 ITypeInfo2_fnGetTypeKind,
7154 ITypeInfo2_fnGetTypeFlags,
7155 ITypeInfo2_fnGetFuncIndexOfMemId,
7156 ITypeInfo2_fnGetVarIndexOfMemId,
7157 ITypeInfo2_fnGetCustData,
7158 ITypeInfo2_fnGetFuncCustData,
7159 ITypeInfo2_fnGetParamCustData,
7160 ITypeInfo2_fnGetVarCustData,
7161 ITypeInfo2_fnGetImplTypeCustData,
7162 ITypeInfo2_fnGetDocumentation2,
7163 ITypeInfo2_fnGetAllCustData,
7164 ITypeInfo2_fnGetAllFuncCustData,
7165 ITypeInfo2_fnGetAllParamCustData,
7166 ITypeInfo2_fnGetAllVarCustData,
7167 ITypeInfo2_fnGetAllImplTypeCustData,
7170 /******************************************************************************
7171 * CreateDispTypeInfo [OLEAUT32.31]
7173 * Build type information for an object so it can be called through an
7174 * IDispatch interface.
7176 * RETURNS
7177 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7178 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7180 * NOTES
7181 * This call allows an objects methods to be accessed through IDispatch, by
7182 * building an ITypeInfo object that IDispatch can use to call through.
7184 HRESULT WINAPI CreateDispTypeInfo(
7185 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7186 LCID lcid, /* [I] Locale Id */
7187 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7189 ITypeInfoImpl *pTIClass, *pTIIface;
7190 ITypeLibImpl *pTypeLibImpl;
7191 int param, func;
7192 TLBFuncDesc **ppFuncDesc;
7193 TLBRefType *ref;
7195 TRACE("\n");
7196 pTypeLibImpl = TypeLibImpl_Constructor();
7197 if (!pTypeLibImpl) return E_FAIL;
7199 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
7200 pTIIface->pTypeLib = pTypeLibImpl;
7201 pTIIface->index = 0;
7202 pTIIface->Name = NULL;
7203 pTIIface->dwHelpContext = -1;
7204 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7205 pTIIface->TypeAttr.lcid = lcid;
7206 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7207 pTIIface->TypeAttr.wMajorVerNum = 0;
7208 pTIIface->TypeAttr.wMinorVerNum = 0;
7209 pTIIface->TypeAttr.cbAlignment = 2;
7210 pTIIface->TypeAttr.cbSizeInstance = -1;
7211 pTIIface->TypeAttr.cbSizeVft = -1;
7212 pTIIface->TypeAttr.cFuncs = 0;
7213 pTIIface->TypeAttr.cImplTypes = 0;
7214 pTIIface->TypeAttr.cVars = 0;
7215 pTIIface->TypeAttr.wTypeFlags = 0;
7217 ppFuncDesc = &pTIIface->funclist;
7218 for(func = 0; func < pidata->cMembers; func++) {
7219 METHODDATA *md = pidata->pmethdata + func;
7220 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
7221 (*ppFuncDesc)->Name = SysAllocString(md->szName);
7222 (*ppFuncDesc)->funcdesc.memid = md->dispid;
7223 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
7224 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
7225 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
7226 (*ppFuncDesc)->funcdesc.callconv = md->cc;
7227 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
7228 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
7229 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
7230 (*ppFuncDesc)->funcdesc.cScodes = 0;
7231 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
7232 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7233 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7234 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7235 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7236 md->cArgs * sizeof(ELEMDESC));
7237 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7238 md->cArgs * sizeof(TLBParDesc));
7239 for(param = 0; param < md->cArgs; param++) {
7240 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7241 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7243 (*ppFuncDesc)->helpcontext = 0;
7244 (*ppFuncDesc)->HelpStringContext = 0;
7245 (*ppFuncDesc)->HelpString = NULL;
7246 (*ppFuncDesc)->Entry = NULL;
7247 (*ppFuncDesc)->ctCustData = 0;
7248 (*ppFuncDesc)->pCustData = NULL;
7249 (*ppFuncDesc)->next = NULL;
7250 pTIIface->TypeAttr.cFuncs++;
7251 ppFuncDesc = &(*ppFuncDesc)->next;
7254 dump_TypeInfo(pTIIface);
7256 pTypeLibImpl->pTypeInfo = pTIIface;
7257 pTypeLibImpl->TypeInfoCount++;
7259 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
7260 pTIClass->pTypeLib = pTypeLibImpl;
7261 pTIClass->index = 1;
7262 pTIClass->Name = NULL;
7263 pTIClass->dwHelpContext = -1;
7264 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7265 pTIClass->TypeAttr.lcid = lcid;
7266 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7267 pTIClass->TypeAttr.wMajorVerNum = 0;
7268 pTIClass->TypeAttr.wMinorVerNum = 0;
7269 pTIClass->TypeAttr.cbAlignment = 2;
7270 pTIClass->TypeAttr.cbSizeInstance = -1;
7271 pTIClass->TypeAttr.cbSizeVft = -1;
7272 pTIClass->TypeAttr.cFuncs = 0;
7273 pTIClass->TypeAttr.cImplTypes = 1;
7274 pTIClass->TypeAttr.cVars = 0;
7275 pTIClass->TypeAttr.wTypeFlags = 0;
7277 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
7278 pTIClass->impltypelist->hRef = 0;
7280 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
7281 ref->index = 0;
7282 ref->reference = 0;
7283 ref->pImpTLInfo = TLB_REF_INTERNAL;
7284 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7286 dump_TypeInfo(pTIClass);
7288 pTIIface->next = pTIClass;
7289 pTypeLibImpl->TypeInfoCount++;
7291 *pptinfo = (ITypeInfo*)pTIClass;
7293 ITypeInfo_AddRef(*pptinfo);
7294 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7296 return S_OK;
7300 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7302 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7304 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7307 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7309 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7311 return ITypeInfo_AddRef((ITypeInfo *)This);
7314 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7316 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7318 return ITypeInfo_Release((ITypeInfo *)This);
7321 static HRESULT WINAPI ITypeComp_fnBind(
7322 ITypeComp * iface,
7323 OLECHAR * szName,
7324 ULONG lHash,
7325 WORD wFlags,
7326 ITypeInfo ** ppTInfo,
7327 DESCKIND * pDescKind,
7328 BINDPTR * pBindPtr)
7330 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7331 const TLBFuncDesc *pFDesc;
7332 const TLBVarDesc *pVDesc;
7333 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7335 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7337 *pDescKind = DESCKIND_NONE;
7338 pBindPtr->lpfuncdesc = NULL;
7339 *ppTInfo = NULL;
7341 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
7342 if (!strcmpiW(pFDesc->Name, szName)) {
7343 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7344 break;
7345 else
7346 /* name found, but wrong flags */
7347 hr = TYPE_E_TYPEMISMATCH;
7350 if (pFDesc)
7352 HRESULT hr = TLB_AllocAndInitFuncDesc(
7353 &pFDesc->funcdesc,
7354 &pBindPtr->lpfuncdesc,
7355 This->TypeAttr.typekind == TKIND_DISPATCH);
7356 if (FAILED(hr))
7357 return hr;
7358 *pDescKind = DESCKIND_FUNCDESC;
7359 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7360 ITypeInfo_AddRef(*ppTInfo);
7361 return S_OK;
7362 } else {
7363 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7364 if (!strcmpiW(pVDesc->Name, szName)) {
7365 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7366 if (FAILED(hr))
7367 return hr;
7368 *pDescKind = DESCKIND_VARDESC;
7369 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7370 ITypeInfo_AddRef(*ppTInfo);
7371 return S_OK;
7375 /* FIXME: search each inherited interface, not just the first */
7376 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7377 /* recursive search */
7378 ITypeInfo *pTInfo;
7379 ITypeComp *pTComp;
7380 HRESULT hr;
7381 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7382 if (SUCCEEDED(hr))
7384 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7385 ITypeInfo_Release(pTInfo);
7387 if (SUCCEEDED(hr))
7389 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7390 ITypeComp_Release(pTComp);
7391 return hr;
7393 WARN("Could not search inherited interface!\n");
7395 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
7396 return hr;
7399 static HRESULT WINAPI ITypeComp_fnBindType(
7400 ITypeComp * iface,
7401 OLECHAR * szName,
7402 ULONG lHash,
7403 ITypeInfo ** ppTInfo,
7404 ITypeComp ** ppTComp)
7406 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7408 /* strange behaviour (does nothing) but like the
7409 * original */
7411 if (!ppTInfo || !ppTComp)
7412 return E_POINTER;
7414 *ppTInfo = NULL;
7415 *ppTComp = NULL;
7417 return S_OK;
7420 static const ITypeCompVtbl tcompvt =
7423 ITypeComp_fnQueryInterface,
7424 ITypeComp_fnAddRef,
7425 ITypeComp_fnRelease,
7427 ITypeComp_fnBind,
7428 ITypeComp_fnBindType