oleaut32: Handle strings with a length of 0xffff in SLTG_DoVars.
[wine/gsoc_dplay.git] / dlls / oleaut32 / typelib.c
blobc569fb2f69aeb151585864597819c7ae2c9bed55
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 /**********************************************************************
1441 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1443 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1445 return pcx->pos;
1448 static inline void MSFT_Seek(TLBContext *pcx, long where)
1450 if (where != DO_NOT_SEEK)
1452 where += pcx->oStart;
1453 if (where > pcx->length)
1455 /* FIXME */
1456 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1457 TLB_abort();
1459 pcx->pos = where;
1463 /* read function */
1464 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1466 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1467 pcx->pos, count, pcx->oStart, pcx->length, where);
1469 MSFT_Seek(pcx, where);
1470 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1471 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1472 pcx->pos += count;
1473 return count;
1476 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1477 long where )
1479 DWORD ret;
1481 ret = MSFT_Read(buffer, count, pcx, where);
1482 FromLEDWords(buffer, ret);
1484 return ret;
1487 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1488 long where )
1490 DWORD ret;
1492 ret = MSFT_Read(buffer, count, pcx, where);
1493 FromLEWords(buffer, ret);
1495 return ret;
1498 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1500 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1501 memset(pGuid,0, sizeof(GUID));
1502 return;
1504 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1505 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1506 pGuid->Data2 = FromLEWord(pGuid->Data2);
1507 pGuid->Data3 = FromLEWord(pGuid->Data3);
1508 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1511 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1513 MSFT_NameIntro niName;
1515 if (offset < 0)
1517 ERR_(typelib)("bad offset %d\n", offset);
1518 return -1;
1521 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1522 pcx->pTblDir->pNametab.offset+offset);
1524 return niName.hreftype;
1527 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1529 char * name;
1530 MSFT_NameIntro niName;
1531 int lengthInChars;
1532 BSTR bstrName = NULL;
1534 if (offset < 0)
1536 ERR_(typelib)("bad offset %d\n", offset);
1537 return NULL;
1539 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1540 pcx->pTblDir->pNametab.offset+offset);
1541 niName.namelen &= 0xFF; /* FIXME: correct ? */
1542 name=TLB_Alloc((niName.namelen & 0xff) +1);
1543 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1544 name[niName.namelen & 0xff]='\0';
1546 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1547 name, -1, NULL, 0);
1549 /* no invalid characters in string */
1550 if (lengthInChars)
1552 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1554 /* don't check for invalid character since this has been done previously */
1555 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1557 TLB_Free(name);
1559 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1560 return bstrName;
1563 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1565 char * string;
1566 INT16 length;
1567 int lengthInChars;
1568 BSTR bstr = NULL;
1570 if(offset<0) return NULL;
1571 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1572 if(length <= 0) return 0;
1573 string=TLB_Alloc(length +1);
1574 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1575 string[length]='\0';
1577 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1578 string, -1, NULL, 0);
1580 /* no invalid characters in string */
1581 if (lengthInChars)
1583 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1585 /* don't check for invalid character since this has been done previously */
1586 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1588 TLB_Free(string);
1590 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1591 return bstr;
1594 * read a value and fill a VARIANT structure
1596 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1598 int size;
1600 TRACE_(typelib)("\n");
1602 if(offset <0) { /* data are packed in here */
1603 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1604 V_I4(pVar) = offset & 0x3ffffff;
1605 return;
1607 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1608 pcx->pTblDir->pCustData.offset + offset );
1609 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1610 switch (V_VT(pVar)){
1611 case VT_EMPTY: /* FIXME: is this right? */
1612 case VT_NULL: /* FIXME: is this right? */
1613 case VT_I2 : /* this should not happen */
1614 case VT_I4 :
1615 case VT_R4 :
1616 case VT_ERROR :
1617 case VT_BOOL :
1618 case VT_I1 :
1619 case VT_UI1 :
1620 case VT_UI2 :
1621 case VT_UI4 :
1622 case VT_INT :
1623 case VT_UINT :
1624 case VT_VOID : /* FIXME: is this right? */
1625 case VT_HRESULT :
1626 size=4; break;
1627 case VT_R8 :
1628 case VT_CY :
1629 case VT_DATE :
1630 case VT_I8 :
1631 case VT_UI8 :
1632 case VT_DECIMAL : /* FIXME: is this right? */
1633 case VT_FILETIME :
1634 size=8;break;
1635 /* pointer types with known behaviour */
1636 case VT_BSTR :{
1637 char * ptr;
1638 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1639 if(size < 0) {
1640 char next;
1641 DWORD origPos = MSFT_Tell(pcx), nullPos;
1643 do {
1644 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1645 } while (next);
1646 nullPos = MSFT_Tell(pcx);
1647 size = nullPos - origPos;
1648 MSFT_Seek(pcx, origPos);
1650 ptr=TLB_Alloc(size);/* allocate temp buffer */
1651 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1652 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1653 /* FIXME: do we need a AtoW conversion here? */
1654 V_UNION(pVar, bstrVal[size])='\0';
1655 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1656 TLB_Free(ptr);
1658 size=-4; break;
1659 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1660 case VT_DISPATCH :
1661 case VT_VARIANT :
1662 case VT_UNKNOWN :
1663 case VT_PTR :
1664 case VT_SAFEARRAY :
1665 case VT_CARRAY :
1666 case VT_USERDEFINED :
1667 case VT_LPSTR :
1668 case VT_LPWSTR :
1669 case VT_BLOB :
1670 case VT_STREAM :
1671 case VT_STORAGE :
1672 case VT_STREAMED_OBJECT :
1673 case VT_STORED_OBJECT :
1674 case VT_BLOB_OBJECT :
1675 case VT_CF :
1676 case VT_CLSID :
1677 default:
1678 size=0;
1679 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1680 V_VT(pVar));
1683 if(size>0) /* (big|small) endian correct? */
1684 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1685 return;
1688 * create a linked list with custom data
1690 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1692 MSFT_CDGuid entry;
1693 TLBCustData* pNew;
1694 int count=0;
1696 TRACE_(typelib)("\n");
1698 while(offset >=0){
1699 count++;
1700 pNew=TLB_Alloc(sizeof(TLBCustData));
1701 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1702 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1703 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1704 /* add new custom data at head of the list */
1705 pNew->next=*ppCustData;
1706 *ppCustData=pNew;
1707 offset = entry.next;
1709 return count;
1712 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1713 ITypeInfoImpl *pTI)
1715 if(type <0)
1716 pTd->vt=type & VT_TYPEMASK;
1717 else
1718 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1720 if(pTd->vt == VT_USERDEFINED)
1721 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1723 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1726 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1728 /* resolve referenced type if any */
1729 while (lpTypeDesc)
1731 switch (lpTypeDesc->vt)
1733 case VT_PTR:
1734 lpTypeDesc = lpTypeDesc->u.lptdesc;
1735 break;
1737 case VT_CARRAY:
1738 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1739 break;
1741 case VT_USERDEFINED:
1742 MSFT_DoRefType(pcx, pTI->pTypeLib,
1743 lpTypeDesc->u.hreftype);
1745 lpTypeDesc = NULL;
1746 break;
1748 default:
1749 lpTypeDesc = NULL;
1754 static void
1755 MSFT_DoFuncs(TLBContext* pcx,
1756 ITypeInfoImpl* pTI,
1757 int cFuncs,
1758 int cVars,
1759 int offset,
1760 TLBFuncDesc** pptfd)
1763 * member information is stored in a data structure at offset
1764 * indicated by the memoffset field of the typeinfo structure
1765 * There are several distinctive parts.
1766 * The first part starts with a field that holds the total length
1767 * of this (first) part excluding this field. Then follow the records,
1768 * for each member there is one record.
1770 * The first entry is always the length of the record (including this
1771 * length word).
1772 * The rest of the record depends on the type of the member. If there is
1773 * a field indicating the member type (function, variable, interface, etc)
1774 * I have not found it yet. At this time we depend on the information
1775 * in the type info and the usual order how things are stored.
1777 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1778 * for each member;
1780 * Third is an equal sized array with file offsets to the name entry
1781 * of each member.
1783 * The fourth and last (?) part is an array with offsets to the records
1784 * in the first part of this file segment.
1787 int infolen, nameoffset, reclength, nrattributes, i;
1788 int recoffset = offset + sizeof(INT);
1790 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1791 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1792 TLBFuncDesc *ptfd_prev = NULL;
1794 TRACE_(typelib)("\n");
1796 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1798 for ( i = 0; i < cFuncs ; i++ )
1800 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1802 /* name, eventually add to a hash table */
1803 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1804 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1806 /* nameoffset is sometimes -1 on the second half of a propget/propput
1807 * pair of functions */
1808 if ((nameoffset == -1) && (i > 0))
1809 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1810 else
1811 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1813 /* read the function information record */
1814 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1816 reclength &= 0xffff;
1818 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1820 /* do the attributes */
1821 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1822 / sizeof(int);
1824 if ( nrattributes > 0 )
1826 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1828 if ( nrattributes > 1 )
1830 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1831 pFuncRec->OptAttr[1]) ;
1833 if ( nrattributes > 2 )
1835 if ( pFuncRec->FKCCIC & 0x2000 )
1837 if (HIWORD(pFuncRec->OptAttr[2]) != 0)
1838 ERR("ordinal 0x%08x invalid, HIWORD != 0\n", pFuncRec->OptAttr[2]);
1839 (*pptfd)->Entry = (BSTR)pFuncRec->OptAttr[2];
1841 else
1843 (*pptfd)->Entry = MSFT_ReadString(pcx,
1844 pFuncRec->OptAttr[2]);
1846 if( nrattributes > 5 )
1848 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1850 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1852 MSFT_CustData(pcx,
1853 pFuncRec->OptAttr[6],
1854 &(*pptfd)->pCustData);
1858 else
1860 (*pptfd)->Entry = (BSTR)-1;
1865 /* fill the FuncDesc Structure */
1866 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1867 offset + infolen + ( i + 1) * sizeof(INT));
1869 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1870 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1871 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1872 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1873 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1874 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1875 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1877 MSFT_GetTdesc(pcx,
1878 pFuncRec->DataType,
1879 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1880 pTI);
1881 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1883 /* do the parameters/arguments */
1884 if(pFuncRec->nrargs)
1886 int j = 0;
1887 MSFT_ParameterInfo paraminfo;
1889 (*pptfd)->funcdesc.lprgelemdescParam =
1890 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1892 (*pptfd)->pParamDesc =
1893 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1895 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1896 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1898 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1900 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1902 MSFT_GetTdesc(pcx,
1903 paraminfo.DataType,
1904 &elemdesc->tdesc,
1905 pTI);
1907 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1909 /* name */
1910 if (paraminfo.oName == -1)
1911 /* this occurs for [propput] or [propget] methods, so
1912 * we should just set the name of the parameter to the
1913 * name of the method. */
1914 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1915 else
1916 (*pptfd)->pParamDesc[j].Name =
1917 MSFT_ReadName( pcx, paraminfo.oName );
1918 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1920 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1922 /* default value */
1923 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1924 (pFuncRec->FKCCIC & 0x1000) )
1926 INT* pInt = (INT *)((char *)pFuncRec +
1927 reclength -
1928 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1930 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1932 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1933 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1935 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1936 pInt[j], pcx);
1938 else
1939 elemdesc->u.paramdesc.pparamdescex = NULL;
1940 /* custom info */
1941 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1943 MSFT_CustData(pcx,
1944 pFuncRec->OptAttr[7+j],
1945 &(*pptfd)->pParamDesc[j].pCustData);
1948 /* SEEK value = jump to offset,
1949 * from there jump to the end of record,
1950 * go back by (j-1) arguments
1952 MSFT_ReadLEDWords( &paraminfo ,
1953 sizeof(MSFT_ParameterInfo), pcx,
1954 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1955 * sizeof(MSFT_ParameterInfo)));
1959 /* scode is not used: archaic win16 stuff FIXME: right? */
1960 (*pptfd)->funcdesc.cScodes = 0 ;
1961 (*pptfd)->funcdesc.lprgscode = NULL ;
1963 ptfd_prev = *pptfd;
1964 pptfd = & ((*pptfd)->next);
1965 recoffset += reclength;
1967 HeapFree(GetProcessHeap(), 0, recbuf);
1970 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1971 int cVars, int offset, TLBVarDesc ** pptvd)
1973 int infolen, nameoffset, reclength;
1974 char recbuf[256];
1975 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1976 int i;
1977 int recoffset;
1979 TRACE_(typelib)("\n");
1981 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1982 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1983 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1984 recoffset += offset+sizeof(INT);
1985 for(i=0;i<cVars;i++){
1986 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1987 /* name, eventually add to a hash table */
1988 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1989 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
1990 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1991 /* read the variable information record */
1992 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1993 reclength &=0xff;
1994 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1995 /* Optional data */
1996 if(reclength >(6*sizeof(INT)) )
1997 (*pptvd)->HelpContext=pVarRec->HelpContext;
1998 if(reclength >(7*sizeof(INT)) )
1999 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
2000 if(reclength >(8*sizeof(INT)) )
2001 if(reclength >(9*sizeof(INT)) )
2002 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
2003 /* fill the VarDesc Structure */
2004 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
2005 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2006 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
2007 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
2008 MSFT_GetTdesc(pcx, pVarRec->DataType,
2009 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
2010 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2011 if(pVarRec->VarKind == VAR_CONST ){
2012 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
2013 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
2014 pVarRec->OffsValue, pcx);
2015 } else
2016 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
2017 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
2018 pptvd=&((*pptvd)->next);
2019 recoffset += reclength;
2022 /* fill in data for a hreftype (offset). When the referenced type is contained
2023 * in the typelib, it's just an (file) offset in the type info base dir.
2024 * If comes from import, it's an offset+1 in the ImpInfo table
2025 * */
2026 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2027 int offset)
2029 TLBRefType *ref;
2031 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2033 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2035 if(ref->reference == offset) return;
2038 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
2039 list_add_tail(&pTL->ref_list, &ref->entry);
2041 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2042 /* external typelib */
2043 MSFT_ImpInfo impinfo;
2044 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2046 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2048 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2049 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2050 while (pImpLib){ /* search the known offsets of all import libraries */
2051 if(pImpLib->offset==impinfo.oImpFile) break;
2052 pImpLib=pImpLib->next;
2054 if(pImpLib){
2055 ref->reference = offset;
2056 ref->pImpTLInfo = pImpLib;
2057 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2058 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2059 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2060 ref->index = TLB_REF_USE_GUID;
2061 } else
2062 ref->index = impinfo.oGuid;
2063 }else{
2064 ERR("Cannot find a reference\n");
2065 ref->reference = -1;
2066 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2068 }else{
2069 /* in this typelib */
2070 ref->index = MSFT_HREFTYPE_INDEX(offset);
2071 ref->reference = offset;
2072 ref->pImpTLInfo = TLB_REF_INTERNAL;
2076 /* process Implemented Interfaces of a com class */
2077 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2078 int offset)
2080 int i;
2081 MSFT_RefRecord refrec;
2082 TLBImplType **ppImpl = &pTI->impltypelist;
2084 TRACE_(typelib)("\n");
2086 for(i=0;i<count;i++){
2087 if(offset<0) break; /* paranoia */
2088 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2089 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2090 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2091 (*ppImpl)->hRef = refrec.reftype;
2092 (*ppImpl)->implflags=refrec.flags;
2093 (*ppImpl)->ctCustData=
2094 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2095 offset=refrec.onext;
2096 ppImpl=&((*ppImpl)->next);
2100 * process a typeinfo record
2102 static ITypeInfoImpl * MSFT_DoTypeInfo(
2103 TLBContext *pcx,
2104 int count,
2105 ITypeLibImpl * pLibInfo)
2107 MSFT_TypeInfoBase tiBase;
2108 ITypeInfoImpl *ptiRet;
2110 TRACE_(typelib)("count=%u\n", count);
2112 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2113 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2114 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2116 /* this is where we are coming from */
2117 ptiRet->pTypeLib = pLibInfo;
2118 ptiRet->index=count;
2119 /* fill in the typeattr fields */
2121 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2122 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2123 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2124 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2125 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2126 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2127 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2128 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2129 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2130 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2131 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2132 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2133 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2134 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2135 MSFT_GetTdesc(pcx, tiBase.datatype1,
2136 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2138 /* FIXME: */
2139 /* IDLDESC idldescType; *//* never saw this one != zero */
2141 /* name, eventually add to a hash table */
2142 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2143 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2144 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2145 /* help info */
2146 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2147 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2148 ptiRet->dwHelpContext=tiBase.helpcontext;
2150 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2151 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2153 /* note: InfoType's Help file and HelpStringDll come from the containing
2154 * library. Further HelpString and Docstring appear to be the same thing :(
2156 /* functions */
2157 if(ptiRet->TypeAttr.cFuncs >0 )
2158 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2159 ptiRet->TypeAttr.cVars,
2160 tiBase.memoffset, & ptiRet->funclist);
2161 /* variables */
2162 if(ptiRet->TypeAttr.cVars >0 )
2163 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2164 ptiRet->TypeAttr.cVars,
2165 tiBase.memoffset, & ptiRet->varlist);
2166 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2167 switch(ptiRet->TypeAttr.typekind)
2169 case TKIND_COCLASS:
2170 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2171 tiBase.datatype1);
2172 break;
2173 case TKIND_DISPATCH:
2174 /* This is not -1 when the interface is a non-base dual interface or
2175 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2176 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2177 not this interface.
2180 if (tiBase.datatype1 != -1)
2182 ptiRet->impltypelist = TLB_Alloc(sizeof(TLBImplType));
2183 ptiRet->impltypelist->hRef = tiBase.datatype1;
2184 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2186 break;
2187 default:
2188 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2189 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2190 ptiRet->impltypelist->hRef = tiBase.datatype1;
2191 break;
2194 ptiRet->ctCustData=
2195 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2197 TRACE_(typelib)("%s guid: %s kind:%s\n",
2198 debugstr_w(ptiRet->Name),
2199 debugstr_guid(&ptiRet->TypeAttr.guid),
2200 typekind_desc[ptiRet->TypeAttr.typekind]);
2202 return ptiRet;
2205 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2206 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2207 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2208 * tradeoff here.
2210 static ITypeLibImpl *tlb_cache_first;
2211 static CRITICAL_SECTION cache_section;
2212 static CRITICAL_SECTION_DEBUG cache_section_debug =
2214 0, 0, &cache_section,
2215 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2216 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2218 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2221 typedef struct TLB_PEFile
2223 const IUnknownVtbl *lpvtbl;
2224 LONG refs;
2225 HMODULE dll;
2226 HRSRC typelib_resource;
2227 HGLOBAL typelib_global;
2228 LPVOID typelib_base;
2229 } TLB_PEFile;
2231 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2233 if (IsEqualIID(riid, &IID_IUnknown))
2235 *ppv = iface;
2236 IUnknown_AddRef(iface);
2237 return S_OK;
2239 *ppv = NULL;
2240 return E_NOINTERFACE;
2243 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2245 TLB_PEFile *This = (TLB_PEFile *)iface;
2246 return InterlockedIncrement(&This->refs);
2249 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2251 TLB_PEFile *This = (TLB_PEFile *)iface;
2252 ULONG refs = InterlockedDecrement(&This->refs);
2253 if (!refs)
2255 if (This->typelib_global)
2256 FreeResource(This->typelib_global);
2257 if (This->dll)
2258 FreeLibrary(This->dll);
2259 HeapFree(GetProcessHeap(), 0, This);
2261 return refs;
2264 static const IUnknownVtbl TLB_PEFile_Vtable =
2266 TLB_PEFile_QueryInterface,
2267 TLB_PEFile_AddRef,
2268 TLB_PEFile_Release
2271 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2273 TLB_PEFile *This;
2275 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2276 if (!This)
2277 return E_OUTOFMEMORY;
2279 This->lpvtbl = &TLB_PEFile_Vtable;
2280 This->refs = 1;
2281 This->dll = NULL;
2282 This->typelib_resource = NULL;
2283 This->typelib_global = NULL;
2284 This->typelib_base = NULL;
2286 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2287 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2289 if (This->dll)
2291 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2292 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2293 if (This->typelib_resource)
2295 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2296 if (This->typelib_global)
2298 This->typelib_base = LockResource(This->typelib_global);
2300 if (This->typelib_base)
2302 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2303 *ppBase = This->typelib_base;
2304 *ppFile = (IUnknown *)&This->lpvtbl;
2305 return S_OK;
2311 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2312 return TYPE_E_CANTLOADLIBRARY;
2316 typedef struct TLB_Mapping
2318 const IUnknownVtbl *lpvtbl;
2319 LONG refs;
2320 HANDLE file;
2321 HANDLE mapping;
2322 LPVOID typelib_base;
2323 } TLB_Mapping;
2325 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2327 if (IsEqualIID(riid, &IID_IUnknown))
2329 *ppv = iface;
2330 IUnknown_AddRef(iface);
2331 return S_OK;
2333 *ppv = NULL;
2334 return E_NOINTERFACE;
2337 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2339 TLB_Mapping *This = (TLB_Mapping *)iface;
2340 return InterlockedIncrement(&This->refs);
2343 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2345 TLB_Mapping *This = (TLB_Mapping *)iface;
2346 ULONG refs = InterlockedDecrement(&This->refs);
2347 if (!refs)
2349 if (This->typelib_base)
2350 UnmapViewOfFile(This->typelib_base);
2351 if (This->mapping)
2352 CloseHandle(This->mapping);
2353 if (This->file != INVALID_HANDLE_VALUE)
2354 CloseHandle(This->file);
2355 HeapFree(GetProcessHeap(), 0, This);
2357 return refs;
2360 static const IUnknownVtbl TLB_Mapping_Vtable =
2362 TLB_Mapping_QueryInterface,
2363 TLB_Mapping_AddRef,
2364 TLB_Mapping_Release
2367 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2369 TLB_Mapping *This;
2371 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2372 if (!This)
2373 return E_OUTOFMEMORY;
2375 This->lpvtbl = &TLB_Mapping_Vtable;
2376 This->refs = 1;
2377 This->file = INVALID_HANDLE_VALUE;
2378 This->mapping = NULL;
2379 This->typelib_base = NULL;
2381 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2382 if (INVALID_HANDLE_VALUE != This->file)
2384 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2385 if (This->mapping)
2387 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2388 if(This->typelib_base)
2390 /* retrieve file size */
2391 *pdwTLBLength = GetFileSize(This->file, NULL);
2392 *ppBase = This->typelib_base;
2393 *ppFile = (IUnknown *)&This->lpvtbl;
2394 return S_OK;
2399 IUnknown_Release((IUnknown *)&This->lpvtbl);
2400 return TYPE_E_CANTLOADLIBRARY;
2403 /****************************************************************************
2404 * TLB_ReadTypeLib
2406 * find the type of the typelib file and map the typelib resource into
2407 * the memory
2409 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2410 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2411 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2413 ITypeLibImpl *entry;
2414 HRESULT ret;
2415 INT index = 1;
2416 LPWSTR index_str, file = (LPWSTR)pszFileName;
2417 LPVOID pBase = NULL;
2418 DWORD dwTLBLength = 0;
2419 IUnknown *pFile = NULL;
2421 *ppTypeLib = NULL;
2423 index_str = strrchrW(pszFileName, '\\');
2424 if(index_str && *++index_str != '\0')
2426 LPWSTR end_ptr;
2427 long idx = strtolW(index_str, &end_ptr, 10);
2428 if(*end_ptr == '\0')
2430 int str_len = index_str - pszFileName - 1;
2431 index = idx;
2432 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
2433 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2434 file[str_len] = 0;
2438 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2440 if(strchrW(file, '\\'))
2442 lstrcpyW(pszPath, file);
2444 else
2446 int len = GetSystemDirectoryW(pszPath, cchPath);
2447 pszPath[len] = '\\';
2448 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2452 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file);
2454 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2456 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2457 EnterCriticalSection(&cache_section);
2458 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2460 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2462 TRACE("cache hit\n");
2463 *ppTypeLib = (ITypeLib2*)entry;
2464 ITypeLib_AddRef(*ppTypeLib);
2465 LeaveCriticalSection(&cache_section);
2466 return S_OK;
2469 LeaveCriticalSection(&cache_section);
2471 /* now actually load and parse the typelib */
2473 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2474 if (ret == TYPE_E_CANTLOADLIBRARY)
2475 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2476 if (SUCCEEDED(ret))
2478 if (dwTLBLength >= 4)
2480 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2481 if (dwSignature == MSFT_SIGNATURE)
2482 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2483 else if (dwSignature == SLTG_SIGNATURE)
2484 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2485 else
2487 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2488 ret = TYPE_E_CANTLOADLIBRARY;
2491 else
2492 ret = TYPE_E_CANTLOADLIBRARY;
2493 IUnknown_Release(pFile);
2496 if(*ppTypeLib) {
2497 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2499 TRACE("adding to cache\n");
2500 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2501 lstrcpyW(impl->path, pszPath);
2502 /* We should really canonicalise the path here. */
2503 impl->index = index;
2505 /* FIXME: check if it has added already in the meantime */
2506 EnterCriticalSection(&cache_section);
2507 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2508 impl->prev = NULL;
2509 tlb_cache_first = impl;
2510 LeaveCriticalSection(&cache_section);
2511 ret = S_OK;
2512 } else
2513 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2515 return ret;
2518 /*================== ITypeLib(2) Methods ===================================*/
2520 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2522 ITypeLibImpl* pTypeLibImpl;
2524 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2525 if (!pTypeLibImpl) return NULL;
2527 pTypeLibImpl->lpVtbl = &tlbvt;
2528 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2529 pTypeLibImpl->ref = 1;
2531 list_init(&pTypeLibImpl->ref_list);
2532 pTypeLibImpl->dispatch_href = -1;
2534 return pTypeLibImpl;
2537 /****************************************************************************
2538 * ITypeLib2_Constructor_MSFT
2540 * loading an MSFT typelib from an in-memory image
2542 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2544 TLBContext cx;
2545 long lPSegDir;
2546 MSFT_Header tlbHeader;
2547 MSFT_SegDir tlbSegDir;
2548 ITypeLibImpl * pTypeLibImpl;
2550 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2552 pTypeLibImpl = TypeLibImpl_Constructor();
2553 if (!pTypeLibImpl) return NULL;
2555 /* get pointer to beginning of typelib data */
2556 cx.pos = 0;
2557 cx.oStart=0;
2558 cx.mapping = pLib;
2559 cx.pLibInfo = pTypeLibImpl;
2560 cx.length = dwTLBLength;
2562 /* read header */
2563 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2564 TRACE_(typelib)("header:\n");
2565 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2566 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2567 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2568 return NULL;
2570 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2572 /* there is a small amount of information here until the next important
2573 * part:
2574 * the segment directory . Try to calculate the amount of data */
2575 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2577 /* now read the segment directory */
2578 TRACE("read segment directory (at %ld)\n",lPSegDir);
2579 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2580 cx.pTblDir = &tlbSegDir;
2582 /* just check two entries */
2583 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2585 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2586 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2587 return NULL;
2590 /* now fill our internal data */
2591 /* TLIBATTR fields */
2592 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2594 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2595 /* Windows seems to have zero here, is this correct? */
2596 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2597 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2598 else
2599 pTypeLibImpl->LibAttr.lcid = 0;
2601 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2602 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2603 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2604 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2606 /* name, eventually add to a hash table */
2607 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2609 /* help info */
2610 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2611 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2613 if( tlbHeader.varflags & HELPDLLFLAG)
2615 int offset;
2616 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2617 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2620 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2622 /* custom data */
2623 if(tlbHeader.CustomDataOffset >= 0)
2625 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2628 /* fill in type descriptions */
2629 if(tlbSegDir.pTypdescTab.length > 0)
2631 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2632 INT16 td[4];
2633 pTypeLibImpl->ctTypeDesc = cTD;
2634 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2635 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2636 for(i=0; i<cTD; )
2638 /* FIXME: add several sanity checks here */
2639 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2640 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2642 /* FIXME: check safearray */
2643 if(td[3] < 0)
2644 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2645 else
2646 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2648 else if(td[0] == VT_CARRAY)
2650 /* array descr table here */
2651 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2653 else if(td[0] == VT_USERDEFINED)
2655 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2657 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2660 /* second time around to fill the array subscript info */
2661 for(i=0;i<cTD;i++)
2663 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2664 if(tlbSegDir.pArrayDescriptions.offset>0)
2666 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2667 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2669 if(td[1]<0)
2670 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2671 else
2672 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2674 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2676 for(j = 0; j<td[2]; j++)
2678 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2679 sizeof(INT), &cx, DO_NOT_SEEK);
2680 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2681 sizeof(INT), &cx, DO_NOT_SEEK);
2684 else
2686 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2687 ERR("didn't find array description data\n");
2692 /* imported type libs */
2693 if(tlbSegDir.pImpFiles.offset>0)
2695 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2696 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2697 UINT16 size;
2699 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2701 char *name;
2702 DWORD len;
2704 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2705 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2706 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2708 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2709 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2710 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2711 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2713 size >>= 2;
2714 name = TLB_Alloc(size+1);
2715 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2716 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2717 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2718 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2719 TLB_Free(name);
2721 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2722 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2724 ppImpLib = &(*ppImpLib)->next;
2728 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
2729 if(pTypeLibImpl->dispatch_href != -1)
2730 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
2732 /* type info's */
2733 if(tlbHeader.nrtypeinfos >= 0 )
2735 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2736 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2737 int i;
2739 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
2741 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2743 ppTI = &((*ppTI)->next);
2744 (pTypeLibImpl->TypeInfoCount)++;
2748 TRACE("(%p)\n", pTypeLibImpl);
2749 return (ITypeLib2*) pTypeLibImpl;
2753 static BSTR TLB_MultiByteToBSTR(const char *ptr)
2755 DWORD len;
2756 WCHAR *nameW;
2757 BSTR ret;
2759 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2760 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2761 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2762 ret = SysAllocString(nameW);
2763 HeapFree(GetProcessHeap(), 0, nameW);
2764 return ret;
2767 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
2769 char b[3];
2770 int i;
2771 short s;
2773 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2774 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2775 return FALSE;
2778 guid->Data4[0] = s >> 8;
2779 guid->Data4[1] = s & 0xff;
2781 b[2] = '\0';
2782 for(i = 0; i < 6; i++) {
2783 memcpy(b, str + 24 + 2 * i, 2);
2784 guid->Data4[i + 2] = strtol(b, NULL, 16);
2786 return TRUE;
2789 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
2791 WORD bytelen;
2792 DWORD len;
2793 WCHAR *nameW;
2795 *pBstr = NULL;
2796 bytelen = *(const WORD*)ptr;
2797 if(bytelen == 0xffff) return 2;
2798 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2799 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2800 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2801 *pBstr = SysAllocStringLen(nameW, len);
2802 HeapFree(GetProcessHeap(), 0, nameW);
2803 return bytelen + 2;
2806 static WORD SLTG_ReadStringA(const char *ptr, char **str)
2808 WORD bytelen;
2810 *str = NULL;
2811 bytelen = *(const WORD*)ptr;
2812 if(bytelen == 0xffff) return 2;
2813 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2814 memcpy(*str, ptr + 2, bytelen);
2815 (*str)[bytelen] = '\0';
2816 return bytelen + 2;
2819 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2821 char *ptr = pLibBlk;
2822 WORD w;
2824 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2825 FIXME("libblk magic = %04x\n", w);
2826 return 0;
2829 ptr += 6;
2830 if((w = *(WORD*)ptr) != 0xffff) {
2831 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2832 ptr += w;
2834 ptr += 2;
2836 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2838 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2840 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2841 ptr += 4;
2843 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2844 ptr += 2;
2846 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2847 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2848 else
2849 pTypeLibImpl->LibAttr.lcid = 0;
2850 ptr += 2;
2852 ptr += 4; /* skip res12 */
2854 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2855 ptr += 2;
2857 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2858 ptr += 2;
2860 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2861 ptr += 2;
2863 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2864 ptr += sizeof(GUID);
2866 return ptr - (char*)pLibBlk;
2869 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
2870 typedef struct
2872 unsigned int num;
2873 HREFTYPE refs[1];
2874 } sltg_ref_lookup_t;
2876 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
2877 HREFTYPE *typelib_ref)
2879 if(typeinfo_ref < table->num)
2881 *typelib_ref = table->refs[typeinfo_ref];
2882 return S_OK;
2885 ERR_(typelib)("Unable to find reference\n");
2886 *typelib_ref = -1;
2887 return E_FAIL;
2890 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
2892 BOOL done = FALSE;
2894 while(!done) {
2895 if((*pType & 0xe00) == 0xe00) {
2896 pTD->vt = VT_PTR;
2897 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2898 sizeof(TYPEDESC));
2899 pTD = pTD->u.lptdesc;
2901 switch(*pType & 0x3f) {
2902 case VT_PTR:
2903 pTD->vt = VT_PTR;
2904 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2905 sizeof(TYPEDESC));
2906 pTD = pTD->u.lptdesc;
2907 break;
2909 case VT_USERDEFINED:
2910 pTD->vt = VT_USERDEFINED;
2911 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
2912 done = TRUE;
2913 break;
2915 case VT_CARRAY:
2917 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2918 array */
2920 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2922 pTD->vt = VT_CARRAY;
2923 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2924 sizeof(ARRAYDESC) +
2925 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2926 pTD->u.lpadesc->cDims = pSA->cDims;
2927 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2928 pSA->cDims * sizeof(SAFEARRAYBOUND));
2930 pTD = &pTD->u.lpadesc->tdescElem;
2931 break;
2934 case VT_SAFEARRAY:
2936 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2937 useful? */
2939 pType++;
2940 pTD->vt = VT_SAFEARRAY;
2941 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2942 sizeof(TYPEDESC));
2943 pTD = pTD->u.lptdesc;
2944 break;
2946 default:
2947 pTD->vt = *pType & 0x3f;
2948 done = TRUE;
2949 break;
2951 pType++;
2953 return pType;
2956 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
2957 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
2959 /* Handle [in/out] first */
2960 if((*pType & 0xc000) == 0xc000)
2961 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2962 else if(*pType & 0x8000)
2963 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2964 else if(*pType & 0x4000)
2965 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2966 else
2967 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2969 if(*pType & 0x2000)
2970 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2972 if(*pType & 0x80)
2973 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2975 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
2979 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
2980 char *pNameTable)
2982 int ref;
2983 char *name;
2984 TLBRefType *ref_type;
2985 sltg_ref_lookup_t *table;
2986 HREFTYPE typelib_ref;
2988 if(pRef->magic != SLTG_REF_MAGIC) {
2989 FIXME("Ref magic = %x\n", pRef->magic);
2990 return NULL;
2992 name = ( (char*)pRef->names + pRef->number);
2994 table = HeapAlloc(GetProcessHeap(), 0, sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
2995 table->num = pRef->number >> 3;
2997 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
2999 /* We don't want the first href to be 0 */
3000 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3002 for(ref = 0; ref < pRef->number >> 3; ref++) {
3003 char *refname;
3004 unsigned int lib_offs, type_num;
3006 ref_type = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref_type));
3008 name += SLTG_ReadStringA(name, &refname);
3009 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3010 FIXME_(typelib)("Can't sscanf ref\n");
3011 if(lib_offs != 0xffff) {
3012 TLBImpLib **import = &pTL->pImpLibs;
3014 while(*import) {
3015 if((*import)->offset == lib_offs)
3016 break;
3017 import = &(*import)->next;
3019 if(!*import) {
3020 char fname[MAX_PATH+1];
3021 int len;
3023 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3024 sizeof(**import));
3025 (*import)->offset = lib_offs;
3026 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3027 &(*import)->guid);
3028 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3029 &(*import)->wVersionMajor,
3030 &(*import)->wVersionMinor,
3031 &(*import)->lcid, fname) != 4) {
3032 FIXME_(typelib)("can't sscanf ref %s\n",
3033 pNameTable + lib_offs + 40);
3035 len = strlen(fname);
3036 if(fname[len-1] != '#')
3037 FIXME("fname = %s\n", fname);
3038 fname[len-1] = '\0';
3039 (*import)->name = TLB_MultiByteToBSTR(fname);
3041 ref_type->pImpTLInfo = *import;
3043 /* Store a reference to IDispatch */
3044 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
3045 pTL->dispatch_href = typelib_ref;
3047 } else { /* internal ref */
3048 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3050 ref_type->reference = typelib_ref;
3051 ref_type->index = type_num;
3053 HeapFree(GetProcessHeap(), 0, refname);
3054 list_add_tail(&pTL->ref_list, &ref_type->entry);
3056 table->refs[ref] = typelib_ref;
3057 typelib_ref += 4;
3059 if((BYTE)*name != SLTG_REF_MAGIC)
3060 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3061 dump_TLBRefType(pTL);
3062 return table;
3065 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3066 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3068 SLTG_ImplInfo *info;
3069 TLBImplType **ppImplType = &pTI->impltypelist;
3070 /* I don't really get this structure, usually it's 0x16 bytes
3071 long, but iuser.tlb contains some that are 0x18 bytes long.
3072 That's ok because we can use the next ptr to jump to the next
3073 one. But how do we know the length of the last one? The WORD
3074 at offs 0x8 might be the clue. For now I'm just assuming that
3075 the last one is the regular 0x16 bytes. */
3077 info = (SLTG_ImplInfo*)pBlk;
3078 while(1) {
3079 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3080 sizeof(**ppImplType));
3081 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef);
3082 (*ppImplType)->implflags = info->impltypeflags;
3083 pTI->TypeAttr.cImplTypes++;
3084 ppImplType = &(*ppImplType)->next;
3086 if(info->next == 0xffff)
3087 break;
3088 if(OneOnly)
3089 FIXME_(typelib)("Interface inheriting more than one interface\n");
3090 info = (SLTG_ImplInfo*)(pBlk + info->next);
3092 info++; /* see comment at top of function */
3093 return (char*)info;
3096 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3097 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3099 TLBVarDesc **ppVarDesc = &pTI->varlist;
3100 BSTR bstrPrevName = NULL;
3101 SLTG_Variable *pItem;
3102 unsigned short i;
3103 WORD *pType;
3105 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3106 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
3108 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3109 sizeof(**ppVarDesc));
3110 (*ppVarDesc)->vardesc.memid = pItem->memid;
3112 if (pItem->magic != SLTG_VAR_MAGIC &&
3113 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3114 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3115 return;
3118 if (pItem->name == 0xfffe)
3119 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
3120 else
3121 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3123 TRACE_(typelib)("name: %s\n", debugstr_w((*ppVarDesc)->Name));
3124 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3125 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3127 if(pItem->flags & 0x02)
3128 pType = &pItem->type;
3129 else
3130 pType = (WORD*)(pBlk + pItem->type);
3132 if (pItem->flags & ~0xda)
3133 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3135 SLTG_DoElem(pType, pBlk,
3136 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup);
3138 if (TRACE_ON(typelib)) {
3139 char buf[300];
3140 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3141 TRACE_(typelib)("elemdescVar: %s\n", buf);
3144 if (pItem->flags & 0x40) {
3145 TRACE_(typelib)("VAR_DISPATCH\n");
3146 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
3148 else if (pItem->flags & 0x10) {
3149 TRACE_(typelib)("VAR_CONST\n");
3150 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3151 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3152 sizeof(VARIANT));
3153 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3154 if (pItem->flags & 0x08)
3155 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) = pItem->byte_offs;
3156 else {
3157 switch ((*ppVarDesc)->vardesc.elemdescVar.tdesc.vt)
3159 case VT_LPSTR:
3160 case VT_LPWSTR:
3161 case VT_BSTR:
3163 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3164 BSTR str;
3165 TRACE_(typelib)("len = %u\n", len);
3166 if (len == 0xffff) {
3167 str = NULL;
3168 } else {
3169 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3170 str = SysAllocStringLen(NULL, alloc_len);
3171 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3173 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_BSTR;
3174 V_BSTR((*ppVarDesc)->vardesc.u.lpvarValue) = str;
3175 break;
3177 case VT_I2:
3178 case VT_UI2:
3179 case VT_I4:
3180 case VT_UI4:
3181 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
3182 *(INT*)(pBlk + pItem->byte_offs);
3183 break;
3184 default:
3185 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt);
3189 else {
3190 TRACE_(typelib)("VAR_PERINSTANCE\n");
3191 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3192 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3195 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3196 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
3198 if (pItem->flags & 0x80)
3199 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3201 bstrPrevName = (*ppVarDesc)->Name;
3202 ppVarDesc = &((*ppVarDesc)->next);
3204 pTI->TypeAttr.cVars = cVars;
3207 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3208 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3210 SLTG_Function *pFunc;
3211 unsigned short i;
3212 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3214 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3215 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3217 int param;
3218 WORD *pType, *pArg;
3220 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3221 sizeof(**ppFuncDesc));
3223 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3224 case SLTG_FUNCTION_MAGIC:
3225 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3226 break;
3227 case SLTG_DISPATCH_FUNCTION_MAGIC:
3228 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3229 break;
3230 case SLTG_STATIC_FUNCTION_MAGIC:
3231 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3232 break;
3233 default:
3234 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3235 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
3236 *ppFuncDesc = NULL;
3237 return;
3239 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3241 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3242 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3243 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3244 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3245 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3246 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3248 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3249 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3251 if(pFunc->retnextopt & 0x80)
3252 pType = &pFunc->rettype;
3253 else
3254 pType = (WORD*)(pBlk + pFunc->rettype);
3256 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3258 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3259 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3260 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3261 (*ppFuncDesc)->pParamDesc =
3262 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3263 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3265 pArg = (WORD*)(pBlk + pFunc->arg_off);
3267 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3268 char *paramName = pNameTable + *pArg;
3269 BOOL HaveOffs;
3270 /* If arg type follows then paramName points to the 2nd
3271 letter of the name, else the next WORD is an offset to
3272 the arg type and paramName points to the first letter.
3273 So let's take one char off paramName and see if we're
3274 pointing at an alpha-numeric char. However if *pArg is
3275 0xffff or 0xfffe then the param has no name, the former
3276 meaning that the next WORD is the type, the latter
3277 meaning that the next WORD is an offset to the type. */
3279 HaveOffs = FALSE;
3280 if(*pArg == 0xffff)
3281 paramName = NULL;
3282 else if(*pArg == 0xfffe) {
3283 paramName = NULL;
3284 HaveOffs = TRUE;
3286 else if(paramName[-1] && !isalnum(paramName[-1]))
3287 HaveOffs = TRUE;
3289 pArg++;
3291 if(HaveOffs) { /* the next word is an offset to type */
3292 pType = (WORD*)(pBlk + *pArg);
3293 SLTG_DoElem(pType, pBlk,
3294 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3295 pArg++;
3296 } else {
3297 if(paramName)
3298 paramName--;
3299 pArg = SLTG_DoElem(pArg, pBlk,
3300 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3303 /* Are we an optional param ? */
3304 if((*ppFuncDesc)->funcdesc.cParams - param <=
3305 (*ppFuncDesc)->funcdesc.cParamsOpt)
3306 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3308 if(paramName) {
3309 (*ppFuncDesc)->pParamDesc[param].Name =
3310 TLB_MultiByteToBSTR(paramName);
3314 ppFuncDesc = &((*ppFuncDesc)->next);
3315 if(pFunc->next == 0xffff) break;
3317 pTI->TypeAttr.cFuncs = cFuncs;
3320 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3321 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3322 SLTG_TypeInfoTail *pTITail)
3324 char *pFirstItem;
3325 sltg_ref_lookup_t *ref_lookup = NULL;
3327 if(pTIHeader->href_table != 0xffffffff) {
3328 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3329 pNameTable);
3332 pFirstItem = pBlk;
3334 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3335 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3337 HeapFree(GetProcessHeap(), 0, ref_lookup);
3341 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3342 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3343 const SLTG_TypeInfoTail *pTITail)
3345 char *pFirstItem;
3346 sltg_ref_lookup_t *ref_lookup = NULL;
3348 if(pTIHeader->href_table != 0xffffffff) {
3349 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3350 pNameTable);
3353 pFirstItem = pBlk;
3355 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3356 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3359 if (pTITail->funcs_off != 0xffff)
3360 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3362 HeapFree(GetProcessHeap(), 0, ref_lookup);
3364 if (TRACE_ON(typelib))
3365 dump_TLBFuncDesc(pTI->funclist);
3368 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3369 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3370 const SLTG_TypeInfoTail *pTITail)
3372 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3375 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3376 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3377 const SLTG_TypeInfoTail *pTITail)
3379 WORD *pType;
3380 sltg_ref_lookup_t *ref_lookup = NULL;
3382 if (pTITail->simple_alias) {
3383 /* if simple alias, no more processing required */
3384 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3385 return;
3388 if(pTIHeader->href_table != 0xffffffff) {
3389 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3390 pNameTable);
3393 /* otherwise it is an offset to a type */
3394 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3396 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3398 HeapFree(GetProcessHeap(), 0, ref_lookup);
3401 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3402 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3403 const SLTG_TypeInfoTail *pTITail)
3405 sltg_ref_lookup_t *ref_lookup = NULL;
3406 if (pTIHeader->href_table != 0xffffffff)
3407 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3408 pNameTable);
3410 if (pTITail->vars_off != 0xffff)
3411 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3413 if (pTITail->funcs_off != 0xffff)
3414 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3416 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3417 * of dispinterface functions including the IDispatch ones, so
3418 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3419 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3421 HeapFree(GetProcessHeap(), 0, ref_lookup);
3422 if (TRACE_ON(typelib))
3423 dump_TLBFuncDesc(pTI->funclist);
3426 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3427 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3428 const SLTG_TypeInfoTail *pTITail)
3430 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3433 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3434 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3435 const SLTG_TypeInfoTail *pTITail)
3437 sltg_ref_lookup_t *ref_lookup = NULL;
3438 if (pTIHeader->href_table != 0xffffffff)
3439 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3440 pNameTable);
3442 if (pTITail->vars_off != 0xffff)
3443 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3445 if (pTITail->funcs_off != 0xffff)
3446 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3447 HeapFree(GetProcessHeap(), 0, ref_lookup);
3448 if (TRACE_ON(typelib))
3449 dump_TypeInfo(pTI);
3452 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3453 managable copy of it into this */
3454 typedef struct {
3455 WORD small_no;
3456 char *index_name;
3457 char *other_name;
3458 WORD res1a;
3459 WORD name_offs;
3460 WORD more_bytes;
3461 char *extra;
3462 WORD res20;
3463 DWORD helpcontext;
3464 WORD res26;
3465 GUID uuid;
3466 } SLTG_InternalOtherTypeInfo;
3468 /****************************************************************************
3469 * ITypeLib2_Constructor_SLTG
3471 * loading a SLTG typelib from an in-memory image
3473 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3475 ITypeLibImpl *pTypeLibImpl;
3476 SLTG_Header *pHeader;
3477 SLTG_BlkEntry *pBlkEntry;
3478 SLTG_Magic *pMagic;
3479 SLTG_Index *pIndex;
3480 SLTG_Pad9 *pPad9;
3481 LPVOID pBlk, pFirstBlk;
3482 SLTG_LibBlk *pLibBlk;
3483 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3484 char *pAfterOTIBlks = NULL;
3485 char *pNameTable, *ptr;
3486 int i;
3487 DWORD len, order;
3488 ITypeInfoImpl **ppTypeInfoImpl;
3490 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3493 pTypeLibImpl = TypeLibImpl_Constructor();
3494 if (!pTypeLibImpl) return NULL;
3496 pHeader = pLib;
3498 TRACE_(typelib)("header:\n");
3499 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3500 pHeader->nrOfFileBlks );
3501 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3502 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3503 pHeader->SLTG_magic);
3504 return NULL;
3507 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3508 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3510 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3511 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3513 /* Next we have a magic block */
3514 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3516 /* Let's see if we're still in sync */
3517 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3518 sizeof(SLTG_COMPOBJ_MAGIC))) {
3519 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3520 return NULL;
3522 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3523 sizeof(SLTG_DIR_MAGIC))) {
3524 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
3525 return NULL;
3528 pIndex = (SLTG_Index*)(pMagic+1);
3530 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3532 pFirstBlk = (LPVOID)(pPad9 + 1);
3534 /* We'll set up a ptr to the main library block, which is the last one. */
3536 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3537 pBlkEntry[order].next != 0;
3538 order = pBlkEntry[order].next - 1, i++) {
3539 pBlk = (char*)pBlk + pBlkEntry[order].len;
3541 pLibBlk = pBlk;
3543 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3545 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3546 interspersed */
3548 len += 0x40;
3550 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3552 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3553 sizeof(*pOtherTypeInfoBlks) *
3554 pTypeLibImpl->TypeInfoCount);
3557 ptr = (char*)pLibBlk + len;
3559 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3560 WORD w, extra;
3561 len = 0;
3563 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3565 w = *(WORD*)(ptr + 2);
3566 if(w != 0xffff) {
3567 len += w;
3568 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3569 w+1);
3570 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3571 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3573 w = *(WORD*)(ptr + 4 + len);
3574 if(w != 0xffff) {
3575 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3576 len += w;
3577 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3578 w+1);
3579 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3580 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3582 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3583 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3584 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3585 if(extra) {
3586 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3587 extra);
3588 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3589 len += extra;
3591 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3592 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3593 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3594 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3595 len += sizeof(SLTG_OtherTypeInfo);
3596 ptr += len;
3599 pAfterOTIBlks = ptr;
3601 /* Skip this WORD and get the next DWORD */
3602 len = *(DWORD*)(pAfterOTIBlks + 2);
3604 /* Now add this to pLibBLk look at what we're pointing at and
3605 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3606 dust and we should be pointing at the beginning of the name
3607 table */
3609 pNameTable = (char*)pLibBlk + len;
3611 switch(*(WORD*)pNameTable) {
3612 case 0xffff:
3613 break;
3614 case 0x0200:
3615 pNameTable += 0x20;
3616 break;
3617 default:
3618 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
3619 break;
3622 pNameTable += 0x216;
3624 pNameTable += 2;
3626 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
3628 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3631 /* Hopefully we now have enough ptrs set up to actually read in
3632 some TypeInfos. It's not clear which order to do them in, so
3633 I'll just follow the links along the BlkEntry chain and read
3634 them in the order in which they are in the file */
3636 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3638 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3639 pBlkEntry[order].next != 0;
3640 order = pBlkEntry[order].next - 1, i++) {
3642 SLTG_TypeInfoHeader *pTIHeader;
3643 SLTG_TypeInfoTail *pTITail;
3644 SLTG_MemberHeader *pMemHeader;
3646 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3647 pOtherTypeInfoBlks[i].index_name)) {
3648 FIXME_(typelib)("Index strings don't match\n");
3649 return NULL;
3652 pTIHeader = pBlk;
3653 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3654 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3655 return NULL;
3657 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
3658 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3659 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3661 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3662 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3663 (*ppTypeInfoImpl)->index = i;
3664 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3665 pOtherTypeInfoBlks[i].name_offs +
3666 pNameTable);
3667 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3668 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
3669 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3670 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3671 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3672 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3673 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3675 if((pTIHeader->typeflags1 & 7) != 2)
3676 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
3677 if(pTIHeader->typeflags3 != 2)
3678 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
3680 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3681 debugstr_w((*ppTypeInfoImpl)->Name),
3682 typekind_desc[pTIHeader->typekind],
3683 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3684 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3686 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3688 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3690 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3691 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3692 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3694 switch(pTIHeader->typekind) {
3695 case TKIND_ENUM:
3696 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3697 pTIHeader, pTITail);
3698 break;
3700 case TKIND_RECORD:
3701 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3702 pTIHeader, pTITail);
3703 break;
3705 case TKIND_INTERFACE:
3706 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3707 pTIHeader, pTITail);
3708 break;
3710 case TKIND_COCLASS:
3711 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3712 pTIHeader, pTITail);
3713 break;
3715 case TKIND_ALIAS:
3716 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3717 pTIHeader, pTITail);
3718 break;
3720 case TKIND_DISPATCH:
3721 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3722 pTIHeader, pTITail);
3723 break;
3725 case TKIND_MODULE:
3726 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3727 pTIHeader, pTITail);
3728 break;
3730 default:
3731 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3732 break;
3736 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3737 but we've already set those */
3738 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3739 X(06);
3740 X(16);
3741 X(18);
3742 X(1a);
3743 X(1e);
3744 X(24);
3745 X(26);
3746 X(2a);
3747 X(2c);
3748 X(2e);
3749 X(30);
3750 X(32);
3751 X(34);
3753 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3754 pBlk = (char*)pBlk + pBlkEntry[order].len;
3757 if(i != pTypeLibImpl->TypeInfoCount) {
3758 FIXME("Somehow processed %d TypeInfos\n", i);
3759 return NULL;
3762 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3763 return (ITypeLib2*)pTypeLibImpl;
3766 /* ITypeLib::QueryInterface
3768 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3769 ITypeLib2 * iface,
3770 REFIID riid,
3771 VOID **ppvObject)
3773 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3775 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3777 *ppvObject=NULL;
3778 if(IsEqualIID(riid, &IID_IUnknown) ||
3779 IsEqualIID(riid,&IID_ITypeLib)||
3780 IsEqualIID(riid,&IID_ITypeLib2))
3782 *ppvObject = This;
3785 if(*ppvObject)
3787 ITypeLib2_AddRef(iface);
3788 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3789 return S_OK;
3791 TRACE("-- Interface: E_NOINTERFACE\n");
3792 return E_NOINTERFACE;
3795 /* ITypeLib::AddRef
3797 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3799 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3800 ULONG ref = InterlockedIncrement(&This->ref);
3802 TRACE("(%p)->ref was %u\n",This, ref - 1);
3804 return ref;
3807 /* ITypeLib::Release
3809 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3811 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3812 ULONG ref = InterlockedDecrement(&This->ref);
3814 TRACE("(%p)->(%u)\n",This, ref);
3816 if (!ref)
3818 TLBImpLib *pImpLib, *pImpLibNext;
3819 TLBCustData *pCustData, *pCustDataNext;
3820 TLBRefType *ref_type;
3821 void *cursor2;
3822 int i;
3824 /* remove cache entry */
3825 if(This->path)
3827 TRACE("removing from cache list\n");
3828 EnterCriticalSection(&cache_section);
3829 if (This->next) This->next->prev = This->prev;
3830 if (This->prev) This->prev->next = This->next;
3831 else tlb_cache_first = This->next;
3832 LeaveCriticalSection(&cache_section);
3833 HeapFree(GetProcessHeap(), 0, This->path);
3835 TRACE(" destroying ITypeLib(%p)\n",This);
3837 if (This->Name)
3839 SysFreeString(This->Name);
3840 This->Name = NULL;
3843 if (This->DocString)
3845 SysFreeString(This->DocString);
3846 This->DocString = NULL;
3849 if (This->HelpFile)
3851 SysFreeString(This->HelpFile);
3852 This->HelpFile = NULL;
3855 if (This->HelpStringDll)
3857 SysFreeString(This->HelpStringDll);
3858 This->HelpStringDll = NULL;
3861 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
3863 VariantClear(&pCustData->data);
3865 pCustDataNext = pCustData->next;
3866 TLB_Free(pCustData);
3869 for (i = 0; i < This->ctTypeDesc; i++)
3870 if (This->pTypeDesc[i].vt == VT_CARRAY)
3871 TLB_Free(This->pTypeDesc[i].u.lpadesc);
3873 TLB_Free(This->pTypeDesc);
3875 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
3877 if (pImpLib->pImpTypeLib)
3878 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
3879 TLB_Free(pImpLib->name);
3881 pImpLibNext = pImpLib->next;
3882 TLB_Free(pImpLib);
3885 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
3887 list_remove(&ref_type->entry);
3888 TLB_Free(ref_type);
3891 if (This->pTypeInfo) /* can be NULL */
3892 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3893 HeapFree(GetProcessHeap(),0,This);
3894 return 0;
3897 return ref;
3900 /* ITypeLib::GetTypeInfoCount
3902 * Returns the number of type descriptions in the type library
3904 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3906 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3907 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3908 return This->TypeInfoCount;
3911 /* ITypeLib::GetTypeInfo
3913 * retrieves the specified type description in the library.
3915 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3916 ITypeLib2 *iface,
3917 UINT index,
3918 ITypeInfo **ppTInfo)
3920 int i;
3922 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3923 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3925 TRACE("(%p)->(index=%d)\n", This, index);
3927 if (!ppTInfo) return E_INVALIDARG;
3929 /* search element n in list */
3930 for(i=0; i < index; i++)
3932 pTypeInfo = pTypeInfo->next;
3933 if (!pTypeInfo)
3935 TRACE("-- element not found\n");
3936 return TYPE_E_ELEMENTNOTFOUND;
3940 *ppTInfo = (ITypeInfo *) pTypeInfo;
3942 ITypeInfo_AddRef(*ppTInfo);
3943 TRACE("-- found (%p)\n",*ppTInfo);
3944 return S_OK;
3948 /* ITypeLibs::GetTypeInfoType
3950 * Retrieves the type of a type description.
3952 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3953 ITypeLib2 *iface,
3954 UINT index,
3955 TYPEKIND *pTKind)
3957 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3958 int i;
3959 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3961 if (ITypeLib2_fnGetTypeInfoCount(iface) < index + 1)
3962 return TYPE_E_ELEMENTNOTFOUND;
3964 TRACE("(%p) index %d\n", This, index);
3966 if(!pTKind) return E_INVALIDARG;
3968 /* search element n in list */
3969 for(i=0; i < index; i++)
3971 if(!pTInfo)
3973 TRACE("-- element not found\n");
3974 return TYPE_E_ELEMENTNOTFOUND;
3976 pTInfo = pTInfo->next;
3979 *pTKind = pTInfo->TypeAttr.typekind;
3980 TRACE("-- found Type (%d)\n", *pTKind);
3981 return S_OK;
3984 /* ITypeLib::GetTypeInfoOfGuid
3986 * Retrieves the type description that corresponds to the specified GUID.
3989 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3990 ITypeLib2 *iface,
3991 REFGUID guid,
3992 ITypeInfo **ppTInfo)
3994 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3995 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3997 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3999 if (!pTypeInfo)
4001 WARN("-- element not found\n");
4002 return TYPE_E_ELEMENTNOTFOUND;
4005 /* search linked list for guid */
4006 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
4008 pTypeInfo = pTypeInfo->next;
4010 if (!pTypeInfo)
4012 /* end of list reached */
4013 WARN("-- element not found\n");
4014 return TYPE_E_ELEMENTNOTFOUND;
4018 TRACE("-- found (%p, %s)\n",
4019 pTypeInfo,
4020 debugstr_w(pTypeInfo->Name));
4022 *ppTInfo = (ITypeInfo*)pTypeInfo;
4023 ITypeInfo_AddRef(*ppTInfo);
4024 return S_OK;
4027 /* ITypeLib::GetLibAttr
4029 * Retrieves the structure that contains the library's attributes.
4032 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4033 ITypeLib2 *iface,
4034 LPTLIBATTR *ppTLibAttr)
4036 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4037 TRACE("(%p)\n",This);
4038 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
4039 **ppTLibAttr = This->LibAttr;
4040 return S_OK;
4043 /* ITypeLib::GetTypeComp
4045 * Enables a client compiler to bind to a library's types, variables,
4046 * constants, and global functions.
4049 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4050 ITypeLib2 *iface,
4051 ITypeComp **ppTComp)
4053 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4055 TRACE("(%p)->(%p)\n",This,ppTComp);
4056 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4057 ITypeComp_AddRef(*ppTComp);
4059 return S_OK;
4062 /* ITypeLib::GetDocumentation
4064 * Retrieves the library's documentation string, the complete Help file name
4065 * and path, and the context identifier for the library Help topic in the Help
4066 * file.
4068 * On a successful return all non-null BSTR pointers will have been set,
4069 * possibly to NULL.
4071 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4072 ITypeLib2 *iface,
4073 INT index,
4074 BSTR *pBstrName,
4075 BSTR *pBstrDocString,
4076 DWORD *pdwHelpContext,
4077 BSTR *pBstrHelpFile)
4079 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4081 HRESULT result = E_INVALIDARG;
4083 ITypeInfo *pTInfo;
4086 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4087 This, index,
4088 pBstrName, pBstrDocString,
4089 pdwHelpContext, pBstrHelpFile);
4091 if(index<0)
4093 /* documentation for the typelib */
4094 if(pBstrName)
4096 if (This->Name)
4098 if(!(*pBstrName = SysAllocString(This->Name)))
4099 goto memerr1;
4101 else
4102 *pBstrName = NULL;
4104 if(pBstrDocString)
4106 if (This->DocString)
4108 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4109 goto memerr2;
4111 else if (This->Name)
4113 if(!(*pBstrDocString = SysAllocString(This->Name)))
4114 goto memerr2;
4116 else
4117 *pBstrDocString = NULL;
4119 if(pdwHelpContext)
4121 *pdwHelpContext = This->dwHelpContext;
4123 if(pBstrHelpFile)
4125 if (This->HelpFile)
4127 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4128 goto memerr3;
4130 else
4131 *pBstrHelpFile = NULL;
4134 result = S_OK;
4136 else
4138 /* for a typeinfo */
4139 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4141 if(SUCCEEDED(result))
4143 result = ITypeInfo_GetDocumentation(pTInfo,
4144 MEMBERID_NIL,
4145 pBstrName,
4146 pBstrDocString,
4147 pdwHelpContext, pBstrHelpFile);
4149 ITypeInfo_Release(pTInfo);
4152 return result;
4153 memerr3:
4154 if (pBstrDocString) SysFreeString (*pBstrDocString);
4155 memerr2:
4156 if (pBstrName) SysFreeString (*pBstrName);
4157 memerr1:
4158 return STG_E_INSUFFICIENTMEMORY;
4161 /* ITypeLib::IsName
4163 * Indicates whether a passed-in string contains the name of a type or member
4164 * described in the library.
4167 static HRESULT WINAPI ITypeLib2_fnIsName(
4168 ITypeLib2 *iface,
4169 LPOLESTR szNameBuf,
4170 ULONG lHashVal,
4171 BOOL *pfName)
4173 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4174 ITypeInfoImpl *pTInfo;
4175 TLBFuncDesc *pFInfo;
4176 TLBVarDesc *pVInfo;
4177 int i;
4178 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4180 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4181 pfName);
4183 *pfName=TRUE;
4184 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
4185 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4186 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4187 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4188 for(i=0;i<pFInfo->funcdesc.cParams;i++)
4189 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
4190 goto ITypeLib2_fnIsName_exit;
4192 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4193 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4196 *pfName=FALSE;
4198 ITypeLib2_fnIsName_exit:
4199 TRACE("(%p)slow! search for %s: %s found!\n", This,
4200 debugstr_w(szNameBuf), *pfName?"NOT":"");
4202 return S_OK;
4205 /* ITypeLib::FindName
4207 * Finds occurrences of a type description in a type library. This may be used
4208 * to quickly verify that a name exists in a type library.
4211 static HRESULT WINAPI ITypeLib2_fnFindName(
4212 ITypeLib2 *iface,
4213 LPOLESTR szNameBuf,
4214 ULONG lHashVal,
4215 ITypeInfo **ppTInfo,
4216 MEMBERID *rgMemId,
4217 UINT16 *pcFound)
4219 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4220 ITypeInfoImpl *pTInfo;
4221 TLBFuncDesc *pFInfo;
4222 TLBVarDesc *pVInfo;
4223 int i,j = 0;
4224 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4226 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
4227 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4228 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4229 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4230 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
4231 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
4232 goto ITypeLib2_fnFindName_exit;
4235 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4236 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4237 continue;
4238 ITypeLib2_fnFindName_exit:
4239 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4240 ppTInfo[j]=(LPTYPEINFO)pTInfo;
4241 j++;
4243 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4244 This, *pcFound, debugstr_w(szNameBuf), j);
4246 *pcFound=j;
4248 return S_OK;
4251 /* ITypeLib::ReleaseTLibAttr
4253 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4256 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4257 ITypeLib2 *iface,
4258 TLIBATTR *pTLibAttr)
4260 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4261 TRACE("freeing (%p)\n",This);
4262 HeapFree(GetProcessHeap(),0,pTLibAttr);
4266 /* ITypeLib2::GetCustData
4268 * gets the custom data
4270 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4271 ITypeLib2 * iface,
4272 REFGUID guid,
4273 VARIANT *pVarVal)
4275 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4276 TLBCustData *pCData;
4278 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4280 if( IsEqualIID(guid, &pCData->guid)) break;
4283 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4285 if(pCData)
4287 VariantInit( pVarVal);
4288 VariantCopy( pVarVal, &pCData->data);
4289 return S_OK;
4291 return E_INVALIDARG; /* FIXME: correct? */
4294 /* ITypeLib2::GetLibStatistics
4296 * Returns statistics about a type library that are required for efficient
4297 * sizing of hash tables.
4300 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4301 ITypeLib2 * iface,
4302 ULONG *pcUniqueNames,
4303 ULONG *pcchUniqueNames)
4305 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4307 FIXME("(%p): stub!\n", This);
4309 if(pcUniqueNames) *pcUniqueNames=1;
4310 if(pcchUniqueNames) *pcchUniqueNames=1;
4311 return S_OK;
4314 /* ITypeLib2::GetDocumentation2
4316 * Retrieves the library's documentation string, the complete Help file name
4317 * and path, the localization context to use, and the context ID for the
4318 * library Help topic in the Help file.
4321 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4322 ITypeLib2 * iface,
4323 INT index,
4324 LCID lcid,
4325 BSTR *pbstrHelpString,
4326 DWORD *pdwHelpStringContext,
4327 BSTR *pbstrHelpStringDll)
4329 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4330 HRESULT result;
4331 ITypeInfo *pTInfo;
4333 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4335 /* the help string should be obtained from the helpstringdll,
4336 * using the _DLLGetDocumentation function, based on the supplied
4337 * lcid. Nice to do sometime...
4339 if(index<0)
4341 /* documentation for the typelib */
4342 if(pbstrHelpString)
4343 *pbstrHelpString=SysAllocString(This->DocString);
4344 if(pdwHelpStringContext)
4345 *pdwHelpStringContext=This->dwHelpContext;
4346 if(pbstrHelpStringDll)
4347 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4349 result = S_OK;
4351 else
4353 /* for a typeinfo */
4354 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4356 if(SUCCEEDED(result))
4358 ITypeInfo2 * pTInfo2;
4359 result = ITypeInfo_QueryInterface(pTInfo,
4360 &IID_ITypeInfo2,
4361 (LPVOID*) &pTInfo2);
4363 if(SUCCEEDED(result))
4365 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4366 MEMBERID_NIL,
4367 lcid,
4368 pbstrHelpString,
4369 pdwHelpStringContext,
4370 pbstrHelpStringDll);
4372 ITypeInfo2_Release(pTInfo2);
4375 ITypeInfo_Release(pTInfo);
4378 return result;
4381 /* ITypeLib2::GetAllCustData
4383 * Gets all custom data items for the library.
4386 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4387 ITypeLib2 * iface,
4388 CUSTDATA *pCustData)
4390 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4391 TLBCustData *pCData;
4392 int i;
4393 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4394 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4395 if(pCustData->prgCustData ){
4396 pCustData->cCustData=This->ctCustData;
4397 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4398 pCustData->prgCustData[i].guid=pCData->guid;
4399 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4401 }else{
4402 ERR(" OUT OF MEMORY!\n");
4403 return E_OUTOFMEMORY;
4405 return S_OK;
4408 static const ITypeLib2Vtbl tlbvt = {
4409 ITypeLib2_fnQueryInterface,
4410 ITypeLib2_fnAddRef,
4411 ITypeLib2_fnRelease,
4412 ITypeLib2_fnGetTypeInfoCount,
4413 ITypeLib2_fnGetTypeInfo,
4414 ITypeLib2_fnGetTypeInfoType,
4415 ITypeLib2_fnGetTypeInfoOfGuid,
4416 ITypeLib2_fnGetLibAttr,
4417 ITypeLib2_fnGetTypeComp,
4418 ITypeLib2_fnGetDocumentation,
4419 ITypeLib2_fnIsName,
4420 ITypeLib2_fnFindName,
4421 ITypeLib2_fnReleaseTLibAttr,
4423 ITypeLib2_fnGetCustData,
4424 ITypeLib2_fnGetLibStatistics,
4425 ITypeLib2_fnGetDocumentation2,
4426 ITypeLib2_fnGetAllCustData
4430 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4432 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4434 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4437 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4439 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4441 return ITypeLib2_AddRef((ITypeLib2 *)This);
4444 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4446 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4448 return ITypeLib2_Release((ITypeLib2 *)This);
4451 static HRESULT WINAPI ITypeLibComp_fnBind(
4452 ITypeComp * iface,
4453 OLECHAR * szName,
4454 ULONG lHash,
4455 WORD wFlags,
4456 ITypeInfo ** ppTInfo,
4457 DESCKIND * pDescKind,
4458 BINDPTR * pBindPtr)
4460 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4461 ITypeInfoImpl *pTypeInfo;
4463 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4465 *pDescKind = DESCKIND_NONE;
4466 pBindPtr->lptcomp = NULL;
4467 *ppTInfo = NULL;
4469 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4471 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4473 /* FIXME: check wFlags here? */
4474 /* FIXME: we should use a hash table to look this info up using lHash
4475 * instead of an O(n) search */
4476 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4477 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4479 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4481 *pDescKind = DESCKIND_TYPECOMP;
4482 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4483 ITypeComp_AddRef(pBindPtr->lptcomp);
4484 TRACE("module or enum: %s\n", debugstr_w(szName));
4485 return S_OK;
4489 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4490 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4492 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4493 HRESULT hr;
4495 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4496 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4498 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4499 return S_OK;
4503 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4504 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4506 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4507 HRESULT hr;
4508 ITypeInfo *subtypeinfo;
4509 BINDPTR subbindptr;
4510 DESCKIND subdesckind;
4512 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4513 &subtypeinfo, &subdesckind, &subbindptr);
4514 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4516 TYPEDESC tdesc_appobject =
4519 (TYPEDESC *)pTypeInfo->hreftype
4521 VT_USERDEFINED
4523 const VARDESC vardesc_appobject =
4525 -2, /* memid */
4526 NULL, /* lpstrSchema */
4528 0 /* oInst */
4531 /* ELEMDESC */
4533 /* TYPEDESC */
4535 &tdesc_appobject
4537 VT_PTR
4540 0, /* wVarFlags */
4541 VAR_STATIC /* varkind */
4544 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4546 /* cleanup things filled in by Bind call so we can put our
4547 * application object data in there instead */
4548 switch (subdesckind)
4550 case DESCKIND_FUNCDESC:
4551 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4552 break;
4553 case DESCKIND_VARDESC:
4554 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4555 break;
4556 default:
4557 break;
4559 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4561 if (pTypeInfo->hreftype == -1)
4562 FIXME("no hreftype for interface %p\n", pTypeInfo);
4564 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4565 if (FAILED(hr))
4566 return hr;
4568 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4569 *ppTInfo = (ITypeInfo *)pTypeInfo;
4570 ITypeInfo_AddRef(*ppTInfo);
4571 return S_OK;
4576 TRACE("name not found %s\n", debugstr_w(szName));
4577 return S_OK;
4580 static HRESULT WINAPI ITypeLibComp_fnBindType(
4581 ITypeComp * iface,
4582 OLECHAR * szName,
4583 ULONG lHash,
4584 ITypeInfo ** ppTInfo,
4585 ITypeComp ** ppTComp)
4587 FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4588 return E_NOTIMPL;
4591 static const ITypeCompVtbl tlbtcvt =
4594 ITypeLibComp_fnQueryInterface,
4595 ITypeLibComp_fnAddRef,
4596 ITypeLibComp_fnRelease,
4598 ITypeLibComp_fnBind,
4599 ITypeLibComp_fnBindType
4602 /*================== ITypeInfo(2) Methods ===================================*/
4603 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4605 ITypeInfoImpl * pTypeInfoImpl;
4607 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4608 if (pTypeInfoImpl)
4610 pTypeInfoImpl->lpVtbl = &tinfvt;
4611 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4612 pTypeInfoImpl->ref=1;
4613 pTypeInfoImpl->hreftype = -1;
4614 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4615 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4617 TRACE("(%p)\n", pTypeInfoImpl);
4618 return (ITypeInfo2*) pTypeInfoImpl;
4621 /* ITypeInfo::QueryInterface
4623 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4624 ITypeInfo2 *iface,
4625 REFIID riid,
4626 VOID **ppvObject)
4628 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4630 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4632 *ppvObject=NULL;
4633 if(IsEqualIID(riid, &IID_IUnknown) ||
4634 IsEqualIID(riid,&IID_ITypeInfo)||
4635 IsEqualIID(riid,&IID_ITypeInfo2))
4636 *ppvObject = This;
4638 if(*ppvObject){
4639 ITypeInfo_AddRef(iface);
4640 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4641 return S_OK;
4643 TRACE("-- Interface: E_NOINTERFACE\n");
4644 return E_NOINTERFACE;
4647 /* ITypeInfo::AddRef
4649 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4651 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4652 ULONG ref = InterlockedIncrement(&This->ref);
4654 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4656 TRACE("(%p)->ref is %u\n",This, ref);
4657 return ref;
4660 /* ITypeInfo::Release
4662 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4664 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4665 ULONG ref = InterlockedDecrement(&This->ref);
4667 TRACE("(%p)->(%u)\n",This, ref);
4669 if (ref) {
4670 /* We don't release ITypeLib when ref=0 because
4671 it means that function is called by ITypeLib2_Release */
4672 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4673 } else {
4674 TLBFuncDesc *pFInfo, *pFInfoNext;
4675 TLBVarDesc *pVInfo, *pVInfoNext;
4676 TLBImplType *pImpl, *pImplNext;
4678 TRACE("destroying ITypeInfo(%p)\n",This);
4680 if (This->no_free_data)
4681 goto finish_free;
4683 if (This->Name)
4685 SysFreeString(This->Name);
4686 This->Name = 0;
4689 if (This->DocString)
4691 SysFreeString(This->DocString);
4692 This->DocString = 0;
4695 if (This->DllName)
4697 SysFreeString(This->DllName);
4698 This->DllName = 0;
4701 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4703 UINT i;
4704 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4706 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4707 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4709 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4710 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4712 SysFreeString(pFInfo->pParamDesc[i].Name);
4714 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4715 TLB_Free(pFInfo->pParamDesc);
4716 TLB_FreeCustData(pFInfo->pCustData);
4717 if (HIWORD(pFInfo->Entry) != 0 && pFInfo->Entry != (BSTR)-1)
4718 SysFreeString(pFInfo->Entry);
4719 SysFreeString(pFInfo->HelpString);
4720 SysFreeString(pFInfo->Name);
4722 pFInfoNext = pFInfo->next;
4723 TLB_Free(pFInfo);
4725 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
4727 if (pVInfo->vardesc.varkind == VAR_CONST)
4729 VariantClear(pVInfo->vardesc.u.lpvarValue);
4730 TLB_Free(pVInfo->vardesc.u.lpvarValue);
4732 TLB_FreeCustData(pVInfo->pCustData);
4733 SysFreeString(pVInfo->Name);
4734 pVInfoNext = pVInfo->next;
4735 TLB_Free(pVInfo);
4737 for(pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
4739 TLB_FreeCustData(pImpl->pCustData);
4740 pImplNext = pImpl->next;
4741 TLB_Free(pImpl);
4743 TLB_FreeCustData(This->pCustData);
4745 finish_free:
4746 if (This->next)
4748 ITypeInfo_Release((ITypeInfo*)This->next);
4751 HeapFree(GetProcessHeap(),0,This);
4752 return 0;
4754 return ref;
4757 /* ITypeInfo::GetTypeAttr
4759 * Retrieves a TYPEATTR structure that contains the attributes of the type
4760 * description.
4763 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4764 LPTYPEATTR *ppTypeAttr)
4766 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4767 SIZE_T size;
4769 TRACE("(%p)\n",This);
4771 size = sizeof(**ppTypeAttr);
4772 if (This->TypeAttr.typekind == TKIND_ALIAS)
4773 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4775 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4776 if (!*ppTypeAttr)
4777 return E_OUTOFMEMORY;
4779 **ppTypeAttr = This->TypeAttr;
4781 if (This->TypeAttr.typekind == TKIND_ALIAS)
4782 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4783 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4785 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4786 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4787 funcs */
4788 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4789 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4791 return S_OK;
4794 /* ITypeInfo::GetTypeComp
4796 * Retrieves the ITypeComp interface for the type description, which enables a
4797 * client compiler to bind to the type description's members.
4800 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4801 ITypeComp * *ppTComp)
4803 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4805 TRACE("(%p)->(%p)\n", This, ppTComp);
4807 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4808 ITypeComp_AddRef(*ppTComp);
4809 return S_OK;
4812 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4814 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4815 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4816 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4817 return size;
4820 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4822 *dest = *src;
4823 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4824 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4826 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4827 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4828 *buffer += sizeof(PARAMDESCEX);
4829 *pparamdescex_dest = *pparamdescex_src;
4830 VariantInit(&pparamdescex_dest->varDefaultValue);
4831 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4832 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4834 else
4835 dest->u.paramdesc.pparamdescex = NULL;
4836 return S_OK;
4839 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4841 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4842 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4845 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4847 FUNCDESC *dest;
4848 char *buffer;
4849 SIZE_T size = sizeof(*src);
4850 SHORT i;
4851 HRESULT hr;
4853 size += sizeof(*src->lprgscode) * src->cScodes;
4854 size += TLB_SizeElemDesc(&src->elemdescFunc);
4855 for (i = 0; i < src->cParams; i++)
4857 size += sizeof(ELEMDESC);
4858 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4861 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4862 if (!dest) return E_OUTOFMEMORY;
4864 *dest = *src;
4865 if (dispinterface) /* overwrite funckind */
4866 dest->funckind = FUNC_DISPATCH;
4867 buffer = (char *)(dest + 1);
4869 dest->lprgscode = (SCODE *)buffer;
4870 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4871 buffer += sizeof(*src->lprgscode) * src->cScodes;
4873 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4874 if (FAILED(hr))
4876 SysFreeString((BSTR)dest);
4877 return hr;
4880 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4881 buffer += sizeof(ELEMDESC) * src->cParams;
4882 for (i = 0; i < src->cParams; i++)
4884 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4885 if (FAILED(hr))
4886 break;
4888 if (FAILED(hr))
4890 /* undo the above actions */
4891 for (i = i - 1; i >= 0; i--)
4892 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4893 TLB_FreeElemDesc(&dest->elemdescFunc);
4894 SysFreeString((BSTR)dest);
4895 return hr;
4898 /* special treatment for dispinterfaces: this makes functions appear
4899 * to return their [retval] value when it is really returning an
4900 * HRESULT */
4901 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4903 if (dest->cParams &&
4904 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4906 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4907 if (elemdesc->tdesc.vt != VT_PTR)
4909 ERR("elemdesc should have started with VT_PTR instead of:\n");
4910 if (ERR_ON(ole))
4911 dump_ELEMDESC(elemdesc);
4912 return E_UNEXPECTED;
4915 /* copy last parameter to the return value. we are using a flat
4916 * buffer so there is no danger of leaking memory in
4917 * elemdescFunc */
4918 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4920 /* remove the last parameter */
4921 dest->cParams--;
4923 else
4924 /* otherwise this function is made to appear to have no return
4925 * value */
4926 dest->elemdescFunc.tdesc.vt = VT_VOID;
4930 *dest_ptr = dest;
4931 return S_OK;
4934 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4936 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4937 const TLBFuncDesc *pFDesc;
4938 int i;
4940 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4943 if (pFDesc)
4945 *ppFuncDesc = &pFDesc->funcdesc;
4946 return S_OK;
4949 return TYPE_E_ELEMENTNOTFOUND;
4952 /* internal function to make the inherited interfaces' methods appear
4953 * part of the interface */
4954 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
4955 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
4957 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4958 HRESULT hr;
4959 UINT implemented_funcs = 0;
4961 if (funcs)
4962 *funcs = 0;
4963 else
4964 *hrefoffset = DISPATCH_HREF_OFFSET;
4966 if(This->impltypelist)
4968 ITypeInfo *pSubTypeInfo;
4969 UINT sub_funcs;
4971 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
4972 if (FAILED(hr))
4973 return hr;
4975 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
4976 index,
4977 ppFuncDesc,
4978 &sub_funcs, hrefoffset);
4979 implemented_funcs += sub_funcs;
4980 ITypeInfo_Release(pSubTypeInfo);
4981 if (SUCCEEDED(hr))
4982 return hr;
4983 *hrefoffset += DISPATCH_HREF_OFFSET;
4986 if (funcs)
4987 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
4988 else
4989 *hrefoffset = 0;
4991 if (index < implemented_funcs)
4992 return E_INVALIDARG;
4993 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
4994 ppFuncDesc);
4997 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
4999 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5000 while (TRUE)
5002 switch (pTypeDesc->vt)
5004 case VT_USERDEFINED:
5005 pTypeDesc->u.hreftype += hrefoffset;
5006 return;
5007 case VT_PTR:
5008 case VT_SAFEARRAY:
5009 pTypeDesc = pTypeDesc->u.lptdesc;
5010 break;
5011 case VT_CARRAY:
5012 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5013 break;
5014 default:
5015 return;
5020 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5022 SHORT i;
5023 for (i = 0; i < pFuncDesc->cParams; i++)
5024 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5025 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5028 /* ITypeInfo::GetFuncDesc
5030 * Retrieves the FUNCDESC structure that contains information about a
5031 * specified function.
5034 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5035 LPFUNCDESC *ppFuncDesc)
5037 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5038 const FUNCDESC *internal_funcdesc;
5039 HRESULT hr;
5040 UINT hrefoffset = 0;
5042 TRACE("(%p) index %d\n", This, index);
5044 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5045 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5046 &internal_funcdesc, NULL,
5047 &hrefoffset);
5048 else
5049 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5050 &internal_funcdesc);
5051 if (FAILED(hr))
5053 WARN("description for function %d not found\n", index);
5054 return hr;
5057 hr = TLB_AllocAndInitFuncDesc(
5058 internal_funcdesc,
5059 ppFuncDesc,
5060 This->TypeAttr.typekind == TKIND_DISPATCH);
5062 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5063 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5065 TRACE("-- 0x%08x\n", hr);
5066 return hr;
5069 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5071 VARDESC *dest;
5072 char *buffer;
5073 SIZE_T size = sizeof(*src);
5074 HRESULT hr;
5076 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5077 if (src->varkind == VAR_CONST)
5078 size += sizeof(VARIANT);
5079 size += TLB_SizeElemDesc(&src->elemdescVar);
5081 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5082 if (!dest) return E_OUTOFMEMORY;
5084 *dest = *src;
5085 buffer = (char *)(dest + 1);
5086 if (src->lpstrSchema)
5088 int len;
5089 dest->lpstrSchema = (LPOLESTR)buffer;
5090 len = strlenW(src->lpstrSchema);
5091 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5092 buffer += (len + 1) * sizeof(WCHAR);
5095 if (src->varkind == VAR_CONST)
5097 HRESULT hr;
5099 dest->u.lpvarValue = (VARIANT *)buffer;
5100 *dest->u.lpvarValue = *src->u.lpvarValue;
5101 buffer += sizeof(VARIANT);
5102 VariantInit(dest->u.lpvarValue);
5103 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5104 if (FAILED(hr))
5106 SysFreeString((BSTR)dest_ptr);
5107 return hr;
5110 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5111 if (FAILED(hr))
5113 if (src->varkind == VAR_CONST)
5114 VariantClear(dest->u.lpvarValue);
5115 SysFreeString((BSTR)dest);
5116 return hr;
5118 *dest_ptr = dest;
5119 return S_OK;
5122 /* ITypeInfo::GetVarDesc
5124 * Retrieves a VARDESC structure that describes the specified variable.
5127 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5128 LPVARDESC *ppVarDesc)
5130 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5131 int i;
5132 const TLBVarDesc *pVDesc;
5134 TRACE("(%p) index %d\n", This, index);
5136 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
5139 if (pVDesc)
5140 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5142 return E_INVALIDARG;
5145 /* ITypeInfo_GetNames
5147 * Retrieves the variable with the specified member ID (or the name of the
5148 * property or method and its parameters) that correspond to the specified
5149 * function ID.
5151 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5152 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5154 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5155 const TLBFuncDesc *pFDesc;
5156 const TLBVarDesc *pVDesc;
5157 int i;
5158 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5159 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
5160 if(pFDesc)
5162 /* function found, now return function and parameter names */
5163 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5165 if(!i)
5166 *rgBstrNames=SysAllocString(pFDesc->Name);
5167 else
5168 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5170 *pcNames=i;
5172 else
5174 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
5175 if(pVDesc)
5177 *rgBstrNames=SysAllocString(pVDesc->Name);
5178 *pcNames=1;
5180 else
5182 if(This->impltypelist &&
5183 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5184 /* recursive search */
5185 ITypeInfo *pTInfo;
5186 HRESULT result;
5187 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5188 &pTInfo);
5189 if(SUCCEEDED(result))
5191 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5192 ITypeInfo_Release(pTInfo);
5193 return result;
5195 WARN("Could not search inherited interface!\n");
5197 else
5199 WARN("no names found\n");
5201 *pcNames=0;
5202 return TYPE_E_ELEMENTNOTFOUND;
5205 return S_OK;
5209 /* ITypeInfo::GetRefTypeOfImplType
5211 * If a type description describes a COM class, it retrieves the type
5212 * description of the implemented interface types. For an interface,
5213 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5214 * if any exist.
5217 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5218 ITypeInfo2 *iface,
5219 UINT index,
5220 HREFTYPE *pRefType)
5222 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5223 int i;
5224 HRESULT hr = S_OK;
5225 const TLBImplType *pImpl = This->impltypelist;
5227 TRACE("(%p) index %d\n", This, index);
5228 if (TRACE_ON(ole)) dump_TypeInfo(This);
5230 if(index==(UINT)-1)
5232 /* only valid on dual interfaces;
5233 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5235 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5237 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
5238 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
5240 *pRefType = -1;
5242 else
5244 hr = TYPE_E_ELEMENTNOTFOUND;
5247 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5249 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5250 *pRefType = This->pTypeLib->dispatch_href;
5252 else
5254 /* get element n from linked list */
5255 for(i=0; pImpl && i<index; i++)
5257 pImpl = pImpl->next;
5260 if (pImpl)
5261 *pRefType = pImpl->hRef;
5262 else
5263 hr = TYPE_E_ELEMENTNOTFOUND;
5266 if(TRACE_ON(ole))
5268 if(SUCCEEDED(hr))
5269 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5270 else
5271 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5274 return hr;
5277 /* ITypeInfo::GetImplTypeFlags
5279 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5280 * or base interface in a type description.
5282 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5283 UINT index, INT *pImplTypeFlags)
5285 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5286 int i;
5287 TLBImplType *pImpl;
5289 TRACE("(%p) index %d\n", This, index);
5290 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5291 i++, pImpl=pImpl->next)
5293 if(i==index && pImpl){
5294 *pImplTypeFlags=pImpl->implflags;
5295 return S_OK;
5297 *pImplTypeFlags=0;
5298 return TYPE_E_ELEMENTNOTFOUND;
5301 /* GetIDsOfNames
5302 * Maps between member names and member IDs, and parameter names and
5303 * parameter IDs.
5305 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5306 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5308 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5309 const TLBFuncDesc *pFDesc;
5310 const TLBVarDesc *pVDesc;
5311 HRESULT ret=S_OK;
5312 int i;
5314 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5315 cNames);
5317 /* init out parameters in case of failure */
5318 for (i = 0; i < cNames; i++)
5319 pMemId[i] = MEMBERID_NIL;
5321 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5322 int j;
5323 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5324 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5325 for(i=1; i < cNames; i++){
5326 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5327 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5328 break;
5329 if( j<pFDesc->funcdesc.cParams)
5330 pMemId[i]=j;
5331 else
5332 ret=DISP_E_UNKNOWNNAME;
5334 TRACE("-- 0x%08x\n", ret);
5335 return ret;
5338 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5339 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5340 if(cNames) *pMemId=pVDesc->vardesc.memid;
5341 return ret;
5344 /* not found, see if it can be found in an inherited interface */
5345 if(This->impltypelist) {
5346 /* recursive search */
5347 ITypeInfo *pTInfo;
5348 ret=ITypeInfo_GetRefTypeInfo(iface,
5349 This->impltypelist->hRef, &pTInfo);
5350 if(SUCCEEDED(ret)){
5351 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5352 ITypeInfo_Release(pTInfo);
5353 return ret;
5355 WARN("Could not search inherited interface!\n");
5356 } else
5357 WARN("no names found\n");
5358 return DISP_E_UNKNOWNNAME;
5361 /* ITypeInfo::Invoke
5363 * Invokes a method, or accesses a property of an object, that implements the
5364 * interface described by the type description.
5366 DWORD
5367 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5368 DWORD res;
5370 if (TRACE_ON(ole)) {
5371 int i;
5372 TRACE("Calling %p(",func);
5373 for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
5374 TRACE(")\n");
5377 switch (callconv) {
5378 case CC_STDCALL:
5380 switch (nrargs) {
5381 case 0:
5382 res = func();
5383 break;
5384 case 1:
5385 res = func(args[0]);
5386 break;
5387 case 2:
5388 res = func(args[0],args[1]);
5389 break;
5390 case 3:
5391 res = func(args[0],args[1],args[2]);
5392 break;
5393 case 4:
5394 res = func(args[0],args[1],args[2],args[3]);
5395 break;
5396 case 5:
5397 res = func(args[0],args[1],args[2],args[3],args[4]);
5398 break;
5399 case 6:
5400 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
5401 break;
5402 case 7:
5403 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
5404 break;
5405 case 8:
5406 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
5407 break;
5408 case 9:
5409 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
5410 break;
5411 case 10:
5412 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
5413 break;
5414 case 11:
5415 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
5416 break;
5417 case 12:
5418 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]);
5419 break;
5420 case 13:
5421 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]);
5422 break;
5423 case 14:
5424 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]);
5425 break;
5426 case 15:
5427 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]);
5428 break;
5429 case 16:
5430 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]);
5431 break;
5432 case 17:
5433 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]);
5434 break;
5435 case 18:
5436 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]);
5437 break;
5438 case 19:
5439 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]);
5440 break;
5441 case 20:
5442 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]);
5443 break;
5444 case 21:
5445 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]);
5446 break;
5447 case 22:
5448 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]);
5449 break;
5450 case 23:
5451 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]);
5452 break;
5453 case 24:
5454 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]);
5455 break;
5456 case 25:
5457 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]);
5458 break;
5459 case 26:
5460 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]);
5461 break;
5462 case 27:
5463 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]);
5464 break;
5465 case 28:
5466 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]);
5467 break;
5468 case 29:
5469 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]);
5470 break;
5471 case 30:
5472 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]);
5473 break;
5474 default:
5475 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
5476 res = -1;
5477 break;
5479 break;
5480 default:
5481 FIXME("unsupported calling convention %d\n",callconv);
5482 res = -1;
5483 break;
5485 TRACE("returns %08x\n",res);
5486 return res;
5489 extern int _argsize(DWORD vt);
5491 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5493 HRESULT hr = S_OK;
5494 ITypeInfo *tinfo2 = NULL;
5495 TYPEATTR *tattr = NULL;
5497 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5498 if (hr)
5500 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5501 "hr = 0x%08x\n",
5502 tdesc->u.hreftype, hr);
5503 return hr;
5505 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5506 if (hr)
5508 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5509 ITypeInfo_Release(tinfo2);
5510 return hr;
5513 switch (tattr->typekind)
5515 case TKIND_ENUM:
5516 *vt |= VT_I4;
5517 break;
5519 case TKIND_ALIAS:
5520 tdesc = &tattr->tdescAlias;
5521 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5522 break;
5524 case TKIND_INTERFACE:
5525 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5526 *vt |= VT_DISPATCH;
5527 else
5528 *vt |= VT_UNKNOWN;
5529 break;
5531 case TKIND_DISPATCH:
5532 *vt |= VT_DISPATCH;
5533 break;
5535 case TKIND_COCLASS:
5536 *vt |= VT_DISPATCH;
5537 break;
5539 case TKIND_RECORD:
5540 FIXME("TKIND_RECORD unhandled.\n");
5541 hr = E_NOTIMPL;
5542 break;
5544 case TKIND_UNION:
5545 FIXME("TKIND_UNION unhandled.\n");
5546 hr = E_NOTIMPL;
5547 break;
5549 default:
5550 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5551 hr = E_NOTIMPL;
5552 break;
5554 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5555 ITypeInfo_Release(tinfo2);
5556 return hr;
5559 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5561 HRESULT hr = S_OK;
5563 /* enforce only one level of pointer indirection */
5564 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5566 tdesc = tdesc->u.lptdesc;
5568 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5569 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5570 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5571 if ((tdesc->vt == VT_USERDEFINED) ||
5572 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5574 VARTYPE vt_userdefined = 0;
5575 const TYPEDESC *tdesc_userdefined = tdesc;
5576 if (tdesc->vt == VT_PTR)
5578 vt_userdefined = VT_BYREF;
5579 tdesc_userdefined = tdesc->u.lptdesc;
5581 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5582 if ((hr == S_OK) &&
5583 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5584 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5586 *vt |= vt_userdefined;
5587 return S_OK;
5590 *vt = VT_BYREF;
5593 switch (tdesc->vt)
5595 case VT_HRESULT:
5596 *vt |= VT_ERROR;
5597 break;
5598 case VT_USERDEFINED:
5599 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5600 break;
5601 case VT_VOID:
5602 case VT_CARRAY:
5603 case VT_PTR:
5604 case VT_LPSTR:
5605 case VT_LPWSTR:
5606 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5607 hr = DISP_E_BADVARTYPE;
5608 break;
5609 case VT_SAFEARRAY:
5610 *vt |= VT_ARRAY;
5611 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5612 break;
5613 default:
5614 *vt |= tdesc->vt;
5615 break;
5617 return hr;
5620 /***********************************************************************
5621 * DispCallFunc (OLEAUT32.@)
5623 * Invokes a function of the specified calling convention, passing the
5624 * specified arguments and returns the result.
5626 * PARAMS
5627 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5628 * oVft [I] The offset in the vtable. See notes.
5629 * cc [I] Calling convention of the function to call.
5630 * vtReturn [I] The return type of the function.
5631 * cActuals [I] Number of parameters.
5632 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5633 * prgpvarg [I] The arguments to pass.
5634 * pvargResult [O] The return value of the function. Can be NULL.
5636 * RETURNS
5637 * Success: S_OK.
5638 * Failure: HRESULT code.
5640 * NOTES
5641 * The HRESULT return value of this function is not affected by the return
5642 * value of the user supplied function, which is returned in pvargResult.
5644 * If pvInstance is NULL then a non-object function is to be called and oVft
5645 * is the address of the function to call.
5647 * The cc parameter can be one of the following values:
5648 *|CC_FASTCALL
5649 *|CC_CDECL
5650 *|CC_PASCAL
5651 *|CC_STDCALL
5652 *|CC_FPFASTCALL
5653 *|CC_SYSCALL
5654 *|CC_MPWCDECL
5655 *|CC_MPWPASCAL
5658 HRESULT WINAPI
5659 DispCallFunc(
5660 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5661 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5663 int i, argsize, argspos;
5664 DWORD *args;
5665 HRESULT hres;
5667 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5668 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5669 pvargResult, V_VT(pvargResult));
5671 argsize = 0;
5672 if (pvInstance)
5673 argsize++; /* for This pointer */
5675 for (i=0;i<cActuals;i++)
5677 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5678 dump_Variant(prgpvarg[i]);
5679 argsize += _argsize(prgvt[i]);
5681 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5683 argspos = 0;
5684 if (pvInstance)
5686 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5687 argspos++;
5690 for (i=0;i<cActuals;i++)
5692 VARIANT *arg = prgpvarg[i];
5693 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5694 if (prgvt[i] == VT_VARIANT)
5695 memcpy(&args[argspos], arg, _argsize(prgvt[i]) * sizeof(DWORD));
5696 else
5697 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5698 argspos += _argsize(prgvt[i]);
5701 if (pvInstance)
5703 FARPROC *vtable = *(FARPROC**)pvInstance;
5704 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5706 else
5707 /* if we aren't invoking an object then the function pointer is stored
5708 * in oVft */
5709 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5711 if (pvargResult && (vtReturn != VT_EMPTY))
5713 TRACE("Method returned 0x%08x\n",hres);
5714 V_VT(pvargResult) = vtReturn;
5715 V_UI4(pvargResult) = hres;
5718 HeapFree(GetProcessHeap(),0,args);
5719 return S_OK;
5722 #define INVBUF_ELEMENT_SIZE \
5723 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5724 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5725 ((VARIANTARG *)(buffer))
5726 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5727 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5728 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5729 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5730 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5731 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5733 static HRESULT WINAPI ITypeInfo_fnInvoke(
5734 ITypeInfo2 *iface,
5735 VOID *pIUnk,
5736 MEMBERID memid,
5737 UINT16 wFlags,
5738 DISPPARAMS *pDispParams,
5739 VARIANT *pVarResult,
5740 EXCEPINFO *pExcepInfo,
5741 UINT *pArgErr)
5743 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5744 int i;
5745 unsigned int var_index;
5746 TYPEKIND type_kind;
5747 HRESULT hres;
5748 const TLBFuncDesc *pFuncInfo;
5750 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
5751 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5754 if (!pDispParams)
5756 ERR("NULL pDispParams not allowed\n");
5757 return E_INVALIDARG;
5760 dump_DispParms(pDispParams);
5762 if (pDispParams->cNamedArgs > pDispParams->cArgs)
5764 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
5765 pDispParams->cNamedArgs, pDispParams->cArgs);
5766 return E_INVALIDARG;
5769 /* we do this instead of using GetFuncDesc since it will return a fake
5770 * FUNCDESC for dispinterfaces and we want the real function description */
5771 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5772 if ((memid == pFuncInfo->funcdesc.memid) &&
5773 (wFlags & pFuncInfo->funcdesc.invkind))
5774 break;
5776 if (pFuncInfo) {
5777 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5779 if (TRACE_ON(ole))
5781 TRACE("invoking:\n");
5782 dump_TLBFuncDescOne(pFuncInfo);
5785 switch (func_desc->funckind) {
5786 case FUNC_PUREVIRTUAL:
5787 case FUNC_VIRTUAL: {
5788 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
5789 VARIANT varresult;
5790 VARIANT retval; /* pointer for storing byref retvals in */
5791 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
5792 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
5793 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
5794 UINT cNamedArgs = pDispParams->cNamedArgs;
5795 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
5797 hres = S_OK;
5799 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
5801 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
5803 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
5804 hres = DISP_E_PARAMNOTFOUND;
5805 goto func_fail;
5807 /* ignore the DISPID_PROPERTYPUT named argument from now on */
5808 cNamedArgs--;
5809 rgdispidNamedArgs++;
5812 if (func_desc->cParamsOpt < 0 && cNamedArgs)
5814 ERR("functions with the vararg attribute do not support named arguments\n");
5815 hres = DISP_E_NONAMEDARGS;
5816 goto func_fail;
5819 for (i = 0; i < func_desc->cParams; i++)
5821 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5822 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
5823 if (FAILED(hres))
5824 goto func_fail;
5827 TRACE("changing args\n");
5828 for (i = 0; i < func_desc->cParams; i++)
5830 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5831 VARIANTARG *src_arg;
5833 if (cNamedArgs)
5835 USHORT j;
5836 src_arg = NULL;
5837 for (j = 0; j < cNamedArgs; j++)
5838 if (rgdispidNamedArgs[j] == i)
5840 src_arg = &pDispParams->rgvarg[j];
5841 break;
5844 else
5845 src_arg = i < pDispParams->cArgs ? &pDispParams->rgvarg[pDispParams->cArgs - 1 - i] : NULL;
5847 if (wParamFlags & PARAMFLAG_FRETVAL)
5849 /* under most conditions the caller is not allowed to
5850 * pass in a dispparam arg in the index of what would be
5851 * the retval parameter. however, there is an exception
5852 * where the extra parameter is used in an extra
5853 * IDispatch::Invoke below */
5854 if ((i < pDispParams->cArgs) &&
5855 ((func_desc->cParams != 1) || !pVarResult ||
5856 !(func_desc->invkind & INVOKE_PROPERTYGET)))
5858 hres = DISP_E_BADPARAMCOUNT;
5859 break;
5862 /* note: this check is placed so that if the caller passes
5863 * in a VARIANTARG for the retval we just ignore it, like
5864 * native does */
5865 if (i == func_desc->cParams - 1)
5867 VARIANTARG *arg;
5868 arg = prgpvarg[i] = &rgvarg[i];
5869 memset(arg, 0, sizeof(*arg));
5870 V_VT(arg) = rgvt[i];
5871 memset(&retval, 0, sizeof(retval));
5872 V_BYREF(arg) = &retval;
5874 else
5876 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
5877 hres = E_UNEXPECTED;
5878 break;
5881 else if (src_arg)
5883 dump_Variant(src_arg);
5885 if (rgvt[i] == VT_VARIANT)
5886 hres = VariantCopy(&rgvarg[i], src_arg);
5887 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
5889 if (rgvt[i] == V_VT(src_arg))
5890 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
5891 else
5893 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5894 hres = VariantCopy(&missing_arg[i], src_arg);
5895 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
5897 V_VT(&rgvarg[i]) = rgvt[i];
5899 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
5901 SAFEARRAY *a;
5902 SAFEARRAYBOUND bound;
5903 VARIANT *v;
5904 LONG j;
5905 bound.lLbound = 0;
5906 bound.cElements = pDispParams->cArgs-i;
5907 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
5909 ERR("SafeArrayCreate failed\n");
5910 break;
5912 hres = SafeArrayAccessData(a, (LPVOID)&v);
5913 if (hres != S_OK)
5915 ERR("SafeArrayAccessData failed with %x\n", hres);
5916 break;
5918 for (j = 0; j < bound.cElements; j++)
5919 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
5920 hres = SafeArrayUnaccessData(a);
5921 if (hres != S_OK)
5923 ERR("SafeArrayUnaccessData failed with %x\n", hres);
5924 break;
5926 V_ARRAY(&rgvarg[i]) = a;
5927 V_VT(&rgvarg[i]) = rgvt[i];
5929 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
5931 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5932 V_VT(&missing_arg[i]) = V_VT(src_arg);
5933 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
5934 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
5935 V_VT(&rgvarg[i]) = rgvt[i];
5937 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
5939 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
5940 V_VT(&rgvarg[i]) = rgvt[i];
5942 else
5944 /* FIXME: this doesn't work for VT_BYREF arguments if
5945 * they are not the same type as in the paramdesc */
5946 V_VT(&rgvarg[i]) = V_VT(src_arg);
5947 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
5948 V_VT(&rgvarg[i]) = rgvt[i];
5951 if (FAILED(hres))
5953 ERR("failed to convert param %d to %s%s from %s%s\n", i,
5954 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
5955 debugstr_VT(src_arg), debugstr_VF(src_arg));
5956 break;
5958 prgpvarg[i] = &rgvarg[i];
5960 else if (wParamFlags & PARAMFLAG_FOPT)
5962 VARIANTARG *arg;
5963 arg = prgpvarg[i] = &rgvarg[i];
5964 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5966 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
5967 if (FAILED(hres))
5968 break;
5970 else
5972 VARIANTARG *missing_arg;
5973 /* if the function wants a pointer to a variant then
5974 * set that up, otherwise just pass the VT_ERROR in
5975 * the argument by value */
5976 if (rgvt[i] & VT_BYREF)
5978 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
5979 V_VT(arg) = VT_VARIANT | VT_BYREF;
5980 V_VARIANTREF(arg) = missing_arg;
5982 else
5983 missing_arg = arg;
5984 V_VT(missing_arg) = VT_ERROR;
5985 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
5988 else
5990 hres = DISP_E_BADPARAMCOUNT;
5991 break;
5994 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5996 /* VT_VOID is a special case for return types, so it is not
5997 * handled in the general function */
5998 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
5999 V_VT(&varresult) = VT_EMPTY;
6000 else
6002 V_VT(&varresult) = 0;
6003 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6004 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6007 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6008 V_VT(&varresult), func_desc->cParams, rgvt,
6009 prgpvarg, &varresult);
6011 for (i = 0; i < func_desc->cParams; i++)
6013 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6014 if (wParamFlags & PARAMFLAG_FRETVAL)
6016 if (TRACE_ON(ole))
6018 TRACE("[retval] value: ");
6019 dump_Variant(prgpvarg[i]);
6022 if (pVarResult)
6024 VariantInit(pVarResult);
6025 /* deref return value */
6026 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6029 /* free data stored in varresult. Note that
6030 * VariantClear doesn't do what we want because we are
6031 * working with byref types. */
6032 /* FIXME: clear safearrays, bstrs, records and
6033 * variants here too */
6034 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
6035 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
6037 if(*V_UNKNOWNREF(prgpvarg[i]))
6038 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
6040 break;
6042 else if (i < pDispParams->cArgs)
6044 if (wParamFlags & PARAMFLAG_FOUT)
6046 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
6048 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
6049 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6051 if (FAILED(hres))
6053 ERR("failed to convert param %d to vt %d\n", i,
6054 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
6055 break;
6058 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6059 func_desc->cParamsOpt < 0 &&
6060 i == func_desc->cParams-1)
6062 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6063 LONG j, ubound;
6064 VARIANT *v;
6065 hres = SafeArrayGetUBound(a, 1, &ubound);
6066 if (hres != S_OK)
6068 ERR("SafeArrayGetUBound failed with %x\n", hres);
6069 break;
6071 hres = SafeArrayAccessData(a, (LPVOID)&v);
6072 if (hres != S_OK)
6074 ERR("SafeArrayAccessData failed with %x\n", hres);
6075 break;
6077 for (j = 0; j <= ubound; j++)
6078 VariantClear(&v[j]);
6079 hres = SafeArrayUnaccessData(a);
6080 if (hres != S_OK)
6082 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6083 break;
6086 VariantClear(&rgvarg[i]);
6088 else if (wParamFlags & PARAMFLAG_FOPT)
6090 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6091 VariantClear(&rgvarg[i]);
6095 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6097 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6098 hres = DISP_E_EXCEPTION;
6099 if (pExcepInfo)
6101 IErrorInfo *pErrorInfo;
6102 pExcepInfo->scode = V_ERROR(&varresult);
6103 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6105 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6106 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6107 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6108 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6110 IErrorInfo_Release(pErrorInfo);
6114 if (V_VT(&varresult) != VT_ERROR)
6116 TRACE("varresult value: ");
6117 dump_Variant(&varresult);
6119 if (pVarResult)
6121 VariantClear(pVarResult);
6122 *pVarResult = varresult;
6124 else
6125 VariantClear(&varresult);
6128 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6129 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6130 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6131 (pDispParams->cArgs != 0))
6133 if (V_VT(pVarResult) == VT_DISPATCH)
6135 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6136 /* Note: not VariantClear; we still need the dispatch
6137 * pointer to be valid */
6138 VariantInit(pVarResult);
6139 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6140 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6141 pDispParams, pVarResult, pExcepInfo, pArgErr);
6142 IDispatch_Release(pDispatch);
6144 else
6146 VariantClear(pVarResult);
6147 hres = DISP_E_NOTACOLLECTION;
6151 func_fail:
6152 HeapFree(GetProcessHeap(), 0, buffer);
6153 break;
6155 case FUNC_DISPATCH: {
6156 IDispatch *disp;
6158 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6159 if (SUCCEEDED(hres)) {
6160 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6161 hres = IDispatch_Invoke(
6162 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6163 pVarResult,pExcepInfo,pArgErr
6165 if (FAILED(hres))
6166 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6167 IDispatch_Release(disp);
6168 } else
6169 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6170 break;
6172 default:
6173 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6174 hres = E_FAIL;
6175 break;
6178 TRACE("-- 0x%08x\n", hres);
6179 return hres;
6181 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6182 VARDESC *var_desc;
6184 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6185 if(FAILED(hres)) return hres;
6187 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6188 dump_VARDESC(var_desc);
6189 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6190 return E_NOTIMPL;
6193 /* not found, look for it in inherited interfaces */
6194 ITypeInfo2_GetTypeKind(iface, &type_kind);
6195 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6196 if(This->impltypelist) {
6197 /* recursive search */
6198 ITypeInfo *pTInfo;
6199 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6200 if(SUCCEEDED(hres)){
6201 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6202 ITypeInfo_Release(pTInfo);
6203 return hres;
6205 WARN("Could not search inherited interface!\n");
6208 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6209 return DISP_E_MEMBERNOTFOUND;
6212 /* ITypeInfo::GetDocumentation
6214 * Retrieves the documentation string, the complete Help file name and path,
6215 * and the context ID for the Help topic for a specified type description.
6217 * (Can be tested by the Visual Basic Editor in Word for instance.)
6219 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6220 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6221 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6223 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6224 const TLBFuncDesc *pFDesc;
6225 const TLBVarDesc *pVDesc;
6226 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6227 " HelpContext(%p) HelpFile(%p)\n",
6228 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6229 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6230 if(pBstrName)
6231 *pBstrName=SysAllocString(This->Name);
6232 if(pBstrDocString)
6233 *pBstrDocString=SysAllocString(This->DocString);
6234 if(pdwHelpContext)
6235 *pdwHelpContext=This->dwHelpContext;
6236 if(pBstrHelpFile)
6237 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6238 return S_OK;
6239 }else {/* for a member */
6240 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6241 if(pFDesc->funcdesc.memid==memid){
6242 if(pBstrName)
6243 *pBstrName = SysAllocString(pFDesc->Name);
6244 if(pBstrDocString)
6245 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6246 if(pdwHelpContext)
6247 *pdwHelpContext=pFDesc->helpcontext;
6248 return S_OK;
6250 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6251 if(pVDesc->vardesc.memid==memid){
6252 if(pBstrName)
6253 *pBstrName = SysAllocString(pVDesc->Name);
6254 if(pBstrDocString)
6255 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6256 if(pdwHelpContext)
6257 *pdwHelpContext=pVDesc->HelpContext;
6258 return S_OK;
6262 if(This->impltypelist &&
6263 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6264 /* recursive search */
6265 ITypeInfo *pTInfo;
6266 HRESULT result;
6267 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6268 &pTInfo);
6269 if(SUCCEEDED(result)) {
6270 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6271 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6272 ITypeInfo_Release(pTInfo);
6273 return result;
6275 WARN("Could not search inherited interface!\n");
6278 WARN("member %d not found\n", memid);
6279 return TYPE_E_ELEMENTNOTFOUND;
6282 /* ITypeInfo::GetDllEntry
6284 * Retrieves a description or specification of an entry point for a function
6285 * in a DLL.
6287 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6288 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6289 WORD *pwOrdinal)
6291 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6292 const TLBFuncDesc *pFDesc;
6294 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6296 if (pBstrDllName) *pBstrDllName = NULL;
6297 if (pBstrName) *pBstrName = NULL;
6298 if (pwOrdinal) *pwOrdinal = 0;
6300 if (This->TypeAttr.typekind != TKIND_MODULE)
6301 return TYPE_E_BADMODULEKIND;
6303 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6304 if(pFDesc->funcdesc.memid==memid){
6305 dump_TypeInfo(This);
6306 if (TRACE_ON(ole))
6307 dump_TLBFuncDescOne(pFDesc);
6309 if (pBstrDllName)
6310 *pBstrDllName = SysAllocString(This->DllName);
6312 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6313 if (pBstrName)
6314 *pBstrName = SysAllocString(pFDesc->Entry);
6315 if (pwOrdinal)
6316 *pwOrdinal = -1;
6317 return S_OK;
6319 if (pBstrName)
6320 *pBstrName = NULL;
6321 if (pwOrdinal)
6322 *pwOrdinal = (DWORD)pFDesc->Entry;
6323 return S_OK;
6325 return TYPE_E_ELEMENTNOTFOUND;
6328 /* internal function to make the inherited interfaces' methods appear
6329 * part of the interface */
6330 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6331 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6333 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6334 HRESULT hr;
6336 TRACE("%p, 0x%x\n", iface, *hRefType);
6338 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK))
6340 ITypeInfo *pSubTypeInfo;
6342 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
6343 if (FAILED(hr))
6344 return hr;
6346 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6347 hRefType, ppTInfo);
6348 ITypeInfo_Release(pSubTypeInfo);
6349 if (SUCCEEDED(hr))
6350 return hr;
6352 *hRefType -= DISPATCH_HREF_OFFSET;
6354 if (!(*hRefType & DISPATCH_HREF_MASK))
6355 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6356 else
6357 return E_FAIL;
6360 /* ITypeInfo::GetRefTypeInfo
6362 * If a type description references other type descriptions, it retrieves
6363 * the referenced type descriptions.
6365 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6366 ITypeInfo2 *iface,
6367 HREFTYPE hRefType,
6368 ITypeInfo **ppTInfo)
6370 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6371 HRESULT result = E_FAIL;
6373 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6375 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6376 ITypeInfo_AddRef(*ppTInfo);
6377 result = S_OK;
6379 else if (hRefType == -1 &&
6380 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6381 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6383 /* when we meet a DUAL dispinterface, we must create the interface
6384 * version of it.
6386 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
6389 /* the interface version contains the same information as the dispinterface
6390 * copy the contents of the structs.
6392 *pTypeInfoImpl = *This;
6393 pTypeInfoImpl->ref = 0;
6395 /* change the type to interface */
6396 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6398 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6400 /* we use data structures from This, so we need to keep a reference
6401 * to it to stop it being destroyed and signal to the new instance to
6402 * not free its data structures when it is destroyed */
6403 pTypeInfoImpl->no_free_data = TRUE;
6404 pTypeInfoImpl->next = This;
6405 ITypeInfo_AddRef((ITypeInfo*) This);
6407 ITypeInfo_AddRef(*ppTInfo);
6409 result = S_OK;
6411 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6412 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6413 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6415 HREFTYPE href_dispatch = hRefType;
6416 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6417 } else {
6418 TLBRefType *ref_type;
6419 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6421 if(ref_type->reference == hRefType)
6422 break;
6424 if(&ref_type->entry == &This->pTypeLib->ref_list)
6426 FIXME("Can't find pRefType for ref %x\n", hRefType);
6427 goto end;
6429 if(hRefType != -1) {
6430 ITypeLib *pTLib = NULL;
6432 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6433 UINT Index;
6434 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6435 } else {
6436 if(ref_type->pImpTLInfo->pImpTypeLib) {
6437 TRACE("typeinfo in imported typelib that is already loaded\n");
6438 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6439 ITypeLib2_AddRef(pTLib);
6440 result = S_OK;
6441 } else {
6442 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6443 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6444 ref_type->pImpTLInfo->wVersionMajor,
6445 ref_type->pImpTLInfo->wVersionMinor,
6446 ref_type->pImpTLInfo->lcid,
6447 &pTLib);
6449 if(!SUCCEEDED(result)) {
6450 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6451 result=LoadTypeLib(libnam, &pTLib);
6452 SysFreeString(libnam);
6454 if(SUCCEEDED(result)) {
6455 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6456 ITypeLib2_AddRef(pTLib);
6460 if(SUCCEEDED(result)) {
6461 if(ref_type->index == TLB_REF_USE_GUID)
6462 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6463 &ref_type->guid,
6464 ppTInfo);
6465 else
6466 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6467 ppTInfo);
6469 if (pTLib != NULL)
6470 ITypeLib2_Release(pTLib);
6474 end:
6475 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6476 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6477 return result;
6480 /* ITypeInfo::AddressOfMember
6482 * Retrieves the addresses of static functions or variables, such as those
6483 * defined in a DLL.
6485 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6486 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6488 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6489 HRESULT hr;
6490 BSTR dll, entry;
6491 WORD ordinal;
6492 HMODULE module;
6494 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6496 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6497 if (FAILED(hr))
6498 return hr;
6500 module = LoadLibraryW(dll);
6501 if (!module)
6503 ERR("couldn't load %s\n", debugstr_w(dll));
6504 SysFreeString(dll);
6505 if (entry) SysFreeString(entry);
6506 return STG_E_FILENOTFOUND;
6508 /* FIXME: store library somewhere where we can free it */
6510 if (entry)
6512 LPSTR entryA;
6513 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6514 entryA = HeapAlloc(GetProcessHeap(), 0, len);
6515 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6517 *ppv = GetProcAddress(module, entryA);
6518 if (!*ppv)
6519 ERR("function not found %s\n", debugstr_a(entryA));
6521 HeapFree(GetProcessHeap(), 0, entryA);
6523 else
6525 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6526 if (!*ppv)
6527 ERR("function not found %d\n", ordinal);
6530 SysFreeString(dll);
6531 if (entry) SysFreeString(entry);
6533 if (!*ppv)
6534 return TYPE_E_DLLFUNCTIONNOTFOUND;
6536 return S_OK;
6539 /* ITypeInfo::CreateInstance
6541 * Creates a new instance of a type that describes a component object class
6542 * (coclass).
6544 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6545 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6547 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6548 HRESULT hr;
6549 TYPEATTR *pTA;
6551 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6553 *ppvObj = NULL;
6555 if(pOuterUnk)
6557 WARN("Not able to aggregate\n");
6558 return CLASS_E_NOAGGREGATION;
6561 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6562 if(FAILED(hr)) return hr;
6564 if(pTA->typekind != TKIND_COCLASS)
6566 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6567 hr = E_INVALIDARG;
6568 goto end;
6571 hr = S_FALSE;
6572 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6574 IUnknown *pUnk;
6575 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6576 TRACE("GetActiveObject rets %08x\n", hr);
6577 if(hr == S_OK)
6579 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6580 IUnknown_Release(pUnk);
6584 if(hr != S_OK)
6585 hr = CoCreateInstance(&pTA->guid, NULL,
6586 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6587 riid, ppvObj);
6589 end:
6590 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6591 return hr;
6594 /* ITypeInfo::GetMops
6596 * Retrieves marshalling information.
6598 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6599 BSTR *pBstrMops)
6601 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6602 FIXME("(%p) stub!\n", This);
6603 return S_OK;
6606 /* ITypeInfo::GetContainingTypeLib
6608 * Retrieves the containing type library and the index of the type description
6609 * within that type library.
6611 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6612 ITypeLib * *ppTLib, UINT *pIndex)
6614 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6616 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6617 if (pIndex) {
6618 *pIndex=This->index;
6619 TRACE("returning pIndex=%d\n", *pIndex);
6622 if (ppTLib) {
6623 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6624 ITypeLib2_AddRef(*ppTLib);
6625 TRACE("returning ppTLib=%p\n", *ppTLib);
6628 return S_OK;
6631 /* ITypeInfo::ReleaseTypeAttr
6633 * Releases a TYPEATTR previously returned by GetTypeAttr.
6636 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6637 TYPEATTR* pTypeAttr)
6639 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6640 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6641 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6644 /* ITypeInfo::ReleaseFuncDesc
6646 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6648 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6649 ITypeInfo2 *iface,
6650 FUNCDESC *pFuncDesc)
6652 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6653 SHORT i;
6655 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6657 for (i = 0; i < pFuncDesc->cParams; i++)
6658 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6659 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6661 SysFreeString((BSTR)pFuncDesc);
6664 /* ITypeInfo::ReleaseVarDesc
6666 * Releases a VARDESC previously returned by GetVarDesc.
6668 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6669 VARDESC *pVarDesc)
6671 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6672 TRACE("(%p)->(%p)\n", This, pVarDesc);
6674 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6675 if (pVarDesc->varkind == VAR_CONST)
6676 VariantClear(pVarDesc->u.lpvarValue);
6677 SysFreeString((BSTR)pVarDesc);
6680 /* ITypeInfo2::GetTypeKind
6682 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6685 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6686 TYPEKIND *pTypeKind)
6688 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6689 *pTypeKind=This->TypeAttr.typekind;
6690 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6691 return S_OK;
6694 /* ITypeInfo2::GetTypeFlags
6696 * Returns the type flags without any allocations. This returns a DWORD type
6697 * flag, which expands the type flags without growing the TYPEATTR (type
6698 * attribute).
6701 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6703 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6704 *pTypeFlags=This->TypeAttr.wTypeFlags;
6705 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6706 return S_OK;
6709 /* ITypeInfo2::GetFuncIndexOfMemId
6710 * Binds to a specific member based on a known DISPID, where the member name
6711 * is not known (for example, when binding to a default member).
6714 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
6715 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
6717 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6718 const TLBFuncDesc *pFuncInfo;
6719 int i;
6720 HRESULT result;
6722 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
6723 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
6724 break;
6725 if(pFuncInfo) {
6726 *pFuncIndex = i;
6727 result = S_OK;
6728 } else
6729 result = TYPE_E_ELEMENTNOTFOUND;
6731 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
6732 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6733 return result;
6736 /* TypeInfo2::GetVarIndexOfMemId
6738 * Binds to a specific member based on a known DISPID, where the member name
6739 * is not known (for example, when binding to a default member).
6742 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
6743 MEMBERID memid, UINT *pVarIndex)
6745 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6746 TLBVarDesc *pVarInfo;
6747 int i;
6748 HRESULT result;
6749 for(i=0, pVarInfo=This->varlist; pVarInfo &&
6750 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
6752 if(pVarInfo) {
6753 *pVarIndex = i;
6754 result = S_OK;
6755 } else
6756 result = TYPE_E_ELEMENTNOTFOUND;
6758 TRACE("(%p) memid 0x%08x -> %s\n", This,
6759 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6760 return result;
6763 /* ITypeInfo2::GetCustData
6765 * Gets the custom data
6767 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
6768 ITypeInfo2 * iface,
6769 REFGUID guid,
6770 VARIANT *pVarVal)
6772 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6773 TLBCustData *pCData;
6775 for(pCData=This->pCustData; pCData; pCData = pCData->next)
6776 if( IsEqualIID(guid, &pCData->guid)) break;
6778 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6780 if(pCData)
6782 VariantInit( pVarVal);
6783 VariantCopy( pVarVal, &pCData->data);
6784 return S_OK;
6786 return E_INVALIDARG; /* FIXME: correct? */
6789 /* ITypeInfo2::GetFuncCustData
6791 * Gets the custom data
6793 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
6794 ITypeInfo2 * iface,
6795 UINT index,
6796 REFGUID guid,
6797 VARIANT *pVarVal)
6799 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6800 TLBCustData *pCData=NULL;
6801 TLBFuncDesc * pFDesc;
6802 int i;
6803 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6804 pFDesc=pFDesc->next);
6806 if(pFDesc)
6807 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
6808 if( IsEqualIID(guid, &pCData->guid)) break;
6810 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6812 if(pCData){
6813 VariantInit( pVarVal);
6814 VariantCopy( pVarVal, &pCData->data);
6815 return S_OK;
6817 return E_INVALIDARG; /* FIXME: correct? */
6820 /* ITypeInfo2::GetParamCustData
6822 * Gets the custom data
6824 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
6825 ITypeInfo2 * iface,
6826 UINT indexFunc,
6827 UINT indexParam,
6828 REFGUID guid,
6829 VARIANT *pVarVal)
6831 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6832 TLBCustData *pCData=NULL;
6833 TLBFuncDesc * pFDesc;
6834 int i;
6836 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
6838 if(pFDesc && indexParam<pFDesc->funcdesc.cParams)
6839 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
6840 pCData = pCData->next)
6841 if( IsEqualIID(guid, &pCData->guid)) break;
6843 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6845 if(pCData)
6847 VariantInit( pVarVal);
6848 VariantCopy( pVarVal, &pCData->data);
6849 return S_OK;
6851 return E_INVALIDARG; /* FIXME: correct? */
6854 /* ITypeInfo2::GetVarCustData
6856 * Gets the custom data
6858 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
6859 ITypeInfo2 * iface,
6860 UINT index,
6861 REFGUID guid,
6862 VARIANT *pVarVal)
6864 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6865 TLBCustData *pCData=NULL;
6866 TLBVarDesc * pVDesc;
6867 int i;
6869 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
6871 if(pVDesc)
6873 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
6875 if( IsEqualIID(guid, &pCData->guid)) break;
6879 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6881 if(pCData)
6883 VariantInit( pVarVal);
6884 VariantCopy( pVarVal, &pCData->data);
6885 return S_OK;
6887 return E_INVALIDARG; /* FIXME: correct? */
6890 /* ITypeInfo2::GetImplCustData
6892 * Gets the custom data
6894 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6895 ITypeInfo2 * iface,
6896 UINT index,
6897 REFGUID guid,
6898 VARIANT *pVarVal)
6900 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6901 TLBCustData *pCData=NULL;
6902 TLBImplType * pRDesc;
6903 int i;
6905 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6907 if(pRDesc)
6909 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6911 if( IsEqualIID(guid, &pCData->guid)) break;
6915 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6917 if(pCData)
6919 VariantInit( pVarVal);
6920 VariantCopy( pVarVal, &pCData->data);
6921 return S_OK;
6923 return E_INVALIDARG; /* FIXME: correct? */
6926 /* ITypeInfo2::GetDocumentation2
6928 * Retrieves the documentation string, the complete Help file name and path,
6929 * the localization context to use, and the context ID for the library Help
6930 * topic in the Help file.
6933 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6934 ITypeInfo2 * iface,
6935 MEMBERID memid,
6936 LCID lcid,
6937 BSTR *pbstrHelpString,
6938 DWORD *pdwHelpStringContext,
6939 BSTR *pbstrHelpStringDll)
6941 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6942 const TLBFuncDesc *pFDesc;
6943 const TLBVarDesc *pVDesc;
6944 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
6945 "HelpStringContext(%p) HelpStringDll(%p)\n",
6946 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6947 pbstrHelpStringDll );
6948 /* the help string should be obtained from the helpstringdll,
6949 * using the _DLLGetDocumentation function, based on the supplied
6950 * lcid. Nice to do sometime...
6952 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6953 if(pbstrHelpString)
6954 *pbstrHelpString=SysAllocString(This->Name);
6955 if(pdwHelpStringContext)
6956 *pdwHelpStringContext=This->dwHelpStringContext;
6957 if(pbstrHelpStringDll)
6958 *pbstrHelpStringDll=
6959 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6960 return S_OK;
6961 }else {/* for a member */
6962 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6963 if(pFDesc->funcdesc.memid==memid){
6964 if(pbstrHelpString)
6965 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6966 if(pdwHelpStringContext)
6967 *pdwHelpStringContext=pFDesc->HelpStringContext;
6968 if(pbstrHelpStringDll)
6969 *pbstrHelpStringDll=
6970 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6971 return S_OK;
6973 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6974 if(pVDesc->vardesc.memid==memid){
6975 if(pbstrHelpString)
6976 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6977 if(pdwHelpStringContext)
6978 *pdwHelpStringContext=pVDesc->HelpStringContext;
6979 if(pbstrHelpStringDll)
6980 *pbstrHelpStringDll=
6981 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6982 return S_OK;
6985 return TYPE_E_ELEMENTNOTFOUND;
6988 /* ITypeInfo2::GetAllCustData
6990 * Gets all custom data items for the Type info.
6993 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6994 ITypeInfo2 * iface,
6995 CUSTDATA *pCustData)
6997 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6998 TLBCustData *pCData;
6999 int i;
7001 TRACE("(%p) returning %d items\n", This, This->ctCustData);
7003 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
7004 if(pCustData->prgCustData ){
7005 pCustData->cCustData=This->ctCustData;
7006 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
7007 pCustData->prgCustData[i].guid=pCData->guid;
7008 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
7010 }else{
7011 ERR(" OUT OF MEMORY!\n");
7012 return E_OUTOFMEMORY;
7014 return S_OK;
7017 /* ITypeInfo2::GetAllFuncCustData
7019 * Gets all custom data items for the specified Function
7022 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7023 ITypeInfo2 * iface,
7024 UINT index,
7025 CUSTDATA *pCustData)
7027 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7028 TLBCustData *pCData;
7029 TLBFuncDesc * pFDesc;
7030 int i;
7031 TRACE("(%p) index %d\n", This, index);
7032 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7033 pFDesc=pFDesc->next)
7035 if(pFDesc){
7036 pCustData->prgCustData =
7037 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
7038 if(pCustData->prgCustData ){
7039 pCustData->cCustData=pFDesc->ctCustData;
7040 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
7041 pCData = pCData->next){
7042 pCustData->prgCustData[i].guid=pCData->guid;
7043 VariantCopy(& pCustData->prgCustData[i].varValue,
7044 & pCData->data);
7046 }else{
7047 ERR(" OUT OF MEMORY!\n");
7048 return E_OUTOFMEMORY;
7050 return S_OK;
7052 return TYPE_E_ELEMENTNOTFOUND;
7055 /* ITypeInfo2::GetAllParamCustData
7057 * Gets all custom data items for the Functions
7060 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7061 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7063 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7064 TLBCustData *pCData=NULL;
7065 TLBFuncDesc * pFDesc;
7066 int i;
7067 TRACE("(%p) index %d\n", This, indexFunc);
7068 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
7069 pFDesc=pFDesc->next)
7071 if(pFDesc && indexParam<pFDesc->funcdesc.cParams){
7072 pCustData->prgCustData =
7073 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
7074 sizeof(CUSTDATAITEM));
7075 if(pCustData->prgCustData ){
7076 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
7077 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
7078 pCData; i++, pCData = pCData->next){
7079 pCustData->prgCustData[i].guid=pCData->guid;
7080 VariantCopy(& pCustData->prgCustData[i].varValue,
7081 & pCData->data);
7083 }else{
7084 ERR(" OUT OF MEMORY!\n");
7085 return E_OUTOFMEMORY;
7087 return S_OK;
7089 return TYPE_E_ELEMENTNOTFOUND;
7092 /* ITypeInfo2::GetAllVarCustData
7094 * Gets all custom data items for the specified Variable
7097 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7098 UINT index, CUSTDATA *pCustData)
7100 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7101 TLBCustData *pCData;
7102 TLBVarDesc * pVDesc;
7103 int i;
7104 TRACE("(%p) index %d\n", This, index);
7105 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
7106 pVDesc=pVDesc->next)
7108 if(pVDesc){
7109 pCustData->prgCustData =
7110 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
7111 if(pCustData->prgCustData ){
7112 pCustData->cCustData=pVDesc->ctCustData;
7113 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
7114 pCData = pCData->next){
7115 pCustData->prgCustData[i].guid=pCData->guid;
7116 VariantCopy(& pCustData->prgCustData[i].varValue,
7117 & pCData->data);
7119 }else{
7120 ERR(" OUT OF MEMORY!\n");
7121 return E_OUTOFMEMORY;
7123 return S_OK;
7125 return TYPE_E_ELEMENTNOTFOUND;
7128 /* ITypeInfo2::GetAllImplCustData
7130 * Gets all custom data items for the specified implementation type
7133 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7134 ITypeInfo2 * iface,
7135 UINT index,
7136 CUSTDATA *pCustData)
7138 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7139 TLBCustData *pCData;
7140 TLBImplType * pRDesc;
7141 int i;
7142 TRACE("(%p) index %d\n", This, index);
7143 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
7144 pRDesc=pRDesc->next)
7146 if(pRDesc){
7147 pCustData->prgCustData =
7148 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
7149 if(pCustData->prgCustData ){
7150 pCustData->cCustData=pRDesc->ctCustData;
7151 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
7152 pCData = pCData->next){
7153 pCustData->prgCustData[i].guid=pCData->guid;
7154 VariantCopy(& pCustData->prgCustData[i].varValue,
7155 & pCData->data);
7157 }else{
7158 ERR(" OUT OF MEMORY!\n");
7159 return E_OUTOFMEMORY;
7161 return S_OK;
7163 return TYPE_E_ELEMENTNOTFOUND;
7166 static const ITypeInfo2Vtbl tinfvt =
7169 ITypeInfo_fnQueryInterface,
7170 ITypeInfo_fnAddRef,
7171 ITypeInfo_fnRelease,
7173 ITypeInfo_fnGetTypeAttr,
7174 ITypeInfo_fnGetTypeComp,
7175 ITypeInfo_fnGetFuncDesc,
7176 ITypeInfo_fnGetVarDesc,
7177 ITypeInfo_fnGetNames,
7178 ITypeInfo_fnGetRefTypeOfImplType,
7179 ITypeInfo_fnGetImplTypeFlags,
7180 ITypeInfo_fnGetIDsOfNames,
7181 ITypeInfo_fnInvoke,
7182 ITypeInfo_fnGetDocumentation,
7183 ITypeInfo_fnGetDllEntry,
7184 ITypeInfo_fnGetRefTypeInfo,
7185 ITypeInfo_fnAddressOfMember,
7186 ITypeInfo_fnCreateInstance,
7187 ITypeInfo_fnGetMops,
7188 ITypeInfo_fnGetContainingTypeLib,
7189 ITypeInfo_fnReleaseTypeAttr,
7190 ITypeInfo_fnReleaseFuncDesc,
7191 ITypeInfo_fnReleaseVarDesc,
7193 ITypeInfo2_fnGetTypeKind,
7194 ITypeInfo2_fnGetTypeFlags,
7195 ITypeInfo2_fnGetFuncIndexOfMemId,
7196 ITypeInfo2_fnGetVarIndexOfMemId,
7197 ITypeInfo2_fnGetCustData,
7198 ITypeInfo2_fnGetFuncCustData,
7199 ITypeInfo2_fnGetParamCustData,
7200 ITypeInfo2_fnGetVarCustData,
7201 ITypeInfo2_fnGetImplTypeCustData,
7202 ITypeInfo2_fnGetDocumentation2,
7203 ITypeInfo2_fnGetAllCustData,
7204 ITypeInfo2_fnGetAllFuncCustData,
7205 ITypeInfo2_fnGetAllParamCustData,
7206 ITypeInfo2_fnGetAllVarCustData,
7207 ITypeInfo2_fnGetAllImplTypeCustData,
7210 /******************************************************************************
7211 * CreateDispTypeInfo [OLEAUT32.31]
7213 * Build type information for an object so it can be called through an
7214 * IDispatch interface.
7216 * RETURNS
7217 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7218 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7220 * NOTES
7221 * This call allows an objects methods to be accessed through IDispatch, by
7222 * building an ITypeInfo object that IDispatch can use to call through.
7224 HRESULT WINAPI CreateDispTypeInfo(
7225 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7226 LCID lcid, /* [I] Locale Id */
7227 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7229 ITypeInfoImpl *pTIClass, *pTIIface;
7230 ITypeLibImpl *pTypeLibImpl;
7231 int param, func;
7232 TLBFuncDesc **ppFuncDesc;
7233 TLBRefType *ref;
7235 TRACE("\n");
7236 pTypeLibImpl = TypeLibImpl_Constructor();
7237 if (!pTypeLibImpl) return E_FAIL;
7239 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
7240 pTIIface->pTypeLib = pTypeLibImpl;
7241 pTIIface->index = 0;
7242 pTIIface->Name = NULL;
7243 pTIIface->dwHelpContext = -1;
7244 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7245 pTIIface->TypeAttr.lcid = lcid;
7246 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7247 pTIIface->TypeAttr.wMajorVerNum = 0;
7248 pTIIface->TypeAttr.wMinorVerNum = 0;
7249 pTIIface->TypeAttr.cbAlignment = 2;
7250 pTIIface->TypeAttr.cbSizeInstance = -1;
7251 pTIIface->TypeAttr.cbSizeVft = -1;
7252 pTIIface->TypeAttr.cFuncs = 0;
7253 pTIIface->TypeAttr.cImplTypes = 0;
7254 pTIIface->TypeAttr.cVars = 0;
7255 pTIIface->TypeAttr.wTypeFlags = 0;
7257 ppFuncDesc = &pTIIface->funclist;
7258 for(func = 0; func < pidata->cMembers; func++) {
7259 METHODDATA *md = pidata->pmethdata + func;
7260 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
7261 (*ppFuncDesc)->Name = SysAllocString(md->szName);
7262 (*ppFuncDesc)->funcdesc.memid = md->dispid;
7263 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
7264 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
7265 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
7266 (*ppFuncDesc)->funcdesc.callconv = md->cc;
7267 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
7268 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
7269 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
7270 (*ppFuncDesc)->funcdesc.cScodes = 0;
7271 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
7272 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7273 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7274 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7275 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7276 md->cArgs * sizeof(ELEMDESC));
7277 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7278 md->cArgs * sizeof(TLBParDesc));
7279 for(param = 0; param < md->cArgs; param++) {
7280 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7281 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7283 (*ppFuncDesc)->helpcontext = 0;
7284 (*ppFuncDesc)->HelpStringContext = 0;
7285 (*ppFuncDesc)->HelpString = NULL;
7286 (*ppFuncDesc)->Entry = NULL;
7287 (*ppFuncDesc)->ctCustData = 0;
7288 (*ppFuncDesc)->pCustData = NULL;
7289 (*ppFuncDesc)->next = NULL;
7290 pTIIface->TypeAttr.cFuncs++;
7291 ppFuncDesc = &(*ppFuncDesc)->next;
7294 dump_TypeInfo(pTIIface);
7296 pTypeLibImpl->pTypeInfo = pTIIface;
7297 pTypeLibImpl->TypeInfoCount++;
7299 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
7300 pTIClass->pTypeLib = pTypeLibImpl;
7301 pTIClass->index = 1;
7302 pTIClass->Name = NULL;
7303 pTIClass->dwHelpContext = -1;
7304 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7305 pTIClass->TypeAttr.lcid = lcid;
7306 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7307 pTIClass->TypeAttr.wMajorVerNum = 0;
7308 pTIClass->TypeAttr.wMinorVerNum = 0;
7309 pTIClass->TypeAttr.cbAlignment = 2;
7310 pTIClass->TypeAttr.cbSizeInstance = -1;
7311 pTIClass->TypeAttr.cbSizeVft = -1;
7312 pTIClass->TypeAttr.cFuncs = 0;
7313 pTIClass->TypeAttr.cImplTypes = 1;
7314 pTIClass->TypeAttr.cVars = 0;
7315 pTIClass->TypeAttr.wTypeFlags = 0;
7317 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
7318 pTIClass->impltypelist->hRef = 0;
7320 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
7321 ref->index = 0;
7322 ref->reference = 0;
7323 ref->pImpTLInfo = TLB_REF_INTERNAL;
7324 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7326 dump_TypeInfo(pTIClass);
7328 pTIIface->next = pTIClass;
7329 pTypeLibImpl->TypeInfoCount++;
7331 *pptinfo = (ITypeInfo*)pTIClass;
7333 ITypeInfo_AddRef(*pptinfo);
7334 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7336 return S_OK;
7340 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7342 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7344 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7347 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7349 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7351 return ITypeInfo_AddRef((ITypeInfo *)This);
7354 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7356 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7358 return ITypeInfo_Release((ITypeInfo *)This);
7361 static HRESULT WINAPI ITypeComp_fnBind(
7362 ITypeComp * iface,
7363 OLECHAR * szName,
7364 ULONG lHash,
7365 WORD wFlags,
7366 ITypeInfo ** ppTInfo,
7367 DESCKIND * pDescKind,
7368 BINDPTR * pBindPtr)
7370 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7371 const TLBFuncDesc *pFDesc;
7372 const TLBVarDesc *pVDesc;
7373 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7375 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7377 *pDescKind = DESCKIND_NONE;
7378 pBindPtr->lpfuncdesc = NULL;
7379 *ppTInfo = NULL;
7381 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
7382 if (!strcmpiW(pFDesc->Name, szName)) {
7383 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7384 break;
7385 else
7386 /* name found, but wrong flags */
7387 hr = TYPE_E_TYPEMISMATCH;
7390 if (pFDesc)
7392 HRESULT hr = TLB_AllocAndInitFuncDesc(
7393 &pFDesc->funcdesc,
7394 &pBindPtr->lpfuncdesc,
7395 This->TypeAttr.typekind == TKIND_DISPATCH);
7396 if (FAILED(hr))
7397 return hr;
7398 *pDescKind = DESCKIND_FUNCDESC;
7399 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7400 ITypeInfo_AddRef(*ppTInfo);
7401 return S_OK;
7402 } else {
7403 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7404 if (!strcmpiW(pVDesc->Name, szName)) {
7405 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7406 if (FAILED(hr))
7407 return hr;
7408 *pDescKind = DESCKIND_VARDESC;
7409 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7410 ITypeInfo_AddRef(*ppTInfo);
7411 return S_OK;
7415 /* FIXME: search each inherited interface, not just the first */
7416 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7417 /* recursive search */
7418 ITypeInfo *pTInfo;
7419 ITypeComp *pTComp;
7420 HRESULT hr;
7421 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7422 if (SUCCEEDED(hr))
7424 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7425 ITypeInfo_Release(pTInfo);
7427 if (SUCCEEDED(hr))
7429 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7430 ITypeComp_Release(pTComp);
7431 return hr;
7433 WARN("Could not search inherited interface!\n");
7435 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
7436 return hr;
7439 static HRESULT WINAPI ITypeComp_fnBindType(
7440 ITypeComp * iface,
7441 OLECHAR * szName,
7442 ULONG lHash,
7443 ITypeInfo ** ppTInfo,
7444 ITypeComp ** ppTComp)
7446 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7448 /* strange behaviour (does nothing) but like the
7449 * original */
7451 if (!ppTInfo || !ppTComp)
7452 return E_POINTER;
7454 *ppTInfo = NULL;
7455 *ppTComp = NULL;
7457 return S_OK;
7460 static const ITypeCompVtbl tcompvt =
7463 ITypeComp_fnQueryInterface,
7464 ITypeComp_fnAddRef,
7465 ITypeComp_fnRelease,
7467 ITypeComp_fnBind,
7468 ITypeComp_fnBindType