push decde5eed3d79f9d889b4d757f73e86ce6ff9241
[wine/hacks.git] / dlls / oleaut32 / typelib.c
blob472ab8d2c7d1c5db05fd7f8dcad76f4c4b6cfee9
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("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("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("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("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("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 (pItem->flags & 0x40) {
3139 TRACE_(typelib)("VAR_DISPATCH\n");
3140 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
3142 else if (pItem->flags & 0x10) {
3143 TRACE_(typelib)("VAR_CONST\n");
3144 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3145 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3146 sizeof(VARIANT));
3147 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3148 if (pItem->flags & 0x08)
3149 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) = pItem->byte_offs;
3150 else {
3151 switch ((*ppVarDesc)->vardesc.elemdescVar.tdesc.vt)
3153 case VT_LPSTR:
3154 case VT_LPWSTR:
3155 case VT_BSTR:
3157 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3158 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3159 BSTR str = SysAllocStringLen(NULL, alloc_len);
3160 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3161 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_BSTR;
3162 V_BSTR((*ppVarDesc)->vardesc.u.lpvarValue) = str;
3163 break;
3165 case VT_I2:
3166 case VT_UI2:
3167 case VT_I4:
3168 case VT_UI4:
3169 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
3170 *(INT*)(pBlk + pItem->byte_offs);
3171 break;
3172 default:
3173 FIXME("VAR_CONST unimplemented for type %d\n", (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt);
3177 else {
3178 TRACE_(typelib)("VAR_PERINSTANCE\n");
3179 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3180 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3183 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3184 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
3186 if (pItem->flags & 0x80)
3187 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3189 if (TRACE_ON(typelib)) {
3190 char buf[300];
3191 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3192 TRACE_(typelib)("elemdescVar: %s\n", buf);
3195 bstrPrevName = (*ppVarDesc)->Name;
3196 ppVarDesc = &((*ppVarDesc)->next);
3198 pTI->TypeAttr.cVars = cVars;
3201 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3202 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3204 SLTG_Function *pFunc;
3205 unsigned short i;
3206 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3208 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3209 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3211 int param;
3212 WORD *pType, *pArg;
3214 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3215 sizeof(**ppFuncDesc));
3217 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3218 case SLTG_FUNCTION_MAGIC:
3219 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3220 break;
3221 case SLTG_DISPATCH_FUNCTION_MAGIC:
3222 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3223 break;
3224 case SLTG_STATIC_FUNCTION_MAGIC:
3225 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3226 break;
3227 default:
3228 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3229 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
3230 *ppFuncDesc = NULL;
3231 return;
3233 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3235 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3236 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3237 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3238 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3239 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3240 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3242 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3243 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3245 if(pFunc->retnextopt & 0x80)
3246 pType = &pFunc->rettype;
3247 else
3248 pType = (WORD*)(pBlk + pFunc->rettype);
3250 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3252 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3253 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3254 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3255 (*ppFuncDesc)->pParamDesc =
3256 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3257 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3259 pArg = (WORD*)(pBlk + pFunc->arg_off);
3261 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3262 char *paramName = pNameTable + *pArg;
3263 BOOL HaveOffs;
3264 /* If arg type follows then paramName points to the 2nd
3265 letter of the name, else the next WORD is an offset to
3266 the arg type and paramName points to the first letter.
3267 So let's take one char off paramName and see if we're
3268 pointing at an alpha-numeric char. However if *pArg is
3269 0xffff or 0xfffe then the param has no name, the former
3270 meaning that the next WORD is the type, the latter
3271 meaning that the next WORD is an offset to the type. */
3273 HaveOffs = FALSE;
3274 if(*pArg == 0xffff)
3275 paramName = NULL;
3276 else if(*pArg == 0xfffe) {
3277 paramName = NULL;
3278 HaveOffs = TRUE;
3280 else if(paramName[-1] && !isalnum(paramName[-1]))
3281 HaveOffs = TRUE;
3283 pArg++;
3285 if(HaveOffs) { /* the next word is an offset to type */
3286 pType = (WORD*)(pBlk + *pArg);
3287 SLTG_DoElem(pType, pBlk,
3288 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3289 pArg++;
3290 } else {
3291 if(paramName)
3292 paramName--;
3293 pArg = SLTG_DoElem(pArg, pBlk,
3294 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3297 /* Are we an optional param ? */
3298 if((*ppFuncDesc)->funcdesc.cParams - param <=
3299 (*ppFuncDesc)->funcdesc.cParamsOpt)
3300 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3302 if(paramName) {
3303 (*ppFuncDesc)->pParamDesc[param].Name =
3304 TLB_MultiByteToBSTR(paramName);
3308 ppFuncDesc = &((*ppFuncDesc)->next);
3309 if(pFunc->next == 0xffff) break;
3311 pTI->TypeAttr.cFuncs = cFuncs;
3314 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3315 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3316 SLTG_TypeInfoTail *pTITail)
3318 char *pFirstItem;
3319 sltg_ref_lookup_t *ref_lookup = NULL;
3321 if(pTIHeader->href_table != 0xffffffff) {
3322 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3323 pNameTable);
3326 pFirstItem = pBlk;
3328 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3329 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3331 HeapFree(GetProcessHeap(), 0, ref_lookup);
3335 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3336 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3337 const SLTG_TypeInfoTail *pTITail)
3339 char *pFirstItem;
3340 sltg_ref_lookup_t *ref_lookup = NULL;
3342 if(pTIHeader->href_table != 0xffffffff) {
3343 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3344 pNameTable);
3347 pFirstItem = pBlk;
3349 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3350 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3353 if (pTITail->funcs_off != 0xffff)
3354 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3356 HeapFree(GetProcessHeap(), 0, ref_lookup);
3358 if (TRACE_ON(typelib))
3359 dump_TLBFuncDesc(pTI->funclist);
3362 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3363 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3364 const SLTG_TypeInfoTail *pTITail)
3366 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3369 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3370 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3371 const SLTG_TypeInfoTail *pTITail)
3373 WORD *pType;
3374 sltg_ref_lookup_t *ref_lookup = NULL;
3376 if (pTITail->simple_alias) {
3377 /* if simple alias, no more processing required */
3378 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3379 return;
3382 if(pTIHeader->href_table != 0xffffffff) {
3383 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3384 pNameTable);
3387 /* otherwise it is an offset to a type */
3388 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3390 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3392 HeapFree(GetProcessHeap(), 0, ref_lookup);
3395 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3396 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3397 const SLTG_TypeInfoTail *pTITail)
3399 sltg_ref_lookup_t *ref_lookup = NULL;
3400 if (pTIHeader->href_table != 0xffffffff)
3401 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3402 pNameTable);
3404 if (pTITail->vars_off != 0xffff)
3405 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3407 if (pTITail->funcs_off != 0xffff)
3408 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3410 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3411 * of dispinterface functions including the IDispatch ones, so
3412 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3413 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3415 HeapFree(GetProcessHeap(), 0, ref_lookup);
3416 if (TRACE_ON(typelib))
3417 dump_TLBFuncDesc(pTI->funclist);
3420 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3421 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3422 const SLTG_TypeInfoTail *pTITail)
3424 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3427 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3428 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3429 const SLTG_TypeInfoTail *pTITail)
3431 sltg_ref_lookup_t *ref_lookup = NULL;
3432 if (pTIHeader->href_table != 0xffffffff)
3433 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3434 pNameTable);
3436 if (pTITail->vars_off != 0xffff)
3437 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3439 if (pTITail->funcs_off != 0xffff)
3440 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3441 HeapFree(GetProcessHeap(), 0, ref_lookup);
3444 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3445 managable copy of it into this */
3446 typedef struct {
3447 WORD small_no;
3448 char *index_name;
3449 char *other_name;
3450 WORD res1a;
3451 WORD name_offs;
3452 WORD more_bytes;
3453 char *extra;
3454 WORD res20;
3455 DWORD helpcontext;
3456 WORD res26;
3457 GUID uuid;
3458 } SLTG_InternalOtherTypeInfo;
3460 /****************************************************************************
3461 * ITypeLib2_Constructor_SLTG
3463 * loading a SLTG typelib from an in-memory image
3465 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3467 ITypeLibImpl *pTypeLibImpl;
3468 SLTG_Header *pHeader;
3469 SLTG_BlkEntry *pBlkEntry;
3470 SLTG_Magic *pMagic;
3471 SLTG_Index *pIndex;
3472 SLTG_Pad9 *pPad9;
3473 LPVOID pBlk, pFirstBlk;
3474 SLTG_LibBlk *pLibBlk;
3475 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3476 char *pAfterOTIBlks = NULL;
3477 char *pNameTable, *ptr;
3478 int i;
3479 DWORD len, order;
3480 ITypeInfoImpl **ppTypeInfoImpl;
3482 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3485 pTypeLibImpl = TypeLibImpl_Constructor();
3486 if (!pTypeLibImpl) return NULL;
3488 pHeader = pLib;
3490 TRACE_(typelib)("header:\n");
3491 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3492 pHeader->nrOfFileBlks );
3493 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3494 FIXME("Header type magic 0x%08x not supported.\n",
3495 pHeader->SLTG_magic);
3496 return NULL;
3499 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3500 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3502 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3503 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3505 /* Next we have a magic block */
3506 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3508 /* Let's see if we're still in sync */
3509 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3510 sizeof(SLTG_COMPOBJ_MAGIC))) {
3511 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3512 return NULL;
3514 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3515 sizeof(SLTG_DIR_MAGIC))) {
3516 FIXME("dir magic = %s\n", pMagic->dir_magic);
3517 return NULL;
3520 pIndex = (SLTG_Index*)(pMagic+1);
3522 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3524 pFirstBlk = (LPVOID)(pPad9 + 1);
3526 /* We'll set up a ptr to the main library block, which is the last one. */
3528 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3529 pBlkEntry[order].next != 0;
3530 order = pBlkEntry[order].next - 1, i++) {
3531 pBlk = (char*)pBlk + pBlkEntry[order].len;
3533 pLibBlk = pBlk;
3535 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3537 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3538 interspersed */
3540 len += 0x40;
3542 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3544 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3545 sizeof(*pOtherTypeInfoBlks) *
3546 pTypeLibImpl->TypeInfoCount);
3549 ptr = (char*)pLibBlk + len;
3551 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3552 WORD w, extra;
3553 len = 0;
3555 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3557 w = *(WORD*)(ptr + 2);
3558 if(w != 0xffff) {
3559 len += w;
3560 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3561 w+1);
3562 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3563 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3565 w = *(WORD*)(ptr + 4 + len);
3566 if(w != 0xffff) {
3567 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3568 len += w;
3569 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3570 w+1);
3571 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3572 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3574 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3575 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3576 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3577 if(extra) {
3578 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3579 extra);
3580 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3581 len += extra;
3583 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3584 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3585 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3586 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3587 len += sizeof(SLTG_OtherTypeInfo);
3588 ptr += len;
3591 pAfterOTIBlks = ptr;
3593 /* Skip this WORD and get the next DWORD */
3594 len = *(DWORD*)(pAfterOTIBlks + 2);
3596 /* Now add this to pLibBLk look at what we're pointing at and
3597 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3598 dust and we should be pointing at the beginning of the name
3599 table */
3601 pNameTable = (char*)pLibBlk + len;
3603 switch(*(WORD*)pNameTable) {
3604 case 0xffff:
3605 break;
3606 case 0x0200:
3607 pNameTable += 0x20;
3608 break;
3609 default:
3610 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3611 break;
3614 pNameTable += 0x216;
3616 pNameTable += 2;
3618 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3620 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3623 /* Hopefully we now have enough ptrs set up to actually read in
3624 some TypeInfos. It's not clear which order to do them in, so
3625 I'll just follow the links along the BlkEntry chain and read
3626 them in the order in which they are in the file */
3628 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3630 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3631 pBlkEntry[order].next != 0;
3632 order = pBlkEntry[order].next - 1, i++) {
3634 SLTG_TypeInfoHeader *pTIHeader;
3635 SLTG_TypeInfoTail *pTITail;
3636 SLTG_MemberHeader *pMemHeader;
3638 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3639 pOtherTypeInfoBlks[i].index_name)) {
3640 FIXME("Index strings don't match\n");
3641 return NULL;
3644 pTIHeader = pBlk;
3645 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3646 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3647 return NULL;
3649 TRACE("pTIHeader->res06 = %x, pTIHeader->res0e = %x, pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3650 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3652 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3653 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3654 (*ppTypeInfoImpl)->index = i;
3655 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3656 pOtherTypeInfoBlks[i].name_offs +
3657 pNameTable);
3658 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3659 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
3660 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3661 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3662 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3663 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3664 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3666 if((pTIHeader->typeflags1 & 7) != 2)
3667 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3668 if(pTIHeader->typeflags3 != 2)
3669 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3671 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3672 debugstr_w((*ppTypeInfoImpl)->Name),
3673 typekind_desc[pTIHeader->typekind],
3674 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3675 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3677 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3679 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3681 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3682 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3683 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3685 switch(pTIHeader->typekind) {
3686 case TKIND_ENUM:
3687 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3688 pTIHeader, pTITail);
3689 break;
3691 case TKIND_RECORD:
3692 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3693 pTIHeader, pTITail);
3694 break;
3696 case TKIND_INTERFACE:
3697 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3698 pTIHeader, pTITail);
3699 break;
3701 case TKIND_COCLASS:
3702 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3703 pTIHeader, pTITail);
3704 break;
3706 case TKIND_ALIAS:
3707 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3708 pTIHeader, pTITail);
3709 break;
3711 case TKIND_DISPATCH:
3712 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3713 pTIHeader, pTITail);
3714 break;
3716 case TKIND_MODULE:
3717 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3718 pTIHeader, pTITail);
3719 break;
3721 default:
3722 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3723 break;
3727 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3728 but we've already set those */
3729 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3730 X(06);
3731 X(16);
3732 X(18);
3733 X(1a);
3734 X(1e);
3735 X(24);
3736 X(26);
3737 X(2a);
3738 X(2c);
3739 X(2e);
3740 X(30);
3741 X(32);
3742 X(34);
3744 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3745 pBlk = (char*)pBlk + pBlkEntry[order].len;
3748 if(i != pTypeLibImpl->TypeInfoCount) {
3749 FIXME("Somehow processed %d TypeInfos\n", i);
3750 return NULL;
3753 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3754 return (ITypeLib2*)pTypeLibImpl;
3757 /* ITypeLib::QueryInterface
3759 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3760 ITypeLib2 * iface,
3761 REFIID riid,
3762 VOID **ppvObject)
3764 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3766 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3768 *ppvObject=NULL;
3769 if(IsEqualIID(riid, &IID_IUnknown) ||
3770 IsEqualIID(riid,&IID_ITypeLib)||
3771 IsEqualIID(riid,&IID_ITypeLib2))
3773 *ppvObject = This;
3776 if(*ppvObject)
3778 ITypeLib2_AddRef(iface);
3779 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3780 return S_OK;
3782 TRACE("-- Interface: E_NOINTERFACE\n");
3783 return E_NOINTERFACE;
3786 /* ITypeLib::AddRef
3788 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3790 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3791 ULONG ref = InterlockedIncrement(&This->ref);
3793 TRACE("(%p)->ref was %u\n",This, ref - 1);
3795 return ref;
3798 /* ITypeLib::Release
3800 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3802 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3803 ULONG ref = InterlockedDecrement(&This->ref);
3805 TRACE("(%p)->(%u)\n",This, ref);
3807 if (!ref)
3809 TLBImpLib *pImpLib, *pImpLibNext;
3810 TLBCustData *pCustData, *pCustDataNext;
3811 TLBRefType *ref_type;
3812 void *cursor2;
3813 int i;
3815 /* remove cache entry */
3816 if(This->path)
3818 TRACE("removing from cache list\n");
3819 EnterCriticalSection(&cache_section);
3820 if (This->next) This->next->prev = This->prev;
3821 if (This->prev) This->prev->next = This->next;
3822 else tlb_cache_first = This->next;
3823 LeaveCriticalSection(&cache_section);
3824 HeapFree(GetProcessHeap(), 0, This->path);
3826 TRACE(" destroying ITypeLib(%p)\n",This);
3828 if (This->Name)
3830 SysFreeString(This->Name);
3831 This->Name = NULL;
3834 if (This->DocString)
3836 SysFreeString(This->DocString);
3837 This->DocString = NULL;
3840 if (This->HelpFile)
3842 SysFreeString(This->HelpFile);
3843 This->HelpFile = NULL;
3846 if (This->HelpStringDll)
3848 SysFreeString(This->HelpStringDll);
3849 This->HelpStringDll = NULL;
3852 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
3854 VariantClear(&pCustData->data);
3856 pCustDataNext = pCustData->next;
3857 TLB_Free(pCustData);
3860 for (i = 0; i < This->ctTypeDesc; i++)
3861 if (This->pTypeDesc[i].vt == VT_CARRAY)
3862 TLB_Free(This->pTypeDesc[i].u.lpadesc);
3864 TLB_Free(This->pTypeDesc);
3866 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
3868 if (pImpLib->pImpTypeLib)
3869 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
3870 TLB_Free(pImpLib->name);
3872 pImpLibNext = pImpLib->next;
3873 TLB_Free(pImpLib);
3876 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
3878 list_remove(&ref_type->entry);
3879 TLB_Free(ref_type);
3882 if (This->pTypeInfo) /* can be NULL */
3883 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3884 HeapFree(GetProcessHeap(),0,This);
3885 return 0;
3888 return ref;
3891 /* ITypeLib::GetTypeInfoCount
3893 * Returns the number of type descriptions in the type library
3895 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3897 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3898 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3899 return This->TypeInfoCount;
3902 /* ITypeLib::GetTypeInfo
3904 * retrieves the specified type description in the library.
3906 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3907 ITypeLib2 *iface,
3908 UINT index,
3909 ITypeInfo **ppTInfo)
3911 int i;
3913 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3914 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3916 TRACE("(%p)->(index=%d)\n", This, index);
3918 if (!ppTInfo) return E_INVALIDARG;
3920 /* search element n in list */
3921 for(i=0; i < index; i++)
3923 pTypeInfo = pTypeInfo->next;
3924 if (!pTypeInfo)
3926 TRACE("-- element not found\n");
3927 return TYPE_E_ELEMENTNOTFOUND;
3931 *ppTInfo = (ITypeInfo *) pTypeInfo;
3933 ITypeInfo_AddRef(*ppTInfo);
3934 TRACE("-- found (%p)\n",*ppTInfo);
3935 return S_OK;
3939 /* ITypeLibs::GetTypeInfoType
3941 * Retrieves the type of a type description.
3943 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3944 ITypeLib2 *iface,
3945 UINT index,
3946 TYPEKIND *pTKind)
3948 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3949 int i;
3950 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3952 if (ITypeLib2_fnGetTypeInfoCount(iface) < index + 1)
3953 return TYPE_E_ELEMENTNOTFOUND;
3955 TRACE("(%p) index %d\n", This, index);
3957 if(!pTKind) return E_INVALIDARG;
3959 /* search element n in list */
3960 for(i=0; i < index; i++)
3962 if(!pTInfo)
3964 TRACE("-- element not found\n");
3965 return TYPE_E_ELEMENTNOTFOUND;
3967 pTInfo = pTInfo->next;
3970 *pTKind = pTInfo->TypeAttr.typekind;
3971 TRACE("-- found Type (%d)\n", *pTKind);
3972 return S_OK;
3975 /* ITypeLib::GetTypeInfoOfGuid
3977 * Retrieves the type description that corresponds to the specified GUID.
3980 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3981 ITypeLib2 *iface,
3982 REFGUID guid,
3983 ITypeInfo **ppTInfo)
3985 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3986 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3988 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3990 if (!pTypeInfo)
3992 WARN("-- element not found\n");
3993 return TYPE_E_ELEMENTNOTFOUND;
3996 /* search linked list for guid */
3997 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3999 pTypeInfo = pTypeInfo->next;
4001 if (!pTypeInfo)
4003 /* end of list reached */
4004 WARN("-- element not found\n");
4005 return TYPE_E_ELEMENTNOTFOUND;
4009 TRACE("-- found (%p, %s)\n",
4010 pTypeInfo,
4011 debugstr_w(pTypeInfo->Name));
4013 *ppTInfo = (ITypeInfo*)pTypeInfo;
4014 ITypeInfo_AddRef(*ppTInfo);
4015 return S_OK;
4018 /* ITypeLib::GetLibAttr
4020 * Retrieves the structure that contains the library's attributes.
4023 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4024 ITypeLib2 *iface,
4025 LPTLIBATTR *ppTLibAttr)
4027 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4028 TRACE("(%p)\n",This);
4029 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
4030 **ppTLibAttr = This->LibAttr;
4031 return S_OK;
4034 /* ITypeLib::GetTypeComp
4036 * Enables a client compiler to bind to a library's types, variables,
4037 * constants, and global functions.
4040 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4041 ITypeLib2 *iface,
4042 ITypeComp **ppTComp)
4044 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4046 TRACE("(%p)->(%p)\n",This,ppTComp);
4047 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4048 ITypeComp_AddRef(*ppTComp);
4050 return S_OK;
4053 /* ITypeLib::GetDocumentation
4055 * Retrieves the library's documentation string, the complete Help file name
4056 * and path, and the context identifier for the library Help topic in the Help
4057 * file.
4059 * On a successful return all non-null BSTR pointers will have been set,
4060 * possibly to NULL.
4062 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4063 ITypeLib2 *iface,
4064 INT index,
4065 BSTR *pBstrName,
4066 BSTR *pBstrDocString,
4067 DWORD *pdwHelpContext,
4068 BSTR *pBstrHelpFile)
4070 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4072 HRESULT result = E_INVALIDARG;
4074 ITypeInfo *pTInfo;
4077 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4078 This, index,
4079 pBstrName, pBstrDocString,
4080 pdwHelpContext, pBstrHelpFile);
4082 if(index<0)
4084 /* documentation for the typelib */
4085 if(pBstrName)
4087 if (This->Name)
4089 if(!(*pBstrName = SysAllocString(This->Name)))
4090 goto memerr1;
4092 else
4093 *pBstrName = NULL;
4095 if(pBstrDocString)
4097 if (This->DocString)
4099 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4100 goto memerr2;
4102 else if (This->Name)
4104 if(!(*pBstrDocString = SysAllocString(This->Name)))
4105 goto memerr2;
4107 else
4108 *pBstrDocString = NULL;
4110 if(pdwHelpContext)
4112 *pdwHelpContext = This->dwHelpContext;
4114 if(pBstrHelpFile)
4116 if (This->HelpFile)
4118 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4119 goto memerr3;
4121 else
4122 *pBstrHelpFile = NULL;
4125 result = S_OK;
4127 else
4129 /* for a typeinfo */
4130 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4132 if(SUCCEEDED(result))
4134 result = ITypeInfo_GetDocumentation(pTInfo,
4135 MEMBERID_NIL,
4136 pBstrName,
4137 pBstrDocString,
4138 pdwHelpContext, pBstrHelpFile);
4140 ITypeInfo_Release(pTInfo);
4143 return result;
4144 memerr3:
4145 if (pBstrDocString) SysFreeString (*pBstrDocString);
4146 memerr2:
4147 if (pBstrName) SysFreeString (*pBstrName);
4148 memerr1:
4149 return STG_E_INSUFFICIENTMEMORY;
4152 /* ITypeLib::IsName
4154 * Indicates whether a passed-in string contains the name of a type or member
4155 * described in the library.
4158 static HRESULT WINAPI ITypeLib2_fnIsName(
4159 ITypeLib2 *iface,
4160 LPOLESTR szNameBuf,
4161 ULONG lHashVal,
4162 BOOL *pfName)
4164 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4165 ITypeInfoImpl *pTInfo;
4166 TLBFuncDesc *pFInfo;
4167 TLBVarDesc *pVInfo;
4168 int i;
4169 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4171 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4172 pfName);
4174 *pfName=TRUE;
4175 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
4176 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4177 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4178 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4179 for(i=0;i<pFInfo->funcdesc.cParams;i++)
4180 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
4181 goto ITypeLib2_fnIsName_exit;
4183 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4184 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4187 *pfName=FALSE;
4189 ITypeLib2_fnIsName_exit:
4190 TRACE("(%p)slow! search for %s: %s found!\n", This,
4191 debugstr_w(szNameBuf), *pfName?"NOT":"");
4193 return S_OK;
4196 /* ITypeLib::FindName
4198 * Finds occurrences of a type description in a type library. This may be used
4199 * to quickly verify that a name exists in a type library.
4202 static HRESULT WINAPI ITypeLib2_fnFindName(
4203 ITypeLib2 *iface,
4204 LPOLESTR szNameBuf,
4205 ULONG lHashVal,
4206 ITypeInfo **ppTInfo,
4207 MEMBERID *rgMemId,
4208 UINT16 *pcFound)
4210 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4211 ITypeInfoImpl *pTInfo;
4212 TLBFuncDesc *pFInfo;
4213 TLBVarDesc *pVInfo;
4214 int i,j = 0;
4215 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4217 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
4218 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4219 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4220 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4221 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
4222 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
4223 goto ITypeLib2_fnFindName_exit;
4226 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4227 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4228 continue;
4229 ITypeLib2_fnFindName_exit:
4230 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4231 ppTInfo[j]=(LPTYPEINFO)pTInfo;
4232 j++;
4234 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4235 This, *pcFound, debugstr_w(szNameBuf), j);
4237 *pcFound=j;
4239 return S_OK;
4242 /* ITypeLib::ReleaseTLibAttr
4244 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4247 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4248 ITypeLib2 *iface,
4249 TLIBATTR *pTLibAttr)
4251 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4252 TRACE("freeing (%p)\n",This);
4253 HeapFree(GetProcessHeap(),0,pTLibAttr);
4257 /* ITypeLib2::GetCustData
4259 * gets the custom data
4261 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4262 ITypeLib2 * iface,
4263 REFGUID guid,
4264 VARIANT *pVarVal)
4266 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4267 TLBCustData *pCData;
4269 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4271 if( IsEqualIID(guid, &pCData->guid)) break;
4274 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4276 if(pCData)
4278 VariantInit( pVarVal);
4279 VariantCopy( pVarVal, &pCData->data);
4280 return S_OK;
4282 return E_INVALIDARG; /* FIXME: correct? */
4285 /* ITypeLib2::GetLibStatistics
4287 * Returns statistics about a type library that are required for efficient
4288 * sizing of hash tables.
4291 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4292 ITypeLib2 * iface,
4293 ULONG *pcUniqueNames,
4294 ULONG *pcchUniqueNames)
4296 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4298 FIXME("(%p): stub!\n", This);
4300 if(pcUniqueNames) *pcUniqueNames=1;
4301 if(pcchUniqueNames) *pcchUniqueNames=1;
4302 return S_OK;
4305 /* ITypeLib2::GetDocumentation2
4307 * Retrieves the library's documentation string, the complete Help file name
4308 * and path, the localization context to use, and the context ID for the
4309 * library Help topic in the Help file.
4312 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4313 ITypeLib2 * iface,
4314 INT index,
4315 LCID lcid,
4316 BSTR *pbstrHelpString,
4317 DWORD *pdwHelpStringContext,
4318 BSTR *pbstrHelpStringDll)
4320 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4321 HRESULT result;
4322 ITypeInfo *pTInfo;
4324 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4326 /* the help string should be obtained from the helpstringdll,
4327 * using the _DLLGetDocumentation function, based on the supplied
4328 * lcid. Nice to do sometime...
4330 if(index<0)
4332 /* documentation for the typelib */
4333 if(pbstrHelpString)
4334 *pbstrHelpString=SysAllocString(This->DocString);
4335 if(pdwHelpStringContext)
4336 *pdwHelpStringContext=This->dwHelpContext;
4337 if(pbstrHelpStringDll)
4338 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4340 result = S_OK;
4342 else
4344 /* for a typeinfo */
4345 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4347 if(SUCCEEDED(result))
4349 ITypeInfo2 * pTInfo2;
4350 result = ITypeInfo_QueryInterface(pTInfo,
4351 &IID_ITypeInfo2,
4352 (LPVOID*) &pTInfo2);
4354 if(SUCCEEDED(result))
4356 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4357 MEMBERID_NIL,
4358 lcid,
4359 pbstrHelpString,
4360 pdwHelpStringContext,
4361 pbstrHelpStringDll);
4363 ITypeInfo2_Release(pTInfo2);
4366 ITypeInfo_Release(pTInfo);
4369 return result;
4372 /* ITypeLib2::GetAllCustData
4374 * Gets all custom data items for the library.
4377 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4378 ITypeLib2 * iface,
4379 CUSTDATA *pCustData)
4381 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4382 TLBCustData *pCData;
4383 int i;
4384 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4385 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4386 if(pCustData->prgCustData ){
4387 pCustData->cCustData=This->ctCustData;
4388 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4389 pCustData->prgCustData[i].guid=pCData->guid;
4390 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4392 }else{
4393 ERR(" OUT OF MEMORY!\n");
4394 return E_OUTOFMEMORY;
4396 return S_OK;
4399 static const ITypeLib2Vtbl tlbvt = {
4400 ITypeLib2_fnQueryInterface,
4401 ITypeLib2_fnAddRef,
4402 ITypeLib2_fnRelease,
4403 ITypeLib2_fnGetTypeInfoCount,
4404 ITypeLib2_fnGetTypeInfo,
4405 ITypeLib2_fnGetTypeInfoType,
4406 ITypeLib2_fnGetTypeInfoOfGuid,
4407 ITypeLib2_fnGetLibAttr,
4408 ITypeLib2_fnGetTypeComp,
4409 ITypeLib2_fnGetDocumentation,
4410 ITypeLib2_fnIsName,
4411 ITypeLib2_fnFindName,
4412 ITypeLib2_fnReleaseTLibAttr,
4414 ITypeLib2_fnGetCustData,
4415 ITypeLib2_fnGetLibStatistics,
4416 ITypeLib2_fnGetDocumentation2,
4417 ITypeLib2_fnGetAllCustData
4421 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4423 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4425 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4428 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4430 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4432 return ITypeLib2_AddRef((ITypeLib2 *)This);
4435 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4437 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4439 return ITypeLib2_Release((ITypeLib2 *)This);
4442 static HRESULT WINAPI ITypeLibComp_fnBind(
4443 ITypeComp * iface,
4444 OLECHAR * szName,
4445 ULONG lHash,
4446 WORD wFlags,
4447 ITypeInfo ** ppTInfo,
4448 DESCKIND * pDescKind,
4449 BINDPTR * pBindPtr)
4451 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4452 ITypeInfoImpl *pTypeInfo;
4454 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4456 *pDescKind = DESCKIND_NONE;
4457 pBindPtr->lptcomp = NULL;
4458 *ppTInfo = NULL;
4460 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4462 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4464 /* FIXME: check wFlags here? */
4465 /* FIXME: we should use a hash table to look this info up using lHash
4466 * instead of an O(n) search */
4467 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4468 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4470 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4472 *pDescKind = DESCKIND_TYPECOMP;
4473 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4474 ITypeComp_AddRef(pBindPtr->lptcomp);
4475 TRACE("module or enum: %s\n", debugstr_w(szName));
4476 return S_OK;
4480 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4481 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4483 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4484 HRESULT hr;
4486 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4487 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4489 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4490 return S_OK;
4494 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4495 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4497 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4498 HRESULT hr;
4499 ITypeInfo *subtypeinfo;
4500 BINDPTR subbindptr;
4501 DESCKIND subdesckind;
4503 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4504 &subtypeinfo, &subdesckind, &subbindptr);
4505 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4507 TYPEDESC tdesc_appobject =
4510 (TYPEDESC *)pTypeInfo->hreftype
4512 VT_USERDEFINED
4514 const VARDESC vardesc_appobject =
4516 -2, /* memid */
4517 NULL, /* lpstrSchema */
4519 0 /* oInst */
4522 /* ELEMDESC */
4524 /* TYPEDESC */
4526 &tdesc_appobject
4528 VT_PTR
4531 0, /* wVarFlags */
4532 VAR_STATIC /* varkind */
4535 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4537 /* cleanup things filled in by Bind call so we can put our
4538 * application object data in there instead */
4539 switch (subdesckind)
4541 case DESCKIND_FUNCDESC:
4542 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4543 break;
4544 case DESCKIND_VARDESC:
4545 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4546 break;
4547 default:
4548 break;
4550 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4552 if (pTypeInfo->hreftype == -1)
4553 FIXME("no hreftype for interface %p\n", pTypeInfo);
4555 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4556 if (FAILED(hr))
4557 return hr;
4559 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4560 *ppTInfo = (ITypeInfo *)pTypeInfo;
4561 ITypeInfo_AddRef(*ppTInfo);
4562 return S_OK;
4567 TRACE("name not found %s\n", debugstr_w(szName));
4568 return S_OK;
4571 static HRESULT WINAPI ITypeLibComp_fnBindType(
4572 ITypeComp * iface,
4573 OLECHAR * szName,
4574 ULONG lHash,
4575 ITypeInfo ** ppTInfo,
4576 ITypeComp ** ppTComp)
4578 FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4579 return E_NOTIMPL;
4582 static const ITypeCompVtbl tlbtcvt =
4585 ITypeLibComp_fnQueryInterface,
4586 ITypeLibComp_fnAddRef,
4587 ITypeLibComp_fnRelease,
4589 ITypeLibComp_fnBind,
4590 ITypeLibComp_fnBindType
4593 /*================== ITypeInfo(2) Methods ===================================*/
4594 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4596 ITypeInfoImpl * pTypeInfoImpl;
4598 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4599 if (pTypeInfoImpl)
4601 pTypeInfoImpl->lpVtbl = &tinfvt;
4602 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4603 pTypeInfoImpl->ref=1;
4604 pTypeInfoImpl->hreftype = -1;
4605 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4606 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4608 TRACE("(%p)\n", pTypeInfoImpl);
4609 return (ITypeInfo2*) pTypeInfoImpl;
4612 /* ITypeInfo::QueryInterface
4614 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4615 ITypeInfo2 *iface,
4616 REFIID riid,
4617 VOID **ppvObject)
4619 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4621 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4623 *ppvObject=NULL;
4624 if(IsEqualIID(riid, &IID_IUnknown) ||
4625 IsEqualIID(riid,&IID_ITypeInfo)||
4626 IsEqualIID(riid,&IID_ITypeInfo2))
4627 *ppvObject = This;
4629 if(*ppvObject){
4630 ITypeInfo_AddRef(iface);
4631 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4632 return S_OK;
4634 TRACE("-- Interface: E_NOINTERFACE\n");
4635 return E_NOINTERFACE;
4638 /* ITypeInfo::AddRef
4640 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4642 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4643 ULONG ref = InterlockedIncrement(&This->ref);
4645 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4647 TRACE("(%p)->ref is %u\n",This, ref);
4648 return ref;
4651 /* ITypeInfo::Release
4653 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4655 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4656 ULONG ref = InterlockedDecrement(&This->ref);
4658 TRACE("(%p)->(%u)\n",This, ref);
4660 if (ref) {
4661 /* We don't release ITypeLib when ref=0 because
4662 it means that function is called by ITypeLib2_Release */
4663 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4664 } else {
4665 TLBFuncDesc *pFInfo, *pFInfoNext;
4666 TLBVarDesc *pVInfo, *pVInfoNext;
4667 TLBImplType *pImpl, *pImplNext;
4669 TRACE("destroying ITypeInfo(%p)\n",This);
4671 if (This->no_free_data)
4672 goto finish_free;
4674 if (This->Name)
4676 SysFreeString(This->Name);
4677 This->Name = 0;
4680 if (This->DocString)
4682 SysFreeString(This->DocString);
4683 This->DocString = 0;
4686 if (This->DllName)
4688 SysFreeString(This->DllName);
4689 This->DllName = 0;
4692 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4694 UINT i;
4695 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4697 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4698 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4700 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4701 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4703 SysFreeString(pFInfo->pParamDesc[i].Name);
4705 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4706 TLB_Free(pFInfo->pParamDesc);
4707 TLB_FreeCustData(pFInfo->pCustData);
4708 if (HIWORD(pFInfo->Entry) != 0 && pFInfo->Entry != (BSTR)-1)
4709 SysFreeString(pFInfo->Entry);
4710 SysFreeString(pFInfo->HelpString);
4711 SysFreeString(pFInfo->Name);
4713 pFInfoNext = pFInfo->next;
4714 TLB_Free(pFInfo);
4716 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
4718 if (pVInfo->vardesc.varkind == VAR_CONST)
4720 VariantClear(pVInfo->vardesc.u.lpvarValue);
4721 TLB_Free(pVInfo->vardesc.u.lpvarValue);
4723 TLB_FreeCustData(pVInfo->pCustData);
4724 SysFreeString(pVInfo->Name);
4725 pVInfoNext = pVInfo->next;
4726 TLB_Free(pVInfo);
4728 for(pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
4730 TLB_FreeCustData(pImpl->pCustData);
4731 pImplNext = pImpl->next;
4732 TLB_Free(pImpl);
4734 TLB_FreeCustData(This->pCustData);
4736 finish_free:
4737 if (This->next)
4739 ITypeInfo_Release((ITypeInfo*)This->next);
4742 HeapFree(GetProcessHeap(),0,This);
4743 return 0;
4745 return ref;
4748 /* ITypeInfo::GetTypeAttr
4750 * Retrieves a TYPEATTR structure that contains the attributes of the type
4751 * description.
4754 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4755 LPTYPEATTR *ppTypeAttr)
4757 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4758 SIZE_T size;
4760 TRACE("(%p)\n",This);
4762 size = sizeof(**ppTypeAttr);
4763 if (This->TypeAttr.typekind == TKIND_ALIAS)
4764 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4766 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4767 if (!*ppTypeAttr)
4768 return E_OUTOFMEMORY;
4770 **ppTypeAttr = This->TypeAttr;
4772 if (This->TypeAttr.typekind == TKIND_ALIAS)
4773 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4774 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4776 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4777 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4778 funcs */
4779 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4780 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4782 return S_OK;
4785 /* ITypeInfo::GetTypeComp
4787 * Retrieves the ITypeComp interface for the type description, which enables a
4788 * client compiler to bind to the type description's members.
4791 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4792 ITypeComp * *ppTComp)
4794 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4796 TRACE("(%p)->(%p)\n", This, ppTComp);
4798 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4799 ITypeComp_AddRef(*ppTComp);
4800 return S_OK;
4803 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4805 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4806 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4807 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4808 return size;
4811 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4813 *dest = *src;
4814 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4815 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4817 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4818 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4819 *buffer += sizeof(PARAMDESCEX);
4820 *pparamdescex_dest = *pparamdescex_src;
4821 VariantInit(&pparamdescex_dest->varDefaultValue);
4822 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4823 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4825 else
4826 dest->u.paramdesc.pparamdescex = NULL;
4827 return S_OK;
4830 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4832 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4833 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4836 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4838 FUNCDESC *dest;
4839 char *buffer;
4840 SIZE_T size = sizeof(*src);
4841 SHORT i;
4842 HRESULT hr;
4844 size += sizeof(*src->lprgscode) * src->cScodes;
4845 size += TLB_SizeElemDesc(&src->elemdescFunc);
4846 for (i = 0; i < src->cParams; i++)
4848 size += sizeof(ELEMDESC);
4849 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4852 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4853 if (!dest) return E_OUTOFMEMORY;
4855 *dest = *src;
4856 if (dispinterface) /* overwrite funckind */
4857 dest->funckind = FUNC_DISPATCH;
4858 buffer = (char *)(dest + 1);
4860 dest->lprgscode = (SCODE *)buffer;
4861 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4862 buffer += sizeof(*src->lprgscode) * src->cScodes;
4864 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4865 if (FAILED(hr))
4867 SysFreeString((BSTR)dest);
4868 return hr;
4871 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4872 buffer += sizeof(ELEMDESC) * src->cParams;
4873 for (i = 0; i < src->cParams; i++)
4875 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4876 if (FAILED(hr))
4877 break;
4879 if (FAILED(hr))
4881 /* undo the above actions */
4882 for (i = i - 1; i >= 0; i--)
4883 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4884 TLB_FreeElemDesc(&dest->elemdescFunc);
4885 SysFreeString((BSTR)dest);
4886 return hr;
4889 /* special treatment for dispinterfaces: this makes functions appear
4890 * to return their [retval] value when it is really returning an
4891 * HRESULT */
4892 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4894 if (dest->cParams &&
4895 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4897 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4898 if (elemdesc->tdesc.vt != VT_PTR)
4900 ERR("elemdesc should have started with VT_PTR instead of:\n");
4901 if (ERR_ON(ole))
4902 dump_ELEMDESC(elemdesc);
4903 return E_UNEXPECTED;
4906 /* copy last parameter to the return value. we are using a flat
4907 * buffer so there is no danger of leaking memory in
4908 * elemdescFunc */
4909 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4911 /* remove the last parameter */
4912 dest->cParams--;
4914 else
4915 /* otherwise this function is made to appear to have no return
4916 * value */
4917 dest->elemdescFunc.tdesc.vt = VT_VOID;
4921 *dest_ptr = dest;
4922 return S_OK;
4925 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4927 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4928 const TLBFuncDesc *pFDesc;
4929 int i;
4931 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4934 if (pFDesc)
4936 *ppFuncDesc = &pFDesc->funcdesc;
4937 return S_OK;
4940 return TYPE_E_ELEMENTNOTFOUND;
4943 /* internal function to make the inherited interfaces' methods appear
4944 * part of the interface */
4945 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
4946 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
4948 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4949 HRESULT hr;
4950 UINT implemented_funcs = 0;
4952 if (funcs)
4953 *funcs = 0;
4954 else
4955 *hrefoffset = DISPATCH_HREF_OFFSET;
4957 if(This->impltypelist)
4959 ITypeInfo *pSubTypeInfo;
4960 UINT sub_funcs;
4962 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
4963 if (FAILED(hr))
4964 return hr;
4966 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
4967 index,
4968 ppFuncDesc,
4969 &sub_funcs, hrefoffset);
4970 implemented_funcs += sub_funcs;
4971 ITypeInfo_Release(pSubTypeInfo);
4972 if (SUCCEEDED(hr))
4973 return hr;
4974 *hrefoffset += DISPATCH_HREF_OFFSET;
4977 if (funcs)
4978 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
4979 else
4980 *hrefoffset = 0;
4982 if (index < implemented_funcs)
4983 return E_INVALIDARG;
4984 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
4985 ppFuncDesc);
4988 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
4990 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
4991 while (TRUE)
4993 switch (pTypeDesc->vt)
4995 case VT_USERDEFINED:
4996 pTypeDesc->u.hreftype += hrefoffset;
4997 return;
4998 case VT_PTR:
4999 case VT_SAFEARRAY:
5000 pTypeDesc = pTypeDesc->u.lptdesc;
5001 break;
5002 case VT_CARRAY:
5003 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5004 break;
5005 default:
5006 return;
5011 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5013 SHORT i;
5014 for (i = 0; i < pFuncDesc->cParams; i++)
5015 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5016 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5019 /* ITypeInfo::GetFuncDesc
5021 * Retrieves the FUNCDESC structure that contains information about a
5022 * specified function.
5025 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5026 LPFUNCDESC *ppFuncDesc)
5028 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5029 const FUNCDESC *internal_funcdesc;
5030 HRESULT hr;
5031 UINT hrefoffset = 0;
5033 TRACE("(%p) index %d\n", This, index);
5035 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5036 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5037 &internal_funcdesc, NULL,
5038 &hrefoffset);
5039 else
5040 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5041 &internal_funcdesc);
5042 if (FAILED(hr))
5044 WARN("description for function %d not found\n", index);
5045 return hr;
5048 hr = TLB_AllocAndInitFuncDesc(
5049 internal_funcdesc,
5050 ppFuncDesc,
5051 This->TypeAttr.typekind == TKIND_DISPATCH);
5053 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5054 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5056 TRACE("-- 0x%08x\n", hr);
5057 return hr;
5060 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5062 VARDESC *dest;
5063 char *buffer;
5064 SIZE_T size = sizeof(*src);
5065 HRESULT hr;
5067 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5068 if (src->varkind == VAR_CONST)
5069 size += sizeof(VARIANT);
5070 size += TLB_SizeElemDesc(&src->elemdescVar);
5072 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5073 if (!dest) return E_OUTOFMEMORY;
5075 *dest = *src;
5076 buffer = (char *)(dest + 1);
5077 if (src->lpstrSchema)
5079 int len;
5080 dest->lpstrSchema = (LPOLESTR)buffer;
5081 len = strlenW(src->lpstrSchema);
5082 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5083 buffer += (len + 1) * sizeof(WCHAR);
5086 if (src->varkind == VAR_CONST)
5088 HRESULT hr;
5090 dest->u.lpvarValue = (VARIANT *)buffer;
5091 *dest->u.lpvarValue = *src->u.lpvarValue;
5092 buffer += sizeof(VARIANT);
5093 VariantInit(dest->u.lpvarValue);
5094 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5095 if (FAILED(hr))
5097 SysFreeString((BSTR)dest_ptr);
5098 return hr;
5101 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5102 if (FAILED(hr))
5104 if (src->varkind == VAR_CONST)
5105 VariantClear(dest->u.lpvarValue);
5106 SysFreeString((BSTR)dest);
5107 return hr;
5109 *dest_ptr = dest;
5110 return S_OK;
5113 /* ITypeInfo::GetVarDesc
5115 * Retrieves a VARDESC structure that describes the specified variable.
5118 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5119 LPVARDESC *ppVarDesc)
5121 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5122 int i;
5123 const TLBVarDesc *pVDesc;
5125 TRACE("(%p) index %d\n", This, index);
5127 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
5130 if (pVDesc)
5131 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5133 return E_INVALIDARG;
5136 /* ITypeInfo_GetNames
5138 * Retrieves the variable with the specified member ID (or the name of the
5139 * property or method and its parameters) that correspond to the specified
5140 * function ID.
5142 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5143 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5145 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5146 const TLBFuncDesc *pFDesc;
5147 const TLBVarDesc *pVDesc;
5148 int i;
5149 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5150 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
5151 if(pFDesc)
5153 /* function found, now return function and parameter names */
5154 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5156 if(!i)
5157 *rgBstrNames=SysAllocString(pFDesc->Name);
5158 else
5159 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5161 *pcNames=i;
5163 else
5165 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
5166 if(pVDesc)
5168 *rgBstrNames=SysAllocString(pVDesc->Name);
5169 *pcNames=1;
5171 else
5173 if(This->impltypelist &&
5174 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5175 /* recursive search */
5176 ITypeInfo *pTInfo;
5177 HRESULT result;
5178 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5179 &pTInfo);
5180 if(SUCCEEDED(result))
5182 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5183 ITypeInfo_Release(pTInfo);
5184 return result;
5186 WARN("Could not search inherited interface!\n");
5188 else
5190 WARN("no names found\n");
5192 *pcNames=0;
5193 return TYPE_E_ELEMENTNOTFOUND;
5196 return S_OK;
5200 /* ITypeInfo::GetRefTypeOfImplType
5202 * If a type description describes a COM class, it retrieves the type
5203 * description of the implemented interface types. For an interface,
5204 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5205 * if any exist.
5208 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5209 ITypeInfo2 *iface,
5210 UINT index,
5211 HREFTYPE *pRefType)
5213 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5214 int i;
5215 HRESULT hr = S_OK;
5216 const TLBImplType *pImpl = This->impltypelist;
5218 TRACE("(%p) index %d\n", This, index);
5219 if (TRACE_ON(ole)) dump_TypeInfo(This);
5221 if(index==(UINT)-1)
5223 /* only valid on dual interfaces;
5224 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5226 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5228 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
5229 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
5231 *pRefType = -1;
5233 else
5235 hr = TYPE_E_ELEMENTNOTFOUND;
5238 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5240 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5241 *pRefType = This->pTypeLib->dispatch_href;
5243 else
5245 /* get element n from linked list */
5246 for(i=0; pImpl && i<index; i++)
5248 pImpl = pImpl->next;
5251 if (pImpl)
5252 *pRefType = pImpl->hRef;
5253 else
5254 hr = TYPE_E_ELEMENTNOTFOUND;
5257 if(TRACE_ON(ole))
5259 if(SUCCEEDED(hr))
5260 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5261 else
5262 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5265 return hr;
5268 /* ITypeInfo::GetImplTypeFlags
5270 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5271 * or base interface in a type description.
5273 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5274 UINT index, INT *pImplTypeFlags)
5276 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5277 int i;
5278 TLBImplType *pImpl;
5280 TRACE("(%p) index %d\n", This, index);
5281 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5282 i++, pImpl=pImpl->next)
5284 if(i==index && pImpl){
5285 *pImplTypeFlags=pImpl->implflags;
5286 return S_OK;
5288 *pImplTypeFlags=0;
5289 return TYPE_E_ELEMENTNOTFOUND;
5292 /* GetIDsOfNames
5293 * Maps between member names and member IDs, and parameter names and
5294 * parameter IDs.
5296 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5297 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5299 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5300 const TLBFuncDesc *pFDesc;
5301 const TLBVarDesc *pVDesc;
5302 HRESULT ret=S_OK;
5303 int i;
5305 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5306 cNames);
5308 /* init out parameters in case of failure */
5309 for (i = 0; i < cNames; i++)
5310 pMemId[i] = MEMBERID_NIL;
5312 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5313 int j;
5314 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5315 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5316 for(i=1; i < cNames; i++){
5317 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5318 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5319 break;
5320 if( j<pFDesc->funcdesc.cParams)
5321 pMemId[i]=j;
5322 else
5323 ret=DISP_E_UNKNOWNNAME;
5325 TRACE("-- 0x%08x\n", ret);
5326 return ret;
5329 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5330 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5331 if(cNames) *pMemId=pVDesc->vardesc.memid;
5332 return ret;
5335 /* not found, see if it can be found in an inherited interface */
5336 if(This->impltypelist) {
5337 /* recursive search */
5338 ITypeInfo *pTInfo;
5339 ret=ITypeInfo_GetRefTypeInfo(iface,
5340 This->impltypelist->hRef, &pTInfo);
5341 if(SUCCEEDED(ret)){
5342 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5343 ITypeInfo_Release(pTInfo);
5344 return ret;
5346 WARN("Could not search inherited interface!\n");
5347 } else
5348 WARN("no names found\n");
5349 return DISP_E_UNKNOWNNAME;
5352 /* ITypeInfo::Invoke
5354 * Invokes a method, or accesses a property of an object, that implements the
5355 * interface described by the type description.
5357 DWORD
5358 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5359 DWORD res;
5361 if (TRACE_ON(ole)) {
5362 int i;
5363 TRACE("Calling %p(",func);
5364 for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
5365 TRACE(")\n");
5368 switch (callconv) {
5369 case CC_STDCALL:
5371 switch (nrargs) {
5372 case 0:
5373 res = func();
5374 break;
5375 case 1:
5376 res = func(args[0]);
5377 break;
5378 case 2:
5379 res = func(args[0],args[1]);
5380 break;
5381 case 3:
5382 res = func(args[0],args[1],args[2]);
5383 break;
5384 case 4:
5385 res = func(args[0],args[1],args[2],args[3]);
5386 break;
5387 case 5:
5388 res = func(args[0],args[1],args[2],args[3],args[4]);
5389 break;
5390 case 6:
5391 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
5392 break;
5393 case 7:
5394 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
5395 break;
5396 case 8:
5397 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
5398 break;
5399 case 9:
5400 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
5401 break;
5402 case 10:
5403 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
5404 break;
5405 case 11:
5406 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
5407 break;
5408 case 12:
5409 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]);
5410 break;
5411 case 13:
5412 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]);
5413 break;
5414 case 14:
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],args[11],args[12],args[13]);
5416 break;
5417 case 15:
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],args[12],args[13],args[14]);
5419 break;
5420 case 16:
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],args[13],args[14],args[15]);
5422 break;
5423 case 17:
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],args[14],args[15],args[16]);
5425 break;
5426 case 18:
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],args[15],args[16],args[17]);
5428 break;
5429 case 19:
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],args[16],args[17],args[18]);
5431 break;
5432 case 20:
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],args[17],args[18],args[19]);
5434 break;
5435 case 21:
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],args[18],args[19],args[20]);
5437 break;
5438 case 22:
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],args[19],args[20],args[21]);
5440 break;
5441 case 23:
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],args[20],args[21],args[22]);
5443 break;
5444 case 24:
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],args[21],args[22],args[23]);
5446 break;
5447 case 25:
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],args[22],args[23],args[24]);
5449 break;
5450 case 26:
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],args[23],args[24],args[25]);
5452 break;
5453 case 27:
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],args[24],args[25],args[26]);
5455 break;
5456 case 28:
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],args[25],args[26],args[27]);
5458 break;
5459 case 29:
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],args[26],args[27],args[28]);
5461 break;
5462 case 30:
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],args[27],args[28],args[29]);
5464 break;
5465 default:
5466 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
5467 res = -1;
5468 break;
5470 break;
5471 default:
5472 FIXME("unsupported calling convention %d\n",callconv);
5473 res = -1;
5474 break;
5476 TRACE("returns %08x\n",res);
5477 return res;
5480 extern int _argsize(DWORD vt);
5482 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5484 HRESULT hr = S_OK;
5485 ITypeInfo *tinfo2 = NULL;
5486 TYPEATTR *tattr = NULL;
5488 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5489 if (hr)
5491 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5492 "hr = 0x%08x\n",
5493 tdesc->u.hreftype, hr);
5494 return hr;
5496 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5497 if (hr)
5499 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5500 ITypeInfo_Release(tinfo2);
5501 return hr;
5504 switch (tattr->typekind)
5506 case TKIND_ENUM:
5507 *vt |= VT_I4;
5508 break;
5510 case TKIND_ALIAS:
5511 tdesc = &tattr->tdescAlias;
5512 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5513 break;
5515 case TKIND_INTERFACE:
5516 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5517 *vt |= VT_DISPATCH;
5518 else
5519 *vt |= VT_UNKNOWN;
5520 break;
5522 case TKIND_DISPATCH:
5523 *vt |= VT_DISPATCH;
5524 break;
5526 case TKIND_COCLASS:
5527 *vt |= VT_DISPATCH;
5528 break;
5530 case TKIND_RECORD:
5531 FIXME("TKIND_RECORD unhandled.\n");
5532 hr = E_NOTIMPL;
5533 break;
5535 case TKIND_UNION:
5536 FIXME("TKIND_UNION unhandled.\n");
5537 hr = E_NOTIMPL;
5538 break;
5540 default:
5541 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5542 hr = E_NOTIMPL;
5543 break;
5545 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5546 ITypeInfo_Release(tinfo2);
5547 return hr;
5550 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5552 HRESULT hr = S_OK;
5554 /* enforce only one level of pointer indirection */
5555 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5557 tdesc = tdesc->u.lptdesc;
5559 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5560 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5561 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5562 if ((tdesc->vt == VT_USERDEFINED) ||
5563 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5565 VARTYPE vt_userdefined = 0;
5566 const TYPEDESC *tdesc_userdefined = tdesc;
5567 if (tdesc->vt == VT_PTR)
5569 vt_userdefined = VT_BYREF;
5570 tdesc_userdefined = tdesc->u.lptdesc;
5572 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5573 if ((hr == S_OK) &&
5574 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5575 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5577 *vt |= vt_userdefined;
5578 return S_OK;
5581 *vt = VT_BYREF;
5584 switch (tdesc->vt)
5586 case VT_HRESULT:
5587 *vt |= VT_ERROR;
5588 break;
5589 case VT_USERDEFINED:
5590 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5591 break;
5592 case VT_VOID:
5593 case VT_CARRAY:
5594 case VT_PTR:
5595 case VT_LPSTR:
5596 case VT_LPWSTR:
5597 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5598 hr = DISP_E_BADVARTYPE;
5599 break;
5600 case VT_SAFEARRAY:
5601 *vt |= VT_ARRAY;
5602 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5603 break;
5604 default:
5605 *vt |= tdesc->vt;
5606 break;
5608 return hr;
5611 /***********************************************************************
5612 * DispCallFunc (OLEAUT32.@)
5614 * Invokes a function of the specified calling convention, passing the
5615 * specified arguments and returns the result.
5617 * PARAMS
5618 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5619 * oVft [I] The offset in the vtable. See notes.
5620 * cc [I] Calling convention of the function to call.
5621 * vtReturn [I] The return type of the function.
5622 * cActuals [I] Number of parameters.
5623 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5624 * prgpvarg [I] The arguments to pass.
5625 * pvargResult [O] The return value of the function. Can be NULL.
5627 * RETURNS
5628 * Success: S_OK.
5629 * Failure: HRESULT code.
5631 * NOTES
5632 * The HRESULT return value of this function is not affected by the return
5633 * value of the user supplied function, which is returned in pvargResult.
5635 * If pvInstance is NULL then a non-object function is to be called and oVft
5636 * is the address of the function to call.
5638 * The cc parameter can be one of the following values:
5639 *|CC_FASTCALL
5640 *|CC_CDECL
5641 *|CC_PASCAL
5642 *|CC_STDCALL
5643 *|CC_FPFASTCALL
5644 *|CC_SYSCALL
5645 *|CC_MPWCDECL
5646 *|CC_MPWPASCAL
5649 HRESULT WINAPI
5650 DispCallFunc(
5651 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5652 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5654 int i, argsize, argspos;
5655 DWORD *args;
5656 HRESULT hres;
5658 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5659 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5660 pvargResult, V_VT(pvargResult));
5662 argsize = 0;
5663 if (pvInstance)
5664 argsize++; /* for This pointer */
5666 for (i=0;i<cActuals;i++)
5668 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5669 dump_Variant(prgpvarg[i]);
5670 argsize += _argsize(prgvt[i]);
5672 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5674 argspos = 0;
5675 if (pvInstance)
5677 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5678 argspos++;
5681 for (i=0;i<cActuals;i++)
5683 VARIANT *arg = prgpvarg[i];
5684 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5685 if (prgvt[i] == VT_VARIANT)
5686 memcpy(&args[argspos], arg, _argsize(prgvt[i]) * sizeof(DWORD));
5687 else
5688 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5689 argspos += _argsize(prgvt[i]);
5692 if (pvInstance)
5694 FARPROC *vtable = *(FARPROC**)pvInstance;
5695 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5697 else
5698 /* if we aren't invoking an object then the function pointer is stored
5699 * in oVft */
5700 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5702 if (pvargResult && (vtReturn != VT_EMPTY))
5704 TRACE("Method returned 0x%08x\n",hres);
5705 V_VT(pvargResult) = vtReturn;
5706 V_UI4(pvargResult) = hres;
5709 HeapFree(GetProcessHeap(),0,args);
5710 return S_OK;
5713 #define INVBUF_ELEMENT_SIZE \
5714 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5715 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5716 ((VARIANTARG *)(buffer))
5717 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5718 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5719 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5720 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5721 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5722 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5724 static HRESULT WINAPI ITypeInfo_fnInvoke(
5725 ITypeInfo2 *iface,
5726 VOID *pIUnk,
5727 MEMBERID memid,
5728 UINT16 wFlags,
5729 DISPPARAMS *pDispParams,
5730 VARIANT *pVarResult,
5731 EXCEPINFO *pExcepInfo,
5732 UINT *pArgErr)
5734 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5735 int i;
5736 unsigned int var_index;
5737 TYPEKIND type_kind;
5738 HRESULT hres;
5739 const TLBFuncDesc *pFuncInfo;
5741 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
5742 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5745 if (!pDispParams)
5747 ERR("NULL pDispParams not allowed\n");
5748 return E_INVALIDARG;
5751 dump_DispParms(pDispParams);
5753 if (pDispParams->cNamedArgs > pDispParams->cArgs)
5755 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
5756 pDispParams->cNamedArgs, pDispParams->cArgs);
5757 return E_INVALIDARG;
5760 /* we do this instead of using GetFuncDesc since it will return a fake
5761 * FUNCDESC for dispinterfaces and we want the real function description */
5762 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5763 if ((memid == pFuncInfo->funcdesc.memid) &&
5764 (wFlags & pFuncInfo->funcdesc.invkind))
5765 break;
5767 if (pFuncInfo) {
5768 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5770 if (TRACE_ON(ole))
5772 TRACE("invoking:\n");
5773 dump_TLBFuncDescOne(pFuncInfo);
5776 switch (func_desc->funckind) {
5777 case FUNC_PUREVIRTUAL:
5778 case FUNC_VIRTUAL: {
5779 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
5780 VARIANT varresult;
5781 VARIANT retval; /* pointer for storing byref retvals in */
5782 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
5783 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
5784 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
5785 UINT cNamedArgs = pDispParams->cNamedArgs;
5786 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
5788 hres = S_OK;
5790 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
5792 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
5794 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
5795 hres = DISP_E_PARAMNOTFOUND;
5796 goto func_fail;
5798 /* ignore the DISPID_PROPERTYPUT named argument from now on */
5799 cNamedArgs--;
5800 rgdispidNamedArgs++;
5803 if (func_desc->cParamsOpt < 0 && cNamedArgs)
5805 ERR("functions with the vararg attribute do not support named arguments\n");
5806 hres = DISP_E_NONAMEDARGS;
5807 goto func_fail;
5810 for (i = 0; i < func_desc->cParams; i++)
5812 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5813 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
5814 if (FAILED(hres))
5815 goto func_fail;
5818 TRACE("changing args\n");
5819 for (i = 0; i < func_desc->cParams; i++)
5821 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5822 VARIANTARG *src_arg;
5824 if (cNamedArgs)
5826 USHORT j;
5827 src_arg = NULL;
5828 for (j = 0; j < cNamedArgs; j++)
5829 if (rgdispidNamedArgs[j] == i)
5831 src_arg = &pDispParams->rgvarg[j];
5832 break;
5835 else
5836 src_arg = i < pDispParams->cArgs ? &pDispParams->rgvarg[pDispParams->cArgs - 1 - i] : NULL;
5838 if (wParamFlags & PARAMFLAG_FRETVAL)
5840 /* under most conditions the caller is not allowed to
5841 * pass in a dispparam arg in the index of what would be
5842 * the retval parameter. however, there is an exception
5843 * where the extra parameter is used in an extra
5844 * IDispatch::Invoke below */
5845 if ((i < pDispParams->cArgs) &&
5846 ((func_desc->cParams != 1) || !pVarResult ||
5847 !(func_desc->invkind & INVOKE_PROPERTYGET)))
5849 hres = DISP_E_BADPARAMCOUNT;
5850 break;
5853 /* note: this check is placed so that if the caller passes
5854 * in a VARIANTARG for the retval we just ignore it, like
5855 * native does */
5856 if (i == func_desc->cParams - 1)
5858 VARIANTARG *arg;
5859 arg = prgpvarg[i] = &rgvarg[i];
5860 memset(arg, 0, sizeof(*arg));
5861 V_VT(arg) = rgvt[i];
5862 memset(&retval, 0, sizeof(retval));
5863 V_BYREF(arg) = &retval;
5865 else
5867 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
5868 hres = E_UNEXPECTED;
5869 break;
5872 else if (src_arg)
5874 dump_Variant(src_arg);
5876 if (rgvt[i] == VT_VARIANT)
5877 hres = VariantCopy(&rgvarg[i], src_arg);
5878 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
5880 if (rgvt[i] == V_VT(src_arg))
5881 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
5882 else
5884 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5885 hres = VariantCopy(&missing_arg[i], src_arg);
5886 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
5888 V_VT(&rgvarg[i]) = rgvt[i];
5890 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
5892 SAFEARRAY *a;
5893 SAFEARRAYBOUND bound;
5894 VARIANT *v;
5895 LONG j;
5896 bound.lLbound = 0;
5897 bound.cElements = pDispParams->cArgs-i;
5898 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
5900 ERR("SafeArrayCreate failed\n");
5901 break;
5903 hres = SafeArrayAccessData(a, (LPVOID)&v);
5904 if (hres != S_OK)
5906 ERR("SafeArrayAccessData failed with %x\n", hres);
5907 break;
5909 for (j = 0; j < bound.cElements; j++)
5910 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
5911 hres = SafeArrayUnaccessData(a);
5912 if (hres != S_OK)
5914 ERR("SafeArrayUnaccessData failed with %x\n", hres);
5915 break;
5917 V_ARRAY(&rgvarg[i]) = a;
5918 V_VT(&rgvarg[i]) = rgvt[i];
5920 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
5922 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5923 V_VT(&missing_arg[i]) = V_VT(src_arg);
5924 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
5925 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
5926 V_VT(&rgvarg[i]) = rgvt[i];
5928 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
5930 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
5931 V_VT(&rgvarg[i]) = rgvt[i];
5933 else
5935 /* FIXME: this doesn't work for VT_BYREF arguments if
5936 * they are not the same type as in the paramdesc */
5937 V_VT(&rgvarg[i]) = V_VT(src_arg);
5938 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
5939 V_VT(&rgvarg[i]) = rgvt[i];
5942 if (FAILED(hres))
5944 ERR("failed to convert param %d to %s%s from %s%s\n", i,
5945 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
5946 debugstr_VT(src_arg), debugstr_VF(src_arg));
5947 break;
5949 prgpvarg[i] = &rgvarg[i];
5951 else if (wParamFlags & PARAMFLAG_FOPT)
5953 VARIANTARG *arg;
5954 arg = prgpvarg[i] = &rgvarg[i];
5955 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5957 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
5958 if (FAILED(hres))
5959 break;
5961 else
5963 VARIANTARG *missing_arg;
5964 /* if the function wants a pointer to a variant then
5965 * set that up, otherwise just pass the VT_ERROR in
5966 * the argument by value */
5967 if (rgvt[i] & VT_BYREF)
5969 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
5970 V_VT(arg) = VT_VARIANT | VT_BYREF;
5971 V_VARIANTREF(arg) = missing_arg;
5973 else
5974 missing_arg = arg;
5975 V_VT(missing_arg) = VT_ERROR;
5976 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
5979 else
5981 hres = DISP_E_BADPARAMCOUNT;
5982 break;
5985 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5987 /* VT_VOID is a special case for return types, so it is not
5988 * handled in the general function */
5989 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
5990 V_VT(&varresult) = VT_EMPTY;
5991 else
5993 V_VT(&varresult) = 0;
5994 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
5995 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5998 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
5999 V_VT(&varresult), func_desc->cParams, rgvt,
6000 prgpvarg, &varresult);
6002 for (i = 0; i < func_desc->cParams; i++)
6004 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6005 if (wParamFlags & PARAMFLAG_FRETVAL)
6007 if (TRACE_ON(ole))
6009 TRACE("[retval] value: ");
6010 dump_Variant(prgpvarg[i]);
6013 if (pVarResult)
6015 VariantInit(pVarResult);
6016 /* deref return value */
6017 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6020 /* free data stored in varresult. Note that
6021 * VariantClear doesn't do what we want because we are
6022 * working with byref types. */
6023 /* FIXME: clear safearrays, bstrs, records and
6024 * variants here too */
6025 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
6026 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
6028 if(*V_UNKNOWNREF(prgpvarg[i]))
6029 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
6031 break;
6033 else if (i < pDispParams->cArgs)
6035 if (wParamFlags & PARAMFLAG_FOUT)
6037 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
6039 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
6040 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6042 if (FAILED(hres))
6044 ERR("failed to convert param %d to vt %d\n", i,
6045 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
6046 break;
6049 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6050 func_desc->cParamsOpt < 0 &&
6051 i == func_desc->cParams-1)
6053 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6054 LONG j, ubound;
6055 VARIANT *v;
6056 hres = SafeArrayGetUBound(a, 1, &ubound);
6057 if (hres != S_OK)
6059 ERR("SafeArrayGetUBound failed with %x\n", hres);
6060 break;
6062 hres = SafeArrayAccessData(a, (LPVOID)&v);
6063 if (hres != S_OK)
6065 ERR("SafeArrayAccessData failed with %x\n", hres);
6066 break;
6068 for (j = 0; j <= ubound; j++)
6069 VariantClear(&v[j]);
6070 hres = SafeArrayUnaccessData(a);
6071 if (hres != S_OK)
6073 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6074 break;
6077 VariantClear(&rgvarg[i]);
6079 else if (wParamFlags & PARAMFLAG_FOPT)
6081 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6082 VariantClear(&rgvarg[i]);
6086 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6088 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6089 hres = DISP_E_EXCEPTION;
6090 if (pExcepInfo)
6092 IErrorInfo *pErrorInfo;
6093 pExcepInfo->scode = V_ERROR(&varresult);
6094 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6096 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6097 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6098 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6099 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6101 IErrorInfo_Release(pErrorInfo);
6105 if (V_VT(&varresult) != VT_ERROR)
6107 TRACE("varresult value: ");
6108 dump_Variant(&varresult);
6110 if (pVarResult)
6112 VariantClear(pVarResult);
6113 *pVarResult = varresult;
6115 else
6116 VariantClear(&varresult);
6119 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6120 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6121 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6122 (pDispParams->cArgs != 0))
6124 if (V_VT(pVarResult) == VT_DISPATCH)
6126 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6127 /* Note: not VariantClear; we still need the dispatch
6128 * pointer to be valid */
6129 VariantInit(pVarResult);
6130 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6131 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6132 pDispParams, pVarResult, pExcepInfo, pArgErr);
6133 IDispatch_Release(pDispatch);
6135 else
6137 VariantClear(pVarResult);
6138 hres = DISP_E_NOTACOLLECTION;
6142 func_fail:
6143 HeapFree(GetProcessHeap(), 0, buffer);
6144 break;
6146 case FUNC_DISPATCH: {
6147 IDispatch *disp;
6149 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6150 if (SUCCEEDED(hres)) {
6151 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6152 hres = IDispatch_Invoke(
6153 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6154 pVarResult,pExcepInfo,pArgErr
6156 if (FAILED(hres))
6157 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6158 IDispatch_Release(disp);
6159 } else
6160 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6161 break;
6163 default:
6164 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6165 hres = E_FAIL;
6166 break;
6169 TRACE("-- 0x%08x\n", hres);
6170 return hres;
6172 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6173 VARDESC *var_desc;
6175 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6176 if(FAILED(hres)) return hres;
6178 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6179 dump_VARDESC(var_desc);
6180 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6181 return E_NOTIMPL;
6184 /* not found, look for it in inherited interfaces */
6185 ITypeInfo2_GetTypeKind(iface, &type_kind);
6186 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6187 if(This->impltypelist) {
6188 /* recursive search */
6189 ITypeInfo *pTInfo;
6190 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6191 if(SUCCEEDED(hres)){
6192 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6193 ITypeInfo_Release(pTInfo);
6194 return hres;
6196 WARN("Could not search inherited interface!\n");
6199 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6200 return DISP_E_MEMBERNOTFOUND;
6203 /* ITypeInfo::GetDocumentation
6205 * Retrieves the documentation string, the complete Help file name and path,
6206 * and the context ID for the Help topic for a specified type description.
6208 * (Can be tested by the Visual Basic Editor in Word for instance.)
6210 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6211 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6212 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6214 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6215 const TLBFuncDesc *pFDesc;
6216 const TLBVarDesc *pVDesc;
6217 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6218 " HelpContext(%p) HelpFile(%p)\n",
6219 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6220 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6221 if(pBstrName)
6222 *pBstrName=SysAllocString(This->Name);
6223 if(pBstrDocString)
6224 *pBstrDocString=SysAllocString(This->DocString);
6225 if(pdwHelpContext)
6226 *pdwHelpContext=This->dwHelpContext;
6227 if(pBstrHelpFile)
6228 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6229 return S_OK;
6230 }else {/* for a member */
6231 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6232 if(pFDesc->funcdesc.memid==memid){
6233 if(pBstrName)
6234 *pBstrName = SysAllocString(pFDesc->Name);
6235 if(pBstrDocString)
6236 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6237 if(pdwHelpContext)
6238 *pdwHelpContext=pFDesc->helpcontext;
6239 return S_OK;
6241 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6242 if(pVDesc->vardesc.memid==memid){
6243 if(pBstrName)
6244 *pBstrName = SysAllocString(pVDesc->Name);
6245 if(pBstrDocString)
6246 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6247 if(pdwHelpContext)
6248 *pdwHelpContext=pVDesc->HelpContext;
6249 return S_OK;
6253 if(This->impltypelist &&
6254 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6255 /* recursive search */
6256 ITypeInfo *pTInfo;
6257 HRESULT result;
6258 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6259 &pTInfo);
6260 if(SUCCEEDED(result)) {
6261 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6262 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6263 ITypeInfo_Release(pTInfo);
6264 return result;
6266 WARN("Could not search inherited interface!\n");
6269 WARN("member %d not found\n", memid);
6270 return TYPE_E_ELEMENTNOTFOUND;
6273 /* ITypeInfo::GetDllEntry
6275 * Retrieves a description or specification of an entry point for a function
6276 * in a DLL.
6278 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6279 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6280 WORD *pwOrdinal)
6282 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6283 const TLBFuncDesc *pFDesc;
6285 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6287 if (pBstrDllName) *pBstrDllName = NULL;
6288 if (pBstrName) *pBstrName = NULL;
6289 if (pwOrdinal) *pwOrdinal = 0;
6291 if (This->TypeAttr.typekind != TKIND_MODULE)
6292 return TYPE_E_BADMODULEKIND;
6294 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6295 if(pFDesc->funcdesc.memid==memid){
6296 dump_TypeInfo(This);
6297 if (TRACE_ON(ole))
6298 dump_TLBFuncDescOne(pFDesc);
6300 if (pBstrDllName)
6301 *pBstrDllName = SysAllocString(This->DllName);
6303 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6304 if (pBstrName)
6305 *pBstrName = SysAllocString(pFDesc->Entry);
6306 if (pwOrdinal)
6307 *pwOrdinal = -1;
6308 return S_OK;
6310 if (pBstrName)
6311 *pBstrName = NULL;
6312 if (pwOrdinal)
6313 *pwOrdinal = (DWORD)pFDesc->Entry;
6314 return S_OK;
6316 return TYPE_E_ELEMENTNOTFOUND;
6319 /* internal function to make the inherited interfaces' methods appear
6320 * part of the interface */
6321 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6322 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6324 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6325 HRESULT hr;
6327 TRACE("%p, 0x%x\n", iface, *hRefType);
6329 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK))
6331 ITypeInfo *pSubTypeInfo;
6333 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
6334 if (FAILED(hr))
6335 return hr;
6337 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6338 hRefType, ppTInfo);
6339 ITypeInfo_Release(pSubTypeInfo);
6340 if (SUCCEEDED(hr))
6341 return hr;
6343 *hRefType -= DISPATCH_HREF_OFFSET;
6345 if (!(*hRefType & DISPATCH_HREF_MASK))
6346 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6347 else
6348 return E_FAIL;
6351 /* ITypeInfo::GetRefTypeInfo
6353 * If a type description references other type descriptions, it retrieves
6354 * the referenced type descriptions.
6356 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6357 ITypeInfo2 *iface,
6358 HREFTYPE hRefType,
6359 ITypeInfo **ppTInfo)
6361 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6362 HRESULT result = E_FAIL;
6364 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6366 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6367 ITypeInfo_AddRef(*ppTInfo);
6368 result = S_OK;
6370 else if (hRefType == -1 &&
6371 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6372 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6374 /* when we meet a DUAL dispinterface, we must create the interface
6375 * version of it.
6377 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
6380 /* the interface version contains the same information as the dispinterface
6381 * copy the contents of the structs.
6383 *pTypeInfoImpl = *This;
6384 pTypeInfoImpl->ref = 0;
6386 /* change the type to interface */
6387 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6389 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6391 /* we use data structures from This, so we need to keep a reference
6392 * to it to stop it being destroyed and signal to the new instance to
6393 * not free its data structures when it is destroyed */
6394 pTypeInfoImpl->no_free_data = TRUE;
6395 pTypeInfoImpl->next = This;
6396 ITypeInfo_AddRef((ITypeInfo*) This);
6398 ITypeInfo_AddRef(*ppTInfo);
6400 result = S_OK;
6402 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6403 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6404 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6406 HREFTYPE href_dispatch = hRefType;
6407 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6408 } else {
6409 TLBRefType *ref_type;
6410 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6412 if(ref_type->reference == hRefType)
6413 break;
6415 if(&ref_type->entry == &This->pTypeLib->ref_list)
6417 FIXME("Can't find pRefType for ref %x\n", hRefType);
6418 goto end;
6420 if(hRefType != -1) {
6421 ITypeLib *pTLib = NULL;
6423 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6424 UINT Index;
6425 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6426 } else {
6427 if(ref_type->pImpTLInfo->pImpTypeLib) {
6428 TRACE("typeinfo in imported typelib that is already loaded\n");
6429 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6430 ITypeLib2_AddRef(pTLib);
6431 result = S_OK;
6432 } else {
6433 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6434 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6435 ref_type->pImpTLInfo->wVersionMajor,
6436 ref_type->pImpTLInfo->wVersionMinor,
6437 ref_type->pImpTLInfo->lcid,
6438 &pTLib);
6440 if(!SUCCEEDED(result)) {
6441 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6442 result=LoadTypeLib(libnam, &pTLib);
6443 SysFreeString(libnam);
6445 if(SUCCEEDED(result)) {
6446 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6447 ITypeLib2_AddRef(pTLib);
6451 if(SUCCEEDED(result)) {
6452 if(ref_type->index == TLB_REF_USE_GUID)
6453 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6454 &ref_type->guid,
6455 ppTInfo);
6456 else
6457 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6458 ppTInfo);
6460 if (pTLib != NULL)
6461 ITypeLib2_Release(pTLib);
6465 end:
6466 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6467 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6468 return result;
6471 /* ITypeInfo::AddressOfMember
6473 * Retrieves the addresses of static functions or variables, such as those
6474 * defined in a DLL.
6476 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6477 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6479 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6480 HRESULT hr;
6481 BSTR dll, entry;
6482 WORD ordinal;
6483 HMODULE module;
6485 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6487 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6488 if (FAILED(hr))
6489 return hr;
6491 module = LoadLibraryW(dll);
6492 if (!module)
6494 ERR("couldn't load %s\n", debugstr_w(dll));
6495 SysFreeString(dll);
6496 if (entry) SysFreeString(entry);
6497 return STG_E_FILENOTFOUND;
6499 /* FIXME: store library somewhere where we can free it */
6501 if (entry)
6503 LPSTR entryA;
6504 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6505 entryA = HeapAlloc(GetProcessHeap(), 0, len);
6506 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6508 *ppv = GetProcAddress(module, entryA);
6509 if (!*ppv)
6510 ERR("function not found %s\n", debugstr_a(entryA));
6512 HeapFree(GetProcessHeap(), 0, entryA);
6514 else
6516 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6517 if (!*ppv)
6518 ERR("function not found %d\n", ordinal);
6521 SysFreeString(dll);
6522 if (entry) SysFreeString(entry);
6524 if (!*ppv)
6525 return TYPE_E_DLLFUNCTIONNOTFOUND;
6527 return S_OK;
6530 /* ITypeInfo::CreateInstance
6532 * Creates a new instance of a type that describes a component object class
6533 * (coclass).
6535 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6536 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6538 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6539 HRESULT hr;
6540 TYPEATTR *pTA;
6542 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6544 *ppvObj = NULL;
6546 if(pOuterUnk)
6548 WARN("Not able to aggregate\n");
6549 return CLASS_E_NOAGGREGATION;
6552 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6553 if(FAILED(hr)) return hr;
6555 if(pTA->typekind != TKIND_COCLASS)
6557 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6558 hr = E_INVALIDARG;
6559 goto end;
6562 hr = S_FALSE;
6563 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6565 IUnknown *pUnk;
6566 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6567 TRACE("GetActiveObject rets %08x\n", hr);
6568 if(hr == S_OK)
6570 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6571 IUnknown_Release(pUnk);
6575 if(hr != S_OK)
6576 hr = CoCreateInstance(&pTA->guid, NULL,
6577 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6578 riid, ppvObj);
6580 end:
6581 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6582 return hr;
6585 /* ITypeInfo::GetMops
6587 * Retrieves marshalling information.
6589 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6590 BSTR *pBstrMops)
6592 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6593 FIXME("(%p) stub!\n", This);
6594 return S_OK;
6597 /* ITypeInfo::GetContainingTypeLib
6599 * Retrieves the containing type library and the index of the type description
6600 * within that type library.
6602 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6603 ITypeLib * *ppTLib, UINT *pIndex)
6605 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6607 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6608 if (pIndex) {
6609 *pIndex=This->index;
6610 TRACE("returning pIndex=%d\n", *pIndex);
6613 if (ppTLib) {
6614 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6615 ITypeLib2_AddRef(*ppTLib);
6616 TRACE("returning ppTLib=%p\n", *ppTLib);
6619 return S_OK;
6622 /* ITypeInfo::ReleaseTypeAttr
6624 * Releases a TYPEATTR previously returned by GetTypeAttr.
6627 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6628 TYPEATTR* pTypeAttr)
6630 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6631 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6632 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6635 /* ITypeInfo::ReleaseFuncDesc
6637 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6639 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6640 ITypeInfo2 *iface,
6641 FUNCDESC *pFuncDesc)
6643 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6644 SHORT i;
6646 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6648 for (i = 0; i < pFuncDesc->cParams; i++)
6649 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6650 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6652 SysFreeString((BSTR)pFuncDesc);
6655 /* ITypeInfo::ReleaseVarDesc
6657 * Releases a VARDESC previously returned by GetVarDesc.
6659 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6660 VARDESC *pVarDesc)
6662 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6663 TRACE("(%p)->(%p)\n", This, pVarDesc);
6665 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6666 if (pVarDesc->varkind == VAR_CONST)
6667 VariantClear(pVarDesc->u.lpvarValue);
6668 SysFreeString((BSTR)pVarDesc);
6671 /* ITypeInfo2::GetTypeKind
6673 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6676 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6677 TYPEKIND *pTypeKind)
6679 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6680 *pTypeKind=This->TypeAttr.typekind;
6681 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6682 return S_OK;
6685 /* ITypeInfo2::GetTypeFlags
6687 * Returns the type flags without any allocations. This returns a DWORD type
6688 * flag, which expands the type flags without growing the TYPEATTR (type
6689 * attribute).
6692 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6694 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6695 *pTypeFlags=This->TypeAttr.wTypeFlags;
6696 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6697 return S_OK;
6700 /* ITypeInfo2::GetFuncIndexOfMemId
6701 * Binds to a specific member based on a known DISPID, where the member name
6702 * is not known (for example, when binding to a default member).
6705 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
6706 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
6708 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6709 const TLBFuncDesc *pFuncInfo;
6710 int i;
6711 HRESULT result;
6713 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
6714 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
6715 break;
6716 if(pFuncInfo) {
6717 *pFuncIndex = i;
6718 result = S_OK;
6719 } else
6720 result = TYPE_E_ELEMENTNOTFOUND;
6722 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
6723 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6724 return result;
6727 /* TypeInfo2::GetVarIndexOfMemId
6729 * Binds to a specific member based on a known DISPID, where the member name
6730 * is not known (for example, when binding to a default member).
6733 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
6734 MEMBERID memid, UINT *pVarIndex)
6736 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6737 TLBVarDesc *pVarInfo;
6738 int i;
6739 HRESULT result;
6740 for(i=0, pVarInfo=This->varlist; pVarInfo &&
6741 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
6743 if(pVarInfo) {
6744 *pVarIndex = i;
6745 result = S_OK;
6746 } else
6747 result = TYPE_E_ELEMENTNOTFOUND;
6749 TRACE("(%p) memid 0x%08x -> %s\n", This,
6750 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6751 return result;
6754 /* ITypeInfo2::GetCustData
6756 * Gets the custom data
6758 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
6759 ITypeInfo2 * iface,
6760 REFGUID guid,
6761 VARIANT *pVarVal)
6763 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6764 TLBCustData *pCData;
6766 for(pCData=This->pCustData; pCData; pCData = pCData->next)
6767 if( IsEqualIID(guid, &pCData->guid)) break;
6769 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6771 if(pCData)
6773 VariantInit( pVarVal);
6774 VariantCopy( pVarVal, &pCData->data);
6775 return S_OK;
6777 return E_INVALIDARG; /* FIXME: correct? */
6780 /* ITypeInfo2::GetFuncCustData
6782 * Gets the custom data
6784 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
6785 ITypeInfo2 * iface,
6786 UINT index,
6787 REFGUID guid,
6788 VARIANT *pVarVal)
6790 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6791 TLBCustData *pCData=NULL;
6792 TLBFuncDesc * pFDesc;
6793 int i;
6794 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6795 pFDesc=pFDesc->next);
6797 if(pFDesc)
6798 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
6799 if( IsEqualIID(guid, &pCData->guid)) break;
6801 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6803 if(pCData){
6804 VariantInit( pVarVal);
6805 VariantCopy( pVarVal, &pCData->data);
6806 return S_OK;
6808 return E_INVALIDARG; /* FIXME: correct? */
6811 /* ITypeInfo2::GetParamCustData
6813 * Gets the custom data
6815 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
6816 ITypeInfo2 * iface,
6817 UINT indexFunc,
6818 UINT indexParam,
6819 REFGUID guid,
6820 VARIANT *pVarVal)
6822 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6823 TLBCustData *pCData=NULL;
6824 TLBFuncDesc * pFDesc;
6825 int i;
6827 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
6829 if(pFDesc && indexParam<pFDesc->funcdesc.cParams)
6830 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
6831 pCData = pCData->next)
6832 if( IsEqualIID(guid, &pCData->guid)) break;
6834 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6836 if(pCData)
6838 VariantInit( pVarVal);
6839 VariantCopy( pVarVal, &pCData->data);
6840 return S_OK;
6842 return E_INVALIDARG; /* FIXME: correct? */
6845 /* ITypeInfo2::GetVarCustData
6847 * Gets the custom data
6849 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
6850 ITypeInfo2 * iface,
6851 UINT index,
6852 REFGUID guid,
6853 VARIANT *pVarVal)
6855 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6856 TLBCustData *pCData=NULL;
6857 TLBVarDesc * pVDesc;
6858 int i;
6860 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
6862 if(pVDesc)
6864 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
6866 if( IsEqualIID(guid, &pCData->guid)) break;
6870 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6872 if(pCData)
6874 VariantInit( pVarVal);
6875 VariantCopy( pVarVal, &pCData->data);
6876 return S_OK;
6878 return E_INVALIDARG; /* FIXME: correct? */
6881 /* ITypeInfo2::GetImplCustData
6883 * Gets the custom data
6885 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6886 ITypeInfo2 * iface,
6887 UINT index,
6888 REFGUID guid,
6889 VARIANT *pVarVal)
6891 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6892 TLBCustData *pCData=NULL;
6893 TLBImplType * pRDesc;
6894 int i;
6896 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6898 if(pRDesc)
6900 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6902 if( IsEqualIID(guid, &pCData->guid)) break;
6906 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6908 if(pCData)
6910 VariantInit( pVarVal);
6911 VariantCopy( pVarVal, &pCData->data);
6912 return S_OK;
6914 return E_INVALIDARG; /* FIXME: correct? */
6917 /* ITypeInfo2::GetDocumentation2
6919 * Retrieves the documentation string, the complete Help file name and path,
6920 * the localization context to use, and the context ID for the library Help
6921 * topic in the Help file.
6924 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6925 ITypeInfo2 * iface,
6926 MEMBERID memid,
6927 LCID lcid,
6928 BSTR *pbstrHelpString,
6929 DWORD *pdwHelpStringContext,
6930 BSTR *pbstrHelpStringDll)
6932 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6933 const TLBFuncDesc *pFDesc;
6934 const TLBVarDesc *pVDesc;
6935 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
6936 "HelpStringContext(%p) HelpStringDll(%p)\n",
6937 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6938 pbstrHelpStringDll );
6939 /* the help string should be obtained from the helpstringdll,
6940 * using the _DLLGetDocumentation function, based on the supplied
6941 * lcid. Nice to do sometime...
6943 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6944 if(pbstrHelpString)
6945 *pbstrHelpString=SysAllocString(This->Name);
6946 if(pdwHelpStringContext)
6947 *pdwHelpStringContext=This->dwHelpStringContext;
6948 if(pbstrHelpStringDll)
6949 *pbstrHelpStringDll=
6950 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6951 return S_OK;
6952 }else {/* for a member */
6953 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6954 if(pFDesc->funcdesc.memid==memid){
6955 if(pbstrHelpString)
6956 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6957 if(pdwHelpStringContext)
6958 *pdwHelpStringContext=pFDesc->HelpStringContext;
6959 if(pbstrHelpStringDll)
6960 *pbstrHelpStringDll=
6961 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6962 return S_OK;
6964 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6965 if(pVDesc->vardesc.memid==memid){
6966 if(pbstrHelpString)
6967 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6968 if(pdwHelpStringContext)
6969 *pdwHelpStringContext=pVDesc->HelpStringContext;
6970 if(pbstrHelpStringDll)
6971 *pbstrHelpStringDll=
6972 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6973 return S_OK;
6976 return TYPE_E_ELEMENTNOTFOUND;
6979 /* ITypeInfo2::GetAllCustData
6981 * Gets all custom data items for the Type info.
6984 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6985 ITypeInfo2 * iface,
6986 CUSTDATA *pCustData)
6988 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6989 TLBCustData *pCData;
6990 int i;
6992 TRACE("(%p) returning %d items\n", This, This->ctCustData);
6994 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6995 if(pCustData->prgCustData ){
6996 pCustData->cCustData=This->ctCustData;
6997 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
6998 pCustData->prgCustData[i].guid=pCData->guid;
6999 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
7001 }else{
7002 ERR(" OUT OF MEMORY!\n");
7003 return E_OUTOFMEMORY;
7005 return S_OK;
7008 /* ITypeInfo2::GetAllFuncCustData
7010 * Gets all custom data items for the specified Function
7013 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7014 ITypeInfo2 * iface,
7015 UINT index,
7016 CUSTDATA *pCustData)
7018 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7019 TLBCustData *pCData;
7020 TLBFuncDesc * pFDesc;
7021 int i;
7022 TRACE("(%p) index %d\n", This, index);
7023 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7024 pFDesc=pFDesc->next)
7026 if(pFDesc){
7027 pCustData->prgCustData =
7028 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
7029 if(pCustData->prgCustData ){
7030 pCustData->cCustData=pFDesc->ctCustData;
7031 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
7032 pCData = pCData->next){
7033 pCustData->prgCustData[i].guid=pCData->guid;
7034 VariantCopy(& pCustData->prgCustData[i].varValue,
7035 & pCData->data);
7037 }else{
7038 ERR(" OUT OF MEMORY!\n");
7039 return E_OUTOFMEMORY;
7041 return S_OK;
7043 return TYPE_E_ELEMENTNOTFOUND;
7046 /* ITypeInfo2::GetAllParamCustData
7048 * Gets all custom data items for the Functions
7051 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7052 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7054 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7055 TLBCustData *pCData=NULL;
7056 TLBFuncDesc * pFDesc;
7057 int i;
7058 TRACE("(%p) index %d\n", This, indexFunc);
7059 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
7060 pFDesc=pFDesc->next)
7062 if(pFDesc && indexParam<pFDesc->funcdesc.cParams){
7063 pCustData->prgCustData =
7064 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
7065 sizeof(CUSTDATAITEM));
7066 if(pCustData->prgCustData ){
7067 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
7068 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
7069 pCData; i++, pCData = pCData->next){
7070 pCustData->prgCustData[i].guid=pCData->guid;
7071 VariantCopy(& pCustData->prgCustData[i].varValue,
7072 & pCData->data);
7074 }else{
7075 ERR(" OUT OF MEMORY!\n");
7076 return E_OUTOFMEMORY;
7078 return S_OK;
7080 return TYPE_E_ELEMENTNOTFOUND;
7083 /* ITypeInfo2::GetAllVarCustData
7085 * Gets all custom data items for the specified Variable
7088 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7089 UINT index, CUSTDATA *pCustData)
7091 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7092 TLBCustData *pCData;
7093 TLBVarDesc * pVDesc;
7094 int i;
7095 TRACE("(%p) index %d\n", This, index);
7096 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
7097 pVDesc=pVDesc->next)
7099 if(pVDesc){
7100 pCustData->prgCustData =
7101 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
7102 if(pCustData->prgCustData ){
7103 pCustData->cCustData=pVDesc->ctCustData;
7104 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
7105 pCData = pCData->next){
7106 pCustData->prgCustData[i].guid=pCData->guid;
7107 VariantCopy(& pCustData->prgCustData[i].varValue,
7108 & pCData->data);
7110 }else{
7111 ERR(" OUT OF MEMORY!\n");
7112 return E_OUTOFMEMORY;
7114 return S_OK;
7116 return TYPE_E_ELEMENTNOTFOUND;
7119 /* ITypeInfo2::GetAllImplCustData
7121 * Gets all custom data items for the specified implementation type
7124 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7125 ITypeInfo2 * iface,
7126 UINT index,
7127 CUSTDATA *pCustData)
7129 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7130 TLBCustData *pCData;
7131 TLBImplType * pRDesc;
7132 int i;
7133 TRACE("(%p) index %d\n", This, index);
7134 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
7135 pRDesc=pRDesc->next)
7137 if(pRDesc){
7138 pCustData->prgCustData =
7139 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
7140 if(pCustData->prgCustData ){
7141 pCustData->cCustData=pRDesc->ctCustData;
7142 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
7143 pCData = pCData->next){
7144 pCustData->prgCustData[i].guid=pCData->guid;
7145 VariantCopy(& pCustData->prgCustData[i].varValue,
7146 & pCData->data);
7148 }else{
7149 ERR(" OUT OF MEMORY!\n");
7150 return E_OUTOFMEMORY;
7152 return S_OK;
7154 return TYPE_E_ELEMENTNOTFOUND;
7157 static const ITypeInfo2Vtbl tinfvt =
7160 ITypeInfo_fnQueryInterface,
7161 ITypeInfo_fnAddRef,
7162 ITypeInfo_fnRelease,
7164 ITypeInfo_fnGetTypeAttr,
7165 ITypeInfo_fnGetTypeComp,
7166 ITypeInfo_fnGetFuncDesc,
7167 ITypeInfo_fnGetVarDesc,
7168 ITypeInfo_fnGetNames,
7169 ITypeInfo_fnGetRefTypeOfImplType,
7170 ITypeInfo_fnGetImplTypeFlags,
7171 ITypeInfo_fnGetIDsOfNames,
7172 ITypeInfo_fnInvoke,
7173 ITypeInfo_fnGetDocumentation,
7174 ITypeInfo_fnGetDllEntry,
7175 ITypeInfo_fnGetRefTypeInfo,
7176 ITypeInfo_fnAddressOfMember,
7177 ITypeInfo_fnCreateInstance,
7178 ITypeInfo_fnGetMops,
7179 ITypeInfo_fnGetContainingTypeLib,
7180 ITypeInfo_fnReleaseTypeAttr,
7181 ITypeInfo_fnReleaseFuncDesc,
7182 ITypeInfo_fnReleaseVarDesc,
7184 ITypeInfo2_fnGetTypeKind,
7185 ITypeInfo2_fnGetTypeFlags,
7186 ITypeInfo2_fnGetFuncIndexOfMemId,
7187 ITypeInfo2_fnGetVarIndexOfMemId,
7188 ITypeInfo2_fnGetCustData,
7189 ITypeInfo2_fnGetFuncCustData,
7190 ITypeInfo2_fnGetParamCustData,
7191 ITypeInfo2_fnGetVarCustData,
7192 ITypeInfo2_fnGetImplTypeCustData,
7193 ITypeInfo2_fnGetDocumentation2,
7194 ITypeInfo2_fnGetAllCustData,
7195 ITypeInfo2_fnGetAllFuncCustData,
7196 ITypeInfo2_fnGetAllParamCustData,
7197 ITypeInfo2_fnGetAllVarCustData,
7198 ITypeInfo2_fnGetAllImplTypeCustData,
7201 /******************************************************************************
7202 * CreateDispTypeInfo [OLEAUT32.31]
7204 * Build type information for an object so it can be called through an
7205 * IDispatch interface.
7207 * RETURNS
7208 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7209 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7211 * NOTES
7212 * This call allows an objects methods to be accessed through IDispatch, by
7213 * building an ITypeInfo object that IDispatch can use to call through.
7215 HRESULT WINAPI CreateDispTypeInfo(
7216 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7217 LCID lcid, /* [I] Locale Id */
7218 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7220 ITypeInfoImpl *pTIClass, *pTIIface;
7221 ITypeLibImpl *pTypeLibImpl;
7222 int param, func;
7223 TLBFuncDesc **ppFuncDesc;
7224 TLBRefType *ref;
7226 TRACE("\n");
7227 pTypeLibImpl = TypeLibImpl_Constructor();
7228 if (!pTypeLibImpl) return E_FAIL;
7230 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
7231 pTIIface->pTypeLib = pTypeLibImpl;
7232 pTIIface->index = 0;
7233 pTIIface->Name = NULL;
7234 pTIIface->dwHelpContext = -1;
7235 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7236 pTIIface->TypeAttr.lcid = lcid;
7237 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7238 pTIIface->TypeAttr.wMajorVerNum = 0;
7239 pTIIface->TypeAttr.wMinorVerNum = 0;
7240 pTIIface->TypeAttr.cbAlignment = 2;
7241 pTIIface->TypeAttr.cbSizeInstance = -1;
7242 pTIIface->TypeAttr.cbSizeVft = -1;
7243 pTIIface->TypeAttr.cFuncs = 0;
7244 pTIIface->TypeAttr.cImplTypes = 0;
7245 pTIIface->TypeAttr.cVars = 0;
7246 pTIIface->TypeAttr.wTypeFlags = 0;
7248 ppFuncDesc = &pTIIface->funclist;
7249 for(func = 0; func < pidata->cMembers; func++) {
7250 METHODDATA *md = pidata->pmethdata + func;
7251 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
7252 (*ppFuncDesc)->Name = SysAllocString(md->szName);
7253 (*ppFuncDesc)->funcdesc.memid = md->dispid;
7254 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
7255 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
7256 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
7257 (*ppFuncDesc)->funcdesc.callconv = md->cc;
7258 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
7259 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
7260 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
7261 (*ppFuncDesc)->funcdesc.cScodes = 0;
7262 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
7263 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7264 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7265 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7266 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7267 md->cArgs * sizeof(ELEMDESC));
7268 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7269 md->cArgs * sizeof(TLBParDesc));
7270 for(param = 0; param < md->cArgs; param++) {
7271 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7272 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7274 (*ppFuncDesc)->helpcontext = 0;
7275 (*ppFuncDesc)->HelpStringContext = 0;
7276 (*ppFuncDesc)->HelpString = NULL;
7277 (*ppFuncDesc)->Entry = NULL;
7278 (*ppFuncDesc)->ctCustData = 0;
7279 (*ppFuncDesc)->pCustData = NULL;
7280 (*ppFuncDesc)->next = NULL;
7281 pTIIface->TypeAttr.cFuncs++;
7282 ppFuncDesc = &(*ppFuncDesc)->next;
7285 dump_TypeInfo(pTIIface);
7287 pTypeLibImpl->pTypeInfo = pTIIface;
7288 pTypeLibImpl->TypeInfoCount++;
7290 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
7291 pTIClass->pTypeLib = pTypeLibImpl;
7292 pTIClass->index = 1;
7293 pTIClass->Name = NULL;
7294 pTIClass->dwHelpContext = -1;
7295 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7296 pTIClass->TypeAttr.lcid = lcid;
7297 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7298 pTIClass->TypeAttr.wMajorVerNum = 0;
7299 pTIClass->TypeAttr.wMinorVerNum = 0;
7300 pTIClass->TypeAttr.cbAlignment = 2;
7301 pTIClass->TypeAttr.cbSizeInstance = -1;
7302 pTIClass->TypeAttr.cbSizeVft = -1;
7303 pTIClass->TypeAttr.cFuncs = 0;
7304 pTIClass->TypeAttr.cImplTypes = 1;
7305 pTIClass->TypeAttr.cVars = 0;
7306 pTIClass->TypeAttr.wTypeFlags = 0;
7308 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
7309 pTIClass->impltypelist->hRef = 0;
7311 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
7312 ref->index = 0;
7313 ref->reference = 0;
7314 ref->pImpTLInfo = TLB_REF_INTERNAL;
7315 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7317 dump_TypeInfo(pTIClass);
7319 pTIIface->next = pTIClass;
7320 pTypeLibImpl->TypeInfoCount++;
7322 *pptinfo = (ITypeInfo*)pTIClass;
7324 ITypeInfo_AddRef(*pptinfo);
7325 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7327 return S_OK;
7331 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7333 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7335 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7338 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7340 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7342 return ITypeInfo_AddRef((ITypeInfo *)This);
7345 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7347 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7349 return ITypeInfo_Release((ITypeInfo *)This);
7352 static HRESULT WINAPI ITypeComp_fnBind(
7353 ITypeComp * iface,
7354 OLECHAR * szName,
7355 ULONG lHash,
7356 WORD wFlags,
7357 ITypeInfo ** ppTInfo,
7358 DESCKIND * pDescKind,
7359 BINDPTR * pBindPtr)
7361 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7362 const TLBFuncDesc *pFDesc;
7363 const TLBVarDesc *pVDesc;
7364 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7366 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7368 *pDescKind = DESCKIND_NONE;
7369 pBindPtr->lpfuncdesc = NULL;
7370 *ppTInfo = NULL;
7372 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
7373 if (!strcmpiW(pFDesc->Name, szName)) {
7374 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7375 break;
7376 else
7377 /* name found, but wrong flags */
7378 hr = TYPE_E_TYPEMISMATCH;
7381 if (pFDesc)
7383 HRESULT hr = TLB_AllocAndInitFuncDesc(
7384 &pFDesc->funcdesc,
7385 &pBindPtr->lpfuncdesc,
7386 This->TypeAttr.typekind == TKIND_DISPATCH);
7387 if (FAILED(hr))
7388 return hr;
7389 *pDescKind = DESCKIND_FUNCDESC;
7390 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7391 ITypeInfo_AddRef(*ppTInfo);
7392 return S_OK;
7393 } else {
7394 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7395 if (!strcmpiW(pVDesc->Name, szName)) {
7396 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7397 if (FAILED(hr))
7398 return hr;
7399 *pDescKind = DESCKIND_VARDESC;
7400 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7401 ITypeInfo_AddRef(*ppTInfo);
7402 return S_OK;
7406 /* FIXME: search each inherited interface, not just the first */
7407 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7408 /* recursive search */
7409 ITypeInfo *pTInfo;
7410 ITypeComp *pTComp;
7411 HRESULT hr;
7412 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7413 if (SUCCEEDED(hr))
7415 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7416 ITypeInfo_Release(pTInfo);
7418 if (SUCCEEDED(hr))
7420 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7421 ITypeComp_Release(pTComp);
7422 return hr;
7424 WARN("Could not search inherited interface!\n");
7426 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
7427 return hr;
7430 static HRESULT WINAPI ITypeComp_fnBindType(
7431 ITypeComp * iface,
7432 OLECHAR * szName,
7433 ULONG lHash,
7434 ITypeInfo ** ppTInfo,
7435 ITypeComp ** ppTComp)
7437 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7439 /* strange behaviour (does nothing) but like the
7440 * original */
7442 if (!ppTInfo || !ppTComp)
7443 return E_POINTER;
7445 *ppTInfo = NULL;
7446 *ppTComp = NULL;
7448 return S_OK;
7451 static const ITypeCompVtbl tcompvt =
7454 ITypeComp_fnQueryInterface,
7455 ITypeComp_fnAddRef,
7456 ITypeComp_fnRelease,
7458 ITypeComp_fnBind,
7459 ITypeComp_fnBindType