push 6495605bb529da27066f1c178d57d902552737a0
[wine/hacks.git] / dlls / oleaut32 / typelib.c
blobd7139d23aa6d895765e2681649752cce5d069d07
1 /*
2 * TYPELIB
4 * Copyright 1997 Marcus Meissner
5 * 1999 Rein Klazes
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 2005 Robert Shearman, for CodeWeavers
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 * --------------------------------------------------------------------------------------
25 * Known problems (2000, Francois Jacques)
27 * - Tested using OLEVIEW (Platform SDK tool) only.
29 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
30 * creating by doing a straight copy of the dispinterface instance and just changing
31 * its typekind. Pointed structures aren't copied - only the address of the pointers.
33 * - locale stuff is partially implemented but hasn't been tested.
35 * - typelib file is still read in its entirety, but it is released now.
37 * --------------------------------------------------------------------------------------
38 * Known problems left from previous implementation (1999, Rein Klazes) :
40 * -. Data structures are straightforward, but slow for look-ups.
41 * -. (related) nothing is hashed
42 * -. Most error return values are just guessed not checked with windows
43 * behaviour.
44 * -. lousy fatal error handling
48 #include "config.h"
49 #include "wine/port.h"
51 #include <stdlib.h>
52 #include <string.h>
53 #include <stdarg.h>
54 #include <stdio.h>
55 #include <ctype.h>
57 #define COBJMACROS
58 #define NONAMELESSUNION
59 #define NONAMELESSSTRUCT
61 #include "winerror.h"
62 #include "windef.h"
63 #include "winbase.h"
64 #include "winnls.h"
65 #include "winreg.h"
66 #include "winuser.h"
68 #include "wine/unicode.h"
69 #include "objbase.h"
70 #include "typelib.h"
71 #include "wine/debug.h"
72 #include "variant.h"
73 #include "wine/list.h"
75 WINE_DEFAULT_DEBUG_CHANNEL(ole);
76 WINE_DECLARE_DEBUG_CHANNEL(typelib);
78 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
79 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
81 /****************************************************************************
82 * FromLExxx
84 * Takes p_iVal (which is in little endian) and returns it
85 * in the host machine's byte order.
87 #ifdef WORDS_BIGENDIAN
88 static WORD FromLEWord(WORD p_iVal)
90 return (((p_iVal & 0x00FF) << 8) |
91 ((p_iVal & 0xFF00) >> 8));
95 static DWORD FromLEDWord(DWORD p_iVal)
97 return (((p_iVal & 0x000000FF) << 24) |
98 ((p_iVal & 0x0000FF00) << 8) |
99 ((p_iVal & 0x00FF0000) >> 8) |
100 ((p_iVal & 0xFF000000) >> 24));
102 #else
103 #define FromLEWord(X) (X)
104 #define FromLEDWord(X) (X)
105 #endif
107 #define DISPATCH_HREF_OFFSET 0x01000000
108 #define DISPATCH_HREF_MASK 0xff000000
110 /****************************************************************************
111 * FromLExxx
113 * Fix byte order in any structure if necessary
115 #ifdef WORDS_BIGENDIAN
116 static void FromLEWords(void *p_Val, int p_iSize)
118 WORD *Val = p_Val;
120 p_iSize /= sizeof(WORD);
122 while (p_iSize) {
123 *Val = FromLEWord(*Val);
124 Val++;
125 p_iSize--;
130 static void FromLEDWords(void *p_Val, int p_iSize)
132 DWORD *Val = p_Val;
134 p_iSize /= sizeof(DWORD);
136 while (p_iSize) {
137 *Val = FromLEDWord(*Val);
138 Val++;
139 p_iSize--;
142 #else
143 #define FromLEWords(X,Y) /*nothing*/
144 #define FromLEDWords(X,Y) /*nothing*/
145 #endif
148 * Find a typelib key which matches a requested maj.min version.
150 static BOOL find_typelib_key( REFGUID guid, WORD wMaj, WORD *wMin )
152 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
153 WCHAR buffer[60];
154 char key_name[16];
155 DWORD len, i;
156 INT best_min = -1;
157 HKEY hkey;
159 memcpy( buffer, typelibW, sizeof(typelibW) );
160 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
162 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
163 return FALSE;
165 len = sizeof(key_name);
166 i = 0;
167 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
169 INT v_maj, v_min;
171 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
173 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
175 if (wMaj == v_maj)
177 if (*wMin == v_min)
179 best_min = v_min;
180 break; /* exact match */
182 if (v_min > best_min) best_min = v_min;
185 len = sizeof(key_name);
187 RegCloseKey( hkey );
188 if (best_min >= 0)
190 *wMin = best_min;
191 return TRUE;
193 return FALSE;
196 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
197 /* buffer must be at least 60 characters long */
198 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
200 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
201 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
203 memcpy( buffer, TypelibW, sizeof(TypelibW) );
204 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
205 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
206 return buffer;
209 /* get the path of an interface key, in the form "Interface\\<guid>" */
210 /* buffer must be at least 50 characters long */
211 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
213 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
215 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
216 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
217 return buffer;
220 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
221 /* buffer must be at least 16 characters long */
222 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
224 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
225 static const WCHAR win16W[] = {'w','i','n','1','6',0};
226 static const WCHAR win32W[] = {'w','i','n','3','2',0};
228 sprintfW( buffer, LcidFormatW, lcid );
229 switch(syskind)
231 case SYS_WIN16: strcatW( buffer, win16W ); break;
232 case SYS_WIN32: strcatW( buffer, win32W ); break;
233 default:
234 TRACE("Typelib is for unsupported syskind %i\n", syskind);
235 return NULL;
237 return buffer;
240 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
243 /****************************************************************************
244 * QueryPathOfRegTypeLib [OLEAUT32.164]
246 * Gets the path to a registered type library.
248 * PARAMS
249 * guid [I] referenced guid
250 * wMaj [I] major version
251 * wMin [I] minor version
252 * lcid [I] locale id
253 * path [O] path of typelib
255 * RETURNS
256 * Success: S_OK.
257 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
258 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
259 * opened.
261 HRESULT WINAPI QueryPathOfRegTypeLib(
262 REFGUID guid,
263 WORD wMaj,
264 WORD wMin,
265 LCID lcid,
266 LPBSTR path )
268 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
269 LCID myLCID = lcid;
270 HKEY hkey;
271 WCHAR buffer[60];
272 WCHAR Path[MAX_PATH];
273 LONG res;
275 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
277 if (!find_typelib_key( guid, wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
278 get_typelib_key( guid, wMaj, wMin, buffer );
280 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
281 if (res == ERROR_FILE_NOT_FOUND)
283 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
284 return TYPE_E_LIBNOTREGISTERED;
286 else if (res != ERROR_SUCCESS)
288 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
289 return TYPE_E_REGISTRYACCESS;
292 while (hr != S_OK)
294 LONG dwPathLen = sizeof(Path);
296 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
298 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
300 if (!lcid)
301 break;
302 else if (myLCID == lcid)
304 /* try with sub-langid */
305 myLCID = SUBLANGID(lcid);
307 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
309 /* try with system langid */
310 myLCID = 0;
312 else
314 break;
317 else
319 *path = SysAllocString( Path );
320 hr = S_OK;
323 RegCloseKey( hkey );
324 TRACE_(typelib)("-- 0x%08x\n", hr);
325 return hr;
328 /******************************************************************************
329 * CreateTypeLib [OLEAUT32.160] creates a typelib
331 * RETURNS
332 * Success: S_OK
333 * Failure: Status
335 HRESULT WINAPI CreateTypeLib(
336 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
338 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
339 return E_FAIL;
342 /******************************************************************************
343 * LoadTypeLib [OLEAUT32.161]
345 * Loads a type library
347 * PARAMS
348 * szFile [I] Name of file to load from.
349 * pptLib [O] Pointer that receives ITypeLib object on success.
351 * RETURNS
352 * Success: S_OK
353 * Failure: Status
355 * SEE
356 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
358 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
360 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
361 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
364 /******************************************************************************
365 * LoadTypeLibEx [OLEAUT32.183]
367 * Loads and optionally registers a type library
369 * RETURNS
370 * Success: S_OK
371 * Failure: Status
373 HRESULT WINAPI LoadTypeLibEx(
374 LPCOLESTR szFile, /* [in] Name of file to load from */
375 REGKIND regkind, /* [in] Specify kind of registration */
376 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
378 WCHAR szPath[MAX_PATH+1];
379 HRESULT res;
381 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
383 *pptLib = NULL;
385 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
387 if (SUCCEEDED(res))
388 switch(regkind)
390 case REGKIND_DEFAULT:
391 /* don't register typelibs supplied with full path. Experimentation confirms the following */
392 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
393 (szFile[0] && (szFile[1] == ':'))) break;
394 /* else fall-through */
396 case REGKIND_REGISTER:
397 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
399 IUnknown_Release(*pptLib);
400 *pptLib = 0;
402 break;
403 case REGKIND_NONE:
404 break;
407 TRACE(" returns %08x\n",res);
408 return res;
411 /******************************************************************************
412 * LoadRegTypeLib [OLEAUT32.162]
414 * Loads a registered type library.
416 * PARAMS
417 * rguid [I] GUID of the registered type library.
418 * wVerMajor [I] major version.
419 * wVerMinor [I] minor version.
420 * lcid [I] locale ID.
421 * ppTLib [O] pointer that receives an ITypeLib object on success.
423 * RETURNS
424 * Success: S_OK.
425 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
426 * LoadTypeLib.
428 HRESULT WINAPI LoadRegTypeLib(
429 REFGUID rguid,
430 WORD wVerMajor,
431 WORD wVerMinor,
432 LCID lcid,
433 ITypeLib **ppTLib)
435 BSTR bstr=NULL;
436 HRESULT res;
438 *ppTLib = NULL;
440 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
442 if(SUCCEEDED(res))
444 res= LoadTypeLib(bstr, ppTLib);
445 SysFreeString(bstr);
448 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
450 return res;
454 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
455 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
456 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
457 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
458 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
459 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
461 /******************************************************************************
462 * RegisterTypeLib [OLEAUT32.163]
463 * Adds information about a type library to the System Registry
464 * NOTES
465 * Docs: ITypeLib FAR * ptlib
466 * Docs: OLECHAR FAR* szFullPath
467 * Docs: OLECHAR FAR* szHelpDir
469 * RETURNS
470 * Success: S_OK
471 * Failure: Status
473 HRESULT WINAPI RegisterTypeLib(
474 ITypeLib * ptlib, /* [in] Pointer to the library*/
475 OLECHAR * szFullPath, /* [in] full Path of the library*/
476 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
477 may be NULL*/
479 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
480 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
481 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
482 HRESULT res;
483 TLIBATTR *attr;
484 WCHAR keyName[60];
485 WCHAR tmp[16];
486 HKEY key, subKey;
487 UINT types, tidx;
488 TYPEKIND kind;
489 DWORD disposition;
491 if (ptlib == NULL || szFullPath == NULL)
492 return E_INVALIDARG;
494 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
495 return E_FAIL;
497 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
499 res = S_OK;
500 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
501 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
503 LPOLESTR doc;
505 /* Set the human-readable name of the typelib */
506 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
508 if (RegSetValueExW(key, NULL, 0, REG_SZ,
509 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
510 res = E_FAIL;
512 SysFreeString(doc);
514 else
515 res = E_FAIL;
517 /* Make up the name of the typelib path subkey */
518 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
520 /* Create the typelib path subkey */
521 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
522 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
524 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
525 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
526 res = E_FAIL;
528 RegCloseKey(subKey);
530 else
531 res = E_FAIL;
533 /* Create the flags subkey */
534 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
535 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
537 /* FIXME: is %u correct? */
538 static const WCHAR formatW[] = {'%','u',0};
539 WCHAR buf[20];
540 sprintfW(buf, formatW, attr->wLibFlags);
541 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
542 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
543 res = E_FAIL;
545 RegCloseKey(subKey);
547 else
548 res = E_FAIL;
550 /* create the helpdir subkey */
551 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
552 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
554 BOOL freeHelpDir = FALSE;
555 OLECHAR* pIndexStr;
557 /* if we created a new key, and helpDir was null, set the helpdir
558 to the directory which contains the typelib. However,
559 if we just opened an existing key, we leave the helpdir alone */
560 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
561 szHelpDir = SysAllocString(szFullPath);
562 pIndexStr = strrchrW(szHelpDir, '\\');
563 if (pIndexStr) {
564 *pIndexStr = 0;
566 freeHelpDir = TRUE;
569 /* if we have an szHelpDir, set it! */
570 if (szHelpDir != NULL) {
571 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
572 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
573 res = E_FAIL;
577 /* tidy up */
578 if (freeHelpDir) SysFreeString(szHelpDir);
579 RegCloseKey(subKey);
581 } else {
582 res = E_FAIL;
585 RegCloseKey(key);
587 else
588 res = E_FAIL;
590 /* register OLE Automation-compatible interfaces for this typelib */
591 types = ITypeLib_GetTypeInfoCount(ptlib);
592 for (tidx=0; tidx<types; tidx++) {
593 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
594 LPOLESTR name = NULL;
595 ITypeInfo *tinfo = NULL;
597 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
599 switch (kind) {
600 case TKIND_INTERFACE:
601 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
602 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
603 break;
605 case TKIND_DISPATCH:
606 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
607 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
608 break;
610 default:
611 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
612 break;
615 if (tinfo) {
616 TYPEATTR *tattr = NULL;
617 ITypeInfo_GetTypeAttr(tinfo, &tattr);
619 if (tattr) {
620 TRACE_(typelib)("guid=%s, flags=%04x (",
621 debugstr_guid(&tattr->guid),
622 tattr->wTypeFlags);
624 if (TRACE_ON(typelib)) {
625 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
626 XX(FAPPOBJECT);
627 XX(FCANCREATE);
628 XX(FLICENSED);
629 XX(FPREDECLID);
630 XX(FHIDDEN);
631 XX(FCONTROL);
632 XX(FDUAL);
633 XX(FNONEXTENSIBLE);
634 XX(FOLEAUTOMATION);
635 XX(FRESTRICTED);
636 XX(FAGGREGATABLE);
637 XX(FREPLACEABLE);
638 XX(FDISPATCHABLE);
639 XX(FREVERSEBIND);
640 XX(FPROXY);
641 #undef XX
642 MESSAGE("\n");
645 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL|TYPEFLAG_FDISPATCHABLE))
647 /* register interface<->typelib coupling */
648 get_interface_key( &tattr->guid, keyName );
649 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
650 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
652 if (name)
653 RegSetValueExW(key, NULL, 0, REG_SZ,
654 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
656 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
657 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
658 RegSetValueExW(subKey, NULL, 0, REG_SZ,
659 (const BYTE *)PSOA, sizeof PSOA);
660 RegCloseKey(subKey);
663 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
664 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
665 RegSetValueExW(subKey, NULL, 0, REG_SZ,
666 (const BYTE *)PSOA, sizeof PSOA);
667 RegCloseKey(subKey);
670 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
671 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
673 WCHAR buffer[40];
674 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
675 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
677 StringFromGUID2(&attr->guid, buffer, 40);
678 RegSetValueExW(subKey, NULL, 0, REG_SZ,
679 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
680 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
681 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
682 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
683 RegCloseKey(subKey);
686 RegCloseKey(key);
690 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
693 ITypeInfo_Release(tinfo);
696 SysFreeString(name);
700 ITypeLib_ReleaseTLibAttr(ptlib, attr);
702 return res;
706 /******************************************************************************
707 * UnRegisterTypeLib [OLEAUT32.186]
708 * Removes information about a type library from the System Registry
709 * NOTES
711 * RETURNS
712 * Success: S_OK
713 * Failure: Status
715 HRESULT WINAPI UnRegisterTypeLib(
716 REFGUID libid, /* [in] Guid of the library */
717 WORD wVerMajor, /* [in] major version */
718 WORD wVerMinor, /* [in] minor version */
719 LCID lcid, /* [in] locale id */
720 SYSKIND syskind)
722 BSTR tlibPath = NULL;
723 DWORD tmpLength;
724 WCHAR keyName[60];
725 WCHAR subKeyName[50];
726 int result = S_OK;
727 DWORD i = 0;
728 BOOL deleteOtherStuff;
729 HKEY key = NULL;
730 HKEY subKey = NULL;
731 TYPEATTR* typeAttr = NULL;
732 TYPEKIND kind;
733 ITypeInfo* typeInfo = NULL;
734 ITypeLib* typeLib = NULL;
735 int numTypes;
737 TRACE("(IID: %s)\n",debugstr_guid(libid));
739 /* Create the path to the key */
740 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
742 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
744 TRACE("Unsupported syskind %i\n", syskind);
745 result = E_INVALIDARG;
746 goto end;
749 /* get the path to the typelib on disk */
750 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
751 result = E_INVALIDARG;
752 goto end;
755 /* Try and open the key to the type library. */
756 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
757 result = E_INVALIDARG;
758 goto end;
761 /* Try and load the type library */
762 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
763 result = TYPE_E_INVALIDSTATE;
764 goto end;
767 /* remove any types registered with this typelib */
768 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
769 for (i=0; i<numTypes; i++) {
770 /* get the kind of type */
771 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
772 goto enddeleteloop;
775 /* skip non-interfaces, and get type info for the type */
776 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
777 goto enddeleteloop;
779 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
780 goto enddeleteloop;
782 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
783 goto enddeleteloop;
786 /* the path to the type */
787 get_interface_key( &typeAttr->guid, subKeyName );
789 /* Delete its bits */
790 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS) {
791 goto enddeleteloop;
793 RegDeleteKeyW(subKey, ProxyStubClsidW);
794 RegDeleteKeyW(subKey, ProxyStubClsid32W);
795 RegDeleteKeyW(subKey, TypeLibW);
796 RegCloseKey(subKey);
797 subKey = NULL;
798 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
800 enddeleteloop:
801 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
802 typeAttr = NULL;
803 if (typeInfo) ITypeInfo_Release(typeInfo);
804 typeInfo = NULL;
807 /* Now, delete the type library path subkey */
808 get_lcid_subkey( lcid, syskind, subKeyName );
809 RegDeleteKeyW(key, subKeyName);
810 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
811 RegDeleteKeyW(key, subKeyName);
813 /* check if there is anything besides the FLAGS/HELPDIR keys.
814 If there is, we don't delete them */
815 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
816 deleteOtherStuff = TRUE;
817 i = 0;
818 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
819 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
821 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
822 if (!strcmpW(subKeyName, FLAGSW)) continue;
823 if (!strcmpW(subKeyName, HELPDIRW)) continue;
824 deleteOtherStuff = FALSE;
825 break;
828 /* only delete the other parts of the key if we're absolutely sure */
829 if (deleteOtherStuff) {
830 RegDeleteKeyW(key, FLAGSW);
831 RegDeleteKeyW(key, HELPDIRW);
832 RegCloseKey(key);
833 key = NULL;
835 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
836 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
837 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
840 end:
841 if (tlibPath) SysFreeString(tlibPath);
842 if (typeLib) ITypeLib_Release(typeLib);
843 if (subKey) RegCloseKey(subKey);
844 if (key) RegCloseKey(key);
845 return result;
848 /*======================= ITypeLib implementation =======================*/
850 typedef struct tagTLBCustData
852 GUID guid;
853 VARIANT data;
854 struct tagTLBCustData* next;
855 } TLBCustData;
857 /* data structure for import typelibs */
858 typedef struct tagTLBImpLib
860 int offset; /* offset in the file (MSFT)
861 offset in nametable (SLTG)
862 just used to identify library while reading
863 data from file */
864 GUID guid; /* libid */
865 BSTR name; /* name */
867 LCID lcid; /* lcid of imported typelib */
869 WORD wVersionMajor; /* major version number */
870 WORD wVersionMinor; /* minor version number */
872 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
873 NULL if not yet loaded */
874 struct tagTLBImpLib * next;
875 } TLBImpLib;
877 /* internal ITypeLib data */
878 typedef struct tagITypeLibImpl
880 const ITypeLib2Vtbl *lpVtbl;
881 const ITypeCompVtbl *lpVtblTypeComp;
882 LONG ref;
883 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
885 /* strings can be stored in tlb as multibyte strings BUT they are *always*
886 * exported to the application as a UNICODE string.
888 BSTR Name;
889 BSTR DocString;
890 BSTR HelpFile;
891 BSTR HelpStringDll;
892 unsigned long dwHelpContext;
893 int TypeInfoCount; /* nr of typeinfo's in librarry */
894 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
895 int ctCustData; /* number of items in cust data list */
896 TLBCustData * pCustData; /* linked list to cust data */
897 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
898 int ctTypeDesc; /* number of items in type desc array */
899 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
900 library. Only used while reading MSFT
901 typelibs */
902 struct list ref_list; /* list of ref types in this typelib */
903 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
906 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
907 struct tagITypeLibImpl *next, *prev;
908 WCHAR *path;
909 INT index;
910 } ITypeLibImpl;
912 static const ITypeLib2Vtbl tlbvt;
913 static const ITypeCompVtbl tlbtcvt;
915 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
917 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
920 /* ITypeLib methods */
921 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
922 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
924 /*======================= ITypeInfo implementation =======================*/
926 /* data for referenced types */
927 typedef struct tagTLBRefType
929 INT index; /* Type index for internal ref or for external ref
930 it the format is SLTG. -2 indicates to
931 use guid */
933 GUID guid; /* guid of the referenced type */
934 /* if index == TLB_REF_USE_GUID */
936 HREFTYPE reference; /* The href of this ref */
937 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
938 TLB_REF_INTERNAL for internal refs
939 TLB_REF_NOT_FOUND for broken refs */
941 struct list entry;
942 } TLBRefType;
944 #define TLB_REF_USE_GUID -2
946 #define TLB_REF_INTERNAL (void*)-2
947 #define TLB_REF_NOT_FOUND (void*)-1
949 /* internal Parameter data */
950 typedef struct tagTLBParDesc
952 BSTR Name;
953 int ctCustData;
954 TLBCustData * pCustData; /* linked list to cust data */
955 } TLBParDesc;
957 /* internal Function data */
958 typedef struct tagTLBFuncDesc
960 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
961 BSTR Name; /* the name of this function */
962 TLBParDesc *pParamDesc; /* array with param names and custom data */
963 int helpcontext;
964 int HelpStringContext;
965 BSTR HelpString;
966 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
967 int ctCustData;
968 TLBCustData * pCustData; /* linked list to cust data; */
969 struct tagTLBFuncDesc * next;
970 } TLBFuncDesc;
972 /* internal Variable data */
973 typedef struct tagTLBVarDesc
975 VARDESC vardesc; /* lots of info on the variable and its attributes. */
976 BSTR Name; /* the name of this variable */
977 int HelpContext;
978 int HelpStringContext; /* FIXME: where? */
979 BSTR HelpString;
980 int ctCustData;
981 TLBCustData * pCustData;/* linked list to cust data; */
982 struct tagTLBVarDesc * next;
983 } TLBVarDesc;
985 /* internal implemented interface data */
986 typedef struct tagTLBImplType
988 HREFTYPE hRef; /* hRef of interface */
989 int implflags; /* IMPLFLAG_*s */
990 int ctCustData;
991 TLBCustData * pCustData;/* linked list to custom data; */
992 struct tagTLBImplType *next;
993 } TLBImplType;
995 /* internal TypeInfo data */
996 typedef struct tagITypeInfoImpl
998 const ITypeInfo2Vtbl *lpVtbl;
999 const ITypeCompVtbl *lpVtblTypeComp;
1000 LONG ref;
1001 BOOL no_free_data; /* don't free data structures */
1002 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1003 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1004 int index; /* index in this typelib; */
1005 HREFTYPE hreftype; /* hreftype for app object binding */
1006 /* type libs seem to store the doc strings in ascii
1007 * so why should we do it in unicode?
1009 BSTR Name;
1010 BSTR DocString;
1011 BSTR DllName;
1012 unsigned long dwHelpContext;
1013 unsigned long dwHelpStringContext;
1015 /* functions */
1016 TLBFuncDesc * funclist; /* linked list with function descriptions */
1018 /* variables */
1019 TLBVarDesc * varlist; /* linked list with variable descriptions */
1021 /* Implemented Interfaces */
1022 TLBImplType * impltypelist;
1024 int ctCustData;
1025 TLBCustData * pCustData; /* linked list to cust data; */
1026 struct tagITypeInfoImpl * next;
1027 } ITypeInfoImpl;
1029 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1031 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1034 static const ITypeInfo2Vtbl tinfvt;
1035 static const ITypeCompVtbl tcompvt;
1037 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
1039 typedef struct tagTLBContext
1041 unsigned int oStart; /* start of TLB in file */
1042 unsigned int pos; /* current pos */
1043 unsigned int length; /* total length */
1044 void *mapping; /* memory mapping */
1045 MSFT_SegDir * pTblDir;
1046 ITypeLibImpl* pLibInfo;
1047 } TLBContext;
1050 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1053 debug
1055 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1056 if (pTD->vt & VT_RESERVED)
1057 szVarType += strlen(strcpy(szVarType, "reserved | "));
1058 if (pTD->vt & VT_BYREF)
1059 szVarType += strlen(strcpy(szVarType, "ref to "));
1060 if (pTD->vt & VT_ARRAY)
1061 szVarType += strlen(strcpy(szVarType, "array of "));
1062 if (pTD->vt & VT_VECTOR)
1063 szVarType += strlen(strcpy(szVarType, "vector of "));
1064 switch(pTD->vt & VT_TYPEMASK) {
1065 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1066 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1067 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1068 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1069 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1070 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1071 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1072 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1073 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1074 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1075 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1076 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1077 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1078 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1079 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1080 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1081 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1082 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1083 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1084 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1085 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1086 pTD->u.hreftype); break;
1087 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1088 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1089 case VT_PTR: sprintf(szVarType, "ptr to ");
1090 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1091 break;
1092 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1093 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1094 break;
1095 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1096 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1097 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1098 break;
1100 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1104 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1105 char buf[200];
1106 USHORT flags = edesc->u.paramdesc.wParamFlags;
1107 dump_TypeDesc(&edesc->tdesc,buf);
1108 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1109 MESSAGE("\t\tu.paramdesc.wParamFlags");
1110 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1111 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1112 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1113 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1114 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1115 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1116 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1117 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1118 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1120 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1121 int i;
1122 MESSAGE("memid is %08x\n",funcdesc->memid);
1123 for (i=0;i<funcdesc->cParams;i++) {
1124 MESSAGE("Param %d:\n",i);
1125 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1127 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1128 switch (funcdesc->funckind) {
1129 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1130 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1131 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1132 case FUNC_STATIC: MESSAGE("static");break;
1133 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1134 default: MESSAGE("unknown");break;
1136 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1137 switch (funcdesc->invkind) {
1138 case INVOKE_FUNC: MESSAGE("func");break;
1139 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1140 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1141 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1143 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1144 switch (funcdesc->callconv) {
1145 case CC_CDECL: MESSAGE("cdecl");break;
1146 case CC_PASCAL: MESSAGE("pascal");break;
1147 case CC_STDCALL: MESSAGE("stdcall");break;
1148 case CC_SYSCALL: MESSAGE("syscall");break;
1149 default:break;
1151 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1152 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1153 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1155 MESSAGE("\telemdescFunc (return value type):\n");
1156 dump_ELEMDESC(&funcdesc->elemdescFunc);
1159 static const char * const typekind_desc[] =
1161 "TKIND_ENUM",
1162 "TKIND_RECORD",
1163 "TKIND_MODULE",
1164 "TKIND_INTERFACE",
1165 "TKIND_DISPATCH",
1166 "TKIND_COCLASS",
1167 "TKIND_ALIAS",
1168 "TKIND_UNION",
1169 "TKIND_MAX"
1172 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1174 int i;
1175 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1176 for (i=0;i<pfd->funcdesc.cParams;i++)
1177 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1180 dump_FUNCDESC(&(pfd->funcdesc));
1182 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1183 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1185 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1187 while (pfd)
1189 dump_TLBFuncDescOne(pfd);
1190 pfd = pfd->next;
1193 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1195 while (pvd)
1197 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1198 pvd = pvd->next;
1202 static void dump_TLBImpLib(const TLBImpLib *import)
1204 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1205 debugstr_w(import->name));
1206 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1207 import->wVersionMinor, import->lcid, import->offset);
1210 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1212 TLBRefType *ref;
1214 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1216 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1217 if(ref->index == -1)
1218 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1219 else
1220 TRACE_(typelib)("type no: %d\n", ref->index);
1222 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1224 TRACE_(typelib)("in lib\n");
1225 dump_TLBImpLib(ref->pImpTLInfo);
1230 static void dump_TLBImplType(const TLBImplType * impl)
1232 while (impl) {
1233 TRACE_(typelib)(
1234 "implementing/inheriting interface hRef = %x implflags %x\n",
1235 impl->hRef, impl->implflags);
1236 impl = impl->next;
1240 static void dump_Variant(const VARIANT * pvar)
1242 SYSTEMTIME st;
1244 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1246 if (pvar)
1248 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1249 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1251 TRACE(",%p", V_BYREF(pvar));
1253 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1255 TRACE(",%p", V_ARRAY(pvar));
1257 else switch (V_TYPE(pvar))
1259 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1260 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1261 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1262 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1263 case VT_INT:
1264 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1265 case VT_UINT:
1266 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1267 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1268 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1269 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1270 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1271 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1272 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1273 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1274 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1275 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1276 V_CY(pvar).s.Lo); break;
1277 case VT_DATE:
1278 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1279 TRACE(",<invalid>");
1280 else
1281 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1282 st.wHour, st.wMinute, st.wSecond);
1283 break;
1284 case VT_ERROR:
1285 case VT_VOID:
1286 case VT_USERDEFINED:
1287 case VT_EMPTY:
1288 case VT_NULL: break;
1289 default: TRACE(",?"); break;
1292 TRACE("}\n");
1295 static void dump_DispParms(const DISPPARAMS * pdp)
1297 int index;
1299 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1301 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1303 TRACE("named args:\n");
1304 for (index = 0; index < pdp->cNamedArgs; index++)
1305 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1308 if (pdp->cArgs && pdp->rgvarg)
1310 TRACE("args:\n");
1311 for (index = 0; index < pdp->cArgs; index++)
1312 dump_Variant( &pdp->rgvarg[index] );
1316 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1318 TRACE("%p ref=%u\n", pty, pty->ref);
1319 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1320 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1321 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1322 TRACE("fct:%u var:%u impl:%u\n",
1323 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1324 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1325 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1326 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1327 if (TRACE_ON(ole))
1328 dump_TLBFuncDesc(pty->funclist);
1329 dump_TLBVarDesc(pty->varlist);
1330 dump_TLBImplType(pty->impltypelist);
1333 static void dump_VARDESC(const VARDESC *v)
1335 MESSAGE("memid %d\n",v->memid);
1336 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1337 MESSAGE("oInst %d\n",v->u.oInst);
1338 dump_ELEMDESC(&(v->elemdescVar));
1339 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1340 MESSAGE("varkind %d\n",v->varkind);
1343 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1345 /* VT_LPWSTR is largest type that */
1346 /* may appear in type description*/
1347 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1348 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1349 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1350 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1351 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1352 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1353 {{0},30},{{0},31}
1356 static void TLB_abort(void)
1358 DebugBreak();
1360 static void * TLB_Alloc(unsigned size)
1362 void * ret;
1363 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1364 /* FIXME */
1365 ERR("cannot allocate memory\n");
1367 return ret;
1370 static void TLB_Free(void * ptr)
1372 HeapFree(GetProcessHeap(), 0, ptr);
1375 /* returns the size required for a deep copy of a typedesc into a
1376 * flat buffer */
1377 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1379 SIZE_T size = 0;
1381 if (alloc_initial_space)
1382 size += sizeof(TYPEDESC);
1384 switch (tdesc->vt)
1386 case VT_PTR:
1387 case VT_SAFEARRAY:
1388 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1389 break;
1390 case VT_CARRAY:
1391 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1392 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1393 break;
1395 return size;
1398 /* deep copy a typedesc into a flat buffer */
1399 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1401 if (!dest)
1403 dest = buffer;
1404 buffer = (char *)buffer + sizeof(TYPEDESC);
1407 *dest = *src;
1409 switch (src->vt)
1411 case VT_PTR:
1412 case VT_SAFEARRAY:
1413 dest->u.lptdesc = buffer;
1414 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1415 break;
1416 case VT_CARRAY:
1417 dest->u.lpadesc = buffer;
1418 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1419 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1420 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1421 break;
1423 return buffer;
1426 /* free custom data allocated by MSFT_CustData */
1427 static inline void TLB_FreeCustData(TLBCustData *pCustData)
1429 TLBCustData *pCustDataNext;
1430 for (; pCustData; pCustData = pCustDataNext)
1432 VariantClear(&pCustData->data);
1434 pCustDataNext = pCustData->next;
1435 TLB_Free(pCustData);
1439 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1441 DWORD len;
1442 BSTR ret;
1444 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1445 ret = SysAllocStringLen(NULL, len - 1);
1446 if (!ret) return ret;
1447 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1448 return ret;
1451 /**********************************************************************
1453 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1455 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1457 return pcx->pos;
1460 static inline void MSFT_Seek(TLBContext *pcx, long where)
1462 if (where != DO_NOT_SEEK)
1464 where += pcx->oStart;
1465 if (where > pcx->length)
1467 /* FIXME */
1468 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1469 TLB_abort();
1471 pcx->pos = where;
1475 /* read function */
1476 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1478 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1479 pcx->pos, count, pcx->oStart, pcx->length, where);
1481 MSFT_Seek(pcx, where);
1482 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1483 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1484 pcx->pos += count;
1485 return count;
1488 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1489 long where )
1491 DWORD ret;
1493 ret = MSFT_Read(buffer, count, pcx, where);
1494 FromLEDWords(buffer, ret);
1496 return ret;
1499 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1500 long where )
1502 DWORD ret;
1504 ret = MSFT_Read(buffer, count, pcx, where);
1505 FromLEWords(buffer, ret);
1507 return ret;
1510 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1512 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1513 memset(pGuid,0, sizeof(GUID));
1514 return;
1516 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1517 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1518 pGuid->Data2 = FromLEWord(pGuid->Data2);
1519 pGuid->Data3 = FromLEWord(pGuid->Data3);
1520 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1523 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1525 MSFT_NameIntro niName;
1527 if (offset < 0)
1529 ERR_(typelib)("bad offset %d\n", offset);
1530 return -1;
1533 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1534 pcx->pTblDir->pNametab.offset+offset);
1536 return niName.hreftype;
1539 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1541 char * name;
1542 MSFT_NameIntro niName;
1543 int lengthInChars;
1544 BSTR bstrName = NULL;
1546 if (offset < 0)
1548 ERR_(typelib)("bad offset %d\n", offset);
1549 return NULL;
1551 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1552 pcx->pTblDir->pNametab.offset+offset);
1553 niName.namelen &= 0xFF; /* FIXME: correct ? */
1554 name=TLB_Alloc((niName.namelen & 0xff) +1);
1555 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1556 name[niName.namelen & 0xff]='\0';
1558 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1559 name, -1, NULL, 0);
1561 /* no invalid characters in string */
1562 if (lengthInChars)
1564 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1566 /* don't check for invalid character since this has been done previously */
1567 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1569 TLB_Free(name);
1571 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1572 return bstrName;
1575 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1577 char * string;
1578 INT16 length;
1579 int lengthInChars;
1580 BSTR bstr = NULL;
1582 if(offset<0) return NULL;
1583 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1584 if(length <= 0) return 0;
1585 string=TLB_Alloc(length +1);
1586 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1587 string[length]='\0';
1589 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1590 string, -1, NULL, 0);
1592 /* no invalid characters in string */
1593 if (lengthInChars)
1595 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1597 /* don't check for invalid character since this has been done previously */
1598 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1600 TLB_Free(string);
1602 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1603 return bstr;
1606 * read a value and fill a VARIANT structure
1608 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1610 int size;
1612 TRACE_(typelib)("\n");
1614 if(offset <0) { /* data are packed in here */
1615 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1616 V_I4(pVar) = offset & 0x3ffffff;
1617 return;
1619 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1620 pcx->pTblDir->pCustData.offset + offset );
1621 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1622 switch (V_VT(pVar)){
1623 case VT_EMPTY: /* FIXME: is this right? */
1624 case VT_NULL: /* FIXME: is this right? */
1625 case VT_I2 : /* this should not happen */
1626 case VT_I4 :
1627 case VT_R4 :
1628 case VT_ERROR :
1629 case VT_BOOL :
1630 case VT_I1 :
1631 case VT_UI1 :
1632 case VT_UI2 :
1633 case VT_UI4 :
1634 case VT_INT :
1635 case VT_UINT :
1636 case VT_VOID : /* FIXME: is this right? */
1637 case VT_HRESULT :
1638 size=4; break;
1639 case VT_R8 :
1640 case VT_CY :
1641 case VT_DATE :
1642 case VT_I8 :
1643 case VT_UI8 :
1644 case VT_DECIMAL : /* FIXME: is this right? */
1645 case VT_FILETIME :
1646 size=8;break;
1647 /* pointer types with known behaviour */
1648 case VT_BSTR :{
1649 char * ptr;
1650 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1651 if(size < 0) {
1652 char next;
1653 DWORD origPos = MSFT_Tell(pcx), nullPos;
1655 do {
1656 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1657 } while (next);
1658 nullPos = MSFT_Tell(pcx);
1659 size = nullPos - origPos;
1660 MSFT_Seek(pcx, origPos);
1662 ptr=TLB_Alloc(size);/* allocate temp buffer */
1663 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1664 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1665 /* FIXME: do we need a AtoW conversion here? */
1666 V_UNION(pVar, bstrVal[size])='\0';
1667 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1668 TLB_Free(ptr);
1670 size=-4; break;
1671 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1672 case VT_DISPATCH :
1673 case VT_VARIANT :
1674 case VT_UNKNOWN :
1675 case VT_PTR :
1676 case VT_SAFEARRAY :
1677 case VT_CARRAY :
1678 case VT_USERDEFINED :
1679 case VT_LPSTR :
1680 case VT_LPWSTR :
1681 case VT_BLOB :
1682 case VT_STREAM :
1683 case VT_STORAGE :
1684 case VT_STREAMED_OBJECT :
1685 case VT_STORED_OBJECT :
1686 case VT_BLOB_OBJECT :
1687 case VT_CF :
1688 case VT_CLSID :
1689 default:
1690 size=0;
1691 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1692 V_VT(pVar));
1695 if(size>0) /* (big|small) endian correct? */
1696 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1697 return;
1700 * create a linked list with custom data
1702 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1704 MSFT_CDGuid entry;
1705 TLBCustData* pNew;
1706 int count=0;
1708 TRACE_(typelib)("\n");
1710 while(offset >=0){
1711 count++;
1712 pNew=TLB_Alloc(sizeof(TLBCustData));
1713 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1714 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1715 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1716 /* add new custom data at head of the list */
1717 pNew->next=*ppCustData;
1718 *ppCustData=pNew;
1719 offset = entry.next;
1721 return count;
1724 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1725 ITypeInfoImpl *pTI)
1727 if(type <0)
1728 pTd->vt=type & VT_TYPEMASK;
1729 else
1730 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1732 if(pTd->vt == VT_USERDEFINED)
1733 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1735 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1738 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1740 /* resolve referenced type if any */
1741 while (lpTypeDesc)
1743 switch (lpTypeDesc->vt)
1745 case VT_PTR:
1746 lpTypeDesc = lpTypeDesc->u.lptdesc;
1747 break;
1749 case VT_CARRAY:
1750 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1751 break;
1753 case VT_USERDEFINED:
1754 MSFT_DoRefType(pcx, pTI->pTypeLib,
1755 lpTypeDesc->u.hreftype);
1757 lpTypeDesc = NULL;
1758 break;
1760 default:
1761 lpTypeDesc = NULL;
1766 static void
1767 MSFT_DoFuncs(TLBContext* pcx,
1768 ITypeInfoImpl* pTI,
1769 int cFuncs,
1770 int cVars,
1771 int offset,
1772 TLBFuncDesc** pptfd)
1775 * member information is stored in a data structure at offset
1776 * indicated by the memoffset field of the typeinfo structure
1777 * There are several distinctive parts.
1778 * The first part starts with a field that holds the total length
1779 * of this (first) part excluding this field. Then follow the records,
1780 * for each member there is one record.
1782 * The first entry is always the length of the record (including this
1783 * length word).
1784 * The rest of the record depends on the type of the member. If there is
1785 * a field indicating the member type (function, variable, interface, etc)
1786 * I have not found it yet. At this time we depend on the information
1787 * in the type info and the usual order how things are stored.
1789 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1790 * for each member;
1792 * Third is an equal sized array with file offsets to the name entry
1793 * of each member.
1795 * The fourth and last (?) part is an array with offsets to the records
1796 * in the first part of this file segment.
1799 int infolen, nameoffset, reclength, nrattributes, i;
1800 int recoffset = offset + sizeof(INT);
1802 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1803 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1804 TLBFuncDesc *ptfd_prev = NULL;
1806 TRACE_(typelib)("\n");
1808 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1810 for ( i = 0; i < cFuncs ; i++ )
1812 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1814 /* name, eventually add to a hash table */
1815 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1816 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1818 /* nameoffset is sometimes -1 on the second half of a propget/propput
1819 * pair of functions */
1820 if ((nameoffset == -1) && (i > 0))
1821 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1822 else
1823 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1825 /* read the function information record */
1826 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1828 reclength &= 0xffff;
1830 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1832 /* do the attributes */
1833 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1834 / sizeof(int);
1836 if ( nrattributes > 0 )
1838 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1840 if ( nrattributes > 1 )
1842 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1843 pFuncRec->OptAttr[1]) ;
1845 if ( nrattributes > 2 )
1847 if ( pFuncRec->FKCCIC & 0x2000 )
1849 if (HIWORD(pFuncRec->OptAttr[2]) != 0)
1850 ERR("ordinal 0x%08x invalid, HIWORD != 0\n", pFuncRec->OptAttr[2]);
1851 (*pptfd)->Entry = (BSTR)pFuncRec->OptAttr[2];
1853 else
1855 (*pptfd)->Entry = MSFT_ReadString(pcx,
1856 pFuncRec->OptAttr[2]);
1858 if( nrattributes > 5 )
1860 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1862 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1864 MSFT_CustData(pcx,
1865 pFuncRec->OptAttr[6],
1866 &(*pptfd)->pCustData);
1870 else
1872 (*pptfd)->Entry = (BSTR)-1;
1877 /* fill the FuncDesc Structure */
1878 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1879 offset + infolen + ( i + 1) * sizeof(INT));
1881 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1882 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1883 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1884 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1885 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1886 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1887 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1889 MSFT_GetTdesc(pcx,
1890 pFuncRec->DataType,
1891 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1892 pTI);
1893 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1895 /* do the parameters/arguments */
1896 if(pFuncRec->nrargs)
1898 int j = 0;
1899 MSFT_ParameterInfo paraminfo;
1901 (*pptfd)->funcdesc.lprgelemdescParam =
1902 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1904 (*pptfd)->pParamDesc =
1905 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1907 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1908 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1910 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1912 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1914 MSFT_GetTdesc(pcx,
1915 paraminfo.DataType,
1916 &elemdesc->tdesc,
1917 pTI);
1919 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1921 /* name */
1922 if (paraminfo.oName == -1)
1923 /* this occurs for [propput] or [propget] methods, so
1924 * we should just set the name of the parameter to the
1925 * name of the method. */
1926 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1927 else
1928 (*pptfd)->pParamDesc[j].Name =
1929 MSFT_ReadName( pcx, paraminfo.oName );
1930 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1932 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1934 /* default value */
1935 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1936 (pFuncRec->FKCCIC & 0x1000) )
1938 INT* pInt = (INT *)((char *)pFuncRec +
1939 reclength -
1940 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1942 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1944 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1945 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1947 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1948 pInt[j], pcx);
1950 else
1951 elemdesc->u.paramdesc.pparamdescex = NULL;
1952 /* custom info */
1953 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1955 MSFT_CustData(pcx,
1956 pFuncRec->OptAttr[7+j],
1957 &(*pptfd)->pParamDesc[j].pCustData);
1960 /* SEEK value = jump to offset,
1961 * from there jump to the end of record,
1962 * go back by (j-1) arguments
1964 MSFT_ReadLEDWords( &paraminfo ,
1965 sizeof(MSFT_ParameterInfo), pcx,
1966 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1967 * sizeof(MSFT_ParameterInfo)));
1971 /* scode is not used: archaic win16 stuff FIXME: right? */
1972 (*pptfd)->funcdesc.cScodes = 0 ;
1973 (*pptfd)->funcdesc.lprgscode = NULL ;
1975 ptfd_prev = *pptfd;
1976 pptfd = & ((*pptfd)->next);
1977 recoffset += reclength;
1979 HeapFree(GetProcessHeap(), 0, recbuf);
1982 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1983 int cVars, int offset, TLBVarDesc ** pptvd)
1985 int infolen, nameoffset, reclength;
1986 char recbuf[256];
1987 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1988 int i;
1989 int recoffset;
1991 TRACE_(typelib)("\n");
1993 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1994 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1995 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1996 recoffset += offset+sizeof(INT);
1997 for(i=0;i<cVars;i++){
1998 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1999 /* name, eventually add to a hash table */
2000 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2001 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2002 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
2003 /* read the variable information record */
2004 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
2005 reclength &=0xff;
2006 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
2007 /* Optional data */
2008 if(reclength >(6*sizeof(INT)) )
2009 (*pptvd)->HelpContext=pVarRec->HelpContext;
2010 if(reclength >(7*sizeof(INT)) )
2011 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
2012 if(reclength >(8*sizeof(INT)) )
2013 if(reclength >(9*sizeof(INT)) )
2014 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
2015 /* fill the VarDesc Structure */
2016 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
2017 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2018 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
2019 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
2020 MSFT_GetTdesc(pcx, pVarRec->DataType,
2021 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
2022 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2023 if(pVarRec->VarKind == VAR_CONST ){
2024 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
2025 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
2026 pVarRec->OffsValue, pcx);
2027 } else
2028 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
2029 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
2030 pptvd=&((*pptvd)->next);
2031 recoffset += reclength;
2034 /* fill in data for a hreftype (offset). When the referenced type is contained
2035 * in the typelib, it's just an (file) offset in the type info base dir.
2036 * If comes from import, it's an offset+1 in the ImpInfo table
2037 * */
2038 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2039 int offset)
2041 TLBRefType *ref;
2043 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2045 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2047 if(ref->reference == offset) return;
2050 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
2051 list_add_tail(&pTL->ref_list, &ref->entry);
2053 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2054 /* external typelib */
2055 MSFT_ImpInfo impinfo;
2056 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2058 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2060 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2061 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2062 while (pImpLib){ /* search the known offsets of all import libraries */
2063 if(pImpLib->offset==impinfo.oImpFile) break;
2064 pImpLib=pImpLib->next;
2066 if(pImpLib){
2067 ref->reference = offset;
2068 ref->pImpTLInfo = pImpLib;
2069 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2070 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2071 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2072 ref->index = TLB_REF_USE_GUID;
2073 } else
2074 ref->index = impinfo.oGuid;
2075 }else{
2076 ERR("Cannot find a reference\n");
2077 ref->reference = -1;
2078 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2080 }else{
2081 /* in this typelib */
2082 ref->index = MSFT_HREFTYPE_INDEX(offset);
2083 ref->reference = offset;
2084 ref->pImpTLInfo = TLB_REF_INTERNAL;
2088 /* process Implemented Interfaces of a com class */
2089 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2090 int offset)
2092 int i;
2093 MSFT_RefRecord refrec;
2094 TLBImplType **ppImpl = &pTI->impltypelist;
2096 TRACE_(typelib)("\n");
2098 for(i=0;i<count;i++){
2099 if(offset<0) break; /* paranoia */
2100 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2101 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2102 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2103 (*ppImpl)->hRef = refrec.reftype;
2104 (*ppImpl)->implflags=refrec.flags;
2105 (*ppImpl)->ctCustData=
2106 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2107 offset=refrec.onext;
2108 ppImpl=&((*ppImpl)->next);
2112 * process a typeinfo record
2114 static ITypeInfoImpl * MSFT_DoTypeInfo(
2115 TLBContext *pcx,
2116 int count,
2117 ITypeLibImpl * pLibInfo)
2119 MSFT_TypeInfoBase tiBase;
2120 ITypeInfoImpl *ptiRet;
2122 TRACE_(typelib)("count=%u\n", count);
2124 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2125 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2126 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2128 /* this is where we are coming from */
2129 ptiRet->pTypeLib = pLibInfo;
2130 ptiRet->index=count;
2131 /* fill in the typeattr fields */
2133 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2134 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2135 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2136 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2137 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2138 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2139 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2140 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2141 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2142 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2143 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2144 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2145 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2146 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2147 MSFT_GetTdesc(pcx, tiBase.datatype1,
2148 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2150 /* FIXME: */
2151 /* IDLDESC idldescType; *//* never saw this one != zero */
2153 /* name, eventually add to a hash table */
2154 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2155 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2156 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2157 /* help info */
2158 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2159 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2160 ptiRet->dwHelpContext=tiBase.helpcontext;
2162 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2163 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2165 /* note: InfoType's Help file and HelpStringDll come from the containing
2166 * library. Further HelpString and Docstring appear to be the same thing :(
2168 /* functions */
2169 if(ptiRet->TypeAttr.cFuncs >0 )
2170 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2171 ptiRet->TypeAttr.cVars,
2172 tiBase.memoffset, & ptiRet->funclist);
2173 /* variables */
2174 if(ptiRet->TypeAttr.cVars >0 )
2175 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2176 ptiRet->TypeAttr.cVars,
2177 tiBase.memoffset, & ptiRet->varlist);
2178 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2179 switch(ptiRet->TypeAttr.typekind)
2181 case TKIND_COCLASS:
2182 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2183 tiBase.datatype1);
2184 break;
2185 case TKIND_DISPATCH:
2186 /* This is not -1 when the interface is a non-base dual interface or
2187 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2188 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2189 not this interface.
2192 if (tiBase.datatype1 != -1)
2194 ptiRet->impltypelist = TLB_Alloc(sizeof(TLBImplType));
2195 ptiRet->impltypelist->hRef = tiBase.datatype1;
2196 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2198 break;
2199 default:
2200 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2201 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2202 ptiRet->impltypelist->hRef = tiBase.datatype1;
2203 break;
2206 ptiRet->ctCustData=
2207 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2209 TRACE_(typelib)("%s guid: %s kind:%s\n",
2210 debugstr_w(ptiRet->Name),
2211 debugstr_guid(&ptiRet->TypeAttr.guid),
2212 typekind_desc[ptiRet->TypeAttr.typekind]);
2214 return ptiRet;
2217 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2218 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2219 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2220 * tradeoff here.
2222 static ITypeLibImpl *tlb_cache_first;
2223 static CRITICAL_SECTION cache_section;
2224 static CRITICAL_SECTION_DEBUG cache_section_debug =
2226 0, 0, &cache_section,
2227 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2228 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2230 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2233 typedef struct TLB_PEFile
2235 const IUnknownVtbl *lpvtbl;
2236 LONG refs;
2237 HMODULE dll;
2238 HRSRC typelib_resource;
2239 HGLOBAL typelib_global;
2240 LPVOID typelib_base;
2241 } TLB_PEFile;
2243 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2245 if (IsEqualIID(riid, &IID_IUnknown))
2247 *ppv = iface;
2248 IUnknown_AddRef(iface);
2249 return S_OK;
2251 *ppv = NULL;
2252 return E_NOINTERFACE;
2255 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2257 TLB_PEFile *This = (TLB_PEFile *)iface;
2258 return InterlockedIncrement(&This->refs);
2261 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2263 TLB_PEFile *This = (TLB_PEFile *)iface;
2264 ULONG refs = InterlockedDecrement(&This->refs);
2265 if (!refs)
2267 if (This->typelib_global)
2268 FreeResource(This->typelib_global);
2269 if (This->dll)
2270 FreeLibrary(This->dll);
2271 HeapFree(GetProcessHeap(), 0, This);
2273 return refs;
2276 static const IUnknownVtbl TLB_PEFile_Vtable =
2278 TLB_PEFile_QueryInterface,
2279 TLB_PEFile_AddRef,
2280 TLB_PEFile_Release
2283 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2285 TLB_PEFile *This;
2287 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2288 if (!This)
2289 return E_OUTOFMEMORY;
2291 This->lpvtbl = &TLB_PEFile_Vtable;
2292 This->refs = 1;
2293 This->dll = NULL;
2294 This->typelib_resource = NULL;
2295 This->typelib_global = NULL;
2296 This->typelib_base = NULL;
2298 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2299 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2301 if (This->dll)
2303 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2304 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2305 if (This->typelib_resource)
2307 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2308 if (This->typelib_global)
2310 This->typelib_base = LockResource(This->typelib_global);
2312 if (This->typelib_base)
2314 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2315 *ppBase = This->typelib_base;
2316 *ppFile = (IUnknown *)&This->lpvtbl;
2317 return S_OK;
2323 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2324 return TYPE_E_CANTLOADLIBRARY;
2328 typedef struct TLB_Mapping
2330 const IUnknownVtbl *lpvtbl;
2331 LONG refs;
2332 HANDLE file;
2333 HANDLE mapping;
2334 LPVOID typelib_base;
2335 } TLB_Mapping;
2337 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2339 if (IsEqualIID(riid, &IID_IUnknown))
2341 *ppv = iface;
2342 IUnknown_AddRef(iface);
2343 return S_OK;
2345 *ppv = NULL;
2346 return E_NOINTERFACE;
2349 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2351 TLB_Mapping *This = (TLB_Mapping *)iface;
2352 return InterlockedIncrement(&This->refs);
2355 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2357 TLB_Mapping *This = (TLB_Mapping *)iface;
2358 ULONG refs = InterlockedDecrement(&This->refs);
2359 if (!refs)
2361 if (This->typelib_base)
2362 UnmapViewOfFile(This->typelib_base);
2363 if (This->mapping)
2364 CloseHandle(This->mapping);
2365 if (This->file != INVALID_HANDLE_VALUE)
2366 CloseHandle(This->file);
2367 HeapFree(GetProcessHeap(), 0, This);
2369 return refs;
2372 static const IUnknownVtbl TLB_Mapping_Vtable =
2374 TLB_Mapping_QueryInterface,
2375 TLB_Mapping_AddRef,
2376 TLB_Mapping_Release
2379 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2381 TLB_Mapping *This;
2383 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2384 if (!This)
2385 return E_OUTOFMEMORY;
2387 This->lpvtbl = &TLB_Mapping_Vtable;
2388 This->refs = 1;
2389 This->file = INVALID_HANDLE_VALUE;
2390 This->mapping = NULL;
2391 This->typelib_base = NULL;
2393 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2394 if (INVALID_HANDLE_VALUE != This->file)
2396 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2397 if (This->mapping)
2399 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2400 if(This->typelib_base)
2402 /* retrieve file size */
2403 *pdwTLBLength = GetFileSize(This->file, NULL);
2404 *ppBase = This->typelib_base;
2405 *ppFile = (IUnknown *)&This->lpvtbl;
2406 return S_OK;
2411 IUnknown_Release((IUnknown *)&This->lpvtbl);
2412 return TYPE_E_CANTLOADLIBRARY;
2415 /****************************************************************************
2416 * TLB_ReadTypeLib
2418 * find the type of the typelib file and map the typelib resource into
2419 * the memory
2421 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2422 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2423 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2425 ITypeLibImpl *entry;
2426 HRESULT ret;
2427 INT index = 1;
2428 LPWSTR index_str, file = (LPWSTR)pszFileName;
2429 LPVOID pBase = NULL;
2430 DWORD dwTLBLength = 0;
2431 IUnknown *pFile = NULL;
2433 *ppTypeLib = NULL;
2435 index_str = strrchrW(pszFileName, '\\');
2436 if(index_str && *++index_str != '\0')
2438 LPWSTR end_ptr;
2439 long idx = strtolW(index_str, &end_ptr, 10);
2440 if(*end_ptr == '\0')
2442 int str_len = index_str - pszFileName - 1;
2443 index = idx;
2444 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
2445 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2446 file[str_len] = 0;
2450 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2452 if(strchrW(file, '\\'))
2454 lstrcpyW(pszPath, file);
2456 else
2458 int len = GetSystemDirectoryW(pszPath, cchPath);
2459 pszPath[len] = '\\';
2460 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2464 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file);
2466 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2468 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2469 EnterCriticalSection(&cache_section);
2470 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2472 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2474 TRACE("cache hit\n");
2475 *ppTypeLib = (ITypeLib2*)entry;
2476 ITypeLib_AddRef(*ppTypeLib);
2477 LeaveCriticalSection(&cache_section);
2478 return S_OK;
2481 LeaveCriticalSection(&cache_section);
2483 /* now actually load and parse the typelib */
2485 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2486 if (ret == TYPE_E_CANTLOADLIBRARY)
2487 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2488 if (SUCCEEDED(ret))
2490 if (dwTLBLength >= 4)
2492 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2493 if (dwSignature == MSFT_SIGNATURE)
2494 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2495 else if (dwSignature == SLTG_SIGNATURE)
2496 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2497 else
2499 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2500 ret = TYPE_E_CANTLOADLIBRARY;
2503 else
2504 ret = TYPE_E_CANTLOADLIBRARY;
2505 IUnknown_Release(pFile);
2508 if(*ppTypeLib) {
2509 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2511 TRACE("adding to cache\n");
2512 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2513 lstrcpyW(impl->path, pszPath);
2514 /* We should really canonicalise the path here. */
2515 impl->index = index;
2517 /* FIXME: check if it has added already in the meantime */
2518 EnterCriticalSection(&cache_section);
2519 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2520 impl->prev = NULL;
2521 tlb_cache_first = impl;
2522 LeaveCriticalSection(&cache_section);
2523 ret = S_OK;
2524 } else
2525 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2527 return ret;
2530 /*================== ITypeLib(2) Methods ===================================*/
2532 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2534 ITypeLibImpl* pTypeLibImpl;
2536 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2537 if (!pTypeLibImpl) return NULL;
2539 pTypeLibImpl->lpVtbl = &tlbvt;
2540 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2541 pTypeLibImpl->ref = 1;
2543 list_init(&pTypeLibImpl->ref_list);
2544 pTypeLibImpl->dispatch_href = -1;
2546 return pTypeLibImpl;
2549 /****************************************************************************
2550 * ITypeLib2_Constructor_MSFT
2552 * loading an MSFT typelib from an in-memory image
2554 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2556 TLBContext cx;
2557 long lPSegDir;
2558 MSFT_Header tlbHeader;
2559 MSFT_SegDir tlbSegDir;
2560 ITypeLibImpl * pTypeLibImpl;
2562 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2564 pTypeLibImpl = TypeLibImpl_Constructor();
2565 if (!pTypeLibImpl) return NULL;
2567 /* get pointer to beginning of typelib data */
2568 cx.pos = 0;
2569 cx.oStart=0;
2570 cx.mapping = pLib;
2571 cx.pLibInfo = pTypeLibImpl;
2572 cx.length = dwTLBLength;
2574 /* read header */
2575 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2576 TRACE_(typelib)("header:\n");
2577 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2578 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2579 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2580 return NULL;
2582 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2584 /* there is a small amount of information here until the next important
2585 * part:
2586 * the segment directory . Try to calculate the amount of data */
2587 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2589 /* now read the segment directory */
2590 TRACE("read segment directory (at %ld)\n",lPSegDir);
2591 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2592 cx.pTblDir = &tlbSegDir;
2594 /* just check two entries */
2595 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2597 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2598 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2599 return NULL;
2602 /* now fill our internal data */
2603 /* TLIBATTR fields */
2604 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2606 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2607 /* Windows seems to have zero here, is this correct? */
2608 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2609 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2610 else
2611 pTypeLibImpl->LibAttr.lcid = 0;
2613 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2614 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2615 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2616 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2618 /* name, eventually add to a hash table */
2619 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2621 /* help info */
2622 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2623 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2625 if( tlbHeader.varflags & HELPDLLFLAG)
2627 int offset;
2628 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2629 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2632 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2634 /* custom data */
2635 if(tlbHeader.CustomDataOffset >= 0)
2637 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2640 /* fill in type descriptions */
2641 if(tlbSegDir.pTypdescTab.length > 0)
2643 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2644 INT16 td[4];
2645 pTypeLibImpl->ctTypeDesc = cTD;
2646 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2647 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2648 for(i=0; i<cTD; )
2650 /* FIXME: add several sanity checks here */
2651 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2652 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2654 /* FIXME: check safearray */
2655 if(td[3] < 0)
2656 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2657 else
2658 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2660 else if(td[0] == VT_CARRAY)
2662 /* array descr table here */
2663 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2665 else if(td[0] == VT_USERDEFINED)
2667 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2669 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2672 /* second time around to fill the array subscript info */
2673 for(i=0;i<cTD;i++)
2675 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2676 if(tlbSegDir.pArrayDescriptions.offset>0)
2678 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2679 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2681 if(td[1]<0)
2682 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2683 else
2684 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2686 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2688 for(j = 0; j<td[2]; j++)
2690 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2691 sizeof(INT), &cx, DO_NOT_SEEK);
2692 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2693 sizeof(INT), &cx, DO_NOT_SEEK);
2696 else
2698 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2699 ERR("didn't find array description data\n");
2704 /* imported type libs */
2705 if(tlbSegDir.pImpFiles.offset>0)
2707 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2708 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2709 UINT16 size;
2711 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2713 char *name;
2715 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2716 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2717 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2719 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2720 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2721 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2722 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2724 size >>= 2;
2725 name = TLB_Alloc(size+1);
2726 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2727 (*ppImpLib)->name = TLB_MultiByteToBSTR(name);
2729 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2730 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2732 ppImpLib = &(*ppImpLib)->next;
2736 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
2737 if(pTypeLibImpl->dispatch_href != -1)
2738 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
2740 /* type info's */
2741 if(tlbHeader.nrtypeinfos >= 0 )
2743 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2744 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2745 int i;
2747 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
2749 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2751 ppTI = &((*ppTI)->next);
2752 (pTypeLibImpl->TypeInfoCount)++;
2756 TRACE("(%p)\n", pTypeLibImpl);
2757 return (ITypeLib2*) pTypeLibImpl;
2761 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
2763 char b[3];
2764 int i;
2765 short s;
2767 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2768 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2769 return FALSE;
2772 guid->Data4[0] = s >> 8;
2773 guid->Data4[1] = s & 0xff;
2775 b[2] = '\0';
2776 for(i = 0; i < 6; i++) {
2777 memcpy(b, str + 24 + 2 * i, 2);
2778 guid->Data4[i + 2] = strtol(b, NULL, 16);
2780 return TRUE;
2783 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
2785 WORD bytelen;
2786 DWORD len;
2788 *pBstr = NULL;
2789 bytelen = *(const WORD*)ptr;
2790 if(bytelen == 0xffff) return 2;
2791 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2792 *pBstr = SysAllocStringLen(NULL, len - 1);
2793 if (*pBstr)
2794 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
2795 return bytelen + 2;
2798 static WORD SLTG_ReadStringA(const char *ptr, char **str)
2800 WORD bytelen;
2802 *str = NULL;
2803 bytelen = *(const WORD*)ptr;
2804 if(bytelen == 0xffff) return 2;
2805 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2806 memcpy(*str, ptr + 2, bytelen);
2807 (*str)[bytelen] = '\0';
2808 return bytelen + 2;
2811 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2813 char *ptr = pLibBlk;
2814 WORD w;
2816 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2817 FIXME("libblk magic = %04x\n", w);
2818 return 0;
2821 ptr += 6;
2822 if((w = *(WORD*)ptr) != 0xffff) {
2823 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2824 ptr += w;
2826 ptr += 2;
2828 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2830 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2832 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2833 ptr += 4;
2835 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2836 ptr += 2;
2838 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2839 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2840 else
2841 pTypeLibImpl->LibAttr.lcid = 0;
2842 ptr += 2;
2844 ptr += 4; /* skip res12 */
2846 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2847 ptr += 2;
2849 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2850 ptr += 2;
2852 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2853 ptr += 2;
2855 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2856 ptr += sizeof(GUID);
2858 return ptr - (char*)pLibBlk;
2861 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
2862 typedef struct
2864 unsigned int num;
2865 HREFTYPE refs[1];
2866 } sltg_ref_lookup_t;
2868 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
2869 HREFTYPE *typelib_ref)
2871 if(typeinfo_ref < table->num)
2873 *typelib_ref = table->refs[typeinfo_ref];
2874 return S_OK;
2877 ERR_(typelib)("Unable to find reference\n");
2878 *typelib_ref = -1;
2879 return E_FAIL;
2882 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
2884 BOOL done = FALSE;
2886 while(!done) {
2887 if((*pType & 0xe00) == 0xe00) {
2888 pTD->vt = VT_PTR;
2889 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2890 sizeof(TYPEDESC));
2891 pTD = pTD->u.lptdesc;
2893 switch(*pType & 0x3f) {
2894 case VT_PTR:
2895 pTD->vt = VT_PTR;
2896 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2897 sizeof(TYPEDESC));
2898 pTD = pTD->u.lptdesc;
2899 break;
2901 case VT_USERDEFINED:
2902 pTD->vt = VT_USERDEFINED;
2903 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
2904 done = TRUE;
2905 break;
2907 case VT_CARRAY:
2909 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2910 array */
2912 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2914 pTD->vt = VT_CARRAY;
2915 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2916 sizeof(ARRAYDESC) +
2917 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2918 pTD->u.lpadesc->cDims = pSA->cDims;
2919 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2920 pSA->cDims * sizeof(SAFEARRAYBOUND));
2922 pTD = &pTD->u.lpadesc->tdescElem;
2923 break;
2926 case VT_SAFEARRAY:
2928 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2929 useful? */
2931 pType++;
2932 pTD->vt = VT_SAFEARRAY;
2933 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2934 sizeof(TYPEDESC));
2935 pTD = pTD->u.lptdesc;
2936 break;
2938 default:
2939 pTD->vt = *pType & 0x3f;
2940 done = TRUE;
2941 break;
2943 pType++;
2945 return pType;
2948 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
2949 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
2951 /* Handle [in/out] first */
2952 if((*pType & 0xc000) == 0xc000)
2953 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2954 else if(*pType & 0x8000)
2955 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2956 else if(*pType & 0x4000)
2957 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2958 else
2959 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2961 if(*pType & 0x2000)
2962 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2964 if(*pType & 0x80)
2965 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2967 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
2971 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
2972 char *pNameTable)
2974 int ref;
2975 char *name;
2976 TLBRefType *ref_type;
2977 sltg_ref_lookup_t *table;
2978 HREFTYPE typelib_ref;
2980 if(pRef->magic != SLTG_REF_MAGIC) {
2981 FIXME("Ref magic = %x\n", pRef->magic);
2982 return NULL;
2984 name = ( (char*)pRef->names + pRef->number);
2986 table = HeapAlloc(GetProcessHeap(), 0, sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
2987 table->num = pRef->number >> 3;
2989 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
2991 /* We don't want the first href to be 0 */
2992 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
2994 for(ref = 0; ref < pRef->number >> 3; ref++) {
2995 char *refname;
2996 unsigned int lib_offs, type_num;
2998 ref_type = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref_type));
3000 name += SLTG_ReadStringA(name, &refname);
3001 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3002 FIXME_(typelib)("Can't sscanf ref\n");
3003 if(lib_offs != 0xffff) {
3004 TLBImpLib **import = &pTL->pImpLibs;
3006 while(*import) {
3007 if((*import)->offset == lib_offs)
3008 break;
3009 import = &(*import)->next;
3011 if(!*import) {
3012 char fname[MAX_PATH+1];
3013 int len;
3015 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3016 sizeof(**import));
3017 (*import)->offset = lib_offs;
3018 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3019 &(*import)->guid);
3020 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3021 &(*import)->wVersionMajor,
3022 &(*import)->wVersionMinor,
3023 &(*import)->lcid, fname) != 4) {
3024 FIXME_(typelib)("can't sscanf ref %s\n",
3025 pNameTable + lib_offs + 40);
3027 len = strlen(fname);
3028 if(fname[len-1] != '#')
3029 FIXME("fname = %s\n", fname);
3030 fname[len-1] = '\0';
3031 (*import)->name = TLB_MultiByteToBSTR(fname);
3033 ref_type->pImpTLInfo = *import;
3035 /* Store a reference to IDispatch */
3036 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
3037 pTL->dispatch_href = typelib_ref;
3039 } else { /* internal ref */
3040 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3042 ref_type->reference = typelib_ref;
3043 ref_type->index = type_num;
3045 HeapFree(GetProcessHeap(), 0, refname);
3046 list_add_tail(&pTL->ref_list, &ref_type->entry);
3048 table->refs[ref] = typelib_ref;
3049 typelib_ref += 4;
3051 if((BYTE)*name != SLTG_REF_MAGIC)
3052 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3053 dump_TLBRefType(pTL);
3054 return table;
3057 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3058 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3060 SLTG_ImplInfo *info;
3061 TLBImplType **ppImplType = &pTI->impltypelist;
3062 /* I don't really get this structure, usually it's 0x16 bytes
3063 long, but iuser.tlb contains some that are 0x18 bytes long.
3064 That's ok because we can use the next ptr to jump to the next
3065 one. But how do we know the length of the last one? The WORD
3066 at offs 0x8 might be the clue. For now I'm just assuming that
3067 the last one is the regular 0x16 bytes. */
3069 info = (SLTG_ImplInfo*)pBlk;
3070 while(1) {
3071 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3072 sizeof(**ppImplType));
3073 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef);
3074 (*ppImplType)->implflags = info->impltypeflags;
3075 pTI->TypeAttr.cImplTypes++;
3076 ppImplType = &(*ppImplType)->next;
3078 if(info->next == 0xffff)
3079 break;
3080 if(OneOnly)
3081 FIXME_(typelib)("Interface inheriting more than one interface\n");
3082 info = (SLTG_ImplInfo*)(pBlk + info->next);
3084 info++; /* see comment at top of function */
3085 return (char*)info;
3088 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3089 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3091 TLBVarDesc **ppVarDesc = &pTI->varlist;
3092 BSTR bstrPrevName = NULL;
3093 SLTG_Variable *pItem;
3094 unsigned short i;
3095 WORD *pType;
3097 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3098 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
3100 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3101 sizeof(**ppVarDesc));
3102 (*ppVarDesc)->vardesc.memid = pItem->memid;
3104 if (pItem->magic != SLTG_VAR_MAGIC &&
3105 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3106 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3107 return;
3110 if (pItem->name == 0xfffe)
3111 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
3112 else
3113 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3115 TRACE_(typelib)("name: %s\n", debugstr_w((*ppVarDesc)->Name));
3116 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3117 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3119 if(pItem->flags & 0x02)
3120 pType = &pItem->type;
3121 else
3122 pType = (WORD*)(pBlk + pItem->type);
3124 if (pItem->flags & ~0xda)
3125 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3127 SLTG_DoElem(pType, pBlk,
3128 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup);
3130 if (TRACE_ON(typelib)) {
3131 char buf[300];
3132 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3133 TRACE_(typelib)("elemdescVar: %s\n", buf);
3136 if (pItem->flags & 0x40) {
3137 TRACE_(typelib)("VAR_DISPATCH\n");
3138 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
3140 else if (pItem->flags & 0x10) {
3141 TRACE_(typelib)("VAR_CONST\n");
3142 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3143 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3144 sizeof(VARIANT));
3145 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3146 if (pItem->flags & 0x08)
3147 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) = pItem->byte_offs;
3148 else {
3149 switch ((*ppVarDesc)->vardesc.elemdescVar.tdesc.vt)
3151 case VT_LPSTR:
3152 case VT_LPWSTR:
3153 case VT_BSTR:
3155 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3156 BSTR str;
3157 TRACE_(typelib)("len = %u\n", len);
3158 if (len == 0xffff) {
3159 str = NULL;
3160 } else {
3161 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3162 str = SysAllocStringLen(NULL, alloc_len);
3163 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3165 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_BSTR;
3166 V_BSTR((*ppVarDesc)->vardesc.u.lpvarValue) = str;
3167 break;
3169 case VT_I2:
3170 case VT_UI2:
3171 case VT_I4:
3172 case VT_UI4:
3173 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
3174 *(INT*)(pBlk + pItem->byte_offs);
3175 break;
3176 default:
3177 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt);
3181 else {
3182 TRACE_(typelib)("VAR_PERINSTANCE\n");
3183 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3184 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3187 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3188 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
3190 if (pItem->flags & 0x80)
3191 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3193 bstrPrevName = (*ppVarDesc)->Name;
3194 ppVarDesc = &((*ppVarDesc)->next);
3196 pTI->TypeAttr.cVars = cVars;
3199 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3200 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3202 SLTG_Function *pFunc;
3203 unsigned short i;
3204 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3206 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3207 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3209 int param;
3210 WORD *pType, *pArg;
3212 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3213 sizeof(**ppFuncDesc));
3215 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3216 case SLTG_FUNCTION_MAGIC:
3217 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3218 break;
3219 case SLTG_DISPATCH_FUNCTION_MAGIC:
3220 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3221 break;
3222 case SLTG_STATIC_FUNCTION_MAGIC:
3223 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3224 break;
3225 default:
3226 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3227 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
3228 *ppFuncDesc = NULL;
3229 return;
3231 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3233 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3234 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3235 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3236 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3237 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3238 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3240 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3241 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3243 if(pFunc->retnextopt & 0x80)
3244 pType = &pFunc->rettype;
3245 else
3246 pType = (WORD*)(pBlk + pFunc->rettype);
3248 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3250 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3251 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3252 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3253 (*ppFuncDesc)->pParamDesc =
3254 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3255 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3257 pArg = (WORD*)(pBlk + pFunc->arg_off);
3259 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3260 char *paramName = pNameTable + *pArg;
3261 BOOL HaveOffs;
3262 /* If arg type follows then paramName points to the 2nd
3263 letter of the name, else the next WORD is an offset to
3264 the arg type and paramName points to the first letter.
3265 So let's take one char off paramName and see if we're
3266 pointing at an alpha-numeric char. However if *pArg is
3267 0xffff or 0xfffe then the param has no name, the former
3268 meaning that the next WORD is the type, the latter
3269 meaning that the next WORD is an offset to the type. */
3271 HaveOffs = FALSE;
3272 if(*pArg == 0xffff)
3273 paramName = NULL;
3274 else if(*pArg == 0xfffe) {
3275 paramName = NULL;
3276 HaveOffs = TRUE;
3278 else if(paramName[-1] && !isalnum(paramName[-1]))
3279 HaveOffs = TRUE;
3281 pArg++;
3283 if(HaveOffs) { /* the next word is an offset to type */
3284 pType = (WORD*)(pBlk + *pArg);
3285 SLTG_DoElem(pType, pBlk,
3286 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3287 pArg++;
3288 } else {
3289 if(paramName)
3290 paramName--;
3291 pArg = SLTG_DoElem(pArg, pBlk,
3292 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3295 /* Are we an optional param ? */
3296 if((*ppFuncDesc)->funcdesc.cParams - param <=
3297 (*ppFuncDesc)->funcdesc.cParamsOpt)
3298 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3300 if(paramName) {
3301 (*ppFuncDesc)->pParamDesc[param].Name =
3302 TLB_MultiByteToBSTR(paramName);
3303 } else {
3304 (*ppFuncDesc)->pParamDesc[param].Name =
3305 SysAllocString((*ppFuncDesc)->Name);
3309 ppFuncDesc = &((*ppFuncDesc)->next);
3310 if(pFunc->next == 0xffff) break;
3312 pTI->TypeAttr.cFuncs = cFuncs;
3315 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3316 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3317 SLTG_TypeInfoTail *pTITail)
3319 char *pFirstItem;
3320 sltg_ref_lookup_t *ref_lookup = NULL;
3322 if(pTIHeader->href_table != 0xffffffff) {
3323 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3324 pNameTable);
3327 pFirstItem = pBlk;
3329 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3330 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3332 HeapFree(GetProcessHeap(), 0, ref_lookup);
3336 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3337 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3338 const SLTG_TypeInfoTail *pTITail)
3340 char *pFirstItem;
3341 sltg_ref_lookup_t *ref_lookup = NULL;
3343 if(pTIHeader->href_table != 0xffffffff) {
3344 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3345 pNameTable);
3348 pFirstItem = pBlk;
3350 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3351 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3354 if (pTITail->funcs_off != 0xffff)
3355 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3357 HeapFree(GetProcessHeap(), 0, ref_lookup);
3359 if (TRACE_ON(typelib))
3360 dump_TLBFuncDesc(pTI->funclist);
3363 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3364 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3365 const SLTG_TypeInfoTail *pTITail)
3367 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3370 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3371 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3372 const SLTG_TypeInfoTail *pTITail)
3374 WORD *pType;
3375 sltg_ref_lookup_t *ref_lookup = NULL;
3377 if (pTITail->simple_alias) {
3378 /* if simple alias, no more processing required */
3379 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3380 return;
3383 if(pTIHeader->href_table != 0xffffffff) {
3384 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3385 pNameTable);
3388 /* otherwise it is an offset to a type */
3389 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3391 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3393 HeapFree(GetProcessHeap(), 0, ref_lookup);
3396 static void SLTG_ProcessDispatch(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);
3411 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3412 * of dispinterface functions including the IDispatch ones, so
3413 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3414 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3416 HeapFree(GetProcessHeap(), 0, ref_lookup);
3417 if (TRACE_ON(typelib))
3418 dump_TLBFuncDesc(pTI->funclist);
3421 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3422 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3423 const SLTG_TypeInfoTail *pTITail)
3425 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3428 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3429 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3430 const SLTG_TypeInfoTail *pTITail)
3432 sltg_ref_lookup_t *ref_lookup = NULL;
3433 if (pTIHeader->href_table != 0xffffffff)
3434 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3435 pNameTable);
3437 if (pTITail->vars_off != 0xffff)
3438 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3440 if (pTITail->funcs_off != 0xffff)
3441 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3442 HeapFree(GetProcessHeap(), 0, ref_lookup);
3443 if (TRACE_ON(typelib))
3444 dump_TypeInfo(pTI);
3447 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3448 managable copy of it into this */
3449 typedef struct {
3450 WORD small_no;
3451 char *index_name;
3452 char *other_name;
3453 WORD res1a;
3454 WORD name_offs;
3455 WORD more_bytes;
3456 char *extra;
3457 WORD res20;
3458 DWORD helpcontext;
3459 WORD res26;
3460 GUID uuid;
3461 } SLTG_InternalOtherTypeInfo;
3463 /****************************************************************************
3464 * ITypeLib2_Constructor_SLTG
3466 * loading a SLTG typelib from an in-memory image
3468 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3470 ITypeLibImpl *pTypeLibImpl;
3471 SLTG_Header *pHeader;
3472 SLTG_BlkEntry *pBlkEntry;
3473 SLTG_Magic *pMagic;
3474 SLTG_Index *pIndex;
3475 SLTG_Pad9 *pPad9;
3476 LPVOID pBlk, pFirstBlk;
3477 SLTG_LibBlk *pLibBlk;
3478 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3479 char *pAfterOTIBlks = NULL;
3480 char *pNameTable, *ptr;
3481 int i;
3482 DWORD len, order;
3483 ITypeInfoImpl **ppTypeInfoImpl;
3485 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3488 pTypeLibImpl = TypeLibImpl_Constructor();
3489 if (!pTypeLibImpl) return NULL;
3491 pHeader = pLib;
3493 TRACE_(typelib)("header:\n");
3494 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3495 pHeader->nrOfFileBlks );
3496 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3497 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3498 pHeader->SLTG_magic);
3499 return NULL;
3502 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3503 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3505 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3506 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3508 /* Next we have a magic block */
3509 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3511 /* Let's see if we're still in sync */
3512 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3513 sizeof(SLTG_COMPOBJ_MAGIC))) {
3514 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3515 return NULL;
3517 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3518 sizeof(SLTG_DIR_MAGIC))) {
3519 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
3520 return NULL;
3523 pIndex = (SLTG_Index*)(pMagic+1);
3525 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3527 pFirstBlk = (LPVOID)(pPad9 + 1);
3529 /* We'll set up a ptr to the main library block, which is the last one. */
3531 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3532 pBlkEntry[order].next != 0;
3533 order = pBlkEntry[order].next - 1, i++) {
3534 pBlk = (char*)pBlk + pBlkEntry[order].len;
3536 pLibBlk = pBlk;
3538 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3540 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3541 interspersed */
3543 len += 0x40;
3545 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3547 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3548 sizeof(*pOtherTypeInfoBlks) *
3549 pTypeLibImpl->TypeInfoCount);
3552 ptr = (char*)pLibBlk + len;
3554 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3555 WORD w, extra;
3556 len = 0;
3558 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3560 w = *(WORD*)(ptr + 2);
3561 if(w != 0xffff) {
3562 len += w;
3563 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3564 w+1);
3565 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3566 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3568 w = *(WORD*)(ptr + 4 + len);
3569 if(w != 0xffff) {
3570 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3571 len += w;
3572 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3573 w+1);
3574 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3575 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3577 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3578 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3579 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3580 if(extra) {
3581 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3582 extra);
3583 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3584 len += extra;
3586 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3587 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3588 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3589 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3590 len += sizeof(SLTG_OtherTypeInfo);
3591 ptr += len;
3594 pAfterOTIBlks = ptr;
3596 /* Skip this WORD and get the next DWORD */
3597 len = *(DWORD*)(pAfterOTIBlks + 2);
3599 /* Now add this to pLibBLk look at what we're pointing at and
3600 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3601 dust and we should be pointing at the beginning of the name
3602 table */
3604 pNameTable = (char*)pLibBlk + len;
3606 switch(*(WORD*)pNameTable) {
3607 case 0xffff:
3608 break;
3609 case 0x0200:
3610 pNameTable += 0x20;
3611 break;
3612 default:
3613 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
3614 break;
3617 pNameTable += 0x216;
3619 pNameTable += 2;
3621 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
3623 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3626 /* Hopefully we now have enough ptrs set up to actually read in
3627 some TypeInfos. It's not clear which order to do them in, so
3628 I'll just follow the links along the BlkEntry chain and read
3629 them in the order in which they are in the file */
3631 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3633 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3634 pBlkEntry[order].next != 0;
3635 order = pBlkEntry[order].next - 1, i++) {
3637 SLTG_TypeInfoHeader *pTIHeader;
3638 SLTG_TypeInfoTail *pTITail;
3639 SLTG_MemberHeader *pMemHeader;
3641 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3642 pOtherTypeInfoBlks[i].index_name)) {
3643 FIXME_(typelib)("Index strings don't match\n");
3644 return NULL;
3647 pTIHeader = pBlk;
3648 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3649 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3650 return NULL;
3652 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
3653 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3654 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3656 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3657 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3658 (*ppTypeInfoImpl)->index = i;
3659 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3660 pOtherTypeInfoBlks[i].name_offs +
3661 pNameTable);
3662 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3663 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
3664 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3665 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3666 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3667 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3668 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3670 if((pTIHeader->typeflags1 & 7) != 2)
3671 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
3672 if(pTIHeader->typeflags3 != 2)
3673 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
3675 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3676 debugstr_w((*ppTypeInfoImpl)->Name),
3677 typekind_desc[pTIHeader->typekind],
3678 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3679 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3681 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3683 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3685 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3686 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3687 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3689 switch(pTIHeader->typekind) {
3690 case TKIND_ENUM:
3691 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3692 pTIHeader, pTITail);
3693 break;
3695 case TKIND_RECORD:
3696 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3697 pTIHeader, pTITail);
3698 break;
3700 case TKIND_INTERFACE:
3701 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3702 pTIHeader, pTITail);
3703 break;
3705 case TKIND_COCLASS:
3706 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3707 pTIHeader, pTITail);
3708 break;
3710 case TKIND_ALIAS:
3711 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3712 pTIHeader, pTITail);
3713 break;
3715 case TKIND_DISPATCH:
3716 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3717 pTIHeader, pTITail);
3718 break;
3720 case TKIND_MODULE:
3721 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3722 pTIHeader, pTITail);
3723 break;
3725 default:
3726 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3727 break;
3731 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3732 but we've already set those */
3733 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3734 X(06);
3735 X(16);
3736 X(18);
3737 X(1a);
3738 X(1e);
3739 X(24);
3740 X(26);
3741 X(2a);
3742 X(2c);
3743 X(2e);
3744 X(30);
3745 X(32);
3746 X(34);
3748 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3749 pBlk = (char*)pBlk + pBlkEntry[order].len;
3752 if(i != pTypeLibImpl->TypeInfoCount) {
3753 FIXME("Somehow processed %d TypeInfos\n", i);
3754 return NULL;
3757 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3758 return (ITypeLib2*)pTypeLibImpl;
3761 /* ITypeLib::QueryInterface
3763 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3764 ITypeLib2 * iface,
3765 REFIID riid,
3766 VOID **ppvObject)
3768 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3770 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3772 *ppvObject=NULL;
3773 if(IsEqualIID(riid, &IID_IUnknown) ||
3774 IsEqualIID(riid,&IID_ITypeLib)||
3775 IsEqualIID(riid,&IID_ITypeLib2))
3777 *ppvObject = This;
3780 if(*ppvObject)
3782 ITypeLib2_AddRef(iface);
3783 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3784 return S_OK;
3786 TRACE("-- Interface: E_NOINTERFACE\n");
3787 return E_NOINTERFACE;
3790 /* ITypeLib::AddRef
3792 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3794 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3795 ULONG ref = InterlockedIncrement(&This->ref);
3797 TRACE("(%p)->ref was %u\n",This, ref - 1);
3799 return ref;
3802 /* ITypeLib::Release
3804 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3806 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3807 ULONG ref = InterlockedDecrement(&This->ref);
3809 TRACE("(%p)->(%u)\n",This, ref);
3811 if (!ref)
3813 TLBImpLib *pImpLib, *pImpLibNext;
3814 TLBCustData *pCustData, *pCustDataNext;
3815 TLBRefType *ref_type;
3816 void *cursor2;
3817 int i;
3819 /* remove cache entry */
3820 if(This->path)
3822 TRACE("removing from cache list\n");
3823 EnterCriticalSection(&cache_section);
3824 if (This->next) This->next->prev = This->prev;
3825 if (This->prev) This->prev->next = This->next;
3826 else tlb_cache_first = This->next;
3827 LeaveCriticalSection(&cache_section);
3828 HeapFree(GetProcessHeap(), 0, This->path);
3830 TRACE(" destroying ITypeLib(%p)\n",This);
3832 if (This->Name)
3834 SysFreeString(This->Name);
3835 This->Name = NULL;
3838 if (This->DocString)
3840 SysFreeString(This->DocString);
3841 This->DocString = NULL;
3844 if (This->HelpFile)
3846 SysFreeString(This->HelpFile);
3847 This->HelpFile = NULL;
3850 if (This->HelpStringDll)
3852 SysFreeString(This->HelpStringDll);
3853 This->HelpStringDll = NULL;
3856 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
3858 VariantClear(&pCustData->data);
3860 pCustDataNext = pCustData->next;
3861 TLB_Free(pCustData);
3864 for (i = 0; i < This->ctTypeDesc; i++)
3865 if (This->pTypeDesc[i].vt == VT_CARRAY)
3866 TLB_Free(This->pTypeDesc[i].u.lpadesc);
3868 TLB_Free(This->pTypeDesc);
3870 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
3872 if (pImpLib->pImpTypeLib)
3873 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
3874 SysFreeString(pImpLib->name);
3876 pImpLibNext = pImpLib->next;
3877 TLB_Free(pImpLib);
3880 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
3882 list_remove(&ref_type->entry);
3883 TLB_Free(ref_type);
3886 if (This->pTypeInfo) /* can be NULL */
3887 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3888 HeapFree(GetProcessHeap(),0,This);
3889 return 0;
3892 return ref;
3895 /* ITypeLib::GetTypeInfoCount
3897 * Returns the number of type descriptions in the type library
3899 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3901 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3902 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3903 return This->TypeInfoCount;
3906 /* ITypeLib::GetTypeInfo
3908 * retrieves the specified type description in the library.
3910 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3911 ITypeLib2 *iface,
3912 UINT index,
3913 ITypeInfo **ppTInfo)
3915 int i;
3917 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3918 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3920 TRACE("(%p)->(index=%d)\n", This, index);
3922 if (!ppTInfo) return E_INVALIDARG;
3924 /* search element n in list */
3925 for(i=0; i < index; i++)
3927 pTypeInfo = pTypeInfo->next;
3928 if (!pTypeInfo)
3930 TRACE("-- element not found\n");
3931 return TYPE_E_ELEMENTNOTFOUND;
3935 *ppTInfo = (ITypeInfo *) pTypeInfo;
3937 ITypeInfo_AddRef(*ppTInfo);
3938 TRACE("-- found (%p)\n",*ppTInfo);
3939 return S_OK;
3943 /* ITypeLibs::GetTypeInfoType
3945 * Retrieves the type of a type description.
3947 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3948 ITypeLib2 *iface,
3949 UINT index,
3950 TYPEKIND *pTKind)
3952 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3953 int i;
3954 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3956 if (ITypeLib2_fnGetTypeInfoCount(iface) < index + 1)
3957 return TYPE_E_ELEMENTNOTFOUND;
3959 TRACE("(%p) index %d\n", This, index);
3961 if(!pTKind) return E_INVALIDARG;
3963 /* search element n in list */
3964 for(i=0; i < index; i++)
3966 if(!pTInfo)
3968 TRACE("-- element not found\n");
3969 return TYPE_E_ELEMENTNOTFOUND;
3971 pTInfo = pTInfo->next;
3974 *pTKind = pTInfo->TypeAttr.typekind;
3975 TRACE("-- found Type (%d)\n", *pTKind);
3976 return S_OK;
3979 /* ITypeLib::GetTypeInfoOfGuid
3981 * Retrieves the type description that corresponds to the specified GUID.
3984 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3985 ITypeLib2 *iface,
3986 REFGUID guid,
3987 ITypeInfo **ppTInfo)
3989 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3990 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3992 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3994 if (!pTypeInfo)
3996 WARN("-- element not found\n");
3997 return TYPE_E_ELEMENTNOTFOUND;
4000 /* search linked list for guid */
4001 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
4003 pTypeInfo = pTypeInfo->next;
4005 if (!pTypeInfo)
4007 /* end of list reached */
4008 WARN("-- element not found\n");
4009 return TYPE_E_ELEMENTNOTFOUND;
4013 TRACE("-- found (%p, %s)\n",
4014 pTypeInfo,
4015 debugstr_w(pTypeInfo->Name));
4017 *ppTInfo = (ITypeInfo*)pTypeInfo;
4018 ITypeInfo_AddRef(*ppTInfo);
4019 return S_OK;
4022 /* ITypeLib::GetLibAttr
4024 * Retrieves the structure that contains the library's attributes.
4027 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4028 ITypeLib2 *iface,
4029 LPTLIBATTR *ppTLibAttr)
4031 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4032 TRACE("(%p)\n",This);
4033 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
4034 **ppTLibAttr = This->LibAttr;
4035 return S_OK;
4038 /* ITypeLib::GetTypeComp
4040 * Enables a client compiler to bind to a library's types, variables,
4041 * constants, and global functions.
4044 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4045 ITypeLib2 *iface,
4046 ITypeComp **ppTComp)
4048 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4050 TRACE("(%p)->(%p)\n",This,ppTComp);
4051 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4052 ITypeComp_AddRef(*ppTComp);
4054 return S_OK;
4057 /* ITypeLib::GetDocumentation
4059 * Retrieves the library's documentation string, the complete Help file name
4060 * and path, and the context identifier for the library Help topic in the Help
4061 * file.
4063 * On a successful return all non-null BSTR pointers will have been set,
4064 * possibly to NULL.
4066 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4067 ITypeLib2 *iface,
4068 INT index,
4069 BSTR *pBstrName,
4070 BSTR *pBstrDocString,
4071 DWORD *pdwHelpContext,
4072 BSTR *pBstrHelpFile)
4074 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4076 HRESULT result = E_INVALIDARG;
4078 ITypeInfo *pTInfo;
4081 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4082 This, index,
4083 pBstrName, pBstrDocString,
4084 pdwHelpContext, pBstrHelpFile);
4086 if(index<0)
4088 /* documentation for the typelib */
4089 if(pBstrName)
4091 if (This->Name)
4093 if(!(*pBstrName = SysAllocString(This->Name)))
4094 goto memerr1;
4096 else
4097 *pBstrName = NULL;
4099 if(pBstrDocString)
4101 if (This->DocString)
4103 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4104 goto memerr2;
4106 else if (This->Name)
4108 if(!(*pBstrDocString = SysAllocString(This->Name)))
4109 goto memerr2;
4111 else
4112 *pBstrDocString = NULL;
4114 if(pdwHelpContext)
4116 *pdwHelpContext = This->dwHelpContext;
4118 if(pBstrHelpFile)
4120 if (This->HelpFile)
4122 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4123 goto memerr3;
4125 else
4126 *pBstrHelpFile = NULL;
4129 result = S_OK;
4131 else
4133 /* for a typeinfo */
4134 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4136 if(SUCCEEDED(result))
4138 result = ITypeInfo_GetDocumentation(pTInfo,
4139 MEMBERID_NIL,
4140 pBstrName,
4141 pBstrDocString,
4142 pdwHelpContext, pBstrHelpFile);
4144 ITypeInfo_Release(pTInfo);
4147 return result;
4148 memerr3:
4149 if (pBstrDocString) SysFreeString (*pBstrDocString);
4150 memerr2:
4151 if (pBstrName) SysFreeString (*pBstrName);
4152 memerr1:
4153 return STG_E_INSUFFICIENTMEMORY;
4156 /* ITypeLib::IsName
4158 * Indicates whether a passed-in string contains the name of a type or member
4159 * described in the library.
4162 static HRESULT WINAPI ITypeLib2_fnIsName(
4163 ITypeLib2 *iface,
4164 LPOLESTR szNameBuf,
4165 ULONG lHashVal,
4166 BOOL *pfName)
4168 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4169 ITypeInfoImpl *pTInfo;
4170 TLBFuncDesc *pFInfo;
4171 TLBVarDesc *pVInfo;
4172 int i;
4173 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4175 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4176 pfName);
4178 *pfName=TRUE;
4179 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
4180 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4181 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4182 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4183 for(i=0;i<pFInfo->funcdesc.cParams;i++)
4184 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
4185 goto ITypeLib2_fnIsName_exit;
4187 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4188 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4191 *pfName=FALSE;
4193 ITypeLib2_fnIsName_exit:
4194 TRACE("(%p)slow! search for %s: %s found!\n", This,
4195 debugstr_w(szNameBuf), *pfName?"NOT":"");
4197 return S_OK;
4200 /* ITypeLib::FindName
4202 * Finds occurrences of a type description in a type library. This may be used
4203 * to quickly verify that a name exists in a type library.
4206 static HRESULT WINAPI ITypeLib2_fnFindName(
4207 ITypeLib2 *iface,
4208 LPOLESTR szNameBuf,
4209 ULONG lHashVal,
4210 ITypeInfo **ppTInfo,
4211 MEMBERID *rgMemId,
4212 UINT16 *pcFound)
4214 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4215 ITypeInfoImpl *pTInfo;
4216 TLBFuncDesc *pFInfo;
4217 TLBVarDesc *pVInfo;
4218 int i,j = 0;
4219 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4221 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
4222 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4223 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4224 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4225 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
4226 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
4227 goto ITypeLib2_fnFindName_exit;
4230 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4231 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4232 continue;
4233 ITypeLib2_fnFindName_exit:
4234 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4235 ppTInfo[j]=(LPTYPEINFO)pTInfo;
4236 j++;
4238 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4239 This, *pcFound, debugstr_w(szNameBuf), j);
4241 *pcFound=j;
4243 return S_OK;
4246 /* ITypeLib::ReleaseTLibAttr
4248 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4251 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4252 ITypeLib2 *iface,
4253 TLIBATTR *pTLibAttr)
4255 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4256 TRACE("freeing (%p)\n",This);
4257 HeapFree(GetProcessHeap(),0,pTLibAttr);
4261 /* ITypeLib2::GetCustData
4263 * gets the custom data
4265 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4266 ITypeLib2 * iface,
4267 REFGUID guid,
4268 VARIANT *pVarVal)
4270 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4271 TLBCustData *pCData;
4273 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4275 if( IsEqualIID(guid, &pCData->guid)) break;
4278 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4280 if(pCData)
4282 VariantInit( pVarVal);
4283 VariantCopy( pVarVal, &pCData->data);
4284 return S_OK;
4286 return E_INVALIDARG; /* FIXME: correct? */
4289 /* ITypeLib2::GetLibStatistics
4291 * Returns statistics about a type library that are required for efficient
4292 * sizing of hash tables.
4295 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4296 ITypeLib2 * iface,
4297 ULONG *pcUniqueNames,
4298 ULONG *pcchUniqueNames)
4300 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4302 FIXME("(%p): stub!\n", This);
4304 if(pcUniqueNames) *pcUniqueNames=1;
4305 if(pcchUniqueNames) *pcchUniqueNames=1;
4306 return S_OK;
4309 /* ITypeLib2::GetDocumentation2
4311 * Retrieves the library's documentation string, the complete Help file name
4312 * and path, the localization context to use, and the context ID for the
4313 * library Help topic in the Help file.
4316 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4317 ITypeLib2 * iface,
4318 INT index,
4319 LCID lcid,
4320 BSTR *pbstrHelpString,
4321 DWORD *pdwHelpStringContext,
4322 BSTR *pbstrHelpStringDll)
4324 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4325 HRESULT result;
4326 ITypeInfo *pTInfo;
4328 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4330 /* the help string should be obtained from the helpstringdll,
4331 * using the _DLLGetDocumentation function, based on the supplied
4332 * lcid. Nice to do sometime...
4334 if(index<0)
4336 /* documentation for the typelib */
4337 if(pbstrHelpString)
4338 *pbstrHelpString=SysAllocString(This->DocString);
4339 if(pdwHelpStringContext)
4340 *pdwHelpStringContext=This->dwHelpContext;
4341 if(pbstrHelpStringDll)
4342 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4344 result = S_OK;
4346 else
4348 /* for a typeinfo */
4349 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4351 if(SUCCEEDED(result))
4353 ITypeInfo2 * pTInfo2;
4354 result = ITypeInfo_QueryInterface(pTInfo,
4355 &IID_ITypeInfo2,
4356 (LPVOID*) &pTInfo2);
4358 if(SUCCEEDED(result))
4360 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4361 MEMBERID_NIL,
4362 lcid,
4363 pbstrHelpString,
4364 pdwHelpStringContext,
4365 pbstrHelpStringDll);
4367 ITypeInfo2_Release(pTInfo2);
4370 ITypeInfo_Release(pTInfo);
4373 return result;
4376 /* ITypeLib2::GetAllCustData
4378 * Gets all custom data items for the library.
4381 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4382 ITypeLib2 * iface,
4383 CUSTDATA *pCustData)
4385 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4386 TLBCustData *pCData;
4387 int i;
4388 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4389 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4390 if(pCustData->prgCustData ){
4391 pCustData->cCustData=This->ctCustData;
4392 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4393 pCustData->prgCustData[i].guid=pCData->guid;
4394 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4396 }else{
4397 ERR(" OUT OF MEMORY!\n");
4398 return E_OUTOFMEMORY;
4400 return S_OK;
4403 static const ITypeLib2Vtbl tlbvt = {
4404 ITypeLib2_fnQueryInterface,
4405 ITypeLib2_fnAddRef,
4406 ITypeLib2_fnRelease,
4407 ITypeLib2_fnGetTypeInfoCount,
4408 ITypeLib2_fnGetTypeInfo,
4409 ITypeLib2_fnGetTypeInfoType,
4410 ITypeLib2_fnGetTypeInfoOfGuid,
4411 ITypeLib2_fnGetLibAttr,
4412 ITypeLib2_fnGetTypeComp,
4413 ITypeLib2_fnGetDocumentation,
4414 ITypeLib2_fnIsName,
4415 ITypeLib2_fnFindName,
4416 ITypeLib2_fnReleaseTLibAttr,
4418 ITypeLib2_fnGetCustData,
4419 ITypeLib2_fnGetLibStatistics,
4420 ITypeLib2_fnGetDocumentation2,
4421 ITypeLib2_fnGetAllCustData
4425 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4427 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4429 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4432 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4434 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4436 return ITypeLib2_AddRef((ITypeLib2 *)This);
4439 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4441 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4443 return ITypeLib2_Release((ITypeLib2 *)This);
4446 static HRESULT WINAPI ITypeLibComp_fnBind(
4447 ITypeComp * iface,
4448 OLECHAR * szName,
4449 ULONG lHash,
4450 WORD wFlags,
4451 ITypeInfo ** ppTInfo,
4452 DESCKIND * pDescKind,
4453 BINDPTR * pBindPtr)
4455 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4456 ITypeInfoImpl *pTypeInfo;
4458 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4460 *pDescKind = DESCKIND_NONE;
4461 pBindPtr->lptcomp = NULL;
4462 *ppTInfo = NULL;
4464 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4466 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4468 /* FIXME: check wFlags here? */
4469 /* FIXME: we should use a hash table to look this info up using lHash
4470 * instead of an O(n) search */
4471 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4472 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4474 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4476 *pDescKind = DESCKIND_TYPECOMP;
4477 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4478 ITypeComp_AddRef(pBindPtr->lptcomp);
4479 TRACE("module or enum: %s\n", debugstr_w(szName));
4480 return S_OK;
4484 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4485 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4487 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4488 HRESULT hr;
4490 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4491 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4493 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4494 return S_OK;
4498 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4499 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4501 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4502 HRESULT hr;
4503 ITypeInfo *subtypeinfo;
4504 BINDPTR subbindptr;
4505 DESCKIND subdesckind;
4507 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4508 &subtypeinfo, &subdesckind, &subbindptr);
4509 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4511 TYPEDESC tdesc_appobject =
4514 (TYPEDESC *)pTypeInfo->hreftype
4516 VT_USERDEFINED
4518 const VARDESC vardesc_appobject =
4520 -2, /* memid */
4521 NULL, /* lpstrSchema */
4523 0 /* oInst */
4526 /* ELEMDESC */
4528 /* TYPEDESC */
4530 &tdesc_appobject
4532 VT_PTR
4535 0, /* wVarFlags */
4536 VAR_STATIC /* varkind */
4539 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4541 /* cleanup things filled in by Bind call so we can put our
4542 * application object data in there instead */
4543 switch (subdesckind)
4545 case DESCKIND_FUNCDESC:
4546 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4547 break;
4548 case DESCKIND_VARDESC:
4549 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4550 break;
4551 default:
4552 break;
4554 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4556 if (pTypeInfo->hreftype == -1)
4557 FIXME("no hreftype for interface %p\n", pTypeInfo);
4559 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4560 if (FAILED(hr))
4561 return hr;
4563 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4564 *ppTInfo = (ITypeInfo *)pTypeInfo;
4565 ITypeInfo_AddRef(*ppTInfo);
4566 return S_OK;
4571 TRACE("name not found %s\n", debugstr_w(szName));
4572 return S_OK;
4575 static HRESULT WINAPI ITypeLibComp_fnBindType(
4576 ITypeComp * iface,
4577 OLECHAR * szName,
4578 ULONG lHash,
4579 ITypeInfo ** ppTInfo,
4580 ITypeComp ** ppTComp)
4582 FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4583 return E_NOTIMPL;
4586 static const ITypeCompVtbl tlbtcvt =
4589 ITypeLibComp_fnQueryInterface,
4590 ITypeLibComp_fnAddRef,
4591 ITypeLibComp_fnRelease,
4593 ITypeLibComp_fnBind,
4594 ITypeLibComp_fnBindType
4597 /*================== ITypeInfo(2) Methods ===================================*/
4598 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4600 ITypeInfoImpl * pTypeInfoImpl;
4602 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4603 if (pTypeInfoImpl)
4605 pTypeInfoImpl->lpVtbl = &tinfvt;
4606 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4607 pTypeInfoImpl->ref=1;
4608 pTypeInfoImpl->hreftype = -1;
4609 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4610 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4612 TRACE("(%p)\n", pTypeInfoImpl);
4613 return (ITypeInfo2*) pTypeInfoImpl;
4616 /* ITypeInfo::QueryInterface
4618 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4619 ITypeInfo2 *iface,
4620 REFIID riid,
4621 VOID **ppvObject)
4623 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4625 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4627 *ppvObject=NULL;
4628 if(IsEqualIID(riid, &IID_IUnknown) ||
4629 IsEqualIID(riid,&IID_ITypeInfo)||
4630 IsEqualIID(riid,&IID_ITypeInfo2))
4631 *ppvObject = This;
4633 if(*ppvObject){
4634 ITypeInfo_AddRef(iface);
4635 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4636 return S_OK;
4638 TRACE("-- Interface: E_NOINTERFACE\n");
4639 return E_NOINTERFACE;
4642 /* ITypeInfo::AddRef
4644 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4646 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4647 ULONG ref = InterlockedIncrement(&This->ref);
4649 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4651 TRACE("(%p)->ref is %u\n",This, ref);
4652 return ref;
4655 /* ITypeInfo::Release
4657 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4659 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4660 ULONG ref = InterlockedDecrement(&This->ref);
4662 TRACE("(%p)->(%u)\n",This, ref);
4664 if (ref) {
4665 /* We don't release ITypeLib when ref=0 because
4666 it means that function is called by ITypeLib2_Release */
4667 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4668 } else {
4669 TLBFuncDesc *pFInfo, *pFInfoNext;
4670 TLBVarDesc *pVInfo, *pVInfoNext;
4671 TLBImplType *pImpl, *pImplNext;
4673 TRACE("destroying ITypeInfo(%p)\n",This);
4675 if (This->no_free_data)
4676 goto finish_free;
4678 if (This->Name)
4680 SysFreeString(This->Name);
4681 This->Name = 0;
4684 if (This->DocString)
4686 SysFreeString(This->DocString);
4687 This->DocString = 0;
4690 if (This->DllName)
4692 SysFreeString(This->DllName);
4693 This->DllName = 0;
4696 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4698 UINT i;
4699 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4701 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4702 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4704 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4705 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4707 SysFreeString(pFInfo->pParamDesc[i].Name);
4709 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4710 TLB_Free(pFInfo->pParamDesc);
4711 TLB_FreeCustData(pFInfo->pCustData);
4712 if (HIWORD(pFInfo->Entry) != 0 && pFInfo->Entry != (BSTR)-1)
4713 SysFreeString(pFInfo->Entry);
4714 SysFreeString(pFInfo->HelpString);
4715 SysFreeString(pFInfo->Name);
4717 pFInfoNext = pFInfo->next;
4718 TLB_Free(pFInfo);
4720 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
4722 if (pVInfo->vardesc.varkind == VAR_CONST)
4724 VariantClear(pVInfo->vardesc.u.lpvarValue);
4725 TLB_Free(pVInfo->vardesc.u.lpvarValue);
4727 TLB_FreeCustData(pVInfo->pCustData);
4728 SysFreeString(pVInfo->Name);
4729 pVInfoNext = pVInfo->next;
4730 TLB_Free(pVInfo);
4732 for(pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
4734 TLB_FreeCustData(pImpl->pCustData);
4735 pImplNext = pImpl->next;
4736 TLB_Free(pImpl);
4738 TLB_FreeCustData(This->pCustData);
4740 finish_free:
4741 if (This->next)
4743 ITypeInfo_Release((ITypeInfo*)This->next);
4746 HeapFree(GetProcessHeap(),0,This);
4747 return 0;
4749 return ref;
4752 /* ITypeInfo::GetTypeAttr
4754 * Retrieves a TYPEATTR structure that contains the attributes of the type
4755 * description.
4758 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4759 LPTYPEATTR *ppTypeAttr)
4761 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4762 SIZE_T size;
4764 TRACE("(%p)\n",This);
4766 size = sizeof(**ppTypeAttr);
4767 if (This->TypeAttr.typekind == TKIND_ALIAS)
4768 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4770 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4771 if (!*ppTypeAttr)
4772 return E_OUTOFMEMORY;
4774 **ppTypeAttr = This->TypeAttr;
4776 if (This->TypeAttr.typekind == TKIND_ALIAS)
4777 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4778 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4780 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4781 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4782 funcs */
4783 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4784 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4786 return S_OK;
4789 /* ITypeInfo::GetTypeComp
4791 * Retrieves the ITypeComp interface for the type description, which enables a
4792 * client compiler to bind to the type description's members.
4795 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4796 ITypeComp * *ppTComp)
4798 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4800 TRACE("(%p)->(%p)\n", This, ppTComp);
4802 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4803 ITypeComp_AddRef(*ppTComp);
4804 return S_OK;
4807 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4809 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4810 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4811 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4812 return size;
4815 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4817 *dest = *src;
4818 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4819 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4821 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4822 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4823 *buffer += sizeof(PARAMDESCEX);
4824 *pparamdescex_dest = *pparamdescex_src;
4825 VariantInit(&pparamdescex_dest->varDefaultValue);
4826 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4827 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4829 else
4830 dest->u.paramdesc.pparamdescex = NULL;
4831 return S_OK;
4834 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4836 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4837 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4840 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4842 FUNCDESC *dest;
4843 char *buffer;
4844 SIZE_T size = sizeof(*src);
4845 SHORT i;
4846 HRESULT hr;
4848 size += sizeof(*src->lprgscode) * src->cScodes;
4849 size += TLB_SizeElemDesc(&src->elemdescFunc);
4850 for (i = 0; i < src->cParams; i++)
4852 size += sizeof(ELEMDESC);
4853 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4856 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4857 if (!dest) return E_OUTOFMEMORY;
4859 *dest = *src;
4860 if (dispinterface) /* overwrite funckind */
4861 dest->funckind = FUNC_DISPATCH;
4862 buffer = (char *)(dest + 1);
4864 dest->lprgscode = (SCODE *)buffer;
4865 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4866 buffer += sizeof(*src->lprgscode) * src->cScodes;
4868 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4869 if (FAILED(hr))
4871 SysFreeString((BSTR)dest);
4872 return hr;
4875 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4876 buffer += sizeof(ELEMDESC) * src->cParams;
4877 for (i = 0; i < src->cParams; i++)
4879 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4880 if (FAILED(hr))
4881 break;
4883 if (FAILED(hr))
4885 /* undo the above actions */
4886 for (i = i - 1; i >= 0; i--)
4887 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4888 TLB_FreeElemDesc(&dest->elemdescFunc);
4889 SysFreeString((BSTR)dest);
4890 return hr;
4893 /* special treatment for dispinterfaces: this makes functions appear
4894 * to return their [retval] value when it is really returning an
4895 * HRESULT */
4896 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4898 if (dest->cParams &&
4899 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4901 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4902 if (elemdesc->tdesc.vt != VT_PTR)
4904 ERR("elemdesc should have started with VT_PTR instead of:\n");
4905 if (ERR_ON(ole))
4906 dump_ELEMDESC(elemdesc);
4907 return E_UNEXPECTED;
4910 /* copy last parameter to the return value. we are using a flat
4911 * buffer so there is no danger of leaking memory in
4912 * elemdescFunc */
4913 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4915 /* remove the last parameter */
4916 dest->cParams--;
4918 else
4919 /* otherwise this function is made to appear to have no return
4920 * value */
4921 dest->elemdescFunc.tdesc.vt = VT_VOID;
4925 *dest_ptr = dest;
4926 return S_OK;
4929 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4931 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4932 const TLBFuncDesc *pFDesc;
4933 int i;
4935 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4938 if (pFDesc)
4940 *ppFuncDesc = &pFDesc->funcdesc;
4941 return S_OK;
4944 return TYPE_E_ELEMENTNOTFOUND;
4947 /* internal function to make the inherited interfaces' methods appear
4948 * part of the interface */
4949 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
4950 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
4952 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4953 HRESULT hr;
4954 UINT implemented_funcs = 0;
4956 if (funcs)
4957 *funcs = 0;
4958 else
4959 *hrefoffset = DISPATCH_HREF_OFFSET;
4961 if(This->impltypelist)
4963 ITypeInfo *pSubTypeInfo;
4964 UINT sub_funcs;
4966 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
4967 if (FAILED(hr))
4968 return hr;
4970 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
4971 index,
4972 ppFuncDesc,
4973 &sub_funcs, hrefoffset);
4974 implemented_funcs += sub_funcs;
4975 ITypeInfo_Release(pSubTypeInfo);
4976 if (SUCCEEDED(hr))
4977 return hr;
4978 *hrefoffset += DISPATCH_HREF_OFFSET;
4981 if (funcs)
4982 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
4983 else
4984 *hrefoffset = 0;
4986 if (index < implemented_funcs)
4987 return E_INVALIDARG;
4988 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
4989 ppFuncDesc);
4992 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
4994 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
4995 while (TRUE)
4997 switch (pTypeDesc->vt)
4999 case VT_USERDEFINED:
5000 pTypeDesc->u.hreftype += hrefoffset;
5001 return;
5002 case VT_PTR:
5003 case VT_SAFEARRAY:
5004 pTypeDesc = pTypeDesc->u.lptdesc;
5005 break;
5006 case VT_CARRAY:
5007 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5008 break;
5009 default:
5010 return;
5015 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5017 SHORT i;
5018 for (i = 0; i < pFuncDesc->cParams; i++)
5019 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5020 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5023 /* ITypeInfo::GetFuncDesc
5025 * Retrieves the FUNCDESC structure that contains information about a
5026 * specified function.
5029 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5030 LPFUNCDESC *ppFuncDesc)
5032 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5033 const FUNCDESC *internal_funcdesc;
5034 HRESULT hr;
5035 UINT hrefoffset = 0;
5037 TRACE("(%p) index %d\n", This, index);
5039 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5040 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5041 &internal_funcdesc, NULL,
5042 &hrefoffset);
5043 else
5044 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5045 &internal_funcdesc);
5046 if (FAILED(hr))
5048 WARN("description for function %d not found\n", index);
5049 return hr;
5052 hr = TLB_AllocAndInitFuncDesc(
5053 internal_funcdesc,
5054 ppFuncDesc,
5055 This->TypeAttr.typekind == TKIND_DISPATCH);
5057 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5058 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5060 TRACE("-- 0x%08x\n", hr);
5061 return hr;
5064 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5066 VARDESC *dest;
5067 char *buffer;
5068 SIZE_T size = sizeof(*src);
5069 HRESULT hr;
5071 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5072 if (src->varkind == VAR_CONST)
5073 size += sizeof(VARIANT);
5074 size += TLB_SizeElemDesc(&src->elemdescVar);
5076 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5077 if (!dest) return E_OUTOFMEMORY;
5079 *dest = *src;
5080 buffer = (char *)(dest + 1);
5081 if (src->lpstrSchema)
5083 int len;
5084 dest->lpstrSchema = (LPOLESTR)buffer;
5085 len = strlenW(src->lpstrSchema);
5086 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5087 buffer += (len + 1) * sizeof(WCHAR);
5090 if (src->varkind == VAR_CONST)
5092 HRESULT hr;
5094 dest->u.lpvarValue = (VARIANT *)buffer;
5095 *dest->u.lpvarValue = *src->u.lpvarValue;
5096 buffer += sizeof(VARIANT);
5097 VariantInit(dest->u.lpvarValue);
5098 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5099 if (FAILED(hr))
5101 SysFreeString((BSTR)dest_ptr);
5102 return hr;
5105 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5106 if (FAILED(hr))
5108 if (src->varkind == VAR_CONST)
5109 VariantClear(dest->u.lpvarValue);
5110 SysFreeString((BSTR)dest);
5111 return hr;
5113 *dest_ptr = dest;
5114 return S_OK;
5117 /* ITypeInfo::GetVarDesc
5119 * Retrieves a VARDESC structure that describes the specified variable.
5122 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5123 LPVARDESC *ppVarDesc)
5125 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5126 int i;
5127 const TLBVarDesc *pVDesc;
5129 TRACE("(%p) index %d\n", This, index);
5131 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
5134 if (pVDesc)
5135 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5137 return E_INVALIDARG;
5140 /* ITypeInfo_GetNames
5142 * Retrieves the variable with the specified member ID (or the name of the
5143 * property or method and its parameters) that correspond to the specified
5144 * function ID.
5146 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5147 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5149 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5150 const TLBFuncDesc *pFDesc;
5151 const TLBVarDesc *pVDesc;
5152 int i;
5153 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5154 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
5155 if(pFDesc)
5157 /* function found, now return function and parameter names */
5158 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5160 if(!i)
5161 *rgBstrNames=SysAllocString(pFDesc->Name);
5162 else
5163 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5165 *pcNames=i;
5167 else
5169 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
5170 if(pVDesc)
5172 *rgBstrNames=SysAllocString(pVDesc->Name);
5173 *pcNames=1;
5175 else
5177 if(This->impltypelist &&
5178 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5179 /* recursive search */
5180 ITypeInfo *pTInfo;
5181 HRESULT result;
5182 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5183 &pTInfo);
5184 if(SUCCEEDED(result))
5186 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5187 ITypeInfo_Release(pTInfo);
5188 return result;
5190 WARN("Could not search inherited interface!\n");
5192 else
5194 WARN("no names found\n");
5196 *pcNames=0;
5197 return TYPE_E_ELEMENTNOTFOUND;
5200 return S_OK;
5204 /* ITypeInfo::GetRefTypeOfImplType
5206 * If a type description describes a COM class, it retrieves the type
5207 * description of the implemented interface types. For an interface,
5208 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5209 * if any exist.
5212 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5213 ITypeInfo2 *iface,
5214 UINT index,
5215 HREFTYPE *pRefType)
5217 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5218 int i;
5219 HRESULT hr = S_OK;
5220 const TLBImplType *pImpl = This->impltypelist;
5222 TRACE("(%p) index %d\n", This, index);
5223 if (TRACE_ON(ole)) dump_TypeInfo(This);
5225 if(index==(UINT)-1)
5227 /* only valid on dual interfaces;
5228 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5230 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5232 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
5233 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
5235 *pRefType = -1;
5237 else
5239 hr = TYPE_E_ELEMENTNOTFOUND;
5242 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5244 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5245 *pRefType = This->pTypeLib->dispatch_href;
5247 else
5249 /* get element n from linked list */
5250 for(i=0; pImpl && i<index; i++)
5252 pImpl = pImpl->next;
5255 if (pImpl)
5256 *pRefType = pImpl->hRef;
5257 else
5258 hr = TYPE_E_ELEMENTNOTFOUND;
5261 if(TRACE_ON(ole))
5263 if(SUCCEEDED(hr))
5264 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5265 else
5266 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5269 return hr;
5272 /* ITypeInfo::GetImplTypeFlags
5274 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5275 * or base interface in a type description.
5277 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5278 UINT index, INT *pImplTypeFlags)
5280 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5281 int i;
5282 TLBImplType *pImpl;
5284 TRACE("(%p) index %d\n", This, index);
5285 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5286 i++, pImpl=pImpl->next)
5288 if(i==index && pImpl){
5289 *pImplTypeFlags=pImpl->implflags;
5290 return S_OK;
5292 *pImplTypeFlags=0;
5293 return TYPE_E_ELEMENTNOTFOUND;
5296 /* GetIDsOfNames
5297 * Maps between member names and member IDs, and parameter names and
5298 * parameter IDs.
5300 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5301 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5303 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5304 const TLBFuncDesc *pFDesc;
5305 const TLBVarDesc *pVDesc;
5306 HRESULT ret=S_OK;
5307 int i;
5309 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5310 cNames);
5312 /* init out parameters in case of failure */
5313 for (i = 0; i < cNames; i++)
5314 pMemId[i] = MEMBERID_NIL;
5316 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5317 int j;
5318 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5319 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5320 for(i=1; i < cNames; i++){
5321 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5322 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5323 break;
5324 if( j<pFDesc->funcdesc.cParams)
5325 pMemId[i]=j;
5326 else
5327 ret=DISP_E_UNKNOWNNAME;
5329 TRACE("-- 0x%08x\n", ret);
5330 return ret;
5333 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5334 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5335 if(cNames) *pMemId=pVDesc->vardesc.memid;
5336 return ret;
5339 /* not found, see if it can be found in an inherited interface */
5340 if(This->impltypelist) {
5341 /* recursive search */
5342 ITypeInfo *pTInfo;
5343 ret=ITypeInfo_GetRefTypeInfo(iface,
5344 This->impltypelist->hRef, &pTInfo);
5345 if(SUCCEEDED(ret)){
5346 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5347 ITypeInfo_Release(pTInfo);
5348 return ret;
5350 WARN("Could not search inherited interface!\n");
5351 } else
5352 WARN("no names found\n");
5353 return DISP_E_UNKNOWNNAME;
5356 /* ITypeInfo::Invoke
5358 * Invokes a method, or accesses a property of an object, that implements the
5359 * interface described by the type description.
5361 DWORD
5362 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5363 DWORD res;
5365 if (TRACE_ON(ole)) {
5366 int i;
5367 TRACE("Calling %p(",func);
5368 for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
5369 TRACE(")\n");
5372 switch (callconv) {
5373 case CC_STDCALL:
5375 switch (nrargs) {
5376 case 0:
5377 res = func();
5378 break;
5379 case 1:
5380 res = func(args[0]);
5381 break;
5382 case 2:
5383 res = func(args[0],args[1]);
5384 break;
5385 case 3:
5386 res = func(args[0],args[1],args[2]);
5387 break;
5388 case 4:
5389 res = func(args[0],args[1],args[2],args[3]);
5390 break;
5391 case 5:
5392 res = func(args[0],args[1],args[2],args[3],args[4]);
5393 break;
5394 case 6:
5395 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
5396 break;
5397 case 7:
5398 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
5399 break;
5400 case 8:
5401 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
5402 break;
5403 case 9:
5404 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
5405 break;
5406 case 10:
5407 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
5408 break;
5409 case 11:
5410 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
5411 break;
5412 case 12:
5413 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11]);
5414 break;
5415 case 13:
5416 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12]);
5417 break;
5418 case 14:
5419 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13]);
5420 break;
5421 case 15:
5422 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14]);
5423 break;
5424 case 16:
5425 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15]);
5426 break;
5427 case 17:
5428 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16]);
5429 break;
5430 case 18:
5431 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17]);
5432 break;
5433 case 19:
5434 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]);
5435 break;
5436 case 20:
5437 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]);
5438 break;
5439 case 21:
5440 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]);
5441 break;
5442 case 22:
5443 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]);
5444 break;
5445 case 23:
5446 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]);
5447 break;
5448 case 24:
5449 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]);
5450 break;
5451 case 25:
5452 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]);
5453 break;
5454 case 26:
5455 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]);
5456 break;
5457 case 27:
5458 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]);
5459 break;
5460 case 28:
5461 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]);
5462 break;
5463 case 29:
5464 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]);
5465 break;
5466 case 30:
5467 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]);
5468 break;
5469 default:
5470 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
5471 res = -1;
5472 break;
5474 break;
5475 default:
5476 FIXME("unsupported calling convention %d\n",callconv);
5477 res = -1;
5478 break;
5480 TRACE("returns %08x\n",res);
5481 return res;
5484 extern int _argsize(DWORD vt);
5486 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5488 HRESULT hr = S_OK;
5489 ITypeInfo *tinfo2 = NULL;
5490 TYPEATTR *tattr = NULL;
5492 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5493 if (hr)
5495 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5496 "hr = 0x%08x\n",
5497 tdesc->u.hreftype, hr);
5498 return hr;
5500 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5501 if (hr)
5503 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5504 ITypeInfo_Release(tinfo2);
5505 return hr;
5508 switch (tattr->typekind)
5510 case TKIND_ENUM:
5511 *vt |= VT_I4;
5512 break;
5514 case TKIND_ALIAS:
5515 tdesc = &tattr->tdescAlias;
5516 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5517 break;
5519 case TKIND_INTERFACE:
5520 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5521 *vt |= VT_DISPATCH;
5522 else
5523 *vt |= VT_UNKNOWN;
5524 break;
5526 case TKIND_DISPATCH:
5527 *vt |= VT_DISPATCH;
5528 break;
5530 case TKIND_COCLASS:
5531 *vt |= VT_DISPATCH;
5532 break;
5534 case TKIND_RECORD:
5535 FIXME("TKIND_RECORD unhandled.\n");
5536 hr = E_NOTIMPL;
5537 break;
5539 case TKIND_UNION:
5540 FIXME("TKIND_UNION unhandled.\n");
5541 hr = E_NOTIMPL;
5542 break;
5544 default:
5545 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5546 hr = E_NOTIMPL;
5547 break;
5549 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5550 ITypeInfo_Release(tinfo2);
5551 return hr;
5554 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5556 HRESULT hr = S_OK;
5558 /* enforce only one level of pointer indirection */
5559 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5561 tdesc = tdesc->u.lptdesc;
5563 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5564 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5565 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5566 if ((tdesc->vt == VT_USERDEFINED) ||
5567 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5569 VARTYPE vt_userdefined = 0;
5570 const TYPEDESC *tdesc_userdefined = tdesc;
5571 if (tdesc->vt == VT_PTR)
5573 vt_userdefined = VT_BYREF;
5574 tdesc_userdefined = tdesc->u.lptdesc;
5576 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5577 if ((hr == S_OK) &&
5578 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5579 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5581 *vt |= vt_userdefined;
5582 return S_OK;
5585 *vt = VT_BYREF;
5588 switch (tdesc->vt)
5590 case VT_HRESULT:
5591 *vt |= VT_ERROR;
5592 break;
5593 case VT_USERDEFINED:
5594 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5595 break;
5596 case VT_VOID:
5597 case VT_CARRAY:
5598 case VT_PTR:
5599 case VT_LPSTR:
5600 case VT_LPWSTR:
5601 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5602 hr = DISP_E_BADVARTYPE;
5603 break;
5604 case VT_SAFEARRAY:
5605 *vt |= VT_ARRAY;
5606 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5607 break;
5608 default:
5609 *vt |= tdesc->vt;
5610 break;
5612 return hr;
5615 /***********************************************************************
5616 * DispCallFunc (OLEAUT32.@)
5618 * Invokes a function of the specified calling convention, passing the
5619 * specified arguments and returns the result.
5621 * PARAMS
5622 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5623 * oVft [I] The offset in the vtable. See notes.
5624 * cc [I] Calling convention of the function to call.
5625 * vtReturn [I] The return type of the function.
5626 * cActuals [I] Number of parameters.
5627 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5628 * prgpvarg [I] The arguments to pass.
5629 * pvargResult [O] The return value of the function. Can be NULL.
5631 * RETURNS
5632 * Success: S_OK.
5633 * Failure: HRESULT code.
5635 * NOTES
5636 * The HRESULT return value of this function is not affected by the return
5637 * value of the user supplied function, which is returned in pvargResult.
5639 * If pvInstance is NULL then a non-object function is to be called and oVft
5640 * is the address of the function to call.
5642 * The cc parameter can be one of the following values:
5643 *|CC_FASTCALL
5644 *|CC_CDECL
5645 *|CC_PASCAL
5646 *|CC_STDCALL
5647 *|CC_FPFASTCALL
5648 *|CC_SYSCALL
5649 *|CC_MPWCDECL
5650 *|CC_MPWPASCAL
5653 HRESULT WINAPI
5654 DispCallFunc(
5655 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5656 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5658 int i, argsize, argspos;
5659 DWORD *args;
5660 HRESULT hres;
5662 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5663 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5664 pvargResult, V_VT(pvargResult));
5666 argsize = 0;
5667 if (pvInstance)
5668 argsize++; /* for This pointer */
5670 for (i=0;i<cActuals;i++)
5672 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5673 dump_Variant(prgpvarg[i]);
5674 argsize += _argsize(prgvt[i]);
5676 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5678 argspos = 0;
5679 if (pvInstance)
5681 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5682 argspos++;
5685 for (i=0;i<cActuals;i++)
5687 VARIANT *arg = prgpvarg[i];
5688 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5689 if (prgvt[i] == VT_VARIANT)
5690 memcpy(&args[argspos], arg, _argsize(prgvt[i]) * sizeof(DWORD));
5691 else
5692 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5693 argspos += _argsize(prgvt[i]);
5696 if (pvInstance)
5698 FARPROC *vtable = *(FARPROC**)pvInstance;
5699 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5701 else
5702 /* if we aren't invoking an object then the function pointer is stored
5703 * in oVft */
5704 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5706 if (pvargResult && (vtReturn != VT_EMPTY))
5708 TRACE("Method returned 0x%08x\n",hres);
5709 V_VT(pvargResult) = vtReturn;
5710 V_UI4(pvargResult) = hres;
5713 HeapFree(GetProcessHeap(),0,args);
5714 return S_OK;
5717 #define INVBUF_ELEMENT_SIZE \
5718 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5719 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5720 ((VARIANTARG *)(buffer))
5721 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5722 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5723 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5724 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5725 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5726 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5728 static HRESULT WINAPI ITypeInfo_fnInvoke(
5729 ITypeInfo2 *iface,
5730 VOID *pIUnk,
5731 MEMBERID memid,
5732 UINT16 wFlags,
5733 DISPPARAMS *pDispParams,
5734 VARIANT *pVarResult,
5735 EXCEPINFO *pExcepInfo,
5736 UINT *pArgErr)
5738 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5739 int i;
5740 unsigned int var_index;
5741 TYPEKIND type_kind;
5742 HRESULT hres;
5743 const TLBFuncDesc *pFuncInfo;
5745 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
5746 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5749 if (!pDispParams)
5751 ERR("NULL pDispParams not allowed\n");
5752 return E_INVALIDARG;
5755 dump_DispParms(pDispParams);
5757 if (pDispParams->cNamedArgs > pDispParams->cArgs)
5759 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
5760 pDispParams->cNamedArgs, pDispParams->cArgs);
5761 return E_INVALIDARG;
5764 /* we do this instead of using GetFuncDesc since it will return a fake
5765 * FUNCDESC for dispinterfaces and we want the real function description */
5766 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5767 if ((memid == pFuncInfo->funcdesc.memid) &&
5768 (wFlags & pFuncInfo->funcdesc.invkind))
5769 break;
5771 if (pFuncInfo) {
5772 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5774 if (TRACE_ON(ole))
5776 TRACE("invoking:\n");
5777 dump_TLBFuncDescOne(pFuncInfo);
5780 switch (func_desc->funckind) {
5781 case FUNC_PUREVIRTUAL:
5782 case FUNC_VIRTUAL: {
5783 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
5784 VARIANT varresult;
5785 VARIANT retval; /* pointer for storing byref retvals in */
5786 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
5787 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
5788 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
5789 UINT cNamedArgs = pDispParams->cNamedArgs;
5790 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
5792 hres = S_OK;
5794 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
5796 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
5798 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
5799 hres = DISP_E_PARAMNOTFOUND;
5800 goto func_fail;
5802 /* ignore the DISPID_PROPERTYPUT named argument from now on */
5803 cNamedArgs--;
5804 rgdispidNamedArgs++;
5807 if (func_desc->cParamsOpt < 0 && cNamedArgs)
5809 ERR("functions with the vararg attribute do not support named arguments\n");
5810 hres = DISP_E_NONAMEDARGS;
5811 goto func_fail;
5814 for (i = 0; i < func_desc->cParams; i++)
5816 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5817 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
5818 if (FAILED(hres))
5819 goto func_fail;
5822 TRACE("changing args\n");
5823 for (i = 0; i < func_desc->cParams; i++)
5825 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5826 VARIANTARG *src_arg;
5828 if (cNamedArgs)
5830 USHORT j;
5831 src_arg = NULL;
5832 for (j = 0; j < cNamedArgs; j++)
5833 if (rgdispidNamedArgs[j] == i)
5835 src_arg = &pDispParams->rgvarg[j];
5836 break;
5839 else
5840 src_arg = i < pDispParams->cArgs ? &pDispParams->rgvarg[pDispParams->cArgs - 1 - i] : NULL;
5842 if (wParamFlags & PARAMFLAG_FRETVAL)
5844 /* under most conditions the caller is not allowed to
5845 * pass in a dispparam arg in the index of what would be
5846 * the retval parameter. however, there is an exception
5847 * where the extra parameter is used in an extra
5848 * IDispatch::Invoke below */
5849 if ((i < pDispParams->cArgs) &&
5850 ((func_desc->cParams != 1) || !pVarResult ||
5851 !(func_desc->invkind & INVOKE_PROPERTYGET)))
5853 hres = DISP_E_BADPARAMCOUNT;
5854 break;
5857 /* note: this check is placed so that if the caller passes
5858 * in a VARIANTARG for the retval we just ignore it, like
5859 * native does */
5860 if (i == func_desc->cParams - 1)
5862 VARIANTARG *arg;
5863 arg = prgpvarg[i] = &rgvarg[i];
5864 memset(arg, 0, sizeof(*arg));
5865 V_VT(arg) = rgvt[i];
5866 memset(&retval, 0, sizeof(retval));
5867 V_BYREF(arg) = &retval;
5869 else
5871 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
5872 hres = E_UNEXPECTED;
5873 break;
5876 else if (src_arg)
5878 dump_Variant(src_arg);
5880 if (rgvt[i] == VT_VARIANT)
5881 hres = VariantCopy(&rgvarg[i], src_arg);
5882 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
5884 if (rgvt[i] == V_VT(src_arg))
5885 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
5886 else
5888 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5889 hres = VariantCopy(&missing_arg[i], src_arg);
5890 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
5892 V_VT(&rgvarg[i]) = rgvt[i];
5894 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
5896 SAFEARRAY *a;
5897 SAFEARRAYBOUND bound;
5898 VARIANT *v;
5899 LONG j;
5900 bound.lLbound = 0;
5901 bound.cElements = pDispParams->cArgs-i;
5902 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
5904 ERR("SafeArrayCreate failed\n");
5905 break;
5907 hres = SafeArrayAccessData(a, (LPVOID)&v);
5908 if (hres != S_OK)
5910 ERR("SafeArrayAccessData failed with %x\n", hres);
5911 break;
5913 for (j = 0; j < bound.cElements; j++)
5914 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
5915 hres = SafeArrayUnaccessData(a);
5916 if (hres != S_OK)
5918 ERR("SafeArrayUnaccessData failed with %x\n", hres);
5919 break;
5921 V_ARRAY(&rgvarg[i]) = a;
5922 V_VT(&rgvarg[i]) = rgvt[i];
5924 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
5926 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5927 V_VT(&missing_arg[i]) = V_VT(src_arg);
5928 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
5929 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
5930 V_VT(&rgvarg[i]) = rgvt[i];
5932 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
5934 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
5935 V_VT(&rgvarg[i]) = rgvt[i];
5937 else
5939 /* FIXME: this doesn't work for VT_BYREF arguments if
5940 * they are not the same type as in the paramdesc */
5941 V_VT(&rgvarg[i]) = V_VT(src_arg);
5942 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
5943 V_VT(&rgvarg[i]) = rgvt[i];
5946 if (FAILED(hres))
5948 ERR("failed to convert param %d to %s%s from %s%s\n", i,
5949 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
5950 debugstr_VT(src_arg), debugstr_VF(src_arg));
5951 break;
5953 prgpvarg[i] = &rgvarg[i];
5955 else if (wParamFlags & PARAMFLAG_FOPT)
5957 VARIANTARG *arg;
5958 arg = prgpvarg[i] = &rgvarg[i];
5959 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5961 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
5962 if (FAILED(hres))
5963 break;
5965 else
5967 VARIANTARG *missing_arg;
5968 /* if the function wants a pointer to a variant then
5969 * set that up, otherwise just pass the VT_ERROR in
5970 * the argument by value */
5971 if (rgvt[i] & VT_BYREF)
5973 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
5974 V_VT(arg) = VT_VARIANT | VT_BYREF;
5975 V_VARIANTREF(arg) = missing_arg;
5977 else
5978 missing_arg = arg;
5979 V_VT(missing_arg) = VT_ERROR;
5980 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
5983 else
5985 hres = DISP_E_BADPARAMCOUNT;
5986 break;
5989 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5991 /* VT_VOID is a special case for return types, so it is not
5992 * handled in the general function */
5993 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
5994 V_VT(&varresult) = VT_EMPTY;
5995 else
5997 V_VT(&varresult) = 0;
5998 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
5999 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6002 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6003 V_VT(&varresult), func_desc->cParams, rgvt,
6004 prgpvarg, &varresult);
6006 for (i = 0; i < func_desc->cParams; i++)
6008 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6009 if (wParamFlags & PARAMFLAG_FRETVAL)
6011 if (TRACE_ON(ole))
6013 TRACE("[retval] value: ");
6014 dump_Variant(prgpvarg[i]);
6017 if (pVarResult)
6019 VariantInit(pVarResult);
6020 /* deref return value */
6021 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6024 /* free data stored in varresult. Note that
6025 * VariantClear doesn't do what we want because we are
6026 * working with byref types. */
6027 /* FIXME: clear safearrays, bstrs, records and
6028 * variants here too */
6029 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
6030 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
6032 if(*V_UNKNOWNREF(prgpvarg[i]))
6033 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
6035 break;
6037 else if (i < pDispParams->cArgs)
6039 if (wParamFlags & PARAMFLAG_FOUT)
6041 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
6043 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
6044 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6046 if (FAILED(hres))
6048 ERR("failed to convert param %d to vt %d\n", i,
6049 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
6050 break;
6053 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6054 func_desc->cParamsOpt < 0 &&
6055 i == func_desc->cParams-1)
6057 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6058 LONG j, ubound;
6059 VARIANT *v;
6060 hres = SafeArrayGetUBound(a, 1, &ubound);
6061 if (hres != S_OK)
6063 ERR("SafeArrayGetUBound failed with %x\n", hres);
6064 break;
6066 hres = SafeArrayAccessData(a, (LPVOID)&v);
6067 if (hres != S_OK)
6069 ERR("SafeArrayAccessData failed with %x\n", hres);
6070 break;
6072 for (j = 0; j <= ubound; j++)
6073 VariantClear(&v[j]);
6074 hres = SafeArrayUnaccessData(a);
6075 if (hres != S_OK)
6077 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6078 break;
6081 VariantClear(&rgvarg[i]);
6083 else if (wParamFlags & PARAMFLAG_FOPT)
6085 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6086 VariantClear(&rgvarg[i]);
6090 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6092 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6093 hres = DISP_E_EXCEPTION;
6094 if (pExcepInfo)
6096 IErrorInfo *pErrorInfo;
6097 pExcepInfo->scode = V_ERROR(&varresult);
6098 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6100 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6101 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6102 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6103 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6105 IErrorInfo_Release(pErrorInfo);
6109 if (V_VT(&varresult) != VT_ERROR)
6111 TRACE("varresult value: ");
6112 dump_Variant(&varresult);
6114 if (pVarResult)
6116 VariantClear(pVarResult);
6117 *pVarResult = varresult;
6119 else
6120 VariantClear(&varresult);
6123 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6124 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6125 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6126 (pDispParams->cArgs != 0))
6128 if (V_VT(pVarResult) == VT_DISPATCH)
6130 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6131 /* Note: not VariantClear; we still need the dispatch
6132 * pointer to be valid */
6133 VariantInit(pVarResult);
6134 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6135 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6136 pDispParams, pVarResult, pExcepInfo, pArgErr);
6137 IDispatch_Release(pDispatch);
6139 else
6141 VariantClear(pVarResult);
6142 hres = DISP_E_NOTACOLLECTION;
6146 func_fail:
6147 HeapFree(GetProcessHeap(), 0, buffer);
6148 break;
6150 case FUNC_DISPATCH: {
6151 IDispatch *disp;
6153 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6154 if (SUCCEEDED(hres)) {
6155 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6156 hres = IDispatch_Invoke(
6157 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6158 pVarResult,pExcepInfo,pArgErr
6160 if (FAILED(hres))
6161 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6162 IDispatch_Release(disp);
6163 } else
6164 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6165 break;
6167 default:
6168 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6169 hres = E_FAIL;
6170 break;
6173 TRACE("-- 0x%08x\n", hres);
6174 return hres;
6176 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6177 VARDESC *var_desc;
6179 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6180 if(FAILED(hres)) return hres;
6182 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6183 dump_VARDESC(var_desc);
6184 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6185 return E_NOTIMPL;
6188 /* not found, look for it in inherited interfaces */
6189 ITypeInfo2_GetTypeKind(iface, &type_kind);
6190 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6191 if(This->impltypelist) {
6192 /* recursive search */
6193 ITypeInfo *pTInfo;
6194 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6195 if(SUCCEEDED(hres)){
6196 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6197 ITypeInfo_Release(pTInfo);
6198 return hres;
6200 WARN("Could not search inherited interface!\n");
6203 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6204 return DISP_E_MEMBERNOTFOUND;
6207 /* ITypeInfo::GetDocumentation
6209 * Retrieves the documentation string, the complete Help file name and path,
6210 * and the context ID for the Help topic for a specified type description.
6212 * (Can be tested by the Visual Basic Editor in Word for instance.)
6214 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6215 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6216 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6218 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6219 const TLBFuncDesc *pFDesc;
6220 const TLBVarDesc *pVDesc;
6221 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6222 " HelpContext(%p) HelpFile(%p)\n",
6223 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6224 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6225 if(pBstrName)
6226 *pBstrName=SysAllocString(This->Name);
6227 if(pBstrDocString)
6228 *pBstrDocString=SysAllocString(This->DocString);
6229 if(pdwHelpContext)
6230 *pdwHelpContext=This->dwHelpContext;
6231 if(pBstrHelpFile)
6232 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6233 return S_OK;
6234 }else {/* for a member */
6235 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6236 if(pFDesc->funcdesc.memid==memid){
6237 if(pBstrName)
6238 *pBstrName = SysAllocString(pFDesc->Name);
6239 if(pBstrDocString)
6240 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6241 if(pdwHelpContext)
6242 *pdwHelpContext=pFDesc->helpcontext;
6243 return S_OK;
6245 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6246 if(pVDesc->vardesc.memid==memid){
6247 if(pBstrName)
6248 *pBstrName = SysAllocString(pVDesc->Name);
6249 if(pBstrDocString)
6250 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6251 if(pdwHelpContext)
6252 *pdwHelpContext=pVDesc->HelpContext;
6253 return S_OK;
6257 if(This->impltypelist &&
6258 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6259 /* recursive search */
6260 ITypeInfo *pTInfo;
6261 HRESULT result;
6262 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6263 &pTInfo);
6264 if(SUCCEEDED(result)) {
6265 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6266 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6267 ITypeInfo_Release(pTInfo);
6268 return result;
6270 WARN("Could not search inherited interface!\n");
6273 WARN("member %d not found\n", memid);
6274 return TYPE_E_ELEMENTNOTFOUND;
6277 /* ITypeInfo::GetDllEntry
6279 * Retrieves a description or specification of an entry point for a function
6280 * in a DLL.
6282 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6283 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6284 WORD *pwOrdinal)
6286 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6287 const TLBFuncDesc *pFDesc;
6289 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6291 if (pBstrDllName) *pBstrDllName = NULL;
6292 if (pBstrName) *pBstrName = NULL;
6293 if (pwOrdinal) *pwOrdinal = 0;
6295 if (This->TypeAttr.typekind != TKIND_MODULE)
6296 return TYPE_E_BADMODULEKIND;
6298 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6299 if(pFDesc->funcdesc.memid==memid){
6300 dump_TypeInfo(This);
6301 if (TRACE_ON(ole))
6302 dump_TLBFuncDescOne(pFDesc);
6304 if (pBstrDllName)
6305 *pBstrDllName = SysAllocString(This->DllName);
6307 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6308 if (pBstrName)
6309 *pBstrName = SysAllocString(pFDesc->Entry);
6310 if (pwOrdinal)
6311 *pwOrdinal = -1;
6312 return S_OK;
6314 if (pBstrName)
6315 *pBstrName = NULL;
6316 if (pwOrdinal)
6317 *pwOrdinal = (DWORD)pFDesc->Entry;
6318 return S_OK;
6320 return TYPE_E_ELEMENTNOTFOUND;
6323 /* internal function to make the inherited interfaces' methods appear
6324 * part of the interface */
6325 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6326 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6328 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6329 HRESULT hr;
6331 TRACE("%p, 0x%x\n", iface, *hRefType);
6333 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK))
6335 ITypeInfo *pSubTypeInfo;
6337 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
6338 if (FAILED(hr))
6339 return hr;
6341 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6342 hRefType, ppTInfo);
6343 ITypeInfo_Release(pSubTypeInfo);
6344 if (SUCCEEDED(hr))
6345 return hr;
6347 *hRefType -= DISPATCH_HREF_OFFSET;
6349 if (!(*hRefType & DISPATCH_HREF_MASK))
6350 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6351 else
6352 return E_FAIL;
6355 /* ITypeInfo::GetRefTypeInfo
6357 * If a type description references other type descriptions, it retrieves
6358 * the referenced type descriptions.
6360 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6361 ITypeInfo2 *iface,
6362 HREFTYPE hRefType,
6363 ITypeInfo **ppTInfo)
6365 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6366 HRESULT result = E_FAIL;
6368 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6370 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6371 ITypeInfo_AddRef(*ppTInfo);
6372 result = S_OK;
6374 else if (hRefType == -1 &&
6375 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6376 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6378 /* when we meet a DUAL dispinterface, we must create the interface
6379 * version of it.
6381 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
6384 /* the interface version contains the same information as the dispinterface
6385 * copy the contents of the structs.
6387 *pTypeInfoImpl = *This;
6388 pTypeInfoImpl->ref = 0;
6390 /* change the type to interface */
6391 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6393 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6395 /* we use data structures from This, so we need to keep a reference
6396 * to it to stop it being destroyed and signal to the new instance to
6397 * not free its data structures when it is destroyed */
6398 pTypeInfoImpl->no_free_data = TRUE;
6399 pTypeInfoImpl->next = This;
6400 ITypeInfo_AddRef((ITypeInfo*) This);
6402 ITypeInfo_AddRef(*ppTInfo);
6404 result = S_OK;
6406 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6407 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6408 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6410 HREFTYPE href_dispatch = hRefType;
6411 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6412 } else {
6413 TLBRefType *ref_type;
6414 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6416 if(ref_type->reference == hRefType)
6417 break;
6419 if(&ref_type->entry == &This->pTypeLib->ref_list)
6421 FIXME("Can't find pRefType for ref %x\n", hRefType);
6422 goto end;
6424 if(hRefType != -1) {
6425 ITypeLib *pTLib = NULL;
6427 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6428 UINT Index;
6429 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6430 } else {
6431 if(ref_type->pImpTLInfo->pImpTypeLib) {
6432 TRACE("typeinfo in imported typelib that is already loaded\n");
6433 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6434 ITypeLib2_AddRef(pTLib);
6435 result = S_OK;
6436 } else {
6437 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6438 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6439 ref_type->pImpTLInfo->wVersionMajor,
6440 ref_type->pImpTLInfo->wVersionMinor,
6441 ref_type->pImpTLInfo->lcid,
6442 &pTLib);
6444 if(!SUCCEEDED(result)) {
6445 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6446 result=LoadTypeLib(libnam, &pTLib);
6447 SysFreeString(libnam);
6449 if(SUCCEEDED(result)) {
6450 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6451 ITypeLib2_AddRef(pTLib);
6455 if(SUCCEEDED(result)) {
6456 if(ref_type->index == TLB_REF_USE_GUID)
6457 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6458 &ref_type->guid,
6459 ppTInfo);
6460 else
6461 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6462 ppTInfo);
6464 if (pTLib != NULL)
6465 ITypeLib2_Release(pTLib);
6469 end:
6470 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6471 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6472 return result;
6475 /* ITypeInfo::AddressOfMember
6477 * Retrieves the addresses of static functions or variables, such as those
6478 * defined in a DLL.
6480 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6481 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6483 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6484 HRESULT hr;
6485 BSTR dll, entry;
6486 WORD ordinal;
6487 HMODULE module;
6489 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6491 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6492 if (FAILED(hr))
6493 return hr;
6495 module = LoadLibraryW(dll);
6496 if (!module)
6498 ERR("couldn't load %s\n", debugstr_w(dll));
6499 SysFreeString(dll);
6500 if (entry) SysFreeString(entry);
6501 return STG_E_FILENOTFOUND;
6503 /* FIXME: store library somewhere where we can free it */
6505 if (entry)
6507 LPSTR entryA;
6508 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6509 entryA = HeapAlloc(GetProcessHeap(), 0, len);
6510 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6512 *ppv = GetProcAddress(module, entryA);
6513 if (!*ppv)
6514 ERR("function not found %s\n", debugstr_a(entryA));
6516 HeapFree(GetProcessHeap(), 0, entryA);
6518 else
6520 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6521 if (!*ppv)
6522 ERR("function not found %d\n", ordinal);
6525 SysFreeString(dll);
6526 if (entry) SysFreeString(entry);
6528 if (!*ppv)
6529 return TYPE_E_DLLFUNCTIONNOTFOUND;
6531 return S_OK;
6534 /* ITypeInfo::CreateInstance
6536 * Creates a new instance of a type that describes a component object class
6537 * (coclass).
6539 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6540 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6542 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6543 HRESULT hr;
6544 TYPEATTR *pTA;
6546 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6548 *ppvObj = NULL;
6550 if(pOuterUnk)
6552 WARN("Not able to aggregate\n");
6553 return CLASS_E_NOAGGREGATION;
6556 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6557 if(FAILED(hr)) return hr;
6559 if(pTA->typekind != TKIND_COCLASS)
6561 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6562 hr = E_INVALIDARG;
6563 goto end;
6566 hr = S_FALSE;
6567 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6569 IUnknown *pUnk;
6570 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6571 TRACE("GetActiveObject rets %08x\n", hr);
6572 if(hr == S_OK)
6574 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6575 IUnknown_Release(pUnk);
6579 if(hr != S_OK)
6580 hr = CoCreateInstance(&pTA->guid, NULL,
6581 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6582 riid, ppvObj);
6584 end:
6585 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6586 return hr;
6589 /* ITypeInfo::GetMops
6591 * Retrieves marshalling information.
6593 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6594 BSTR *pBstrMops)
6596 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6597 FIXME("(%p) stub!\n", This);
6598 return S_OK;
6601 /* ITypeInfo::GetContainingTypeLib
6603 * Retrieves the containing type library and the index of the type description
6604 * within that type library.
6606 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6607 ITypeLib * *ppTLib, UINT *pIndex)
6609 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6611 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6612 if (pIndex) {
6613 *pIndex=This->index;
6614 TRACE("returning pIndex=%d\n", *pIndex);
6617 if (ppTLib) {
6618 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6619 ITypeLib2_AddRef(*ppTLib);
6620 TRACE("returning ppTLib=%p\n", *ppTLib);
6623 return S_OK;
6626 /* ITypeInfo::ReleaseTypeAttr
6628 * Releases a TYPEATTR previously returned by GetTypeAttr.
6631 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6632 TYPEATTR* pTypeAttr)
6634 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6635 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6636 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6639 /* ITypeInfo::ReleaseFuncDesc
6641 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6643 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6644 ITypeInfo2 *iface,
6645 FUNCDESC *pFuncDesc)
6647 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6648 SHORT i;
6650 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6652 for (i = 0; i < pFuncDesc->cParams; i++)
6653 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6654 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6656 SysFreeString((BSTR)pFuncDesc);
6659 /* ITypeInfo::ReleaseVarDesc
6661 * Releases a VARDESC previously returned by GetVarDesc.
6663 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6664 VARDESC *pVarDesc)
6666 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6667 TRACE("(%p)->(%p)\n", This, pVarDesc);
6669 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6670 if (pVarDesc->varkind == VAR_CONST)
6671 VariantClear(pVarDesc->u.lpvarValue);
6672 SysFreeString((BSTR)pVarDesc);
6675 /* ITypeInfo2::GetTypeKind
6677 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6680 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6681 TYPEKIND *pTypeKind)
6683 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6684 *pTypeKind=This->TypeAttr.typekind;
6685 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6686 return S_OK;
6689 /* ITypeInfo2::GetTypeFlags
6691 * Returns the type flags without any allocations. This returns a DWORD type
6692 * flag, which expands the type flags without growing the TYPEATTR (type
6693 * attribute).
6696 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6698 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6699 *pTypeFlags=This->TypeAttr.wTypeFlags;
6700 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6701 return S_OK;
6704 /* ITypeInfo2::GetFuncIndexOfMemId
6705 * Binds to a specific member based on a known DISPID, where the member name
6706 * is not known (for example, when binding to a default member).
6709 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
6710 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
6712 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6713 const TLBFuncDesc *pFuncInfo;
6714 int i;
6715 HRESULT result;
6717 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
6718 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
6719 break;
6720 if(pFuncInfo) {
6721 *pFuncIndex = i;
6722 result = S_OK;
6723 } else
6724 result = TYPE_E_ELEMENTNOTFOUND;
6726 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
6727 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6728 return result;
6731 /* TypeInfo2::GetVarIndexOfMemId
6733 * Binds to a specific member based on a known DISPID, where the member name
6734 * is not known (for example, when binding to a default member).
6737 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
6738 MEMBERID memid, UINT *pVarIndex)
6740 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6741 TLBVarDesc *pVarInfo;
6742 int i;
6743 HRESULT result;
6744 for(i=0, pVarInfo=This->varlist; pVarInfo &&
6745 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
6747 if(pVarInfo) {
6748 *pVarIndex = i;
6749 result = S_OK;
6750 } else
6751 result = TYPE_E_ELEMENTNOTFOUND;
6753 TRACE("(%p) memid 0x%08x -> %s\n", This,
6754 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6755 return result;
6758 /* ITypeInfo2::GetCustData
6760 * Gets the custom data
6762 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
6763 ITypeInfo2 * iface,
6764 REFGUID guid,
6765 VARIANT *pVarVal)
6767 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6768 TLBCustData *pCData;
6770 for(pCData=This->pCustData; pCData; pCData = pCData->next)
6771 if( IsEqualIID(guid, &pCData->guid)) break;
6773 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6775 if(pCData)
6777 VariantInit( pVarVal);
6778 VariantCopy( pVarVal, &pCData->data);
6779 return S_OK;
6781 return E_INVALIDARG; /* FIXME: correct? */
6784 /* ITypeInfo2::GetFuncCustData
6786 * Gets the custom data
6788 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
6789 ITypeInfo2 * iface,
6790 UINT index,
6791 REFGUID guid,
6792 VARIANT *pVarVal)
6794 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6795 TLBCustData *pCData=NULL;
6796 TLBFuncDesc * pFDesc;
6797 int i;
6798 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6799 pFDesc=pFDesc->next);
6801 if(pFDesc)
6802 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
6803 if( IsEqualIID(guid, &pCData->guid)) break;
6805 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6807 if(pCData){
6808 VariantInit( pVarVal);
6809 VariantCopy( pVarVal, &pCData->data);
6810 return S_OK;
6812 return E_INVALIDARG; /* FIXME: correct? */
6815 /* ITypeInfo2::GetParamCustData
6817 * Gets the custom data
6819 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
6820 ITypeInfo2 * iface,
6821 UINT indexFunc,
6822 UINT indexParam,
6823 REFGUID guid,
6824 VARIANT *pVarVal)
6826 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6827 TLBCustData *pCData=NULL;
6828 TLBFuncDesc * pFDesc;
6829 int i;
6831 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
6833 if(pFDesc && indexParam<pFDesc->funcdesc.cParams)
6834 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
6835 pCData = pCData->next)
6836 if( IsEqualIID(guid, &pCData->guid)) break;
6838 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6840 if(pCData)
6842 VariantInit( pVarVal);
6843 VariantCopy( pVarVal, &pCData->data);
6844 return S_OK;
6846 return E_INVALIDARG; /* FIXME: correct? */
6849 /* ITypeInfo2::GetVarCustData
6851 * Gets the custom data
6853 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
6854 ITypeInfo2 * iface,
6855 UINT index,
6856 REFGUID guid,
6857 VARIANT *pVarVal)
6859 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6860 TLBCustData *pCData=NULL;
6861 TLBVarDesc * pVDesc;
6862 int i;
6864 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
6866 if(pVDesc)
6868 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
6870 if( IsEqualIID(guid, &pCData->guid)) break;
6874 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6876 if(pCData)
6878 VariantInit( pVarVal);
6879 VariantCopy( pVarVal, &pCData->data);
6880 return S_OK;
6882 return E_INVALIDARG; /* FIXME: correct? */
6885 /* ITypeInfo2::GetImplCustData
6887 * Gets the custom data
6889 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6890 ITypeInfo2 * iface,
6891 UINT index,
6892 REFGUID guid,
6893 VARIANT *pVarVal)
6895 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6896 TLBCustData *pCData=NULL;
6897 TLBImplType * pRDesc;
6898 int i;
6900 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6902 if(pRDesc)
6904 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6906 if( IsEqualIID(guid, &pCData->guid)) break;
6910 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6912 if(pCData)
6914 VariantInit( pVarVal);
6915 VariantCopy( pVarVal, &pCData->data);
6916 return S_OK;
6918 return E_INVALIDARG; /* FIXME: correct? */
6921 /* ITypeInfo2::GetDocumentation2
6923 * Retrieves the documentation string, the complete Help file name and path,
6924 * the localization context to use, and the context ID for the library Help
6925 * topic in the Help file.
6928 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6929 ITypeInfo2 * iface,
6930 MEMBERID memid,
6931 LCID lcid,
6932 BSTR *pbstrHelpString,
6933 DWORD *pdwHelpStringContext,
6934 BSTR *pbstrHelpStringDll)
6936 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6937 const TLBFuncDesc *pFDesc;
6938 const TLBVarDesc *pVDesc;
6939 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
6940 "HelpStringContext(%p) HelpStringDll(%p)\n",
6941 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6942 pbstrHelpStringDll );
6943 /* the help string should be obtained from the helpstringdll,
6944 * using the _DLLGetDocumentation function, based on the supplied
6945 * lcid. Nice to do sometime...
6947 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6948 if(pbstrHelpString)
6949 *pbstrHelpString=SysAllocString(This->Name);
6950 if(pdwHelpStringContext)
6951 *pdwHelpStringContext=This->dwHelpStringContext;
6952 if(pbstrHelpStringDll)
6953 *pbstrHelpStringDll=
6954 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6955 return S_OK;
6956 }else {/* for a member */
6957 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6958 if(pFDesc->funcdesc.memid==memid){
6959 if(pbstrHelpString)
6960 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6961 if(pdwHelpStringContext)
6962 *pdwHelpStringContext=pFDesc->HelpStringContext;
6963 if(pbstrHelpStringDll)
6964 *pbstrHelpStringDll=
6965 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6966 return S_OK;
6968 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6969 if(pVDesc->vardesc.memid==memid){
6970 if(pbstrHelpString)
6971 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6972 if(pdwHelpStringContext)
6973 *pdwHelpStringContext=pVDesc->HelpStringContext;
6974 if(pbstrHelpStringDll)
6975 *pbstrHelpStringDll=
6976 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6977 return S_OK;
6980 return TYPE_E_ELEMENTNOTFOUND;
6983 /* ITypeInfo2::GetAllCustData
6985 * Gets all custom data items for the Type info.
6988 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6989 ITypeInfo2 * iface,
6990 CUSTDATA *pCustData)
6992 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6993 TLBCustData *pCData;
6994 int i;
6996 TRACE("(%p) returning %d items\n", This, This->ctCustData);
6998 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6999 if(pCustData->prgCustData ){
7000 pCustData->cCustData=This->ctCustData;
7001 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
7002 pCustData->prgCustData[i].guid=pCData->guid;
7003 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
7005 }else{
7006 ERR(" OUT OF MEMORY!\n");
7007 return E_OUTOFMEMORY;
7009 return S_OK;
7012 /* ITypeInfo2::GetAllFuncCustData
7014 * Gets all custom data items for the specified Function
7017 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7018 ITypeInfo2 * iface,
7019 UINT index,
7020 CUSTDATA *pCustData)
7022 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7023 TLBCustData *pCData;
7024 TLBFuncDesc * pFDesc;
7025 int i;
7026 TRACE("(%p) index %d\n", This, index);
7027 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7028 pFDesc=pFDesc->next)
7030 if(pFDesc){
7031 pCustData->prgCustData =
7032 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
7033 if(pCustData->prgCustData ){
7034 pCustData->cCustData=pFDesc->ctCustData;
7035 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
7036 pCData = pCData->next){
7037 pCustData->prgCustData[i].guid=pCData->guid;
7038 VariantCopy(& pCustData->prgCustData[i].varValue,
7039 & pCData->data);
7041 }else{
7042 ERR(" OUT OF MEMORY!\n");
7043 return E_OUTOFMEMORY;
7045 return S_OK;
7047 return TYPE_E_ELEMENTNOTFOUND;
7050 /* ITypeInfo2::GetAllParamCustData
7052 * Gets all custom data items for the Functions
7055 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7056 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7058 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7059 TLBCustData *pCData=NULL;
7060 TLBFuncDesc * pFDesc;
7061 int i;
7062 TRACE("(%p) index %d\n", This, indexFunc);
7063 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
7064 pFDesc=pFDesc->next)
7066 if(pFDesc && indexParam<pFDesc->funcdesc.cParams){
7067 pCustData->prgCustData =
7068 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
7069 sizeof(CUSTDATAITEM));
7070 if(pCustData->prgCustData ){
7071 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
7072 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
7073 pCData; i++, pCData = pCData->next){
7074 pCustData->prgCustData[i].guid=pCData->guid;
7075 VariantCopy(& pCustData->prgCustData[i].varValue,
7076 & pCData->data);
7078 }else{
7079 ERR(" OUT OF MEMORY!\n");
7080 return E_OUTOFMEMORY;
7082 return S_OK;
7084 return TYPE_E_ELEMENTNOTFOUND;
7087 /* ITypeInfo2::GetAllVarCustData
7089 * Gets all custom data items for the specified Variable
7092 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7093 UINT index, CUSTDATA *pCustData)
7095 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7096 TLBCustData *pCData;
7097 TLBVarDesc * pVDesc;
7098 int i;
7099 TRACE("(%p) index %d\n", This, index);
7100 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
7101 pVDesc=pVDesc->next)
7103 if(pVDesc){
7104 pCustData->prgCustData =
7105 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
7106 if(pCustData->prgCustData ){
7107 pCustData->cCustData=pVDesc->ctCustData;
7108 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
7109 pCData = pCData->next){
7110 pCustData->prgCustData[i].guid=pCData->guid;
7111 VariantCopy(& pCustData->prgCustData[i].varValue,
7112 & pCData->data);
7114 }else{
7115 ERR(" OUT OF MEMORY!\n");
7116 return E_OUTOFMEMORY;
7118 return S_OK;
7120 return TYPE_E_ELEMENTNOTFOUND;
7123 /* ITypeInfo2::GetAllImplCustData
7125 * Gets all custom data items for the specified implementation type
7128 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7129 ITypeInfo2 * iface,
7130 UINT index,
7131 CUSTDATA *pCustData)
7133 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7134 TLBCustData *pCData;
7135 TLBImplType * pRDesc;
7136 int i;
7137 TRACE("(%p) index %d\n", This, index);
7138 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
7139 pRDesc=pRDesc->next)
7141 if(pRDesc){
7142 pCustData->prgCustData =
7143 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
7144 if(pCustData->prgCustData ){
7145 pCustData->cCustData=pRDesc->ctCustData;
7146 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
7147 pCData = pCData->next){
7148 pCustData->prgCustData[i].guid=pCData->guid;
7149 VariantCopy(& pCustData->prgCustData[i].varValue,
7150 & pCData->data);
7152 }else{
7153 ERR(" OUT OF MEMORY!\n");
7154 return E_OUTOFMEMORY;
7156 return S_OK;
7158 return TYPE_E_ELEMENTNOTFOUND;
7161 static const ITypeInfo2Vtbl tinfvt =
7164 ITypeInfo_fnQueryInterface,
7165 ITypeInfo_fnAddRef,
7166 ITypeInfo_fnRelease,
7168 ITypeInfo_fnGetTypeAttr,
7169 ITypeInfo_fnGetTypeComp,
7170 ITypeInfo_fnGetFuncDesc,
7171 ITypeInfo_fnGetVarDesc,
7172 ITypeInfo_fnGetNames,
7173 ITypeInfo_fnGetRefTypeOfImplType,
7174 ITypeInfo_fnGetImplTypeFlags,
7175 ITypeInfo_fnGetIDsOfNames,
7176 ITypeInfo_fnInvoke,
7177 ITypeInfo_fnGetDocumentation,
7178 ITypeInfo_fnGetDllEntry,
7179 ITypeInfo_fnGetRefTypeInfo,
7180 ITypeInfo_fnAddressOfMember,
7181 ITypeInfo_fnCreateInstance,
7182 ITypeInfo_fnGetMops,
7183 ITypeInfo_fnGetContainingTypeLib,
7184 ITypeInfo_fnReleaseTypeAttr,
7185 ITypeInfo_fnReleaseFuncDesc,
7186 ITypeInfo_fnReleaseVarDesc,
7188 ITypeInfo2_fnGetTypeKind,
7189 ITypeInfo2_fnGetTypeFlags,
7190 ITypeInfo2_fnGetFuncIndexOfMemId,
7191 ITypeInfo2_fnGetVarIndexOfMemId,
7192 ITypeInfo2_fnGetCustData,
7193 ITypeInfo2_fnGetFuncCustData,
7194 ITypeInfo2_fnGetParamCustData,
7195 ITypeInfo2_fnGetVarCustData,
7196 ITypeInfo2_fnGetImplTypeCustData,
7197 ITypeInfo2_fnGetDocumentation2,
7198 ITypeInfo2_fnGetAllCustData,
7199 ITypeInfo2_fnGetAllFuncCustData,
7200 ITypeInfo2_fnGetAllParamCustData,
7201 ITypeInfo2_fnGetAllVarCustData,
7202 ITypeInfo2_fnGetAllImplTypeCustData,
7205 /******************************************************************************
7206 * CreateDispTypeInfo [OLEAUT32.31]
7208 * Build type information for an object so it can be called through an
7209 * IDispatch interface.
7211 * RETURNS
7212 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7213 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7215 * NOTES
7216 * This call allows an objects methods to be accessed through IDispatch, by
7217 * building an ITypeInfo object that IDispatch can use to call through.
7219 HRESULT WINAPI CreateDispTypeInfo(
7220 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7221 LCID lcid, /* [I] Locale Id */
7222 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7224 ITypeInfoImpl *pTIClass, *pTIIface;
7225 ITypeLibImpl *pTypeLibImpl;
7226 int param, func;
7227 TLBFuncDesc **ppFuncDesc;
7228 TLBRefType *ref;
7230 TRACE("\n");
7231 pTypeLibImpl = TypeLibImpl_Constructor();
7232 if (!pTypeLibImpl) return E_FAIL;
7234 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
7235 pTIIface->pTypeLib = pTypeLibImpl;
7236 pTIIface->index = 0;
7237 pTIIface->Name = NULL;
7238 pTIIface->dwHelpContext = -1;
7239 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7240 pTIIface->TypeAttr.lcid = lcid;
7241 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7242 pTIIface->TypeAttr.wMajorVerNum = 0;
7243 pTIIface->TypeAttr.wMinorVerNum = 0;
7244 pTIIface->TypeAttr.cbAlignment = 2;
7245 pTIIface->TypeAttr.cbSizeInstance = -1;
7246 pTIIface->TypeAttr.cbSizeVft = -1;
7247 pTIIface->TypeAttr.cFuncs = 0;
7248 pTIIface->TypeAttr.cImplTypes = 0;
7249 pTIIface->TypeAttr.cVars = 0;
7250 pTIIface->TypeAttr.wTypeFlags = 0;
7252 ppFuncDesc = &pTIIface->funclist;
7253 for(func = 0; func < pidata->cMembers; func++) {
7254 METHODDATA *md = pidata->pmethdata + func;
7255 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
7256 (*ppFuncDesc)->Name = SysAllocString(md->szName);
7257 (*ppFuncDesc)->funcdesc.memid = md->dispid;
7258 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
7259 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
7260 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
7261 (*ppFuncDesc)->funcdesc.callconv = md->cc;
7262 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
7263 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
7264 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
7265 (*ppFuncDesc)->funcdesc.cScodes = 0;
7266 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
7267 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7268 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7269 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7270 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7271 md->cArgs * sizeof(ELEMDESC));
7272 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7273 md->cArgs * sizeof(TLBParDesc));
7274 for(param = 0; param < md->cArgs; param++) {
7275 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7276 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7278 (*ppFuncDesc)->helpcontext = 0;
7279 (*ppFuncDesc)->HelpStringContext = 0;
7280 (*ppFuncDesc)->HelpString = NULL;
7281 (*ppFuncDesc)->Entry = NULL;
7282 (*ppFuncDesc)->ctCustData = 0;
7283 (*ppFuncDesc)->pCustData = NULL;
7284 (*ppFuncDesc)->next = NULL;
7285 pTIIface->TypeAttr.cFuncs++;
7286 ppFuncDesc = &(*ppFuncDesc)->next;
7289 dump_TypeInfo(pTIIface);
7291 pTypeLibImpl->pTypeInfo = pTIIface;
7292 pTypeLibImpl->TypeInfoCount++;
7294 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
7295 pTIClass->pTypeLib = pTypeLibImpl;
7296 pTIClass->index = 1;
7297 pTIClass->Name = NULL;
7298 pTIClass->dwHelpContext = -1;
7299 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7300 pTIClass->TypeAttr.lcid = lcid;
7301 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7302 pTIClass->TypeAttr.wMajorVerNum = 0;
7303 pTIClass->TypeAttr.wMinorVerNum = 0;
7304 pTIClass->TypeAttr.cbAlignment = 2;
7305 pTIClass->TypeAttr.cbSizeInstance = -1;
7306 pTIClass->TypeAttr.cbSizeVft = -1;
7307 pTIClass->TypeAttr.cFuncs = 0;
7308 pTIClass->TypeAttr.cImplTypes = 1;
7309 pTIClass->TypeAttr.cVars = 0;
7310 pTIClass->TypeAttr.wTypeFlags = 0;
7312 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
7313 pTIClass->impltypelist->hRef = 0;
7315 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
7316 ref->index = 0;
7317 ref->reference = 0;
7318 ref->pImpTLInfo = TLB_REF_INTERNAL;
7319 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7321 dump_TypeInfo(pTIClass);
7323 pTIIface->next = pTIClass;
7324 pTypeLibImpl->TypeInfoCount++;
7326 *pptinfo = (ITypeInfo*)pTIClass;
7328 ITypeInfo_AddRef(*pptinfo);
7329 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7331 return S_OK;
7335 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7337 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7339 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7342 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7344 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7346 return ITypeInfo_AddRef((ITypeInfo *)This);
7349 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7351 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7353 return ITypeInfo_Release((ITypeInfo *)This);
7356 static HRESULT WINAPI ITypeComp_fnBind(
7357 ITypeComp * iface,
7358 OLECHAR * szName,
7359 ULONG lHash,
7360 WORD wFlags,
7361 ITypeInfo ** ppTInfo,
7362 DESCKIND * pDescKind,
7363 BINDPTR * pBindPtr)
7365 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7366 const TLBFuncDesc *pFDesc;
7367 const TLBVarDesc *pVDesc;
7368 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7370 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7372 *pDescKind = DESCKIND_NONE;
7373 pBindPtr->lpfuncdesc = NULL;
7374 *ppTInfo = NULL;
7376 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
7377 if (!strcmpiW(pFDesc->Name, szName)) {
7378 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7379 break;
7380 else
7381 /* name found, but wrong flags */
7382 hr = TYPE_E_TYPEMISMATCH;
7385 if (pFDesc)
7387 HRESULT hr = TLB_AllocAndInitFuncDesc(
7388 &pFDesc->funcdesc,
7389 &pBindPtr->lpfuncdesc,
7390 This->TypeAttr.typekind == TKIND_DISPATCH);
7391 if (FAILED(hr))
7392 return hr;
7393 *pDescKind = DESCKIND_FUNCDESC;
7394 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7395 ITypeInfo_AddRef(*ppTInfo);
7396 return S_OK;
7397 } else {
7398 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7399 if (!strcmpiW(pVDesc->Name, szName)) {
7400 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7401 if (FAILED(hr))
7402 return hr;
7403 *pDescKind = DESCKIND_VARDESC;
7404 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7405 ITypeInfo_AddRef(*ppTInfo);
7406 return S_OK;
7410 /* FIXME: search each inherited interface, not just the first */
7411 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7412 /* recursive search */
7413 ITypeInfo *pTInfo;
7414 ITypeComp *pTComp;
7415 HRESULT hr;
7416 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7417 if (SUCCEEDED(hr))
7419 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7420 ITypeInfo_Release(pTInfo);
7422 if (SUCCEEDED(hr))
7424 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7425 ITypeComp_Release(pTComp);
7426 return hr;
7428 WARN("Could not search inherited interface!\n");
7430 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
7431 return hr;
7434 static HRESULT WINAPI ITypeComp_fnBindType(
7435 ITypeComp * iface,
7436 OLECHAR * szName,
7437 ULONG lHash,
7438 ITypeInfo ** ppTInfo,
7439 ITypeComp ** ppTComp)
7441 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7443 /* strange behaviour (does nothing) but like the
7444 * original */
7446 if (!ppTInfo || !ppTComp)
7447 return E_POINTER;
7449 *ppTInfo = NULL;
7450 *ppTComp = NULL;
7452 return S_OK;
7455 static const ITypeCompVtbl tcompvt =
7458 ITypeComp_fnQueryInterface,
7459 ITypeComp_fnAddRef,
7460 ITypeComp_fnRelease,
7462 ITypeComp_fnBind,
7463 ITypeComp_fnBindType