crypt32: Use set encoding function for encoding PKCS signed info.
[wine/multimedia.git] / dlls / oleaut32 / typelib.c
blobb55599fba2d8249ba72aac0a607f9098ac9e149c
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 int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
243 /****************************************************************************
244 * QueryPathOfRegTypeLib [OLEAUT32.164]
246 * Gets the path to a registered type library.
248 * PARAMS
249 * guid [I] referenced guid
250 * wMaj [I] major version
251 * wMin [I] minor version
252 * lcid [I] locale id
253 * path [O] path of typelib
255 * RETURNS
256 * Success: S_OK.
257 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
258 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
259 * opened.
261 HRESULT WINAPI QueryPathOfRegTypeLib(
262 REFGUID guid,
263 WORD wMaj,
264 WORD wMin,
265 LCID lcid,
266 LPBSTR path )
268 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
269 LCID myLCID = lcid;
270 HKEY hkey;
271 WCHAR buffer[60];
272 WCHAR Path[MAX_PATH];
273 LONG res;
275 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
277 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
278 get_typelib_key( guid, wMaj, wMin, buffer );
280 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
281 if (res == ERROR_FILE_NOT_FOUND)
283 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
284 return TYPE_E_LIBNOTREGISTERED;
286 else if (res != ERROR_SUCCESS)
288 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
289 return TYPE_E_REGISTRYACCESS;
292 while (hr != S_OK)
294 LONG dwPathLen = sizeof(Path);
296 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
298 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
300 if (!lcid)
301 break;
302 else if (myLCID == lcid)
304 /* try with sub-langid */
305 myLCID = SUBLANGID(lcid);
307 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
309 /* try with system langid */
310 myLCID = 0;
312 else
314 break;
317 else
319 *path = SysAllocString( Path );
320 hr = S_OK;
323 RegCloseKey( hkey );
324 TRACE_(typelib)("-- 0x%08x\n", hr);
325 return hr;
328 /******************************************************************************
329 * CreateTypeLib [OLEAUT32.160] creates a typelib
331 * RETURNS
332 * Success: S_OK
333 * Failure: Status
335 HRESULT WINAPI CreateTypeLib(
336 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
338 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
339 return E_FAIL;
342 /******************************************************************************
343 * LoadTypeLib [OLEAUT32.161]
345 * Loads a type library
347 * PARAMS
348 * szFile [I] Name of file to load from.
349 * pptLib [O] Pointer that receives ITypeLib object on success.
351 * RETURNS
352 * Success: S_OK
353 * Failure: Status
355 * SEE
356 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
358 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
360 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
361 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
364 /******************************************************************************
365 * LoadTypeLibEx [OLEAUT32.183]
367 * Loads and optionally registers a type library
369 * RETURNS
370 * Success: S_OK
371 * Failure: Status
373 HRESULT WINAPI LoadTypeLibEx(
374 LPCOLESTR szFile, /* [in] Name of file to load from */
375 REGKIND regkind, /* [in] Specify kind of registration */
376 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
378 WCHAR szPath[MAX_PATH+1];
379 HRESULT res;
381 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
383 *pptLib = NULL;
385 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
387 if (SUCCEEDED(res))
388 switch(regkind)
390 case REGKIND_DEFAULT:
391 /* don't register typelibs supplied with full path. Experimentation confirms the following */
392 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
393 (szFile[0] && (szFile[1] == ':'))) break;
394 /* else fall-through */
396 case REGKIND_REGISTER:
397 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
399 IUnknown_Release(*pptLib);
400 *pptLib = 0;
402 break;
403 case REGKIND_NONE:
404 break;
407 TRACE(" returns %08x\n",res);
408 return res;
411 /******************************************************************************
412 * LoadRegTypeLib [OLEAUT32.162]
414 * Loads a registered type library.
416 * PARAMS
417 * rguid [I] GUID of the registered type library.
418 * wVerMajor [I] major version.
419 * wVerMinor [I] minor version.
420 * lcid [I] locale ID.
421 * ppTLib [O] pointer that receives an ITypeLib object on success.
423 * RETURNS
424 * Success: S_OK.
425 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
426 * LoadTypeLib.
428 HRESULT WINAPI LoadRegTypeLib(
429 REFGUID rguid,
430 WORD wVerMajor,
431 WORD wVerMinor,
432 LCID lcid,
433 ITypeLib **ppTLib)
435 BSTR bstr=NULL;
436 HRESULT res;
438 *ppTLib = NULL;
440 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
442 if(SUCCEEDED(res))
444 res= LoadTypeLib(bstr, ppTLib);
445 SysFreeString(bstr);
448 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
450 return res;
454 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
455 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
456 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
457 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
458 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
459 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
461 /******************************************************************************
462 * RegisterTypeLib [OLEAUT32.163]
463 * Adds information about a type library to the System Registry
464 * NOTES
465 * Docs: ITypeLib FAR * ptlib
466 * Docs: OLECHAR FAR* szFullPath
467 * Docs: OLECHAR FAR* szHelpDir
469 * RETURNS
470 * Success: S_OK
471 * Failure: Status
473 HRESULT WINAPI RegisterTypeLib(
474 ITypeLib * ptlib, /* [in] Pointer to the library*/
475 OLECHAR * szFullPath, /* [in] full Path of the library*/
476 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
477 may be NULL*/
479 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
480 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
481 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
482 HRESULT res;
483 TLIBATTR *attr;
484 WCHAR keyName[60];
485 WCHAR tmp[16];
486 HKEY key, subKey;
487 UINT types, tidx;
488 TYPEKIND kind;
489 DWORD disposition;
491 if (ptlib == NULL || szFullPath == NULL)
492 return E_INVALIDARG;
494 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
495 return E_FAIL;
497 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
499 res = S_OK;
500 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
501 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
503 LPOLESTR doc;
505 /* Set the human-readable name of the typelib */
506 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
508 if (RegSetValueExW(key, NULL, 0, REG_SZ,
509 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
510 res = E_FAIL;
512 SysFreeString(doc);
514 else
515 res = E_FAIL;
517 /* Make up the name of the typelib path subkey */
518 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
520 /* Create the typelib path subkey */
521 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
522 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
524 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
525 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
526 res = E_FAIL;
528 RegCloseKey(subKey);
530 else
531 res = E_FAIL;
533 /* Create the flags subkey */
534 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
535 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
537 /* FIXME: is %u correct? */
538 static const WCHAR formatW[] = {'%','u',0};
539 WCHAR buf[20];
540 sprintfW(buf, formatW, attr->wLibFlags);
541 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
542 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
543 res = E_FAIL;
545 RegCloseKey(subKey);
547 else
548 res = E_FAIL;
550 /* create the helpdir subkey */
551 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
552 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
554 BOOL freeHelpDir = FALSE;
555 OLECHAR* pIndexStr;
557 /* if we created a new key, and helpDir was null, set the helpdir
558 to the directory which contains the typelib. However,
559 if we just opened an existing key, we leave the helpdir alone */
560 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
561 szHelpDir = SysAllocString(szFullPath);
562 pIndexStr = strrchrW(szHelpDir, '\\');
563 if (pIndexStr) {
564 *pIndexStr = 0;
566 freeHelpDir = TRUE;
569 /* if we have an szHelpDir, set it! */
570 if (szHelpDir != NULL) {
571 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
572 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
573 res = E_FAIL;
577 /* tidy up */
578 if (freeHelpDir) SysFreeString(szHelpDir);
579 RegCloseKey(subKey);
581 } else {
582 res = E_FAIL;
585 RegCloseKey(key);
587 else
588 res = E_FAIL;
590 /* register OLE Automation-compatible interfaces for this typelib */
591 types = ITypeLib_GetTypeInfoCount(ptlib);
592 for (tidx=0; tidx<types; tidx++) {
593 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
594 LPOLESTR name = NULL;
595 ITypeInfo *tinfo = NULL;
597 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
599 switch (kind) {
600 case TKIND_INTERFACE:
601 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
602 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
603 break;
605 case TKIND_DISPATCH:
606 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
607 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
608 break;
610 default:
611 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
612 break;
615 if (tinfo) {
616 TYPEATTR *tattr = NULL;
617 ITypeInfo_GetTypeAttr(tinfo, &tattr);
619 if (tattr) {
620 TRACE_(typelib)("guid=%s, flags=%04x (",
621 debugstr_guid(&tattr->guid),
622 tattr->wTypeFlags);
624 if (TRACE_ON(typelib)) {
625 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
626 XX(FAPPOBJECT);
627 XX(FCANCREATE);
628 XX(FLICENSED);
629 XX(FPREDECLID);
630 XX(FHIDDEN);
631 XX(FCONTROL);
632 XX(FDUAL);
633 XX(FNONEXTENSIBLE);
634 XX(FOLEAUTOMATION);
635 XX(FRESTRICTED);
636 XX(FAGGREGATABLE);
637 XX(FREPLACEABLE);
638 XX(FDISPATCHABLE);
639 XX(FREVERSEBIND);
640 XX(FPROXY);
641 #undef XX
642 MESSAGE("\n");
645 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL|TYPEFLAG_FDISPATCHABLE))
647 /* register interface<->typelib coupling */
648 get_interface_key( &tattr->guid, keyName );
649 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
650 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
652 if (name)
653 RegSetValueExW(key, NULL, 0, REG_SZ,
654 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
656 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
657 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
658 RegSetValueExW(subKey, NULL, 0, REG_SZ,
659 (const BYTE *)PSOA, sizeof PSOA);
660 RegCloseKey(subKey);
663 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
664 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
665 RegSetValueExW(subKey, NULL, 0, REG_SZ,
666 (const BYTE *)PSOA, sizeof PSOA);
667 RegCloseKey(subKey);
670 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
671 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
673 WCHAR buffer[40];
674 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
675 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
677 StringFromGUID2(&attr->guid, buffer, 40);
678 RegSetValueExW(subKey, NULL, 0, REG_SZ,
679 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
680 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
681 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
682 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
683 RegCloseKey(subKey);
686 RegCloseKey(key);
690 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
693 ITypeInfo_Release(tinfo);
696 SysFreeString(name);
700 ITypeLib_ReleaseTLibAttr(ptlib, attr);
702 return res;
706 /******************************************************************************
707 * UnRegisterTypeLib [OLEAUT32.186]
708 * Removes information about a type library from the System Registry
709 * NOTES
711 * RETURNS
712 * Success: S_OK
713 * Failure: Status
715 HRESULT WINAPI UnRegisterTypeLib(
716 REFGUID libid, /* [in] Guid of the library */
717 WORD wVerMajor, /* [in] major version */
718 WORD wVerMinor, /* [in] minor version */
719 LCID lcid, /* [in] locale id */
720 SYSKIND syskind)
722 BSTR tlibPath = NULL;
723 DWORD tmpLength;
724 WCHAR keyName[60];
725 WCHAR subKeyName[50];
726 int result = S_OK;
727 DWORD i = 0;
728 BOOL deleteOtherStuff;
729 HKEY key = NULL;
730 HKEY subKey = NULL;
731 TYPEATTR* typeAttr = NULL;
732 TYPEKIND kind;
733 ITypeInfo* typeInfo = NULL;
734 ITypeLib* typeLib = NULL;
735 int numTypes;
737 TRACE("(IID: %s)\n",debugstr_guid(libid));
739 /* Create the path to the key */
740 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
742 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
744 TRACE("Unsupported syskind %i\n", syskind);
745 result = E_INVALIDARG;
746 goto end;
749 /* get the path to the typelib on disk */
750 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
751 result = E_INVALIDARG;
752 goto end;
755 /* Try and open the key to the type library. */
756 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
757 result = E_INVALIDARG;
758 goto end;
761 /* Try and load the type library */
762 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
763 result = TYPE_E_INVALIDSTATE;
764 goto end;
767 /* remove any types registered with this typelib */
768 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
769 for (i=0; i<numTypes; i++) {
770 /* get the kind of type */
771 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
772 goto enddeleteloop;
775 /* skip non-interfaces, and get type info for the type */
776 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
777 goto enddeleteloop;
779 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
780 goto enddeleteloop;
782 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
783 goto enddeleteloop;
786 /* the path to the type */
787 get_interface_key( &typeAttr->guid, subKeyName );
789 /* Delete its bits */
790 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS) {
791 goto enddeleteloop;
793 RegDeleteKeyW(subKey, ProxyStubClsidW);
794 RegDeleteKeyW(subKey, ProxyStubClsid32W);
795 RegDeleteKeyW(subKey, TypeLibW);
796 RegCloseKey(subKey);
797 subKey = NULL;
798 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
800 enddeleteloop:
801 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
802 typeAttr = NULL;
803 if (typeInfo) ITypeInfo_Release(typeInfo);
804 typeInfo = NULL;
807 /* Now, delete the type library path subkey */
808 get_lcid_subkey( lcid, syskind, subKeyName );
809 RegDeleteKeyW(key, subKeyName);
810 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
811 RegDeleteKeyW(key, subKeyName);
813 /* check if there is anything besides the FLAGS/HELPDIR keys.
814 If there is, we don't delete them */
815 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
816 deleteOtherStuff = TRUE;
817 i = 0;
818 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
819 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
821 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
822 if (!strcmpW(subKeyName, FLAGSW)) continue;
823 if (!strcmpW(subKeyName, HELPDIRW)) continue;
824 deleteOtherStuff = FALSE;
825 break;
828 /* only delete the other parts of the key if we're absolutely sure */
829 if (deleteOtherStuff) {
830 RegDeleteKeyW(key, FLAGSW);
831 RegDeleteKeyW(key, HELPDIRW);
832 RegCloseKey(key);
833 key = NULL;
835 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
836 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
837 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
840 end:
841 if (tlibPath) SysFreeString(tlibPath);
842 if (typeLib) ITypeLib_Release(typeLib);
843 if (subKey) RegCloseKey(subKey);
844 if (key) RegCloseKey(key);
845 return result;
848 /*======================= ITypeLib implementation =======================*/
850 typedef struct tagTLBCustData
852 GUID guid;
853 VARIANT data;
854 struct tagTLBCustData* next;
855 } TLBCustData;
857 /* data structure for import typelibs */
858 typedef struct tagTLBImpLib
860 int offset; /* offset in the file (MSFT)
861 offset in nametable (SLTG)
862 just used to identify library while reading
863 data from file */
864 GUID guid; /* libid */
865 BSTR name; /* name */
867 LCID lcid; /* lcid of imported typelib */
869 WORD wVersionMajor; /* major version number */
870 WORD wVersionMinor; /* minor version number */
872 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
873 NULL if not yet loaded */
874 struct tagTLBImpLib * next;
875 } TLBImpLib;
877 /* internal ITypeLib data */
878 typedef struct tagITypeLibImpl
880 const ITypeLib2Vtbl *lpVtbl;
881 const ITypeCompVtbl *lpVtblTypeComp;
882 LONG ref;
883 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
885 /* strings can be stored in tlb as multibyte strings BUT they are *always*
886 * exported to the application as a UNICODE string.
888 BSTR Name;
889 BSTR DocString;
890 BSTR HelpFile;
891 BSTR HelpStringDll;
892 unsigned long dwHelpContext;
893 int TypeInfoCount; /* nr of typeinfo's in librarry */
894 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
895 int ctCustData; /* number of items in cust data list */
896 TLBCustData * pCustData; /* linked list to cust data */
897 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
898 int ctTypeDesc; /* number of items in type desc array */
899 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
900 library. Only used while reading MSFT
901 typelibs */
902 struct list ref_list; /* list of ref types in this typelib */
903 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
906 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
907 struct tagITypeLibImpl *next, *prev;
908 WCHAR *path;
909 INT index;
910 } ITypeLibImpl;
912 static const ITypeLib2Vtbl tlbvt;
913 static const ITypeCompVtbl tlbtcvt;
915 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
917 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
920 /* ITypeLib methods */
921 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
922 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
924 /*======================= ITypeInfo implementation =======================*/
926 /* data for referenced types */
927 typedef struct tagTLBRefType
929 INT index; /* Type index for internal ref or for external ref
930 it the format is SLTG. -2 indicates to
931 use guid */
933 GUID guid; /* guid of the referenced type */
934 /* if index == TLB_REF_USE_GUID */
936 HREFTYPE reference; /* The href of this ref */
937 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
938 TLB_REF_INTERNAL for internal refs
939 TLB_REF_NOT_FOUND for broken refs */
941 struct list entry;
942 } TLBRefType;
944 #define TLB_REF_USE_GUID -2
946 #define TLB_REF_INTERNAL (void*)-2
947 #define TLB_REF_NOT_FOUND (void*)-1
949 /* internal Parameter data */
950 typedef struct tagTLBParDesc
952 BSTR Name;
953 int ctCustData;
954 TLBCustData * pCustData; /* linked list to cust data */
955 } TLBParDesc;
957 /* internal Function data */
958 typedef struct tagTLBFuncDesc
960 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
961 BSTR Name; /* the name of this function */
962 TLBParDesc *pParamDesc; /* array with param names and custom data */
963 int helpcontext;
964 int HelpStringContext;
965 BSTR HelpString;
966 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
967 int ctCustData;
968 TLBCustData * pCustData; /* linked list to cust data; */
969 struct tagTLBFuncDesc * next;
970 } TLBFuncDesc;
972 /* internal Variable data */
973 typedef struct tagTLBVarDesc
975 VARDESC vardesc; /* lots of info on the variable and its attributes. */
976 BSTR Name; /* the name of this variable */
977 int HelpContext;
978 int HelpStringContext; /* FIXME: where? */
979 BSTR HelpString;
980 int ctCustData;
981 TLBCustData * pCustData;/* linked list to cust data; */
982 struct tagTLBVarDesc * next;
983 } TLBVarDesc;
985 /* internal implemented interface data */
986 typedef struct tagTLBImplType
988 HREFTYPE hRef; /* hRef of interface */
989 int implflags; /* IMPLFLAG_*s */
990 int ctCustData;
991 TLBCustData * pCustData;/* linked list to custom data; */
992 struct tagTLBImplType *next;
993 } TLBImplType;
995 /* internal TypeInfo data */
996 typedef struct tagITypeInfoImpl
998 const ITypeInfo2Vtbl *lpVtbl;
999 const ITypeCompVtbl *lpVtblTypeComp;
1000 LONG ref;
1001 BOOL no_free_data; /* don't free data structurees */
1002 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1003 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1004 int index; /* index in this typelib; */
1005 HREFTYPE hreftype; /* hreftype for app object binding */
1006 /* type libs seem to store the doc strings in ascii
1007 * so why should we do it in unicode?
1009 BSTR Name;
1010 BSTR DocString;
1011 BSTR DllName;
1012 unsigned long dwHelpContext;
1013 unsigned long dwHelpStringContext;
1015 /* functions */
1016 TLBFuncDesc * funclist; /* linked list with function descriptions */
1018 /* variables */
1019 TLBVarDesc * varlist; /* linked list with variable descriptions */
1021 /* Implemented Interfaces */
1022 TLBImplType * impltypelist;
1024 int ctCustData;
1025 TLBCustData * pCustData; /* linked list to cust data; */
1026 struct tagITypeInfoImpl * next;
1027 } ITypeInfoImpl;
1029 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1031 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1034 static const ITypeInfo2Vtbl tinfvt;
1035 static const ITypeCompVtbl tcompvt;
1037 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
1039 typedef struct tagTLBContext
1041 unsigned int oStart; /* start of TLB in file */
1042 unsigned int pos; /* current pos */
1043 unsigned int length; /* total length */
1044 void *mapping; /* memory mapping */
1045 MSFT_SegDir * pTblDir;
1046 ITypeLibImpl* pLibInfo;
1047 } TLBContext;
1050 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1053 debug
1055 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1056 if (pTD->vt & VT_RESERVED)
1057 szVarType += strlen(strcpy(szVarType, "reserved | "));
1058 if (pTD->vt & VT_BYREF)
1059 szVarType += strlen(strcpy(szVarType, "ref to "));
1060 if (pTD->vt & VT_ARRAY)
1061 szVarType += strlen(strcpy(szVarType, "array of "));
1062 if (pTD->vt & VT_VECTOR)
1063 szVarType += strlen(strcpy(szVarType, "vector of "));
1064 switch(pTD->vt & VT_TYPEMASK) {
1065 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1066 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1067 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1068 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1069 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1070 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1071 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1072 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1073 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1074 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1075 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1076 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1077 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1078 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1079 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1080 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1081 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1082 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1083 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1084 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1085 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1086 pTD->u.hreftype); break;
1087 case VT_PTR: sprintf(szVarType, "ptr to ");
1088 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1089 break;
1090 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1091 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1092 break;
1093 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1094 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1095 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1096 break;
1098 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1102 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1103 char buf[200];
1104 USHORT flags = edesc->u.paramdesc.wParamFlags;
1105 dump_TypeDesc(&edesc->tdesc,buf);
1106 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1107 MESSAGE("\t\tu.paramdesc.wParamFlags");
1108 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1109 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1110 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1111 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1112 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1113 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1114 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1115 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1116 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1118 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1119 int i;
1120 MESSAGE("memid is %08x\n",funcdesc->memid);
1121 for (i=0;i<funcdesc->cParams;i++) {
1122 MESSAGE("Param %d:\n",i);
1123 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1125 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1126 switch (funcdesc->funckind) {
1127 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1128 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1129 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1130 case FUNC_STATIC: MESSAGE("static");break;
1131 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1132 default: MESSAGE("unknown");break;
1134 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1135 switch (funcdesc->invkind) {
1136 case INVOKE_FUNC: MESSAGE("func");break;
1137 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1138 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1139 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1141 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1142 switch (funcdesc->callconv) {
1143 case CC_CDECL: MESSAGE("cdecl");break;
1144 case CC_PASCAL: MESSAGE("pascal");break;
1145 case CC_STDCALL: MESSAGE("stdcall");break;
1146 case CC_SYSCALL: MESSAGE("syscall");break;
1147 default:break;
1149 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1150 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1151 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1153 MESSAGE("\telemdescFunc (return value type):\n");
1154 dump_ELEMDESC(&funcdesc->elemdescFunc);
1157 static const char * const typekind_desc[] =
1159 "TKIND_ENUM",
1160 "TKIND_RECORD",
1161 "TKIND_MODULE",
1162 "TKIND_INTERFACE",
1163 "TKIND_DISPATCH",
1164 "TKIND_COCLASS",
1165 "TKIND_ALIAS",
1166 "TKIND_UNION",
1167 "TKIND_MAX"
1170 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1172 int i;
1173 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1174 for (i=0;i<pfd->funcdesc.cParams;i++)
1175 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1178 dump_FUNCDESC(&(pfd->funcdesc));
1180 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1181 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1183 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1185 while (pfd)
1187 dump_TLBFuncDescOne(pfd);
1188 pfd = pfd->next;
1191 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1193 while (pvd)
1195 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1196 pvd = pvd->next;
1200 static void dump_TLBImpLib(const TLBImpLib *import)
1202 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1203 debugstr_w(import->name));
1204 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1205 import->wVersionMinor, import->lcid, import->offset);
1208 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1210 TLBRefType *ref;
1212 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1214 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1215 if(ref->index == -1)
1216 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1217 else
1218 TRACE_(typelib)("type no: %d\n", ref->index);
1220 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1222 TRACE_(typelib)("in lib\n");
1223 dump_TLBImpLib(ref->pImpTLInfo);
1228 static void dump_TLBImplType(const TLBImplType * impl)
1230 while (impl) {
1231 TRACE_(typelib)(
1232 "implementing/inheriting interface hRef = %x implflags %x\n",
1233 impl->hRef, impl->implflags);
1234 impl = impl->next;
1238 static void dump_Variant(const VARIANT * pvar)
1240 SYSTEMTIME st;
1242 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1244 if (pvar)
1246 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1247 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1249 TRACE(",%p", V_BYREF(pvar));
1251 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1253 TRACE(",%p", V_ARRAY(pvar));
1255 else switch (V_TYPE(pvar))
1257 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1258 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1259 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1260 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1261 case VT_INT:
1262 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1263 case VT_UINT:
1264 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1265 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1266 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1267 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1268 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1269 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1270 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1271 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1272 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1273 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1274 V_CY(pvar).s.Lo); break;
1275 case VT_DATE:
1276 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1277 TRACE(",<invalid>");
1278 else
1279 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1280 st.wHour, st.wMinute, st.wSecond);
1281 break;
1282 case VT_ERROR:
1283 case VT_VOID:
1284 case VT_USERDEFINED:
1285 case VT_EMPTY:
1286 case VT_NULL: break;
1287 default: TRACE(",?"); break;
1290 TRACE("}\n");
1293 static void dump_DispParms(const DISPPARAMS * pdp)
1295 int index;
1297 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1299 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1301 TRACE("named args:\n");
1302 for (index = 0; index < pdp->cNamedArgs; index++)
1303 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1306 if (pdp->cArgs && pdp->rgvarg)
1308 TRACE("args:\n");
1309 for (index = 0; index < pdp->cArgs; index++)
1310 dump_Variant( &pdp->rgvarg[index] );
1314 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1316 TRACE("%p ref=%u\n", pty, pty->ref);
1317 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1318 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1319 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1320 TRACE("fct:%u var:%u impl:%u\n",
1321 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1322 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1323 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1324 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1325 if (TRACE_ON(ole))
1326 dump_TLBFuncDesc(pty->funclist);
1327 dump_TLBVarDesc(pty->varlist);
1328 dump_TLBImplType(pty->impltypelist);
1331 static void dump_VARDESC(const VARDESC *v)
1333 MESSAGE("memid %d\n",v->memid);
1334 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1335 MESSAGE("oInst %d\n",v->u.oInst);
1336 dump_ELEMDESC(&(v->elemdescVar));
1337 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1338 MESSAGE("varkind %d\n",v->varkind);
1341 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1343 /* VT_LPWSTR is largest type that */
1344 /* may appear in type description*/
1345 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1346 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1347 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1348 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1349 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1350 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1351 {{0},30},{{0},31}
1354 static void TLB_abort(void)
1356 DebugBreak();
1358 static void * TLB_Alloc(unsigned size)
1360 void * ret;
1361 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1362 /* FIXME */
1363 ERR("cannot allocate memory\n");
1365 return ret;
1368 static void TLB_Free(void * ptr)
1370 HeapFree(GetProcessHeap(), 0, ptr);
1373 /* returns the size required for a deep copy of a typedesc into a
1374 * flat buffer */
1375 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1377 SIZE_T size = 0;
1379 if (alloc_initial_space)
1380 size += sizeof(TYPEDESC);
1382 switch (tdesc->vt)
1384 case VT_PTR:
1385 case VT_SAFEARRAY:
1386 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1387 break;
1388 case VT_CARRAY:
1389 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1390 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1391 break;
1393 return size;
1396 /* deep copy a typedesc into a flat buffer */
1397 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1399 if (!dest)
1401 dest = buffer;
1402 buffer = (char *)buffer + sizeof(TYPEDESC);
1405 *dest = *src;
1407 switch (src->vt)
1409 case VT_PTR:
1410 case VT_SAFEARRAY:
1411 dest->u.lptdesc = buffer;
1412 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1413 break;
1414 case VT_CARRAY:
1415 dest->u.lpadesc = buffer;
1416 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1417 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1418 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1419 break;
1421 return buffer;
1424 /**********************************************************************
1426 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1428 static inline unsigned int MSFT_Tell(TLBContext *pcx)
1430 return pcx->pos;
1433 static inline void MSFT_Seek(TLBContext *pcx, long where)
1435 if (where != DO_NOT_SEEK)
1437 where += pcx->oStart;
1438 if (where > pcx->length)
1440 /* FIXME */
1441 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1442 TLB_abort();
1444 pcx->pos = where;
1448 /* read function */
1449 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1451 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1452 pcx->pos, count, pcx->oStart, pcx->length, where);
1454 MSFT_Seek(pcx, where);
1455 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1456 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1457 pcx->pos += count;
1458 return count;
1461 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1462 long where )
1464 DWORD ret;
1466 ret = MSFT_Read(buffer, count, pcx, where);
1467 FromLEDWords(buffer, ret);
1469 return ret;
1472 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1473 long where )
1475 DWORD ret;
1477 ret = MSFT_Read(buffer, count, pcx, where);
1478 FromLEWords(buffer, ret);
1480 return ret;
1483 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1485 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1486 memset(pGuid,0, sizeof(GUID));
1487 return;
1489 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1490 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1491 pGuid->Data2 = FromLEWord(pGuid->Data2);
1492 pGuid->Data3 = FromLEWord(pGuid->Data3);
1493 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1496 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1498 MSFT_NameIntro niName;
1500 if (offset < 0)
1502 ERR_(typelib)("bad offset %d\n", offset);
1503 return -1;
1506 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1507 pcx->pTblDir->pNametab.offset+offset);
1509 return niName.hreftype;
1512 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1514 char * name;
1515 MSFT_NameIntro niName;
1516 int lengthInChars;
1517 BSTR bstrName = NULL;
1519 if (offset < 0)
1521 ERR_(typelib)("bad offset %d\n", offset);
1522 return NULL;
1524 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1525 pcx->pTblDir->pNametab.offset+offset);
1526 niName.namelen &= 0xFF; /* FIXME: correct ? */
1527 name=TLB_Alloc((niName.namelen & 0xff) +1);
1528 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1529 name[niName.namelen & 0xff]='\0';
1531 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1532 name, -1, NULL, 0);
1534 /* no invalid characters in string */
1535 if (lengthInChars)
1537 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1539 /* don't check for invalid character since this has been done previously */
1540 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1542 TLB_Free(name);
1544 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1545 return bstrName;
1548 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1550 char * string;
1551 INT16 length;
1552 int lengthInChars;
1553 BSTR bstr = NULL;
1555 if(offset<0) return NULL;
1556 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1557 if(length <= 0) return 0;
1558 string=TLB_Alloc(length +1);
1559 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1560 string[length]='\0';
1562 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1563 string, -1, NULL, 0);
1565 /* no invalid characters in string */
1566 if (lengthInChars)
1568 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1570 /* don't check for invalid character since this has been done previously */
1571 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1573 TLB_Free(string);
1575 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1576 return bstr;
1579 * read a value and fill a VARIANT structure
1581 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1583 int size;
1585 TRACE_(typelib)("\n");
1587 if(offset <0) { /* data are packed in here */
1588 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1589 V_I4(pVar) = offset & 0x3ffffff;
1590 return;
1592 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1593 pcx->pTblDir->pCustData.offset + offset );
1594 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1595 switch (V_VT(pVar)){
1596 case VT_EMPTY: /* FIXME: is this right? */
1597 case VT_NULL: /* FIXME: is this right? */
1598 case VT_I2 : /* this should not happen */
1599 case VT_I4 :
1600 case VT_R4 :
1601 case VT_ERROR :
1602 case VT_BOOL :
1603 case VT_I1 :
1604 case VT_UI1 :
1605 case VT_UI2 :
1606 case VT_UI4 :
1607 case VT_INT :
1608 case VT_UINT :
1609 case VT_VOID : /* FIXME: is this right? */
1610 case VT_HRESULT :
1611 size=4; break;
1612 case VT_R8 :
1613 case VT_CY :
1614 case VT_DATE :
1615 case VT_I8 :
1616 case VT_UI8 :
1617 case VT_DECIMAL : /* FIXME: is this right? */
1618 case VT_FILETIME :
1619 size=8;break;
1620 /* pointer types with known behaviour */
1621 case VT_BSTR :{
1622 char * ptr;
1623 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1624 if(size < 0) {
1625 char next;
1626 DWORD origPos = MSFT_Tell(pcx), nullPos;
1628 do {
1629 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1630 } while (next);
1631 nullPos = MSFT_Tell(pcx);
1632 size = nullPos - origPos;
1633 MSFT_Seek(pcx, origPos);
1635 ptr=TLB_Alloc(size);/* allocate temp buffer */
1636 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1637 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1638 /* FIXME: do we need a AtoW conversion here? */
1639 V_UNION(pVar, bstrVal[size])='\0';
1640 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1641 TLB_Free(ptr);
1643 size=-4; break;
1644 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1645 case VT_DISPATCH :
1646 case VT_VARIANT :
1647 case VT_UNKNOWN :
1648 case VT_PTR :
1649 case VT_SAFEARRAY :
1650 case VT_CARRAY :
1651 case VT_USERDEFINED :
1652 case VT_LPSTR :
1653 case VT_LPWSTR :
1654 case VT_BLOB :
1655 case VT_STREAM :
1656 case VT_STORAGE :
1657 case VT_STREAMED_OBJECT :
1658 case VT_STORED_OBJECT :
1659 case VT_BLOB_OBJECT :
1660 case VT_CF :
1661 case VT_CLSID :
1662 default:
1663 size=0;
1664 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1665 V_VT(pVar));
1668 if(size>0) /* (big|small) endian correct? */
1669 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1670 return;
1673 * create a linked list with custom data
1675 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1677 MSFT_CDGuid entry;
1678 TLBCustData* pNew;
1679 int count=0;
1681 TRACE_(typelib)("\n");
1683 while(offset >=0){
1684 count++;
1685 pNew=TLB_Alloc(sizeof(TLBCustData));
1686 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1687 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1688 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1689 /* add new custom data at head of the list */
1690 pNew->next=*ppCustData;
1691 *ppCustData=pNew;
1692 offset = entry.next;
1694 return count;
1697 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1698 ITypeInfoImpl *pTI)
1700 if(type <0)
1701 pTd->vt=type & VT_TYPEMASK;
1702 else
1703 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1705 if(pTd->vt == VT_USERDEFINED)
1706 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1708 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1711 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1713 /* resolve referenced type if any */
1714 while (lpTypeDesc)
1716 switch (lpTypeDesc->vt)
1718 case VT_PTR:
1719 lpTypeDesc = lpTypeDesc->u.lptdesc;
1720 break;
1722 case VT_CARRAY:
1723 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1724 break;
1726 case VT_USERDEFINED:
1727 MSFT_DoRefType(pcx, pTI->pTypeLib,
1728 lpTypeDesc->u.hreftype);
1730 lpTypeDesc = NULL;
1731 break;
1733 default:
1734 lpTypeDesc = NULL;
1739 static void
1740 MSFT_DoFuncs(TLBContext* pcx,
1741 ITypeInfoImpl* pTI,
1742 int cFuncs,
1743 int cVars,
1744 int offset,
1745 TLBFuncDesc** pptfd)
1748 * member information is stored in a data structure at offset
1749 * indicated by the memoffset field of the typeinfo structure
1750 * There are several distinctive parts.
1751 * The first part starts with a field that holds the total length
1752 * of this (first) part excluding this field. Then follow the records,
1753 * for each member there is one record.
1755 * The first entry is always the length of the record (including this
1756 * length word).
1757 * The rest of the record depends on the type of the member. If there is
1758 * a field indicating the member type (function, variable, interface, etc)
1759 * I have not found it yet. At this time we depend on the information
1760 * in the type info and the usual order how things are stored.
1762 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1763 * for each member;
1765 * Third is an equal sized array with file offsets to the name entry
1766 * of each member.
1768 * The fourth and last (?) part is an array with offsets to the records
1769 * in the first part of this file segment.
1772 int infolen, nameoffset, reclength, nrattributes, i;
1773 int recoffset = offset + sizeof(INT);
1775 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1776 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1777 TLBFuncDesc *ptfd_prev = NULL;
1779 TRACE_(typelib)("\n");
1781 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1783 for ( i = 0; i < cFuncs ; i++ )
1785 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1787 /* name, eventually add to a hash table */
1788 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1789 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1791 /* nameoffset is sometimes -1 on the second half of a propget/propput
1792 * pair of functions */
1793 if ((nameoffset == -1) && (i > 0))
1794 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1795 else
1796 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1798 /* read the function information record */
1799 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1801 reclength &= 0xffff;
1803 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1805 /* do the attributes */
1806 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1807 / sizeof(int);
1809 if ( nrattributes > 0 )
1811 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1813 if ( nrattributes > 1 )
1815 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1816 pFuncRec->OptAttr[1]) ;
1818 if ( nrattributes > 2 )
1820 if ( pFuncRec->FKCCIC & 0x2000 )
1822 if (HIWORD(pFuncRec->OptAttr[2]) != 0)
1823 ERR("ordinal 0x%08x invalid, HIWORD != 0\n", pFuncRec->OptAttr[2]);
1824 (*pptfd)->Entry = (BSTR)pFuncRec->OptAttr[2];
1826 else
1828 (*pptfd)->Entry = MSFT_ReadString(pcx,
1829 pFuncRec->OptAttr[2]);
1831 if( nrattributes > 5 )
1833 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1835 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1837 MSFT_CustData(pcx,
1838 pFuncRec->OptAttr[6],
1839 &(*pptfd)->pCustData);
1843 else
1845 (*pptfd)->Entry = (BSTR)-1;
1850 /* fill the FuncDesc Structure */
1851 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1852 offset + infolen + ( i + 1) * sizeof(INT));
1854 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1855 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1856 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1857 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1858 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1859 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1860 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1862 MSFT_GetTdesc(pcx,
1863 pFuncRec->DataType,
1864 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1865 pTI);
1866 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1868 /* do the parameters/arguments */
1869 if(pFuncRec->nrargs)
1871 int j = 0;
1872 MSFT_ParameterInfo paraminfo;
1874 (*pptfd)->funcdesc.lprgelemdescParam =
1875 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1877 (*pptfd)->pParamDesc =
1878 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1880 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1881 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1883 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1885 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1887 MSFT_GetTdesc(pcx,
1888 paraminfo.DataType,
1889 &elemdesc->tdesc,
1890 pTI);
1892 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1894 /* name */
1895 if (paraminfo.oName == -1)
1896 /* this occurs for [propput] or [propget] methods, so
1897 * we should just set the name of the parameter to the
1898 * name of the method. */
1899 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1900 else
1901 (*pptfd)->pParamDesc[j].Name =
1902 MSFT_ReadName( pcx, paraminfo.oName );
1903 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1905 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1907 /* default value */
1908 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1909 (pFuncRec->FKCCIC & 0x1000) )
1911 INT* pInt = (INT *)((char *)pFuncRec +
1912 reclength -
1913 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1915 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1917 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1918 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1920 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1921 pInt[j], pcx);
1923 else
1924 elemdesc->u.paramdesc.pparamdescex = NULL;
1925 /* custom info */
1926 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1928 MSFT_CustData(pcx,
1929 pFuncRec->OptAttr[7+j],
1930 &(*pptfd)->pParamDesc[j].pCustData);
1933 /* SEEK value = jump to offset,
1934 * from there jump to the end of record,
1935 * go back by (j-1) arguments
1937 MSFT_ReadLEDWords( &paraminfo ,
1938 sizeof(MSFT_ParameterInfo), pcx,
1939 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1940 * sizeof(MSFT_ParameterInfo)));
1944 /* scode is not used: archaic win16 stuff FIXME: right? */
1945 (*pptfd)->funcdesc.cScodes = 0 ;
1946 (*pptfd)->funcdesc.lprgscode = NULL ;
1948 ptfd_prev = *pptfd;
1949 pptfd = & ((*pptfd)->next);
1950 recoffset += reclength;
1952 HeapFree(GetProcessHeap(), 0, recbuf);
1955 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1956 int cVars, int offset, TLBVarDesc ** pptvd)
1958 int infolen, nameoffset, reclength;
1959 char recbuf[256];
1960 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1961 int i;
1962 int recoffset;
1964 TRACE_(typelib)("\n");
1966 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1967 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1968 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1969 recoffset += offset+sizeof(INT);
1970 for(i=0;i<cVars;i++){
1971 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1972 /* name, eventually add to a hash table */
1973 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1974 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
1975 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1976 /* read the variable information record */
1977 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1978 reclength &=0xff;
1979 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1980 /* Optional data */
1981 if(reclength >(6*sizeof(INT)) )
1982 (*pptvd)->HelpContext=pVarRec->HelpContext;
1983 if(reclength >(7*sizeof(INT)) )
1984 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1985 if(reclength >(8*sizeof(INT)) )
1986 if(reclength >(9*sizeof(INT)) )
1987 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1988 /* fill the VarDesc Structure */
1989 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1990 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
1991 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1992 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1993 MSFT_GetTdesc(pcx, pVarRec->DataType,
1994 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1995 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1996 if(pVarRec->VarKind == VAR_CONST ){
1997 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1998 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1999 pVarRec->OffsValue, pcx);
2000 } else
2001 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
2002 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
2003 pptvd=&((*pptvd)->next);
2004 recoffset += reclength;
2007 /* fill in data for a hreftype (offset). When the referenced type is contained
2008 * in the typelib, it's just an (file) offset in the type info base dir.
2009 * If comes from import, it's an offset+1 in the ImpInfo table
2010 * */
2011 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2012 int offset)
2014 int j;
2015 TLBRefType *ref;
2017 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2019 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2021 if(ref->reference == offset) return;
2024 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
2025 list_add_tail(&pTL->ref_list, &ref->entry);
2027 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2028 /* external typelib */
2029 MSFT_ImpInfo impinfo;
2030 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2032 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2034 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2035 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2036 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
2037 if(pImpLib->offset==impinfo.oImpFile) break;
2038 pImpLib=pImpLib->next;
2040 if(pImpLib){
2041 ref->reference = offset;
2042 ref->pImpTLInfo = pImpLib;
2043 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2044 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2045 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2046 ref->index = TLB_REF_USE_GUID;
2047 } else
2048 ref->index = impinfo.oGuid;
2049 }else{
2050 ERR("Cannot find a reference\n");
2051 ref->reference = -1;
2052 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2054 }else{
2055 /* in this typelib */
2056 ref->index = MSFT_HREFTYPE_INDEX(offset);
2057 ref->reference = offset;
2058 ref->pImpTLInfo = TLB_REF_INTERNAL;
2062 /* process Implemented Interfaces of a com class */
2063 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2064 int offset)
2066 int i;
2067 MSFT_RefRecord refrec;
2068 TLBImplType **ppImpl = &pTI->impltypelist;
2070 TRACE_(typelib)("\n");
2072 for(i=0;i<count;i++){
2073 if(offset<0) break; /* paranoia */
2074 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2075 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2076 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2077 (*ppImpl)->hRef = refrec.reftype;
2078 (*ppImpl)->implflags=refrec.flags;
2079 (*ppImpl)->ctCustData=
2080 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2081 offset=refrec.onext;
2082 ppImpl=&((*ppImpl)->next);
2086 * process a typeinfo record
2088 static ITypeInfoImpl * MSFT_DoTypeInfo(
2089 TLBContext *pcx,
2090 int count,
2091 ITypeLibImpl * pLibInfo)
2093 MSFT_TypeInfoBase tiBase;
2094 ITypeInfoImpl *ptiRet;
2096 TRACE_(typelib)("count=%u\n", count);
2098 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2099 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2100 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2102 /* this is where we are coming from */
2103 ptiRet->pTypeLib = pLibInfo;
2104 ptiRet->index=count;
2105 /* fill in the typeattr fields */
2107 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2108 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2109 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2110 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2111 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2112 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2113 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2114 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2115 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2116 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2117 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2118 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2119 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2120 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2121 MSFT_GetTdesc(pcx, tiBase.datatype1,
2122 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2124 /* FIXME: */
2125 /* IDLDESC idldescType; *//* never saw this one != zero */
2127 /* name, eventually add to a hash table */
2128 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2129 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2130 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2131 /* help info */
2132 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2133 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2134 ptiRet->dwHelpContext=tiBase.helpcontext;
2136 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2137 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2139 /* note: InfoType's Help file and HelpStringDll come from the containing
2140 * library. Further HelpString and Docstring appear to be the same thing :(
2142 /* functions */
2143 if(ptiRet->TypeAttr.cFuncs >0 )
2144 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2145 ptiRet->TypeAttr.cVars,
2146 tiBase.memoffset, & ptiRet->funclist);
2147 /* variables */
2148 if(ptiRet->TypeAttr.cVars >0 )
2149 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2150 ptiRet->TypeAttr.cVars,
2151 tiBase.memoffset, & ptiRet->varlist);
2152 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2153 switch(ptiRet->TypeAttr.typekind)
2155 case TKIND_COCLASS:
2156 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2157 tiBase.datatype1);
2158 break;
2159 case TKIND_DISPATCH:
2160 /* This is not -1 when the interface is a non-base dual interface or
2161 when a dispinterface wraps an interface ie the idl 'dispinterface x {interface y;};'.
2162 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2163 not this interface.
2166 if (tiBase.datatype1 != -1)
2168 ptiRet->impltypelist = TLB_Alloc(sizeof(TLBImplType));
2169 ptiRet->impltypelist->hRef = tiBase.datatype1;
2170 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2172 break;
2173 default:
2174 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2175 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2176 ptiRet->impltypelist->hRef = tiBase.datatype1;
2177 break;
2180 ptiRet->ctCustData=
2181 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2183 TRACE_(typelib)("%s guid: %s kind:%s\n",
2184 debugstr_w(ptiRet->Name),
2185 debugstr_guid(&ptiRet->TypeAttr.guid),
2186 typekind_desc[ptiRet->TypeAttr.typekind]);
2188 return ptiRet;
2191 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2192 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2193 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2194 * tradeoff here.
2196 static ITypeLibImpl *tlb_cache_first;
2197 static CRITICAL_SECTION cache_section;
2198 static CRITICAL_SECTION_DEBUG cache_section_debug =
2200 0, 0, &cache_section,
2201 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2202 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2204 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2207 /****************************************************************************
2208 * TLB_ReadTypeLib
2210 * find the type of the typelib file and map the typelib resource into
2211 * the memory
2213 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2214 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2215 static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2217 ITypeLibImpl *entry;
2218 int ret = TYPE_E_CANTLOADLIBRARY;
2219 INT index = 1;
2220 HINSTANCE hinstDLL;
2221 LPWSTR index_str, file = (LPWSTR)pszFileName;
2223 *ppTypeLib = NULL;
2225 index_str = strrchrW(pszFileName, '\\');
2226 if(index_str && *++index_str != '\0')
2228 LPWSTR end_ptr;
2229 long idx = strtolW(index_str, &end_ptr, 10);
2230 if(*end_ptr == '\0')
2232 int str_len = index_str - pszFileName - 1;
2233 index = idx;
2234 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
2235 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2236 file[str_len] = 0;
2240 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2242 if(strchrW(file, '\\'))
2244 lstrcpyW(pszPath, file);
2246 else
2248 int len = GetSystemDirectoryW(pszPath, cchPath);
2249 pszPath[len] = '\\';
2250 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2254 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file);
2256 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2258 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2259 EnterCriticalSection(&cache_section);
2260 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2262 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2264 TRACE("cache hit\n");
2265 *ppTypeLib = (ITypeLib2*)entry;
2266 ITypeLib_AddRef(*ppTypeLib);
2267 LeaveCriticalSection(&cache_section);
2268 return S_OK;
2271 LeaveCriticalSection(&cache_section);
2273 /* now actually load and parse the typelib */
2275 hinstDLL = LoadLibraryExW(pszPath, 0, DONT_RESOLVE_DLL_REFERENCES |
2276 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2278 if (hinstDLL)
2280 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2281 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2282 if (hrsrc)
2284 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2285 if (hGlobal)
2287 LPVOID pBase = LockResource(hGlobal);
2288 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2290 if (pBase)
2292 /* try to load as incore resource */
2293 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2294 if (dwSignature == MSFT_SIGNATURE)
2295 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2296 else if (dwSignature == SLTG_SIGNATURE)
2297 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2298 else
2299 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2301 FreeResource( hGlobal );
2304 FreeLibrary(hinstDLL);
2306 else
2308 HANDLE hFile = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2309 if (INVALID_HANDLE_VALUE != hFile)
2311 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2312 if (hMapping)
2314 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2315 if(pBase)
2317 /* retrieve file size */
2318 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2319 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2321 if (dwSignature == MSFT_SIGNATURE)
2322 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2323 else if (dwSignature == SLTG_SIGNATURE)
2324 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2326 UnmapViewOfFile(pBase);
2328 CloseHandle(hMapping);
2330 CloseHandle(hFile);
2334 if(*ppTypeLib) {
2335 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2337 TRACE("adding to cache\n");
2338 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2339 lstrcpyW(impl->path, pszPath);
2340 /* We should really canonicalise the path here. */
2341 impl->index = index;
2343 /* FIXME: check if it has added already in the meantime */
2344 EnterCriticalSection(&cache_section);
2345 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2346 impl->prev = NULL;
2347 tlb_cache_first = impl;
2348 LeaveCriticalSection(&cache_section);
2349 ret = S_OK;
2350 } else
2351 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2353 return ret;
2356 /*================== ITypeLib(2) Methods ===================================*/
2358 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2360 ITypeLibImpl* pTypeLibImpl;
2362 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2363 if (!pTypeLibImpl) return NULL;
2365 pTypeLibImpl->lpVtbl = &tlbvt;
2366 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2367 pTypeLibImpl->ref = 1;
2369 list_init(&pTypeLibImpl->ref_list);
2370 pTypeLibImpl->dispatch_href = -1;
2372 return pTypeLibImpl;
2375 /****************************************************************************
2376 * ITypeLib2_Constructor_MSFT
2378 * loading an MSFT typelib from an in-memory image
2380 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2382 TLBContext cx;
2383 long lPSegDir;
2384 MSFT_Header tlbHeader;
2385 MSFT_SegDir tlbSegDir;
2386 ITypeLibImpl * pTypeLibImpl;
2388 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2390 pTypeLibImpl = TypeLibImpl_Constructor();
2391 if (!pTypeLibImpl) return NULL;
2393 /* get pointer to beginning of typelib data */
2394 cx.pos = 0;
2395 cx.oStart=0;
2396 cx.mapping = pLib;
2397 cx.pLibInfo = pTypeLibImpl;
2398 cx.length = dwTLBLength;
2400 /* read header */
2401 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2402 TRACE_(typelib)("header:\n");
2403 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2404 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2405 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2406 return NULL;
2408 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2410 /* there is a small amount of information here until the next important
2411 * part:
2412 * the segment directory . Try to calculate the amount of data */
2413 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2415 /* now read the segment directory */
2416 TRACE("read segment directory (at %ld)\n",lPSegDir);
2417 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2418 cx.pTblDir = &tlbSegDir;
2420 /* just check two entries */
2421 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2423 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2424 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2425 return NULL;
2428 /* now fill our internal data */
2429 /* TLIBATTR fields */
2430 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2432 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2433 /* Windows seems to have zero here, is this correct? */
2434 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2435 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2436 else
2437 pTypeLibImpl->LibAttr.lcid = 0;
2439 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2440 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2441 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2442 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2444 /* name, eventually add to a hash table */
2445 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2447 /* help info */
2448 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2449 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2451 if( tlbHeader.varflags & HELPDLLFLAG)
2453 int offset;
2454 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2455 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2458 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2460 /* custom data */
2461 if(tlbHeader.CustomDataOffset >= 0)
2463 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2466 /* fill in typedescriptions */
2467 if(tlbSegDir.pTypdescTab.length > 0)
2469 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2470 INT16 td[4];
2471 pTypeLibImpl->ctTypeDesc = cTD;
2472 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2473 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2474 for(i=0; i<cTD; )
2476 /* FIXME: add several sanity checks here */
2477 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2478 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2480 /* FIXME: check safearray */
2481 if(td[3] < 0)
2482 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2483 else
2484 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2486 else if(td[0] == VT_CARRAY)
2488 /* array descr table here */
2489 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2491 else if(td[0] == VT_USERDEFINED)
2493 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2495 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2498 /* second time around to fill the array subscript info */
2499 for(i=0;i<cTD;i++)
2501 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2502 if(tlbSegDir.pArrayDescriptions.offset>0)
2504 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2505 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2507 if(td[1]<0)
2508 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2509 else
2510 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2512 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2514 for(j = 0; j<td[2]; j++)
2516 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2517 sizeof(INT), &cx, DO_NOT_SEEK);
2518 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2519 sizeof(INT), &cx, DO_NOT_SEEK);
2522 else
2524 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2525 ERR("didn't find array description data\n");
2530 /* imported type libs */
2531 if(tlbSegDir.pImpFiles.offset>0)
2533 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2534 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2535 UINT16 size;
2537 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2539 char *name;
2540 DWORD len;
2542 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2543 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2544 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2546 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2547 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2548 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2549 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2551 size >>= 2;
2552 name = TLB_Alloc(size+1);
2553 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2554 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2555 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2556 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2557 TLB_Free(name);
2559 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2560 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2562 ppImpLib = &(*ppImpLib)->next;
2566 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
2567 if(pTypeLibImpl->dispatch_href != -1)
2568 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
2570 /* type info's */
2571 if(tlbHeader.nrtypeinfos >= 0 )
2573 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2574 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2575 int i;
2577 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2579 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2581 ppTI = &((*ppTI)->next);
2582 (pTypeLibImpl->TypeInfoCount)++;
2586 TRACE("(%p)\n", pTypeLibImpl);
2587 return (ITypeLib2*) pTypeLibImpl;
2591 static BSTR TLB_MultiByteToBSTR(char *ptr)
2593 DWORD len;
2594 WCHAR *nameW;
2595 BSTR ret;
2597 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2598 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2599 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2600 ret = SysAllocString(nameW);
2601 HeapFree(GetProcessHeap(), 0, nameW);
2602 return ret;
2605 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2607 char b[3];
2608 int i;
2609 short s;
2611 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2612 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2613 return FALSE;
2616 guid->Data4[0] = s >> 8;
2617 guid->Data4[1] = s & 0xff;
2619 b[2] = '\0';
2620 for(i = 0; i < 6; i++) {
2621 memcpy(b, str + 24 + 2 * i, 2);
2622 guid->Data4[i + 2] = strtol(b, NULL, 16);
2624 return TRUE;
2627 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2629 WORD bytelen;
2630 DWORD len;
2631 WCHAR *nameW;
2633 *pBstr = NULL;
2634 bytelen = *(WORD*)ptr;
2635 if(bytelen == 0xffff) return 2;
2636 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2637 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2638 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2639 *pBstr = SysAllocStringLen(nameW, len);
2640 HeapFree(GetProcessHeap(), 0, nameW);
2641 return bytelen + 2;
2644 static WORD SLTG_ReadStringA(char *ptr, char **str)
2646 WORD bytelen;
2648 *str = NULL;
2649 bytelen = *(WORD*)ptr;
2650 if(bytelen == 0xffff) return 2;
2651 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2652 memcpy(*str, ptr + 2, bytelen);
2653 (*str)[bytelen] = '\0';
2654 return bytelen + 2;
2657 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2659 char *ptr = pLibBlk;
2660 WORD w;
2662 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2663 FIXME("libblk magic = %04x\n", w);
2664 return 0;
2667 ptr += 6;
2668 if((w = *(WORD*)ptr) != 0xffff) {
2669 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2670 ptr += w;
2672 ptr += 2;
2674 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2676 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2678 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2679 ptr += 4;
2681 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2682 ptr += 2;
2684 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2685 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2686 else
2687 pTypeLibImpl->LibAttr.lcid = 0;
2688 ptr += 2;
2690 ptr += 4; /* skip res12 */
2692 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2693 ptr += 2;
2695 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2696 ptr += 2;
2698 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2699 ptr += 2;
2701 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2702 ptr += sizeof(GUID);
2704 return ptr - (char*)pLibBlk;
2707 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
2708 typedef struct
2710 unsigned int num;
2711 HREFTYPE refs[1];
2712 } sltg_ref_lookup_t;
2714 static HRESULT sltg_get_typelib_ref(sltg_ref_lookup_t *table, DWORD typeinfo_ref, HREFTYPE *typelib_ref)
2716 if(typeinfo_ref < table->num)
2718 *typelib_ref = table->refs[typeinfo_ref];
2719 return S_OK;
2722 ERR("Unable to find reference\n");
2723 *typelib_ref = -1;
2724 return E_FAIL;
2727 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, sltg_ref_lookup_t *ref_lookup)
2729 BOOL done = FALSE;
2731 while(!done) {
2732 if((*pType & 0xe00) == 0xe00) {
2733 pTD->vt = VT_PTR;
2734 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2735 sizeof(TYPEDESC));
2736 pTD = pTD->u.lptdesc;
2738 switch(*pType & 0x3f) {
2739 case VT_PTR:
2740 pTD->vt = VT_PTR;
2741 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2742 sizeof(TYPEDESC));
2743 pTD = pTD->u.lptdesc;
2744 break;
2746 case VT_USERDEFINED:
2747 pTD->vt = VT_USERDEFINED;
2748 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
2749 done = TRUE;
2750 break;
2752 case VT_CARRAY:
2754 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2755 array */
2757 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2759 pTD->vt = VT_CARRAY;
2760 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2761 sizeof(ARRAYDESC) +
2762 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2763 pTD->u.lpadesc->cDims = pSA->cDims;
2764 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2765 pSA->cDims * sizeof(SAFEARRAYBOUND));
2767 pTD = &pTD->u.lpadesc->tdescElem;
2768 break;
2771 case VT_SAFEARRAY:
2773 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2774 useful? */
2776 pType++;
2777 pTD->vt = VT_SAFEARRAY;
2778 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2779 sizeof(TYPEDESC));
2780 pTD = pTD->u.lptdesc;
2781 break;
2783 default:
2784 pTD->vt = *pType & 0x3f;
2785 done = TRUE;
2786 break;
2788 pType++;
2790 return pType;
2793 static WORD *SLTG_DoElem(WORD *pType, char *pBlk, ELEMDESC *pElem, sltg_ref_lookup_t *ref_lookup)
2795 /* Handle [in/out] first */
2796 if((*pType & 0xc000) == 0xc000)
2797 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2798 else if(*pType & 0x8000)
2799 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2800 else if(*pType & 0x4000)
2801 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2802 else
2803 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2805 if(*pType & 0x2000)
2806 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2808 if(*pType & 0x80)
2809 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2811 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
2815 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
2816 char *pNameTable)
2818 int ref;
2819 char *name;
2820 TLBRefType *ref_type;
2821 sltg_ref_lookup_t *table;
2822 HREFTYPE typelib_ref;
2824 if(pRef->magic != SLTG_REF_MAGIC) {
2825 FIXME("Ref magic = %x\n", pRef->magic);
2826 return NULL;
2828 name = ( (char*)(&pRef->names) + pRef->number);
2830 table = HeapAlloc(GetProcessHeap(), 0, sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
2831 table->num = pRef->number >> 3;
2833 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
2835 /* We don't want the first href to be 0 */
2836 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
2838 for(ref = 0; ref < pRef->number >> 3; ref++) {
2839 char *refname;
2840 unsigned int lib_offs, type_num;
2842 ref_type = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref_type));
2844 name += SLTG_ReadStringA(name, &refname);
2845 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2846 FIXME("Can't sscanf ref\n");
2847 if(lib_offs != 0xffff) {
2848 TLBImpLib **import = &pTL->pImpLibs;
2850 while(*import) {
2851 if((*import)->offset == lib_offs)
2852 break;
2853 import = &(*import)->next;
2855 if(!*import) {
2856 char fname[MAX_PATH+1];
2857 int len;
2859 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2860 sizeof(**import));
2861 (*import)->offset = lib_offs;
2862 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2863 &(*import)->guid);
2864 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
2865 &(*import)->wVersionMajor,
2866 &(*import)->wVersionMinor,
2867 &(*import)->lcid, fname) != 4) {
2868 FIXME("can't sscanf ref %s\n",
2869 pNameTable + lib_offs + 40);
2871 len = strlen(fname);
2872 if(fname[len-1] != '#')
2873 FIXME("fname = %s\n", fname);
2874 fname[len-1] = '\0';
2875 (*import)->name = TLB_MultiByteToBSTR(fname);
2877 ref_type->pImpTLInfo = *import;
2879 /* Store a reference to IDispatch */
2880 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
2881 pTL->dispatch_href = typelib_ref;
2883 } else { /* internal ref */
2884 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
2886 ref_type->reference = typelib_ref;
2887 ref_type->index = type_num;
2889 HeapFree(GetProcessHeap(), 0, refname);
2890 list_add_tail(&pTL->ref_list, &ref_type->entry);
2892 table->refs[ref] = typelib_ref;
2893 typelib_ref += 4;
2895 if((BYTE)*name != SLTG_REF_MAGIC)
2896 FIXME("End of ref block magic = %x\n", *name);
2897 dump_TLBRefType(pTL);
2898 return table;
2901 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2902 BOOL OneOnly, sltg_ref_lookup_t *ref_lookup)
2904 SLTG_ImplInfo *info;
2905 TLBImplType **ppImplType = &pTI->impltypelist;
2906 /* I don't really get this structure, usually it's 0x16 bytes
2907 long, but iuser.tlb contains some that are 0x18 bytes long.
2908 That's ok because we can use the next ptr to jump to the next
2909 one. But how do we know the length of the last one? The WORD
2910 at offs 0x8 might be the clue. For now I'm just assuming that
2911 the last one is the regular 0x16 bytes. */
2913 info = (SLTG_ImplInfo*)pBlk;
2914 while(1) {
2915 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2916 sizeof(**ppImplType));
2917 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef);
2918 (*ppImplType)->implflags = info->impltypeflags;
2919 pTI->TypeAttr.cImplTypes++;
2920 ppImplType = &(*ppImplType)->next;
2922 if(info->next == 0xffff)
2923 break;
2924 if(OneOnly)
2925 FIXME("Interface inheriting more than one interface\n");
2926 info = (SLTG_ImplInfo*)(pBlk + info->next);
2928 info++; /* see comment at top of function */
2929 return (char*)info;
2932 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars, char *pNameTable, sltg_ref_lookup_t *ref_lookup)
2934 TLBVarDesc **ppVarDesc = &pTI->varlist;
2935 BSTR bstrPrevName = NULL;
2936 SLTG_Variable *pItem;
2937 unsigned short i;
2938 WORD *pType;
2939 char buf[300];
2941 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
2942 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
2944 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2945 sizeof(**ppVarDesc));
2946 (*ppVarDesc)->vardesc.memid = pItem->memid;
2948 if (pItem->magic != SLTG_VAR_MAGIC &&
2949 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
2950 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
2951 return;
2954 if (pItem->name == 0xfffe)
2955 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
2956 else
2957 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2959 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
2960 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
2962 if (pItem->flags & 0x40) {
2963 TRACE_(typelib)("VAR_DISPATCH\n");
2964 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
2966 else if (pItem->flags & 0x10) {
2967 TRACE_(typelib)("VAR_CONST\n");
2968 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2969 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2970 sizeof(VARIANT));
2971 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2972 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2973 *(INT*)(pBlk + pItem->byte_offs);
2975 else {
2976 TRACE_(typelib)("VAR_PERINSTANCE\n");
2977 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2978 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2981 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
2982 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
2984 if (pItem->flags & 0x80)
2985 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
2987 if(pItem->flags & 0x02)
2988 pType = &pItem->type;
2989 else
2990 pType = (WORD*)(pBlk + pItem->type);
2992 if (pItem->flags & ~0xd2)
2993 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xd2);
2995 SLTG_DoElem(pType, pBlk,
2996 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup);
2998 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3000 bstrPrevName = (*ppVarDesc)->Name;
3001 ppVarDesc = &((*ppVarDesc)->next);
3003 pTI->TypeAttr.cVars = cVars;
3006 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cFuncs, char *pNameTable, sltg_ref_lookup_t *ref_lookup)
3008 SLTG_Function *pFunc;
3009 unsigned short i;
3010 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3012 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3013 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3015 int param;
3016 WORD *pType, *pArg;
3018 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3019 sizeof(**ppFuncDesc));
3021 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3022 case SLTG_FUNCTION_MAGIC:
3023 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3024 break;
3025 case SLTG_DISPATCH_FUNCTION_MAGIC:
3026 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3027 break;
3028 case SLTG_STATIC_FUNCTION_MAGIC:
3029 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3030 break;
3031 default:
3032 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3033 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
3034 *ppFuncDesc = NULL;
3035 return;
3037 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3039 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3040 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3041 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3042 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3043 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3044 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3046 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3047 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3049 if(pFunc->retnextopt & 0x80)
3050 pType = &pFunc->rettype;
3051 else
3052 pType = (WORD*)(pBlk + pFunc->rettype);
3054 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3056 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3057 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3058 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3059 (*ppFuncDesc)->pParamDesc =
3060 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3061 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3063 pArg = (WORD*)(pBlk + pFunc->arg_off);
3065 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3066 char *paramName = pNameTable + *pArg;
3067 BOOL HaveOffs;
3068 /* If arg type follows then paramName points to the 2nd
3069 letter of the name, else the next WORD is an offset to
3070 the arg type and paramName points to the first letter.
3071 So let's take one char off paramName and see if we're
3072 pointing at an alpha-numeric char. However if *pArg is
3073 0xffff or 0xfffe then the param has no name, the former
3074 meaning that the next WORD is the type, the latter
3075 meaning the the next WORD is an offset to the type. */
3077 HaveOffs = FALSE;
3078 if(*pArg == 0xffff)
3079 paramName = NULL;
3080 else if(*pArg == 0xfffe) {
3081 paramName = NULL;
3082 HaveOffs = TRUE;
3084 else if(paramName[-1] && !isalnum(paramName[-1]))
3085 HaveOffs = TRUE;
3087 pArg++;
3089 if(HaveOffs) { /* the next word is an offset to type */
3090 pType = (WORD*)(pBlk + *pArg);
3091 SLTG_DoElem(pType, pBlk,
3092 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3093 pArg++;
3094 } else {
3095 if(paramName)
3096 paramName--;
3097 pArg = SLTG_DoElem(pArg, pBlk,
3098 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3101 /* Are we an optional param ? */
3102 if((*ppFuncDesc)->funcdesc.cParams - param <=
3103 (*ppFuncDesc)->funcdesc.cParamsOpt)
3104 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3106 if(paramName) {
3107 (*ppFuncDesc)->pParamDesc[param].Name =
3108 TLB_MultiByteToBSTR(paramName);
3112 ppFuncDesc = &((*ppFuncDesc)->next);
3113 if(pFunc->next == 0xffff) break;
3115 pTI->TypeAttr.cFuncs = cFuncs;
3118 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3119 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3120 SLTG_TypeInfoTail *pTITail)
3122 char *pFirstItem, *pNextItem;
3123 sltg_ref_lookup_t *ref_lookup = NULL;
3125 if(pTIHeader->href_table != 0xffffffff) {
3126 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3127 pNameTable);
3130 pFirstItem = pNextItem = pBlk;
3132 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3133 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3135 HeapFree(GetProcessHeap(), 0, ref_lookup);
3139 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3140 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3141 SLTG_TypeInfoTail *pTITail)
3143 char *pFirstItem, *pNextItem;
3144 sltg_ref_lookup_t *ref_lookup = NULL;
3146 if(pTIHeader->href_table != 0xffffffff) {
3147 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3148 pNameTable);
3151 pFirstItem = pNextItem = pBlk;
3153 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3154 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3157 if (pTITail->funcs_off != 0xffff)
3158 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3160 HeapFree(GetProcessHeap(), 0, ref_lookup);
3162 if (TRACE_ON(typelib))
3163 dump_TLBFuncDesc(pTI->funclist);
3166 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3167 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3168 SLTG_TypeInfoTail *pTITail)
3170 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3173 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3174 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3175 SLTG_TypeInfoTail *pTITail)
3177 WORD *pType;
3178 sltg_ref_lookup_t *ref_lookup = NULL;
3180 if (pTITail->simple_alias) {
3181 /* if simple alias, no more processing required */
3182 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3183 return;
3186 if(pTIHeader->href_table != 0xffffffff) {
3187 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3188 pNameTable);
3191 /* otherwise it is an offset to a type */
3192 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3194 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3196 HeapFree(GetProcessHeap(), 0, ref_lookup);
3199 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3200 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3201 SLTG_TypeInfoTail *pTITail)
3203 sltg_ref_lookup_t *ref_lookup = NULL;
3204 if (pTIHeader->href_table != 0xffffffff)
3205 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3206 pNameTable);
3208 if (pTITail->vars_off != 0xffff)
3209 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3211 if (pTITail->funcs_off != 0xffff)
3212 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3214 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3215 * of dispinterface functons including the IDispatch ones, so
3216 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3217 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3219 HeapFree(GetProcessHeap(), 0, ref_lookup);
3220 if (TRACE_ON(typelib))
3221 dump_TLBFuncDesc(pTI->funclist);
3224 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3225 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3226 SLTG_TypeInfoTail *pTITail)
3228 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3231 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3232 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3233 SLTG_TypeInfoTail *pTITail)
3235 sltg_ref_lookup_t *ref_lookup = NULL;
3236 if (pTIHeader->href_table != 0xffffffff)
3237 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3238 pNameTable);
3240 if (pTITail->vars_off != 0xffff)
3241 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3243 if (pTITail->funcs_off != 0xffff)
3244 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3245 HeapFree(GetProcessHeap(), 0, ref_lookup);
3248 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3249 managable copy of it into this */
3250 typedef struct {
3251 WORD small_no;
3252 char *index_name;
3253 char *other_name;
3254 WORD res1a;
3255 WORD name_offs;
3256 WORD more_bytes;
3257 char *extra;
3258 WORD res20;
3259 DWORD helpcontext;
3260 WORD res26;
3261 GUID uuid;
3262 } SLTG_InternalOtherTypeInfo;
3264 /****************************************************************************
3265 * ITypeLib2_Constructor_SLTG
3267 * loading a SLTG typelib from an in-memory image
3269 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3271 ITypeLibImpl *pTypeLibImpl;
3272 SLTG_Header *pHeader;
3273 SLTG_BlkEntry *pBlkEntry;
3274 SLTG_Magic *pMagic;
3275 SLTG_Index *pIndex;
3276 SLTG_Pad9 *pPad9;
3277 LPVOID pBlk, pFirstBlk;
3278 SLTG_LibBlk *pLibBlk;
3279 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3280 char *pAfterOTIBlks = NULL;
3281 char *pNameTable, *ptr;
3282 int i;
3283 DWORD len, order;
3284 ITypeInfoImpl **ppTypeInfoImpl;
3286 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3289 pTypeLibImpl = TypeLibImpl_Constructor();
3290 if (!pTypeLibImpl) return NULL;
3292 pHeader = pLib;
3294 TRACE_(typelib)("header:\n");
3295 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3296 pHeader->nrOfFileBlks );
3297 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3298 FIXME("Header type magic 0x%08x not supported.\n",
3299 pHeader->SLTG_magic);
3300 return NULL;
3303 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3304 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3306 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3307 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3309 /* Next we have a magic block */
3310 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3312 /* Let's see if we're still in sync */
3313 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3314 sizeof(SLTG_COMPOBJ_MAGIC))) {
3315 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3316 return NULL;
3318 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3319 sizeof(SLTG_DIR_MAGIC))) {
3320 FIXME("dir magic = %s\n", pMagic->dir_magic);
3321 return NULL;
3324 pIndex = (SLTG_Index*)(pMagic+1);
3326 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3328 pFirstBlk = (LPVOID)(pPad9 + 1);
3330 /* We'll set up a ptr to the main library block, which is the last one. */
3332 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3333 pBlkEntry[order].next != 0;
3334 order = pBlkEntry[order].next - 1, i++) {
3335 pBlk = (char*)pBlk + pBlkEntry[order].len;
3337 pLibBlk = pBlk;
3339 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3341 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3342 interspersed */
3344 len += 0x40;
3346 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3348 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3349 sizeof(*pOtherTypeInfoBlks) *
3350 pTypeLibImpl->TypeInfoCount);
3353 ptr = (char*)pLibBlk + len;
3355 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3356 WORD w, extra;
3357 len = 0;
3359 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3361 w = *(WORD*)(ptr + 2);
3362 if(w != 0xffff) {
3363 len += w;
3364 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3365 w+1);
3366 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3367 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3369 w = *(WORD*)(ptr + 4 + len);
3370 if(w != 0xffff) {
3371 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3372 len += w;
3373 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3374 w+1);
3375 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3376 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3378 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3379 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3380 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3381 if(extra) {
3382 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3383 extra);
3384 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3385 len += extra;
3387 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3388 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3389 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3390 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3391 len += sizeof(SLTG_OtherTypeInfo);
3392 ptr += len;
3395 pAfterOTIBlks = ptr;
3397 /* Skip this WORD and get the next DWORD */
3398 len = *(DWORD*)(pAfterOTIBlks + 2);
3400 /* Now add this to pLibBLk look at what we're pointing at and
3401 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3402 dust and we should be pointing at the beginning of the name
3403 table */
3405 pNameTable = (char*)pLibBlk + len;
3407 switch(*(WORD*)pNameTable) {
3408 case 0xffff:
3409 break;
3410 case 0x0200:
3411 pNameTable += 0x20;
3412 break;
3413 default:
3414 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3415 break;
3418 pNameTable += 0x216;
3420 pNameTable += 2;
3422 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3424 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3427 /* Hopefully we now have enough ptrs set up to actually read in
3428 some TypeInfos. It's not clear which order to do them in, so
3429 I'll just follow the links along the BlkEntry chain and read
3430 them in the order in which they are in the file */
3432 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3434 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3435 pBlkEntry[order].next != 0;
3436 order = pBlkEntry[order].next - 1, i++) {
3438 SLTG_TypeInfoHeader *pTIHeader;
3439 SLTG_TypeInfoTail *pTITail;
3440 SLTG_MemberHeader *pMemHeader;
3442 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3443 pOtherTypeInfoBlks[i].index_name)) {
3444 FIXME("Index strings don't match\n");
3445 return NULL;
3448 pTIHeader = pBlk;
3449 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3450 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3451 return NULL;
3453 TRACE("pTIHeader->res06 = %x, pTIHeader->res0e = %x, pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3454 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3456 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3457 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3458 (*ppTypeInfoImpl)->index = i;
3459 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3460 pOtherTypeInfoBlks[i].name_offs +
3461 pNameTable);
3462 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3463 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3464 sizeof(GUID));
3465 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3466 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3467 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3468 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3469 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3471 if((pTIHeader->typeflags1 & 7) != 2)
3472 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3473 if(pTIHeader->typeflags3 != 2)
3474 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3476 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3477 debugstr_w((*ppTypeInfoImpl)->Name),
3478 typekind_desc[pTIHeader->typekind],
3479 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3480 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3482 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3484 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3486 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3487 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3488 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3490 switch(pTIHeader->typekind) {
3491 case TKIND_ENUM:
3492 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3493 pTIHeader, pTITail);
3494 break;
3496 case TKIND_RECORD:
3497 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3498 pTIHeader, pTITail);
3499 break;
3501 case TKIND_INTERFACE:
3502 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3503 pTIHeader, pTITail);
3504 break;
3506 case TKIND_COCLASS:
3507 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3508 pTIHeader, pTITail);
3509 break;
3511 case TKIND_ALIAS:
3512 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3513 pTIHeader, pTITail);
3514 break;
3516 case TKIND_DISPATCH:
3517 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3518 pTIHeader, pTITail);
3519 break;
3521 case TKIND_MODULE:
3522 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3523 pTIHeader, pTITail);
3524 break;
3526 default:
3527 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3528 break;
3532 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3533 but we've already set those */
3534 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3535 X(06);
3536 X(16);
3537 X(18);
3538 X(1a);
3539 X(1e);
3540 X(24);
3541 X(26);
3542 X(2a);
3543 X(2c);
3544 X(2e);
3545 X(30);
3546 X(32);
3547 X(34);
3549 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3550 pBlk = (char*)pBlk + pBlkEntry[order].len;
3553 if(i != pTypeLibImpl->TypeInfoCount) {
3554 FIXME("Somehow processed %d TypeInfos\n", i);
3555 return NULL;
3558 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3559 return (ITypeLib2*)pTypeLibImpl;
3562 /* ITypeLib::QueryInterface
3564 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3565 ITypeLib2 * iface,
3566 REFIID riid,
3567 VOID **ppvObject)
3569 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3571 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3573 *ppvObject=NULL;
3574 if(IsEqualIID(riid, &IID_IUnknown) ||
3575 IsEqualIID(riid,&IID_ITypeLib)||
3576 IsEqualIID(riid,&IID_ITypeLib2))
3578 *ppvObject = This;
3581 if(*ppvObject)
3583 ITypeLib2_AddRef(iface);
3584 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3585 return S_OK;
3587 TRACE("-- Interface: E_NOINTERFACE\n");
3588 return E_NOINTERFACE;
3591 /* ITypeLib::AddRef
3593 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3595 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3596 ULONG ref = InterlockedIncrement(&This->ref);
3598 TRACE("(%p)->ref was %u\n",This, ref - 1);
3600 return ref;
3603 /* ITypeLib::Release
3605 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3607 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3608 ULONG ref = InterlockedDecrement(&This->ref);
3610 TRACE("(%p)->(%u)\n",This, ref);
3612 if (!ref)
3614 TLBImpLib *pImpLib, *pImpLibNext;
3615 TLBCustData *pCustData, *pCustDataNext;
3616 TLBRefType *ref_type;
3617 void *cursor2;
3618 int i;
3620 /* remove cache entry */
3621 if(This->path)
3623 TRACE("removing from cache list\n");
3624 EnterCriticalSection(&cache_section);
3625 if (This->next) This->next->prev = This->prev;
3626 if (This->prev) This->prev->next = This->next;
3627 else tlb_cache_first = This->next;
3628 LeaveCriticalSection(&cache_section);
3629 HeapFree(GetProcessHeap(), 0, This->path);
3631 TRACE(" destroying ITypeLib(%p)\n",This);
3633 if (This->Name)
3635 SysFreeString(This->Name);
3636 This->Name = NULL;
3639 if (This->DocString)
3641 SysFreeString(This->DocString);
3642 This->DocString = NULL;
3645 if (This->HelpFile)
3647 SysFreeString(This->HelpFile);
3648 This->HelpFile = NULL;
3651 if (This->HelpStringDll)
3653 SysFreeString(This->HelpStringDll);
3654 This->HelpStringDll = NULL;
3657 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
3659 VariantClear(&pCustData->data);
3661 pCustDataNext = pCustData->next;
3662 TLB_Free(pCustData);
3665 for (i = 0; i < This->ctTypeDesc; i++)
3666 if (This->pTypeDesc[i].vt == VT_CARRAY)
3667 TLB_Free(This->pTypeDesc[i].u.lpadesc);
3669 TLB_Free(This->pTypeDesc);
3671 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
3673 if (pImpLib->pImpTypeLib)
3674 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
3675 TLB_Free(pImpLib->name);
3677 pImpLibNext = pImpLib->next;
3678 TLB_Free(pImpLib);
3681 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
3683 list_remove(&ref_type->entry);
3684 TLB_Free(ref_type);
3687 if (This->pTypeInfo) /* can be NULL */
3688 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3689 HeapFree(GetProcessHeap(),0,This);
3690 return 0;
3693 return ref;
3696 /* ITypeLib::GetTypeInfoCount
3698 * Returns the number of type descriptions in the type library
3700 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3702 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3703 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3704 return This->TypeInfoCount;
3707 /* ITypeLib::GetTypeInfo
3709 * retrieves the specified type description in the library.
3711 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3712 ITypeLib2 *iface,
3713 UINT index,
3714 ITypeInfo **ppTInfo)
3716 int i;
3718 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3719 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3721 TRACE("(%p)->(index=%d)\n", This, index);
3723 if (!ppTInfo) return E_INVALIDARG;
3725 /* search element n in list */
3726 for(i=0; i < index; i++)
3728 pTypeInfo = pTypeInfo->next;
3729 if (!pTypeInfo)
3731 TRACE("-- element not found\n");
3732 return TYPE_E_ELEMENTNOTFOUND;
3736 *ppTInfo = (ITypeInfo *) pTypeInfo;
3738 ITypeInfo_AddRef(*ppTInfo);
3739 TRACE("-- found (%p)\n",*ppTInfo);
3740 return S_OK;
3744 /* ITypeLibs::GetTypeInfoType
3746 * Retrieves the type of a type description.
3748 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3749 ITypeLib2 *iface,
3750 UINT index,
3751 TYPEKIND *pTKind)
3753 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3754 int i;
3755 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3757 if ((ITypeLib2_fnGetTypeInfoCount(iface) < index + 1) || (index < 0))
3758 return TYPE_E_ELEMENTNOTFOUND;
3760 TRACE("(%p) index %d\n", This, index);
3762 if(!pTKind) return E_INVALIDARG;
3764 /* search element n in list */
3765 for(i=0; i < index; i++)
3767 if(!pTInfo)
3769 TRACE("-- element not found\n");
3770 return TYPE_E_ELEMENTNOTFOUND;
3772 pTInfo = pTInfo->next;
3775 *pTKind = pTInfo->TypeAttr.typekind;
3776 TRACE("-- found Type (%d)\n", *pTKind);
3777 return S_OK;
3780 /* ITypeLib::GetTypeInfoOfGuid
3782 * Retrieves the type description that corresponds to the specified GUID.
3785 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3786 ITypeLib2 *iface,
3787 REFGUID guid,
3788 ITypeInfo **ppTInfo)
3790 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3791 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3793 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3795 if (!pTypeInfo)
3797 WARN("-- element not found\n");
3798 return TYPE_E_ELEMENTNOTFOUND;
3801 /* search linked list for guid */
3802 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3804 pTypeInfo = pTypeInfo->next;
3806 if (!pTypeInfo)
3808 /* end of list reached */
3809 WARN("-- element not found\n");
3810 return TYPE_E_ELEMENTNOTFOUND;
3814 TRACE("-- found (%p, %s)\n",
3815 pTypeInfo,
3816 debugstr_w(pTypeInfo->Name));
3818 *ppTInfo = (ITypeInfo*)pTypeInfo;
3819 ITypeInfo_AddRef(*ppTInfo);
3820 return S_OK;
3823 /* ITypeLib::GetLibAttr
3825 * Retrieves the structure that contains the library's attributes.
3828 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3829 ITypeLib2 *iface,
3830 LPTLIBATTR *ppTLibAttr)
3832 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3833 TRACE("(%p)\n",This);
3834 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3835 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3836 return S_OK;
3839 /* ITypeLib::GetTypeComp
3841 * Enables a client compiler to bind to a library's types, variables,
3842 * constants, and global functions.
3845 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3846 ITypeLib2 *iface,
3847 ITypeComp **ppTComp)
3849 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3851 TRACE("(%p)->(%p)\n",This,ppTComp);
3852 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3853 ITypeComp_AddRef(*ppTComp);
3855 return S_OK;
3858 /* ITypeLib::GetDocumentation
3860 * Retrieves the library's documentation string, the complete Help file name
3861 * and path, and the context identifier for the library Help topic in the Help
3862 * file.
3864 * On a successful return all non-null BSTR pointers will have been set,
3865 * possibly to NULL.
3867 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3868 ITypeLib2 *iface,
3869 INT index,
3870 BSTR *pBstrName,
3871 BSTR *pBstrDocString,
3872 DWORD *pdwHelpContext,
3873 BSTR *pBstrHelpFile)
3875 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3877 HRESULT result = E_INVALIDARG;
3879 ITypeInfo *pTInfo;
3882 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3883 This, index,
3884 pBstrName, pBstrDocString,
3885 pdwHelpContext, pBstrHelpFile);
3887 if(index<0)
3889 /* documentation for the typelib */
3890 if(pBstrName)
3892 if (This->Name)
3894 if(!(*pBstrName = SysAllocString(This->Name)))
3895 goto memerr1;
3897 else
3898 *pBstrName = NULL;
3900 if(pBstrDocString)
3902 if (This->DocString)
3904 if(!(*pBstrDocString = SysAllocString(This->DocString)))
3905 goto memerr2;
3907 else if (This->Name)
3909 if(!(*pBstrDocString = SysAllocString(This->Name)))
3910 goto memerr2;
3912 else
3913 *pBstrDocString = NULL;
3915 if(pdwHelpContext)
3917 *pdwHelpContext = This->dwHelpContext;
3919 if(pBstrHelpFile)
3921 if (This->HelpFile)
3923 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
3924 goto memerr3;
3926 else
3927 *pBstrHelpFile = NULL;
3930 result = S_OK;
3932 else
3934 /* for a typeinfo */
3935 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3937 if(SUCCEEDED(result))
3939 result = ITypeInfo_GetDocumentation(pTInfo,
3940 MEMBERID_NIL,
3941 pBstrName,
3942 pBstrDocString,
3943 pdwHelpContext, pBstrHelpFile);
3945 ITypeInfo_Release(pTInfo);
3948 return result;
3949 memerr3:
3950 if (pBstrDocString) SysFreeString (*pBstrDocString);
3951 memerr2:
3952 if (pBstrName) SysFreeString (*pBstrName);
3953 memerr1:
3954 return STG_E_INSUFFICIENTMEMORY;
3957 /* ITypeLib::IsName
3959 * Indicates whether a passed-in string contains the name of a type or member
3960 * described in the library.
3963 static HRESULT WINAPI ITypeLib2_fnIsName(
3964 ITypeLib2 *iface,
3965 LPOLESTR szNameBuf,
3966 ULONG lHashVal,
3967 BOOL *pfName)
3969 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3970 ITypeInfoImpl *pTInfo;
3971 TLBFuncDesc *pFInfo;
3972 TLBVarDesc *pVInfo;
3973 int i;
3974 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3976 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3977 pfName);
3979 *pfName=TRUE;
3980 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3981 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3982 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3983 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3984 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3985 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3986 goto ITypeLib2_fnIsName_exit;
3988 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3989 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3992 *pfName=FALSE;
3994 ITypeLib2_fnIsName_exit:
3995 TRACE("(%p)slow! search for %s: %s found!\n", This,
3996 debugstr_w(szNameBuf), *pfName?"NOT":"");
3998 return S_OK;
4001 /* ITypeLib::FindName
4003 * Finds occurrences of a type description in a type library. This may be used
4004 * to quickly verify that a name exists in a type library.
4007 static HRESULT WINAPI ITypeLib2_fnFindName(
4008 ITypeLib2 *iface,
4009 LPOLESTR szNameBuf,
4010 ULONG lHashVal,
4011 ITypeInfo **ppTInfo,
4012 MEMBERID *rgMemId,
4013 UINT16 *pcFound)
4015 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4016 ITypeInfoImpl *pTInfo;
4017 TLBFuncDesc *pFInfo;
4018 TLBVarDesc *pVInfo;
4019 int i,j = 0;
4020 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4022 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
4023 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4024 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4025 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4026 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
4027 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
4028 goto ITypeLib2_fnFindName_exit;
4031 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4032 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4033 continue;
4034 ITypeLib2_fnFindName_exit:
4035 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4036 ppTInfo[j]=(LPTYPEINFO)pTInfo;
4037 j++;
4039 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4040 This, *pcFound, debugstr_w(szNameBuf), j);
4042 *pcFound=j;
4044 return S_OK;
4047 /* ITypeLib::ReleaseTLibAttr
4049 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4052 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4053 ITypeLib2 *iface,
4054 TLIBATTR *pTLibAttr)
4056 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4057 TRACE("freeing (%p)\n",This);
4058 HeapFree(GetProcessHeap(),0,pTLibAttr);
4062 /* ITypeLib2::GetCustData
4064 * gets the custom data
4066 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4067 ITypeLib2 * iface,
4068 REFGUID guid,
4069 VARIANT *pVarVal)
4071 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4072 TLBCustData *pCData;
4074 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4076 if( IsEqualIID(guid, &pCData->guid)) break;
4079 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4081 if(pCData)
4083 VariantInit( pVarVal);
4084 VariantCopy( pVarVal, &pCData->data);
4085 return S_OK;
4087 return E_INVALIDARG; /* FIXME: correct? */
4090 /* ITypeLib2::GetLibStatistics
4092 * Returns statistics about a type library that are required for efficient
4093 * sizing of hash tables.
4096 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4097 ITypeLib2 * iface,
4098 ULONG *pcUniqueNames,
4099 ULONG *pcchUniqueNames)
4101 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4103 FIXME("(%p): stub!\n", This);
4105 if(pcUniqueNames) *pcUniqueNames=1;
4106 if(pcchUniqueNames) *pcchUniqueNames=1;
4107 return S_OK;
4110 /* ITypeLib2::GetDocumentation2
4112 * Retrieves the library's documentation string, the complete Help file name
4113 * and path, the localization context to use, and the context ID for the
4114 * library Help topic in the Help file.
4117 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4118 ITypeLib2 * iface,
4119 INT index,
4120 LCID lcid,
4121 BSTR *pbstrHelpString,
4122 DWORD *pdwHelpStringContext,
4123 BSTR *pbstrHelpStringDll)
4125 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4126 HRESULT result;
4127 ITypeInfo *pTInfo;
4129 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4131 /* the help string should be obtained from the helpstringdll,
4132 * using the _DLLGetDocumentation function, based on the supplied
4133 * lcid. Nice to do sometime...
4135 if(index<0)
4137 /* documentation for the typelib */
4138 if(pbstrHelpString)
4139 *pbstrHelpString=SysAllocString(This->DocString);
4140 if(pdwHelpStringContext)
4141 *pdwHelpStringContext=This->dwHelpContext;
4142 if(pbstrHelpStringDll)
4143 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4145 result = S_OK;
4147 else
4149 /* for a typeinfo */
4150 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4152 if(SUCCEEDED(result))
4154 ITypeInfo2 * pTInfo2;
4155 result = ITypeInfo_QueryInterface(pTInfo,
4156 &IID_ITypeInfo2,
4157 (LPVOID*) &pTInfo2);
4159 if(SUCCEEDED(result))
4161 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4162 MEMBERID_NIL,
4163 lcid,
4164 pbstrHelpString,
4165 pdwHelpStringContext,
4166 pbstrHelpStringDll);
4168 ITypeInfo2_Release(pTInfo2);
4171 ITypeInfo_Release(pTInfo);
4174 return result;
4177 /* ITypeLib2::GetAllCustData
4179 * Gets all custom data items for the library.
4182 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4183 ITypeLib2 * iface,
4184 CUSTDATA *pCustData)
4186 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4187 TLBCustData *pCData;
4188 int i;
4189 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4190 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4191 if(pCustData->prgCustData ){
4192 pCustData->cCustData=This->ctCustData;
4193 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4194 pCustData->prgCustData[i].guid=pCData->guid;
4195 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4197 }else{
4198 ERR(" OUT OF MEMORY!\n");
4199 return E_OUTOFMEMORY;
4201 return S_OK;
4204 static const ITypeLib2Vtbl tlbvt = {
4205 ITypeLib2_fnQueryInterface,
4206 ITypeLib2_fnAddRef,
4207 ITypeLib2_fnRelease,
4208 ITypeLib2_fnGetTypeInfoCount,
4209 ITypeLib2_fnGetTypeInfo,
4210 ITypeLib2_fnGetTypeInfoType,
4211 ITypeLib2_fnGetTypeInfoOfGuid,
4212 ITypeLib2_fnGetLibAttr,
4213 ITypeLib2_fnGetTypeComp,
4214 ITypeLib2_fnGetDocumentation,
4215 ITypeLib2_fnIsName,
4216 ITypeLib2_fnFindName,
4217 ITypeLib2_fnReleaseTLibAttr,
4219 ITypeLib2_fnGetCustData,
4220 ITypeLib2_fnGetLibStatistics,
4221 ITypeLib2_fnGetDocumentation2,
4222 ITypeLib2_fnGetAllCustData
4226 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4228 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4230 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4233 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4235 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4237 return ITypeLib2_AddRef((ITypeLib2 *)This);
4240 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4242 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4244 return ITypeLib2_Release((ITypeLib2 *)This);
4247 static HRESULT WINAPI ITypeLibComp_fnBind(
4248 ITypeComp * iface,
4249 OLECHAR * szName,
4250 ULONG lHash,
4251 WORD wFlags,
4252 ITypeInfo ** ppTInfo,
4253 DESCKIND * pDescKind,
4254 BINDPTR * pBindPtr)
4256 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4257 ITypeInfoImpl *pTypeInfo;
4259 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4261 *pDescKind = DESCKIND_NONE;
4262 pBindPtr->lptcomp = NULL;
4263 *ppTInfo = NULL;
4265 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4267 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4269 /* FIXME: check wFlags here? */
4270 /* FIXME: we should use a hash table to look this info up using lHash
4271 * instead of an O(n) search */
4272 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4273 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4275 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4277 *pDescKind = DESCKIND_TYPECOMP;
4278 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4279 ITypeComp_AddRef(pBindPtr->lptcomp);
4280 TRACE("module or enum: %s\n", debugstr_w(szName));
4281 return S_OK;
4285 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4286 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4288 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4289 HRESULT hr;
4291 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4292 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4294 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4295 return S_OK;
4299 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4300 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4302 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4303 HRESULT hr;
4304 ITypeInfo *subtypeinfo;
4305 BINDPTR subbindptr;
4306 DESCKIND subdesckind;
4308 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4309 &subtypeinfo, &subdesckind, &subbindptr);
4310 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4312 TYPEDESC tdesc_appobject =
4315 (TYPEDESC *)pTypeInfo->hreftype
4317 VT_USERDEFINED
4319 const VARDESC vardesc_appobject =
4321 -2, /* memid */
4322 NULL, /* lpstrSchema */
4324 0 /* oInst */
4327 /* ELEMDESC */
4329 /* TYPEDESC */
4331 &tdesc_appobject
4333 VT_PTR
4336 0, /* wVarFlags */
4337 VAR_STATIC /* varkind */
4340 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4342 /* cleanup things filled in by Bind call so we can put our
4343 * application object data in there instead */
4344 switch (subdesckind)
4346 case DESCKIND_FUNCDESC:
4347 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4348 break;
4349 case DESCKIND_VARDESC:
4350 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4351 break;
4352 default:
4353 break;
4355 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4357 if (pTypeInfo->hreftype == -1)
4358 FIXME("no hreftype for interface %p\n", pTypeInfo);
4360 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4361 if (FAILED(hr))
4362 return hr;
4364 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4365 *ppTInfo = (ITypeInfo *)pTypeInfo;
4366 ITypeInfo_AddRef(*ppTInfo);
4367 return S_OK;
4372 TRACE("name not found %s\n", debugstr_w(szName));
4373 return S_OK;
4376 static HRESULT WINAPI ITypeLibComp_fnBindType(
4377 ITypeComp * iface,
4378 OLECHAR * szName,
4379 ULONG lHash,
4380 ITypeInfo ** ppTInfo,
4381 ITypeComp ** ppTComp)
4383 FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4384 return E_NOTIMPL;
4387 static const ITypeCompVtbl tlbtcvt =
4390 ITypeLibComp_fnQueryInterface,
4391 ITypeLibComp_fnAddRef,
4392 ITypeLibComp_fnRelease,
4394 ITypeLibComp_fnBind,
4395 ITypeLibComp_fnBindType
4398 /*================== ITypeInfo(2) Methods ===================================*/
4399 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4401 ITypeInfoImpl * pTypeInfoImpl;
4403 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4404 if (pTypeInfoImpl)
4406 pTypeInfoImpl->lpVtbl = &tinfvt;
4407 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4408 pTypeInfoImpl->ref=1;
4409 pTypeInfoImpl->hreftype = -1;
4410 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4411 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4413 TRACE("(%p)\n", pTypeInfoImpl);
4414 return (ITypeInfo2*) pTypeInfoImpl;
4417 /* ITypeInfo::QueryInterface
4419 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4420 ITypeInfo2 *iface,
4421 REFIID riid,
4422 VOID **ppvObject)
4424 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4426 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4428 *ppvObject=NULL;
4429 if(IsEqualIID(riid, &IID_IUnknown) ||
4430 IsEqualIID(riid,&IID_ITypeInfo)||
4431 IsEqualIID(riid,&IID_ITypeInfo2))
4432 *ppvObject = This;
4434 if(*ppvObject){
4435 ITypeInfo_AddRef(iface);
4436 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4437 return S_OK;
4439 TRACE("-- Interface: E_NOINTERFACE\n");
4440 return E_NOINTERFACE;
4443 /* ITypeInfo::AddRef
4445 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4447 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4448 ULONG ref = InterlockedIncrement(&This->ref);
4450 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4452 TRACE("(%p)->ref is %u\n",This, ref);
4453 return ref;
4456 /* ITypeInfo::Release
4458 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4460 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4461 ULONG ref = InterlockedDecrement(&This->ref);
4463 TRACE("(%p)->(%u)\n",This, ref);
4465 if (ref) {
4466 /* We don't release ITypeLib when ref=0 because
4467 it means that function is called by ITypeLib2_Release */
4468 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4469 } else {
4470 TLBFuncDesc *pFInfo, *pFInfoNext;
4471 TLBVarDesc *pVInfo, *pVInfoNext;
4472 TLBImplType *pImpl, *pImplNext;
4473 TLBCustData *pCustData, *pCustDataNext;
4475 TRACE("destroying ITypeInfo(%p)\n",This);
4477 if (This->no_free_data)
4478 goto finish_free;
4480 if (This->Name)
4482 SysFreeString(This->Name);
4483 This->Name = 0;
4486 if (This->DocString)
4488 SysFreeString(This->DocString);
4489 This->DocString = 0;
4492 if (This->DllName)
4494 SysFreeString(This->DllName);
4495 This->DllName = 0;
4498 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4500 UINT i;
4501 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4503 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4504 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4506 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4507 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4509 SysFreeString(pFInfo->pParamDesc[i].Name);
4511 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4512 TLB_Free(pFInfo->pParamDesc);
4513 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
4515 VariantClear(&pCustData->data);
4517 pCustDataNext = pCustData->next;
4518 TLB_Free(pCustData);
4520 if (HIWORD(pFInfo->Entry) != 0 && pFInfo->Entry != (BSTR)-1)
4521 SysFreeString(pFInfo->Entry);
4522 SysFreeString(pFInfo->HelpString);
4523 SysFreeString(pFInfo->Name);
4525 pFInfoNext = pFInfo->next;
4526 TLB_Free(pFInfo);
4528 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
4530 if (pVInfo->vardesc.varkind == VAR_CONST)
4532 VariantClear(pVInfo->vardesc.u.lpvarValue);
4533 TLB_Free(pVInfo->vardesc.u.lpvarValue);
4535 SysFreeString(pVInfo->Name);
4536 pVInfoNext = pVInfo->next;
4537 TLB_Free(pVInfo);
4539 for(pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
4541 for (pCustData = pImpl->pCustData; pCustData; pCustData = pCustDataNext)
4543 VariantClear(&pCustData->data);
4545 pCustDataNext = pCustData->next;
4546 TLB_Free(pCustData);
4548 pImplNext = pImpl->next;
4549 TLB_Free(pImpl);
4551 TLB_Free(This->pCustData);
4553 finish_free:
4554 if (This->next)
4556 ITypeInfo_Release((ITypeInfo*)This->next);
4559 HeapFree(GetProcessHeap(),0,This);
4560 return 0;
4562 return ref;
4565 /* ITypeInfo::GetTypeAttr
4567 * Retrieves a TYPEATTR structure that contains the attributes of the type
4568 * description.
4571 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4572 LPTYPEATTR *ppTypeAttr)
4574 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4575 SIZE_T size;
4577 TRACE("(%p)\n",This);
4579 size = sizeof(**ppTypeAttr);
4580 if (This->TypeAttr.typekind == TKIND_ALIAS)
4581 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4583 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4584 if (!*ppTypeAttr)
4585 return E_OUTOFMEMORY;
4587 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4589 if (This->TypeAttr.typekind == TKIND_ALIAS)
4590 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4591 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4593 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4594 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4595 funcs */
4596 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4597 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4599 return S_OK;
4602 /* ITypeInfo::GetTypeComp
4604 * Retrieves the ITypeComp interface for the type description, which enables a
4605 * client compiler to bind to the type description's members.
4608 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4609 ITypeComp * *ppTComp)
4611 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4613 TRACE("(%p)->(%p)\n", This, ppTComp);
4615 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4616 ITypeComp_AddRef(*ppTComp);
4617 return S_OK;
4620 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4622 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4623 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4624 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4625 return size;
4628 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4630 memcpy(dest, src, sizeof(ELEMDESC));
4631 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4632 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4634 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4635 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4636 *buffer += sizeof(PARAMDESCEX);
4637 memcpy(pparamdescex_dest, pparamdescex_src, sizeof(PARAMDESCEX));
4638 VariantInit(&pparamdescex_dest->varDefaultValue);
4639 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4640 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4642 else
4643 dest->u.paramdesc.pparamdescex = NULL;
4644 return S_OK;
4647 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4649 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4650 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4653 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4655 FUNCDESC *dest;
4656 char *buffer;
4657 SIZE_T size = sizeof(*src);
4658 SHORT i;
4659 HRESULT hr;
4661 size += sizeof(*src->lprgscode) * src->cScodes;
4662 size += TLB_SizeElemDesc(&src->elemdescFunc);
4663 for (i = 0; i < src->cParams; i++)
4665 size += sizeof(ELEMDESC);
4666 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4669 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4670 if (!dest) return E_OUTOFMEMORY;
4672 memcpy(dest, src, sizeof(FUNCDESC));
4673 buffer = (char *)(dest + 1);
4675 dest->lprgscode = (SCODE *)buffer;
4676 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4677 buffer += sizeof(*src->lprgscode) * src->cScodes;
4679 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4680 if (FAILED(hr))
4682 SysFreeString((BSTR)dest);
4683 return hr;
4686 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4687 buffer += sizeof(ELEMDESC) * src->cParams;
4688 for (i = 0; i < src->cParams; i++)
4690 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4691 if (FAILED(hr))
4692 break;
4694 if (FAILED(hr))
4696 /* undo the above actions */
4697 for (i = i - 1; i >= 0; i--)
4698 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4699 TLB_FreeElemDesc(&dest->elemdescFunc);
4700 SysFreeString((BSTR)dest);
4701 return hr;
4704 /* special treatment for dispinterfaces: this makes functions appear
4705 * to return their [retval] value when it is really returning an
4706 * HRESULT */
4707 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4709 if (dest->cParams &&
4710 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4712 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4713 if (elemdesc->tdesc.vt != VT_PTR)
4715 ERR("elemdesc should have started with VT_PTR instead of:\n");
4716 if (ERR_ON(ole))
4717 dump_ELEMDESC(elemdesc);
4718 return E_UNEXPECTED;
4721 /* copy last parameter to the return value. we are using a flat
4722 * buffer so there is no danger of leaking memory in
4723 * elemdescFunc */
4724 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4726 /* remove the last parameter */
4727 dest->cParams--;
4729 else
4730 /* otherwise this function is made to appear to have no return
4731 * value */
4732 dest->elemdescFunc.tdesc.vt = VT_VOID;
4736 *dest_ptr = dest;
4737 return S_OK;
4740 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4742 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4743 const TLBFuncDesc *pFDesc;
4744 int i;
4746 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4749 if (pFDesc)
4751 *ppFuncDesc = &pFDesc->funcdesc;
4752 return S_OK;
4755 return TYPE_E_ELEMENTNOTFOUND;
4758 /* internal function to make the inherited interfaces' methods appear
4759 * part of the interface */
4760 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
4761 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
4763 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4764 HRESULT hr;
4765 UINT implemented_funcs = 0;
4767 if (funcs)
4768 *funcs = 0;
4769 else
4770 *hrefoffset = DISPATCH_HREF_OFFSET;
4772 if(This->impltypelist)
4774 ITypeInfo *pSubTypeInfo;
4775 UINT sub_funcs;
4777 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
4778 if (FAILED(hr))
4779 return hr;
4781 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
4782 index,
4783 ppFuncDesc,
4784 &sub_funcs, hrefoffset);
4785 implemented_funcs += sub_funcs;
4786 ITypeInfo_Release(pSubTypeInfo);
4787 if (SUCCEEDED(hr))
4788 return hr;
4789 *hrefoffset += DISPATCH_HREF_OFFSET;
4792 if (funcs)
4793 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
4794 else
4795 *hrefoffset = 0;
4797 if (index < implemented_funcs)
4798 return E_INVALIDARG;
4799 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
4800 ppFuncDesc);
4803 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
4805 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
4806 while (TRUE)
4808 switch (pTypeDesc->vt)
4810 case VT_USERDEFINED:
4811 pTypeDesc->u.hreftype += hrefoffset;
4812 return;
4813 case VT_PTR:
4814 case VT_SAFEARRAY:
4815 pTypeDesc = pTypeDesc->u.lptdesc;
4816 break;
4817 case VT_CARRAY:
4818 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
4819 break;
4820 default:
4821 return;
4826 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
4828 SHORT i;
4829 for (i = 0; i < pFuncDesc->cParams; i++)
4830 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
4831 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
4834 /* ITypeInfo::GetFuncDesc
4836 * Retrieves the FUNCDESC structure that contains information about a
4837 * specified function.
4840 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4841 LPFUNCDESC *ppFuncDesc)
4843 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4844 const FUNCDESC *internal_funcdesc;
4845 HRESULT hr;
4846 UINT hrefoffset = 0;
4848 TRACE("(%p) index %d\n", This, index);
4850 if (This->TypeAttr.typekind == TKIND_DISPATCH)
4851 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
4852 &internal_funcdesc, NULL,
4853 &hrefoffset);
4854 else
4855 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
4856 &internal_funcdesc);
4857 if (FAILED(hr))
4859 WARN("description for function %d not found\n", index);
4860 return hr;
4863 hr = TLB_AllocAndInitFuncDesc(
4864 internal_funcdesc,
4865 ppFuncDesc,
4866 This->TypeAttr.typekind == TKIND_DISPATCH);
4868 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
4869 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
4871 TRACE("-- 0x%08x\n", hr);
4872 return hr;
4875 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
4877 VARDESC *dest;
4878 char *buffer;
4879 SIZE_T size = sizeof(*src);
4880 HRESULT hr;
4882 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
4883 if (src->varkind == VAR_CONST)
4884 size += sizeof(VARIANT);
4885 size += TLB_SizeElemDesc(&src->elemdescVar);
4887 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
4888 if (!dest) return E_OUTOFMEMORY;
4890 *dest = *src;
4891 buffer = (char *)(dest + 1);
4892 if (src->lpstrSchema)
4894 int len;
4895 dest->lpstrSchema = (LPOLESTR)buffer;
4896 len = strlenW(src->lpstrSchema);
4897 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
4898 buffer += (len + 1) * sizeof(WCHAR);
4901 if (src->varkind == VAR_CONST)
4903 HRESULT hr;
4905 dest->u.lpvarValue = (VARIANT *)buffer;
4906 *dest->u.lpvarValue = *src->u.lpvarValue;
4907 buffer += sizeof(VARIANT);
4908 VariantInit(dest->u.lpvarValue);
4909 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
4910 if (FAILED(hr))
4912 SysFreeString((BSTR)dest_ptr);
4913 return hr;
4916 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
4917 if (FAILED(hr))
4919 if (src->varkind == VAR_CONST)
4920 VariantClear(dest->u.lpvarValue);
4921 SysFreeString((BSTR)dest);
4922 return hr;
4924 *dest_ptr = dest;
4925 return S_OK;
4928 /* ITypeInfo::GetVarDesc
4930 * Retrieves a VARDESC structure that describes the specified variable.
4933 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4934 LPVARDESC *ppVarDesc)
4936 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4937 int i;
4938 const TLBVarDesc *pVDesc;
4940 TRACE("(%p) index %d\n", This, index);
4942 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4945 if (pVDesc)
4946 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
4948 return E_INVALIDARG;
4951 /* ITypeInfo_GetNames
4953 * Retrieves the variable with the specified member ID (or the name of the
4954 * property or method and its parameters) that correspond to the specified
4955 * function ID.
4957 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4958 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4960 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4961 const TLBFuncDesc *pFDesc;
4962 const TLBVarDesc *pVDesc;
4963 int i;
4964 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
4965 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4966 if(pFDesc)
4968 /* function found, now return function and parameter names */
4969 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4971 if(!i)
4972 *rgBstrNames=SysAllocString(pFDesc->Name);
4973 else
4974 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4976 *pcNames=i;
4978 else
4980 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4981 if(pVDesc)
4983 *rgBstrNames=SysAllocString(pVDesc->Name);
4984 *pcNames=1;
4986 else
4988 if(This->impltypelist &&
4989 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4990 /* recursive search */
4991 ITypeInfo *pTInfo;
4992 HRESULT result;
4993 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4994 &pTInfo);
4995 if(SUCCEEDED(result))
4997 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4998 ITypeInfo_Release(pTInfo);
4999 return result;
5001 WARN("Could not search inherited interface!\n");
5003 else
5005 WARN("no names found\n");
5007 *pcNames=0;
5008 return TYPE_E_ELEMENTNOTFOUND;
5011 return S_OK;
5015 /* ITypeInfo::GetRefTypeOfImplType
5017 * If a type description describes a COM class, it retrieves the type
5018 * description of the implemented interface types. For an interface,
5019 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5020 * if any exist.
5023 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5024 ITypeInfo2 *iface,
5025 UINT index,
5026 HREFTYPE *pRefType)
5028 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5029 int i;
5030 HRESULT hr = S_OK;
5031 const TLBImplType *pImpl = This->impltypelist;
5033 TRACE("(%p) index %d\n", This, index);
5034 if (TRACE_ON(ole)) dump_TypeInfo(This);
5036 if(index==(UINT)-1)
5038 /* only valid on dual interfaces;
5039 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5041 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5043 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
5044 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
5046 *pRefType = -1;
5048 else
5050 hr = TYPE_E_ELEMENTNOTFOUND;
5053 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5055 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5056 *pRefType = This->pTypeLib->dispatch_href;
5058 else
5060 /* get element n from linked list */
5061 for(i=0; pImpl && i<index; i++)
5063 pImpl = pImpl->next;
5066 if (pImpl)
5067 *pRefType = pImpl->hRef;
5068 else
5069 hr = TYPE_E_ELEMENTNOTFOUND;
5072 if(TRACE_ON(ole))
5074 if(SUCCEEDED(hr))
5075 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5076 else
5077 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5080 return hr;
5083 /* ITypeInfo::GetImplTypeFlags
5085 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5086 * or base interface in a type description.
5088 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5089 UINT index, INT *pImplTypeFlags)
5091 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5092 int i;
5093 TLBImplType *pImpl;
5095 TRACE("(%p) index %d\n", This, index);
5096 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5097 i++, pImpl=pImpl->next)
5099 if(i==index && pImpl){
5100 *pImplTypeFlags=pImpl->implflags;
5101 return S_OK;
5103 *pImplTypeFlags=0;
5104 return TYPE_E_ELEMENTNOTFOUND;
5107 /* GetIDsOfNames
5108 * Maps between member names and member IDs, and parameter names and
5109 * parameter IDs.
5111 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5112 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5114 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5115 const TLBFuncDesc *pFDesc;
5116 const TLBVarDesc *pVDesc;
5117 HRESULT ret=S_OK;
5118 int i;
5120 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5121 cNames);
5123 /* init out parameters in case of failure */
5124 for (i = 0; i < cNames; i++)
5125 pMemId[i] = MEMBERID_NIL;
5127 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5128 int j;
5129 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5130 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5131 for(i=1; i < cNames; i++){
5132 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5133 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5134 break;
5135 if( j<pFDesc->funcdesc.cParams)
5136 pMemId[i]=j;
5137 else
5138 ret=DISP_E_UNKNOWNNAME;
5140 TRACE("-- 0x%08x\n", ret);
5141 return ret;
5144 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5145 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5146 if(cNames) *pMemId=pVDesc->vardesc.memid;
5147 return ret;
5150 /* not found, see if it can be found in an inherited interface */
5151 if(This->impltypelist) {
5152 /* recursive search */
5153 ITypeInfo *pTInfo;
5154 ret=ITypeInfo_GetRefTypeInfo(iface,
5155 This->impltypelist->hRef, &pTInfo);
5156 if(SUCCEEDED(ret)){
5157 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5158 ITypeInfo_Release(pTInfo);
5159 return ret;
5161 WARN("Could not search inherited interface!\n");
5162 } else
5163 WARN("no names found\n");
5164 return DISP_E_UNKNOWNNAME;
5167 /* ITypeInfo::Invoke
5169 * Invokes a method, or accesses a property of an object, that implements the
5170 * interface described by the type description.
5172 DWORD
5173 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5174 DWORD res;
5176 if (TRACE_ON(ole)) {
5177 int i;
5178 TRACE("Calling %p(",func);
5179 for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
5180 TRACE(")\n");
5183 switch (callconv) {
5184 case CC_STDCALL:
5186 switch (nrargs) {
5187 case 0:
5188 res = func();
5189 break;
5190 case 1:
5191 res = func(args[0]);
5192 break;
5193 case 2:
5194 res = func(args[0],args[1]);
5195 break;
5196 case 3:
5197 res = func(args[0],args[1],args[2]);
5198 break;
5199 case 4:
5200 res = func(args[0],args[1],args[2],args[3]);
5201 break;
5202 case 5:
5203 res = func(args[0],args[1],args[2],args[3],args[4]);
5204 break;
5205 case 6:
5206 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
5207 break;
5208 case 7:
5209 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
5210 break;
5211 case 8:
5212 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
5213 break;
5214 case 9:
5215 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
5216 break;
5217 case 10:
5218 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
5219 break;
5220 case 11:
5221 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
5222 break;
5223 case 12:
5224 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]);
5225 break;
5226 case 13:
5227 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]);
5228 break;
5229 case 14:
5230 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]);
5231 break;
5232 case 15:
5233 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]);
5234 break;
5235 case 16:
5236 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]);
5237 break;
5238 case 17:
5239 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]);
5240 break;
5241 case 18:
5242 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]);
5243 break;
5244 case 19:
5245 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]);
5246 break;
5247 case 20:
5248 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]);
5249 break;
5250 case 21:
5251 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]);
5252 break;
5253 case 22:
5254 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]);
5255 break;
5256 case 23:
5257 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]);
5258 break;
5259 case 24:
5260 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]);
5261 break;
5262 case 25:
5263 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]);
5264 break;
5265 case 26:
5266 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]);
5267 break;
5268 case 27:
5269 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]);
5270 break;
5271 case 28:
5272 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]);
5273 break;
5274 case 29:
5275 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]);
5276 break;
5277 case 30:
5278 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]);
5279 break;
5280 default:
5281 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
5282 res = -1;
5283 break;
5285 break;
5286 default:
5287 FIXME("unsupported calling convention %d\n",callconv);
5288 res = -1;
5289 break;
5291 TRACE("returns %08x\n",res);
5292 return res;
5295 extern int _argsize(DWORD vt);
5297 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5299 HRESULT hr = S_OK;
5300 ITypeInfo *tinfo2 = NULL;
5301 TYPEATTR *tattr = NULL;
5303 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5304 if (hr)
5306 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5307 "hr = 0x%08x\n",
5308 tdesc->u.hreftype, hr);
5309 return hr;
5311 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5312 if (hr)
5314 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5315 ITypeInfo_Release(tinfo2);
5316 return hr;
5319 switch (tattr->typekind)
5321 case TKIND_ENUM:
5322 *vt |= VT_I4;
5323 break;
5325 case TKIND_ALIAS:
5326 tdesc = &tattr->tdescAlias;
5327 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5328 break;
5330 case TKIND_INTERFACE:
5331 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5332 *vt |= VT_DISPATCH;
5333 else
5334 *vt |= VT_UNKNOWN;
5335 break;
5337 case TKIND_DISPATCH:
5338 *vt |= VT_DISPATCH;
5339 break;
5341 case TKIND_COCLASS:
5342 *vt |= VT_DISPATCH;
5343 break;
5345 case TKIND_RECORD:
5346 FIXME("TKIND_RECORD unhandled.\n");
5347 hr = E_NOTIMPL;
5348 break;
5350 case TKIND_UNION:
5351 FIXME("TKIND_UNION unhandled.\n");
5352 hr = E_NOTIMPL;
5353 break;
5355 default:
5356 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5357 hr = E_NOTIMPL;
5358 break;
5360 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5361 ITypeInfo_Release(tinfo2);
5362 return hr;
5365 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5367 HRESULT hr = S_OK;
5369 /* enforce only one level of pointer indirection */
5370 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5372 tdesc = tdesc->u.lptdesc;
5374 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5375 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5376 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5377 if ((tdesc->vt == VT_USERDEFINED) ||
5378 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5380 VARTYPE vt_userdefined = 0;
5381 const TYPEDESC *tdesc_userdefined = tdesc;
5382 if (tdesc->vt == VT_PTR)
5384 vt_userdefined = VT_BYREF;
5385 tdesc_userdefined = tdesc->u.lptdesc;
5387 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5388 if ((hr == S_OK) &&
5389 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5390 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5392 *vt |= vt_userdefined;
5393 return S_OK;
5396 *vt = VT_BYREF;
5399 switch (tdesc->vt)
5401 case VT_HRESULT:
5402 *vt |= VT_ERROR;
5403 break;
5404 case VT_USERDEFINED:
5405 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5406 break;
5407 case VT_VOID:
5408 case VT_CARRAY:
5409 case VT_PTR:
5410 case VT_LPSTR:
5411 case VT_LPWSTR:
5412 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5413 hr = DISP_E_BADVARTYPE;
5414 break;
5415 case VT_SAFEARRAY:
5416 *vt |= VT_ARRAY;
5417 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5418 break;
5419 default:
5420 *vt |= tdesc->vt;
5421 break;
5423 return hr;
5426 /***********************************************************************
5427 * DispCallFunc (OLEAUT32.@)
5429 * Invokes a function of the specifed calling convention, passing the
5430 * specified arguments and returns the result.
5432 * PARAMS
5433 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5434 * oVft [I] The offset in the vtable. See notes.
5435 * cc [I] Calling convention of the function to call.
5436 * vtReturn [I] The return type of the function.
5437 * cActuals [I] Number of parameters.
5438 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5439 * prgpvarg [I] The arguments to pass.
5440 * pvargResult [O] The return value of the function. Can be NULL.
5442 * RETURNS
5443 * Success: S_OK.
5444 * Failure: HRESULT code.
5446 * NOTES
5447 * The HRESULT return value of this function is not affected by the return
5448 * value of the user supplied function, which is returned in pvargResult.
5450 * If pvInstance is NULL then a non-object function is to be called and oVft
5451 * is the address of the function to call.
5453 * The cc parameter can be one of the following values:
5454 *|CC_FASTCALL
5455 *|CC_CDECL
5456 *|CC_PASCAL
5457 *|CC_STDCALL
5458 *|CC_FPFASTCALL
5459 *|CC_SYSCALL
5460 *|CC_MPWCDECL
5461 *|CC_MPWPASCAL
5464 HRESULT WINAPI
5465 DispCallFunc(
5466 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5467 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5469 int i, argsize, argspos;
5470 DWORD *args;
5471 HRESULT hres;
5473 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5474 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5475 pvargResult, V_VT(pvargResult));
5477 argsize = 0;
5478 if (pvInstance)
5479 argsize++; /* for This pointer */
5481 for (i=0;i<cActuals;i++)
5483 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5484 dump_Variant(prgpvarg[i]);
5485 argsize += _argsize(prgvt[i]);
5487 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5489 argspos = 0;
5490 if (pvInstance)
5492 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5493 argspos++;
5496 for (i=0;i<cActuals;i++)
5498 VARIANT *arg = prgpvarg[i];
5499 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5500 if (prgvt[i] == VT_VARIANT)
5501 memcpy(&args[argspos], arg, _argsize(prgvt[i]) * sizeof(DWORD));
5502 else
5503 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5504 argspos += _argsize(prgvt[i]);
5507 if (pvInstance)
5509 FARPROC *vtable = *(FARPROC**)pvInstance;
5510 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5512 else
5513 /* if we aren't invoking an object then the function pointer is stored
5514 * in oVft */
5515 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5517 if (pvargResult && (vtReturn != VT_EMPTY))
5519 TRACE("Method returned 0x%08x\n",hres);
5520 V_VT(pvargResult) = vtReturn;
5521 V_UI4(pvargResult) = hres;
5524 HeapFree(GetProcessHeap(),0,args);
5525 return S_OK;
5528 #define INVBUF_ELEMENT_SIZE \
5529 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5530 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5531 ((VARIANTARG *)(buffer))
5532 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5533 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5534 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5535 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5536 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5537 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5539 static HRESULT WINAPI ITypeInfo_fnInvoke(
5540 ITypeInfo2 *iface,
5541 VOID *pIUnk,
5542 MEMBERID memid,
5543 UINT16 wFlags,
5544 DISPPARAMS *pDispParams,
5545 VARIANT *pVarResult,
5546 EXCEPINFO *pExcepInfo,
5547 UINT *pArgErr)
5549 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5550 int i;
5551 unsigned int var_index;
5552 TYPEKIND type_kind;
5553 HRESULT hres;
5554 const TLBFuncDesc *pFuncInfo;
5556 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
5557 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5560 if (!pDispParams)
5562 ERR("NULL pDispParams not allowed\n");
5563 return E_INVALIDARG;
5566 dump_DispParms(pDispParams);
5568 if (pDispParams->cNamedArgs > pDispParams->cArgs)
5570 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
5571 pDispParams->cNamedArgs, pDispParams->cArgs);
5572 return E_INVALIDARG;
5575 /* we do this instead of using GetFuncDesc since it will return a fake
5576 * FUNCDESC for dispinterfaces and we want the real function description */
5577 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5578 if ((memid == pFuncInfo->funcdesc.memid) &&
5579 (wFlags & pFuncInfo->funcdesc.invkind))
5580 break;
5582 if (pFuncInfo) {
5583 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5585 if (TRACE_ON(ole))
5587 TRACE("invoking:\n");
5588 dump_TLBFuncDescOne(pFuncInfo);
5591 switch (func_desc->funckind) {
5592 case FUNC_PUREVIRTUAL:
5593 case FUNC_VIRTUAL: {
5594 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
5595 VARIANT varresult;
5596 VARIANT retval; /* pointer for storing byref retvals in */
5597 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
5598 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
5599 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
5600 UINT cNamedArgs = pDispParams->cNamedArgs;
5601 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
5603 hres = S_OK;
5605 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
5607 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
5609 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
5610 hres = DISP_E_PARAMNOTFOUND;
5611 goto func_fail;
5613 /* ignore the DISPID_PROPERTYPUT named argument from now on */
5614 cNamedArgs--;
5615 rgdispidNamedArgs++;
5618 if (func_desc->cParamsOpt < 0 && cNamedArgs)
5620 ERR("functions with the vararg attribute do not support named arguments\n");
5621 hres = DISP_E_NONAMEDARGS;
5622 goto func_fail;
5625 for (i = 0; i < func_desc->cParams; i++)
5627 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5628 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
5629 if (FAILED(hres))
5630 goto func_fail;
5633 TRACE("changing args\n");
5634 for (i = 0; i < func_desc->cParams; i++)
5636 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5637 VARIANTARG *src_arg;
5639 if (cNamedArgs)
5641 USHORT j;
5642 src_arg = NULL;
5643 for (j = 0; j < cNamedArgs; j++)
5644 if (rgdispidNamedArgs[j] == i)
5646 src_arg = &pDispParams->rgvarg[j];
5647 break;
5650 else
5651 src_arg = i < pDispParams->cArgs ? &pDispParams->rgvarg[pDispParams->cArgs - 1 - i] : NULL;
5653 if (wParamFlags & PARAMFLAG_FRETVAL)
5655 /* under most conditions the caller is not allowed to
5656 * pass in a dispparam arg in the index of what would be
5657 * the retval parameter. however, there is an exception
5658 * where the extra parameter is used in an extra
5659 * IDispatch::Invoke below */
5660 if ((i < pDispParams->cArgs) &&
5661 ((func_desc->cParams != 1) || !pVarResult ||
5662 !(func_desc->invkind & INVOKE_PROPERTYGET)))
5664 hres = DISP_E_BADPARAMCOUNT;
5665 break;
5668 /* note: this check is placed so that if the caller passes
5669 * in a VARIANTARG for the retval we just ignore it, like
5670 * native does */
5671 if (i == func_desc->cParams - 1)
5673 VARIANTARG *arg;
5674 arg = prgpvarg[i] = &rgvarg[i];
5675 memset(arg, 0, sizeof(*arg));
5676 V_VT(arg) = rgvt[i];
5677 memset(&retval, 0, sizeof(retval));
5678 V_BYREF(arg) = &retval;
5680 else
5682 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
5683 hres = E_UNEXPECTED;
5684 break;
5687 else if (src_arg)
5689 dump_Variant(src_arg);
5691 if (rgvt[i] == VT_VARIANT)
5692 hres = VariantCopy(&rgvarg[i], src_arg);
5693 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
5695 if (rgvt[i] == V_VT(src_arg))
5696 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
5697 else
5699 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5700 hres = VariantCopy(&missing_arg[i], src_arg);
5701 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
5703 V_VT(&rgvarg[i]) = rgvt[i];
5705 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
5707 SAFEARRAY *a;
5708 SAFEARRAYBOUND bound;
5709 VARIANT *v;
5710 LONG j;
5711 bound.lLbound = 0;
5712 bound.cElements = pDispParams->cArgs-i;
5713 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
5715 ERR("SafeArrayCreate failed\n");
5716 break;
5718 hres = SafeArrayAccessData(a, (LPVOID)&v);
5719 if (hres != S_OK)
5721 ERR("SafeArrayAccessData failed with %x\n", hres);
5722 break;
5724 for (j = 0; j < bound.cElements; j++)
5725 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
5726 hres = SafeArrayUnaccessData(a);
5727 if (hres != S_OK)
5729 ERR("SafeArrayUnaccessData failed with %x\n", hres);
5730 break;
5732 V_ARRAY(&rgvarg[i]) = a;
5733 V_VT(&rgvarg[i]) = rgvt[i];
5735 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
5737 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5738 V_VT(&missing_arg[i]) = V_VT(src_arg);
5739 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
5740 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
5741 V_VT(&rgvarg[i]) = rgvt[i];
5743 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
5745 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
5746 V_VT(&rgvarg[i]) = rgvt[i];
5748 else
5750 /* FIXME: this doesn't work for VT_BYREF arguments if
5751 * they are not the same type as in the paramdesc */
5752 V_VT(&rgvarg[i]) = V_VT(src_arg);
5753 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
5754 V_VT(&rgvarg[i]) = rgvt[i];
5757 if (FAILED(hres))
5759 ERR("failed to convert param %d to %s%s from %s%s\n", i,
5760 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
5761 debugstr_VT(src_arg), debugstr_VF(src_arg));
5762 break;
5764 prgpvarg[i] = &rgvarg[i];
5766 else if (wParamFlags & PARAMFLAG_FOPT)
5768 VARIANTARG *arg;
5769 arg = prgpvarg[i] = &rgvarg[i];
5770 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5772 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
5773 if (FAILED(hres))
5774 break;
5776 else
5778 VARIANTARG *missing_arg;
5779 /* if the function wants a pointer to a variant then
5780 * set that up, otherwise just pass the VT_ERROR in
5781 * the argument by value */
5782 if (rgvt[i] & VT_BYREF)
5784 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
5785 V_VT(arg) = VT_VARIANT | VT_BYREF;
5786 V_VARIANTREF(arg) = missing_arg;
5788 else
5789 missing_arg = arg;
5790 V_VT(missing_arg) = VT_ERROR;
5791 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
5794 else
5796 hres = DISP_E_BADPARAMCOUNT;
5797 break;
5800 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5802 /* VT_VOID is a special case for return types, so it is not
5803 * handled in the general function */
5804 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
5805 V_VT(&varresult) = VT_EMPTY;
5806 else
5808 V_VT(&varresult) = 0;
5809 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
5810 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5813 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
5814 V_VT(&varresult), func_desc->cParams, rgvt,
5815 prgpvarg, &varresult);
5817 for (i = 0; i < func_desc->cParams; i++)
5819 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5820 if (wParamFlags & PARAMFLAG_FRETVAL)
5822 if (TRACE_ON(ole))
5824 TRACE("[retval] value: ");
5825 dump_Variant(prgpvarg[i]);
5828 if (pVarResult)
5830 VariantInit(pVarResult);
5831 /* deref return value */
5832 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
5835 /* free data stored in varresult. Note that
5836 * VariantClear doesn't do what we want because we are
5837 * working with byref types. */
5838 /* FIXME: clear safearrays, bstrs, records and
5839 * variants here too */
5840 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
5841 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
5843 if(*V_UNKNOWNREF(prgpvarg[i]))
5844 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
5846 break;
5848 else if (i < pDispParams->cArgs)
5850 if (wParamFlags & PARAMFLAG_FOUT)
5852 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5854 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
5855 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
5857 if (FAILED(hres))
5859 ERR("failed to convert param %d to vt %d\n", i,
5860 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
5861 break;
5864 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
5865 func_desc->cParamsOpt < 0 &&
5866 i == func_desc->cParams-1)
5868 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
5869 LONG j, ubound;
5870 VARIANT *v;
5871 hres = SafeArrayGetUBound(a, 1, &ubound);
5872 if (hres != S_OK)
5874 ERR("SafeArrayGetUBound failed with %x\n", hres);
5875 break;
5877 hres = SafeArrayAccessData(a, (LPVOID)&v);
5878 if (hres != S_OK)
5880 ERR("SafeArrayAccessData failed with %x\n", hres);
5881 break;
5883 for (j = 0; j <= ubound; j++)
5884 VariantClear(&v[j]);
5885 hres = SafeArrayUnaccessData(a);
5886 if (hres != S_OK)
5888 ERR("SafeArrayUnaccessData failed with %x\n", hres);
5889 break;
5892 VariantClear(&rgvarg[i]);
5894 else if (wParamFlags & PARAMFLAG_FOPT)
5896 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5897 VariantClear(&rgvarg[i]);
5901 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
5903 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
5904 hres = DISP_E_EXCEPTION;
5905 if (pExcepInfo)
5907 IErrorInfo *pErrorInfo;
5908 pExcepInfo->scode = V_ERROR(&varresult);
5909 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
5911 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
5912 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
5913 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
5914 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
5916 IErrorInfo_Release(pErrorInfo);
5920 if (V_VT(&varresult) != VT_ERROR)
5922 TRACE("varresult value: ");
5923 dump_Variant(&varresult);
5925 if (pVarResult)
5927 VariantClear(pVarResult);
5928 *pVarResult = varresult;
5930 else
5931 VariantClear(&varresult);
5934 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
5935 (func_desc->invkind & INVOKE_PROPERTYGET) &&
5936 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
5937 (pDispParams->cArgs != 0))
5939 if (V_VT(pVarResult) == VT_DISPATCH)
5941 IDispatch *pDispatch = V_DISPATCH(pVarResult);
5942 /* Note: not VariantClear; we still need the dispatch
5943 * pointer to be valid */
5944 VariantInit(pVarResult);
5945 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
5946 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
5947 pDispParams, pVarResult, pExcepInfo, pArgErr);
5948 IDispatch_Release(pDispatch);
5950 else
5952 VariantClear(pVarResult);
5953 hres = DISP_E_NOTACOLLECTION;
5957 func_fail:
5958 HeapFree(GetProcessHeap(), 0, buffer);
5959 break;
5961 case FUNC_DISPATCH: {
5962 IDispatch *disp;
5964 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5965 if (SUCCEEDED(hres)) {
5966 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5967 hres = IDispatch_Invoke(
5968 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
5969 pVarResult,pExcepInfo,pArgErr
5971 if (FAILED(hres))
5972 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
5973 IDispatch_Release(disp);
5974 } else
5975 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5976 break;
5978 default:
5979 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5980 hres = E_FAIL;
5981 break;
5984 TRACE("-- 0x%08x\n", hres);
5985 return hres;
5987 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5988 VARDESC *var_desc;
5990 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5991 if(FAILED(hres)) return hres;
5993 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5994 dump_VARDESC(var_desc);
5995 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
5996 return E_NOTIMPL;
5999 /* not found, look for it in inherited interfaces */
6000 ITypeInfo2_GetTypeKind(iface, &type_kind);
6001 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6002 if(This->impltypelist) {
6003 /* recursive search */
6004 ITypeInfo *pTInfo;
6005 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6006 if(SUCCEEDED(hres)){
6007 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6008 ITypeInfo_Release(pTInfo);
6009 return hres;
6011 WARN("Could not search inherited interface!\n");
6014 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6015 return DISP_E_MEMBERNOTFOUND;
6018 /* ITypeInfo::GetDocumentation
6020 * Retrieves the documentation string, the complete Help file name and path,
6021 * and the context ID for the Help topic for a specified type description.
6023 * (Can be tested by the Visual Basic Editor in Word for instance.)
6025 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6026 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6027 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6029 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6030 const TLBFuncDesc *pFDesc;
6031 const TLBVarDesc *pVDesc;
6032 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6033 " HelpContext(%p) HelpFile(%p)\n",
6034 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6035 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6036 if(pBstrName)
6037 *pBstrName=SysAllocString(This->Name);
6038 if(pBstrDocString)
6039 *pBstrDocString=SysAllocString(This->DocString);
6040 if(pdwHelpContext)
6041 *pdwHelpContext=This->dwHelpContext;
6042 if(pBstrHelpFile)
6043 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6044 return S_OK;
6045 }else {/* for a member */
6046 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6047 if(pFDesc->funcdesc.memid==memid){
6048 if(pBstrName)
6049 *pBstrName = SysAllocString(pFDesc->Name);
6050 if(pBstrDocString)
6051 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6052 if(pdwHelpContext)
6053 *pdwHelpContext=pFDesc->helpcontext;
6054 return S_OK;
6056 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6057 if(pVDesc->vardesc.memid==memid){
6058 if(pBstrName)
6059 *pBstrName = SysAllocString(pVDesc->Name);
6060 if(pBstrDocString)
6061 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6062 if(pdwHelpContext)
6063 *pdwHelpContext=pVDesc->HelpContext;
6064 return S_OK;
6068 if(This->impltypelist &&
6069 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6070 /* recursive search */
6071 ITypeInfo *pTInfo;
6072 HRESULT result;
6073 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6074 &pTInfo);
6075 if(SUCCEEDED(result)) {
6076 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6077 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6078 ITypeInfo_Release(pTInfo);
6079 return result;
6081 WARN("Could not search inherited interface!\n");
6084 WARN("member %d not found\n", memid);
6085 return TYPE_E_ELEMENTNOTFOUND;
6088 /* ITypeInfo::GetDllEntry
6090 * Retrieves a description or specification of an entry point for a function
6091 * in a DLL.
6093 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6094 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6095 WORD *pwOrdinal)
6097 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6098 const TLBFuncDesc *pFDesc;
6100 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6102 if (pBstrDllName) *pBstrDllName = NULL;
6103 if (pBstrName) *pBstrName = NULL;
6104 if (pwOrdinal) *pwOrdinal = 0;
6106 if (This->TypeAttr.typekind != TKIND_MODULE)
6107 return TYPE_E_BADMODULEKIND;
6109 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6110 if(pFDesc->funcdesc.memid==memid){
6111 dump_TypeInfo(This);
6112 if (TRACE_ON(ole))
6113 dump_TLBFuncDescOne(pFDesc);
6115 if (pBstrDllName)
6116 *pBstrDllName = SysAllocString(This->DllName);
6118 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6119 if (pBstrName)
6120 *pBstrName = SysAllocString(pFDesc->Entry);
6121 if (pwOrdinal)
6122 *pwOrdinal = -1;
6123 return S_OK;
6125 if (pBstrName)
6126 *pBstrName = NULL;
6127 if (pwOrdinal)
6128 *pwOrdinal = (DWORD)pFDesc->Entry;
6129 return S_OK;
6131 return TYPE_E_ELEMENTNOTFOUND;
6134 /* internal function to make the inherited interfaces' methods appear
6135 * part of the interface */
6136 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6137 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6139 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6140 HRESULT hr;
6142 TRACE("%p, 0x%x\n", iface, *hRefType);
6144 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK))
6146 ITypeInfo *pSubTypeInfo;
6148 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
6149 if (FAILED(hr))
6150 return hr;
6152 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6153 hRefType, ppTInfo);
6154 ITypeInfo_Release(pSubTypeInfo);
6155 if (SUCCEEDED(hr))
6156 return hr;
6158 *hRefType -= DISPATCH_HREF_OFFSET;
6160 if (!(*hRefType & DISPATCH_HREF_MASK))
6161 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6162 else
6163 return E_FAIL;
6166 /* ITypeInfo::GetRefTypeInfo
6168 * If a type description references other type descriptions, it retrieves
6169 * the referenced type descriptions.
6171 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6172 ITypeInfo2 *iface,
6173 HREFTYPE hRefType,
6174 ITypeInfo **ppTInfo)
6176 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6177 HRESULT result = E_FAIL;
6179 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6181 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6182 ITypeInfo_AddRef(*ppTInfo);
6183 result = S_OK;
6185 else if (hRefType == -1 &&
6186 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6187 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6189 /* when we meet a DUAL dispinterface, we must create the interface
6190 * version of it.
6192 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
6195 /* the interface version contains the same information as the dispinterface
6196 * copy the contents of the structs.
6198 *pTypeInfoImpl = *This;
6199 pTypeInfoImpl->ref = 0;
6201 /* change the type to interface */
6202 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6204 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6206 /* we use data structures from This, so we need to keep a reference
6207 * to it to stop it being destroyed and signal to the new instance to
6208 * not free its data structures when it is destroyed */
6209 pTypeInfoImpl->no_free_data = TRUE;
6210 pTypeInfoImpl->next = This;
6211 ITypeInfo_AddRef((ITypeInfo*) This);
6213 ITypeInfo_AddRef(*ppTInfo);
6215 result = S_OK;
6217 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6218 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6219 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6221 HREFTYPE href_dispatch = hRefType;
6222 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6223 } else {
6224 TLBRefType *ref_type;
6225 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6227 if(ref_type->reference == hRefType)
6228 break;
6230 if(&ref_type->entry == &This->pTypeLib->ref_list)
6232 FIXME("Can't find pRefType for ref %x\n", hRefType);
6233 goto end;
6235 if(hRefType != -1) {
6236 ITypeLib *pTLib = NULL;
6238 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6239 UINT Index;
6240 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6241 } else {
6242 if(ref_type->pImpTLInfo->pImpTypeLib) {
6243 TRACE("typeinfo in imported typelib that is already loaded\n");
6244 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6245 ITypeLib2_AddRef((ITypeLib*) pTLib);
6246 result = S_OK;
6247 } else {
6248 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6249 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6250 ref_type->pImpTLInfo->wVersionMajor,
6251 ref_type->pImpTLInfo->wVersionMinor,
6252 ref_type->pImpTLInfo->lcid,
6253 &pTLib);
6255 if(!SUCCEEDED(result)) {
6256 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6257 result=LoadTypeLib(libnam, &pTLib);
6258 SysFreeString(libnam);
6260 if(SUCCEEDED(result)) {
6261 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6262 ITypeLib2_AddRef(pTLib);
6266 if(SUCCEEDED(result)) {
6267 if(ref_type->index == TLB_REF_USE_GUID)
6268 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6269 &ref_type->guid,
6270 ppTInfo);
6271 else
6272 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6273 ppTInfo);
6275 if (pTLib != NULL)
6276 ITypeLib2_Release(pTLib);
6280 end:
6281 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6282 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6283 return result;
6286 /* ITypeInfo::AddressOfMember
6288 * Retrieves the addresses of static functions or variables, such as those
6289 * defined in a DLL.
6291 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6292 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6294 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6295 HRESULT hr;
6296 BSTR dll, entry;
6297 WORD ordinal;
6298 HMODULE module;
6300 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6302 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6303 if (FAILED(hr))
6304 return hr;
6306 module = LoadLibraryW(dll);
6307 if (!module)
6309 ERR("couldn't load %s\n", debugstr_w(dll));
6310 SysFreeString(dll);
6311 if (entry) SysFreeString(entry);
6312 return STG_E_FILENOTFOUND;
6314 /* FIXME: store library somewhere where we can free it */
6316 if (entry)
6318 LPSTR entryA;
6319 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6320 entryA = HeapAlloc(GetProcessHeap(), 0, len);
6321 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6323 *ppv = GetProcAddress(module, entryA);
6324 if (!*ppv)
6325 ERR("function not found %s\n", debugstr_a(entryA));
6327 HeapFree(GetProcessHeap(), 0, entryA);
6329 else
6331 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6332 if (!*ppv)
6333 ERR("function not found %d\n", ordinal);
6336 SysFreeString(dll);
6337 if (entry) SysFreeString(entry);
6339 if (!*ppv)
6340 return TYPE_E_DLLFUNCTIONNOTFOUND;
6342 return S_OK;
6345 /* ITypeInfo::CreateInstance
6347 * Creates a new instance of a type that describes a component object class
6348 * (coclass).
6350 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6351 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6353 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6354 HRESULT hr;
6355 TYPEATTR *pTA;
6357 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6359 *ppvObj = NULL;
6361 if(pOuterUnk)
6363 WARN("Not able to aggregate\n");
6364 return CLASS_E_NOAGGREGATION;
6367 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6368 if(FAILED(hr)) return hr;
6370 if(pTA->typekind != TKIND_COCLASS)
6372 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6373 hr = E_INVALIDARG;
6374 goto end;
6377 hr = S_FALSE;
6378 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6380 IUnknown *pUnk;
6381 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6382 TRACE("GetActiveObject rets %08x\n", hr);
6383 if(hr == S_OK)
6385 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6386 IUnknown_Release(pUnk);
6390 if(hr != S_OK)
6391 hr = CoCreateInstance(&pTA->guid, NULL,
6392 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6393 riid, ppvObj);
6395 end:
6396 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6397 return hr;
6400 /* ITypeInfo::GetMops
6402 * Retrieves marshalling information.
6404 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6405 BSTR *pBstrMops)
6407 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6408 FIXME("(%p) stub!\n", This);
6409 return S_OK;
6412 /* ITypeInfo::GetContainingTypeLib
6414 * Retrieves the containing type library and the index of the type description
6415 * within that type library.
6417 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6418 ITypeLib * *ppTLib, UINT *pIndex)
6420 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6422 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6423 if (pIndex) {
6424 *pIndex=This->index;
6425 TRACE("returning pIndex=%d\n", *pIndex);
6428 if (ppTLib) {
6429 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6430 ITypeLib2_AddRef(*ppTLib);
6431 TRACE("returning ppTLib=%p\n", *ppTLib);
6434 return S_OK;
6437 /* ITypeInfo::ReleaseTypeAttr
6439 * Releases a TYPEATTR previously returned by GetTypeAttr.
6442 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6443 TYPEATTR* pTypeAttr)
6445 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6446 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6447 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6450 /* ITypeInfo::ReleaseFuncDesc
6452 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6454 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6455 ITypeInfo2 *iface,
6456 FUNCDESC *pFuncDesc)
6458 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6459 SHORT i;
6461 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6463 for (i = 0; i < pFuncDesc->cParams; i++)
6464 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6465 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6467 SysFreeString((BSTR)pFuncDesc);
6470 /* ITypeInfo::ReleaseVarDesc
6472 * Releases a VARDESC previously returned by GetVarDesc.
6474 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6475 VARDESC *pVarDesc)
6477 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6478 TRACE("(%p)->(%p)\n", This, pVarDesc);
6480 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6481 if (pVarDesc->varkind == VAR_CONST)
6482 VariantClear(pVarDesc->u.lpvarValue);
6483 SysFreeString((BSTR)pVarDesc);
6486 /* ITypeInfo2::GetTypeKind
6488 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6491 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6492 TYPEKIND *pTypeKind)
6494 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6495 *pTypeKind=This->TypeAttr.typekind;
6496 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6497 return S_OK;
6500 /* ITypeInfo2::GetTypeFlags
6502 * Returns the type flags without any allocations. This returns a DWORD type
6503 * flag, which expands the type flags without growing the TYPEATTR (type
6504 * attribute).
6507 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6509 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6510 *pTypeFlags=This->TypeAttr.wTypeFlags;
6511 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6512 return S_OK;
6515 /* ITypeInfo2::GetFuncIndexOfMemId
6516 * Binds to a specific member based on a known DISPID, where the member name
6517 * is not known (for example, when binding to a default member).
6520 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
6521 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
6523 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6524 const TLBFuncDesc *pFuncInfo;
6525 int i;
6526 HRESULT result;
6528 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
6529 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
6530 break;
6531 if(pFuncInfo) {
6532 *pFuncIndex = i;
6533 result = S_OK;
6534 } else
6535 result = TYPE_E_ELEMENTNOTFOUND;
6537 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
6538 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6539 return result;
6542 /* TypeInfo2::GetVarIndexOfMemId
6544 * Binds to a specific member based on a known DISPID, where the member name
6545 * is not known (for example, when binding to a default member).
6548 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
6549 MEMBERID memid, UINT *pVarIndex)
6551 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6552 TLBVarDesc *pVarInfo;
6553 int i;
6554 HRESULT result;
6555 for(i=0, pVarInfo=This->varlist; pVarInfo &&
6556 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
6558 if(pVarInfo) {
6559 *pVarIndex = i;
6560 result = S_OK;
6561 } else
6562 result = TYPE_E_ELEMENTNOTFOUND;
6564 TRACE("(%p) memid 0x%08x -> %s\n", This,
6565 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6566 return result;
6569 /* ITypeInfo2::GetCustData
6571 * Gets the custom data
6573 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
6574 ITypeInfo2 * iface,
6575 REFGUID guid,
6576 VARIANT *pVarVal)
6578 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6579 TLBCustData *pCData;
6581 for(pCData=This->pCustData; pCData; pCData = pCData->next)
6582 if( IsEqualIID(guid, &pCData->guid)) break;
6584 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6586 if(pCData)
6588 VariantInit( pVarVal);
6589 VariantCopy( pVarVal, &pCData->data);
6590 return S_OK;
6592 return E_INVALIDARG; /* FIXME: correct? */
6595 /* ITypeInfo2::GetFuncCustData
6597 * Gets the custom data
6599 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
6600 ITypeInfo2 * iface,
6601 UINT index,
6602 REFGUID guid,
6603 VARIANT *pVarVal)
6605 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6606 TLBCustData *pCData=NULL;
6607 TLBFuncDesc * pFDesc;
6608 int i;
6609 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6610 pFDesc=pFDesc->next);
6612 if(pFDesc)
6613 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
6614 if( IsEqualIID(guid, &pCData->guid)) break;
6616 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6618 if(pCData){
6619 VariantInit( pVarVal);
6620 VariantCopy( pVarVal, &pCData->data);
6621 return S_OK;
6623 return E_INVALIDARG; /* FIXME: correct? */
6626 /* ITypeInfo2::GetParamCustData
6628 * Gets the custom data
6630 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
6631 ITypeInfo2 * iface,
6632 UINT indexFunc,
6633 UINT indexParam,
6634 REFGUID guid,
6635 VARIANT *pVarVal)
6637 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6638 TLBCustData *pCData=NULL;
6639 TLBFuncDesc * pFDesc;
6640 int i;
6642 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
6644 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
6645 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
6646 pCData = pCData->next)
6647 if( IsEqualIID(guid, &pCData->guid)) break;
6649 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6651 if(pCData)
6653 VariantInit( pVarVal);
6654 VariantCopy( pVarVal, &pCData->data);
6655 return S_OK;
6657 return E_INVALIDARG; /* FIXME: correct? */
6660 /* ITypeInfo2::GetVarCustData
6662 * Gets the custom data
6664 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
6665 ITypeInfo2 * iface,
6666 UINT index,
6667 REFGUID guid,
6668 VARIANT *pVarVal)
6670 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6671 TLBCustData *pCData=NULL;
6672 TLBVarDesc * pVDesc;
6673 int i;
6675 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
6677 if(pVDesc)
6679 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
6681 if( IsEqualIID(guid, &pCData->guid)) break;
6685 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6687 if(pCData)
6689 VariantInit( pVarVal);
6690 VariantCopy( pVarVal, &pCData->data);
6691 return S_OK;
6693 return E_INVALIDARG; /* FIXME: correct? */
6696 /* ITypeInfo2::GetImplCustData
6698 * Gets the custom data
6700 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6701 ITypeInfo2 * iface,
6702 UINT index,
6703 REFGUID guid,
6704 VARIANT *pVarVal)
6706 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6707 TLBCustData *pCData=NULL;
6708 TLBImplType * pRDesc;
6709 int i;
6711 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6713 if(pRDesc)
6715 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6717 if( IsEqualIID(guid, &pCData->guid)) break;
6721 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6723 if(pCData)
6725 VariantInit( pVarVal);
6726 VariantCopy( pVarVal, &pCData->data);
6727 return S_OK;
6729 return E_INVALIDARG; /* FIXME: correct? */
6732 /* ITypeInfo2::GetDocumentation2
6734 * Retrieves the documentation string, the complete Help file name and path,
6735 * the localization context to use, and the context ID for the library Help
6736 * topic in the Help file.
6739 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6740 ITypeInfo2 * iface,
6741 MEMBERID memid,
6742 LCID lcid,
6743 BSTR *pbstrHelpString,
6744 DWORD *pdwHelpStringContext,
6745 BSTR *pbstrHelpStringDll)
6747 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6748 const TLBFuncDesc *pFDesc;
6749 const TLBVarDesc *pVDesc;
6750 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
6751 "HelpStringContext(%p) HelpStringDll(%p)\n",
6752 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6753 pbstrHelpStringDll );
6754 /* the help string should be obtained from the helpstringdll,
6755 * using the _DLLGetDocumentation function, based on the supplied
6756 * lcid. Nice to do sometime...
6758 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6759 if(pbstrHelpString)
6760 *pbstrHelpString=SysAllocString(This->Name);
6761 if(pdwHelpStringContext)
6762 *pdwHelpStringContext=This->dwHelpStringContext;
6763 if(pbstrHelpStringDll)
6764 *pbstrHelpStringDll=
6765 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6766 return S_OK;
6767 }else {/* for a member */
6768 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6769 if(pFDesc->funcdesc.memid==memid){
6770 if(pbstrHelpString)
6771 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6772 if(pdwHelpStringContext)
6773 *pdwHelpStringContext=pFDesc->HelpStringContext;
6774 if(pbstrHelpStringDll)
6775 *pbstrHelpStringDll=
6776 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6777 return S_OK;
6779 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6780 if(pVDesc->vardesc.memid==memid){
6781 if(pbstrHelpString)
6782 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6783 if(pdwHelpStringContext)
6784 *pdwHelpStringContext=pVDesc->HelpStringContext;
6785 if(pbstrHelpStringDll)
6786 *pbstrHelpStringDll=
6787 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6788 return S_OK;
6791 return TYPE_E_ELEMENTNOTFOUND;
6794 /* ITypeInfo2::GetAllCustData
6796 * Gets all custom data items for the Type info.
6799 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6800 ITypeInfo2 * iface,
6801 CUSTDATA *pCustData)
6803 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6804 TLBCustData *pCData;
6805 int i;
6807 TRACE("(%p) returning %d items\n", This, This->ctCustData);
6809 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6810 if(pCustData->prgCustData ){
6811 pCustData->cCustData=This->ctCustData;
6812 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
6813 pCustData->prgCustData[i].guid=pCData->guid;
6814 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
6816 }else{
6817 ERR(" OUT OF MEMORY!\n");
6818 return E_OUTOFMEMORY;
6820 return S_OK;
6823 /* ITypeInfo2::GetAllFuncCustData
6825 * Gets all custom data items for the specified Function
6828 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
6829 ITypeInfo2 * iface,
6830 UINT index,
6831 CUSTDATA *pCustData)
6833 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6834 TLBCustData *pCData;
6835 TLBFuncDesc * pFDesc;
6836 int i;
6837 TRACE("(%p) index %d\n", This, index);
6838 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6839 pFDesc=pFDesc->next)
6841 if(pFDesc){
6842 pCustData->prgCustData =
6843 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
6844 if(pCustData->prgCustData ){
6845 pCustData->cCustData=pFDesc->ctCustData;
6846 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
6847 pCData = pCData->next){
6848 pCustData->prgCustData[i].guid=pCData->guid;
6849 VariantCopy(& pCustData->prgCustData[i].varValue,
6850 & pCData->data);
6852 }else{
6853 ERR(" OUT OF MEMORY!\n");
6854 return E_OUTOFMEMORY;
6856 return S_OK;
6858 return TYPE_E_ELEMENTNOTFOUND;
6861 /* ITypeInfo2::GetAllParamCustData
6863 * Gets all custom data items for the Functions
6866 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
6867 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
6869 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6870 TLBCustData *pCData=NULL;
6871 TLBFuncDesc * pFDesc;
6872 int i;
6873 TRACE("(%p) index %d\n", This, indexFunc);
6874 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
6875 pFDesc=pFDesc->next)
6877 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
6878 pCustData->prgCustData =
6879 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
6880 sizeof(CUSTDATAITEM));
6881 if(pCustData->prgCustData ){
6882 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
6883 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
6884 pCData; i++, pCData = pCData->next){
6885 pCustData->prgCustData[i].guid=pCData->guid;
6886 VariantCopy(& pCustData->prgCustData[i].varValue,
6887 & pCData->data);
6889 }else{
6890 ERR(" OUT OF MEMORY!\n");
6891 return E_OUTOFMEMORY;
6893 return S_OK;
6895 return TYPE_E_ELEMENTNOTFOUND;
6898 /* ITypeInfo2::GetAllVarCustData
6900 * Gets all custom data items for the specified Variable
6903 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
6904 UINT index, CUSTDATA *pCustData)
6906 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6907 TLBCustData *pCData;
6908 TLBVarDesc * pVDesc;
6909 int i;
6910 TRACE("(%p) index %d\n", This, index);
6911 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
6912 pVDesc=pVDesc->next)
6914 if(pVDesc){
6915 pCustData->prgCustData =
6916 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
6917 if(pCustData->prgCustData ){
6918 pCustData->cCustData=pVDesc->ctCustData;
6919 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
6920 pCData = pCData->next){
6921 pCustData->prgCustData[i].guid=pCData->guid;
6922 VariantCopy(& pCustData->prgCustData[i].varValue,
6923 & pCData->data);
6925 }else{
6926 ERR(" OUT OF MEMORY!\n");
6927 return E_OUTOFMEMORY;
6929 return S_OK;
6931 return TYPE_E_ELEMENTNOTFOUND;
6934 /* ITypeInfo2::GetAllImplCustData
6936 * Gets all custom data items for the specified implementation type
6939 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
6940 ITypeInfo2 * iface,
6941 UINT index,
6942 CUSTDATA *pCustData)
6944 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6945 TLBCustData *pCData;
6946 TLBImplType * pRDesc;
6947 int i;
6948 TRACE("(%p) index %d\n", This, index);
6949 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
6950 pRDesc=pRDesc->next)
6952 if(pRDesc){
6953 pCustData->prgCustData =
6954 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
6955 if(pCustData->prgCustData ){
6956 pCustData->cCustData=pRDesc->ctCustData;
6957 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
6958 pCData = pCData->next){
6959 pCustData->prgCustData[i].guid=pCData->guid;
6960 VariantCopy(& pCustData->prgCustData[i].varValue,
6961 & pCData->data);
6963 }else{
6964 ERR(" OUT OF MEMORY!\n");
6965 return E_OUTOFMEMORY;
6967 return S_OK;
6969 return TYPE_E_ELEMENTNOTFOUND;
6972 static const ITypeInfo2Vtbl tinfvt =
6975 ITypeInfo_fnQueryInterface,
6976 ITypeInfo_fnAddRef,
6977 ITypeInfo_fnRelease,
6979 ITypeInfo_fnGetTypeAttr,
6980 ITypeInfo_fnGetTypeComp,
6981 ITypeInfo_fnGetFuncDesc,
6982 ITypeInfo_fnGetVarDesc,
6983 ITypeInfo_fnGetNames,
6984 ITypeInfo_fnGetRefTypeOfImplType,
6985 ITypeInfo_fnGetImplTypeFlags,
6986 ITypeInfo_fnGetIDsOfNames,
6987 ITypeInfo_fnInvoke,
6988 ITypeInfo_fnGetDocumentation,
6989 ITypeInfo_fnGetDllEntry,
6990 ITypeInfo_fnGetRefTypeInfo,
6991 ITypeInfo_fnAddressOfMember,
6992 ITypeInfo_fnCreateInstance,
6993 ITypeInfo_fnGetMops,
6994 ITypeInfo_fnGetContainingTypeLib,
6995 ITypeInfo_fnReleaseTypeAttr,
6996 ITypeInfo_fnReleaseFuncDesc,
6997 ITypeInfo_fnReleaseVarDesc,
6999 ITypeInfo2_fnGetTypeKind,
7000 ITypeInfo2_fnGetTypeFlags,
7001 ITypeInfo2_fnGetFuncIndexOfMemId,
7002 ITypeInfo2_fnGetVarIndexOfMemId,
7003 ITypeInfo2_fnGetCustData,
7004 ITypeInfo2_fnGetFuncCustData,
7005 ITypeInfo2_fnGetParamCustData,
7006 ITypeInfo2_fnGetVarCustData,
7007 ITypeInfo2_fnGetImplTypeCustData,
7008 ITypeInfo2_fnGetDocumentation2,
7009 ITypeInfo2_fnGetAllCustData,
7010 ITypeInfo2_fnGetAllFuncCustData,
7011 ITypeInfo2_fnGetAllParamCustData,
7012 ITypeInfo2_fnGetAllVarCustData,
7013 ITypeInfo2_fnGetAllImplTypeCustData,
7016 /******************************************************************************
7017 * CreateDispTypeInfo [OLEAUT32.31]
7019 * Build type information for an object so it can be called through an
7020 * IDispatch interface.
7022 * RETURNS
7023 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7024 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7026 * NOTES
7027 * This call allows an objects methods to be accessed through IDispatch, by
7028 * building an ITypeInfo object that IDispatch can use to call through.
7030 HRESULT WINAPI CreateDispTypeInfo(
7031 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7032 LCID lcid, /* [I] Locale Id */
7033 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7035 ITypeInfoImpl *pTIClass, *pTIIface;
7036 ITypeLibImpl *pTypeLibImpl;
7037 int param, func;
7038 TLBFuncDesc **ppFuncDesc;
7039 TLBRefType *ref;
7041 TRACE("\n");
7042 pTypeLibImpl = TypeLibImpl_Constructor();
7043 if (!pTypeLibImpl) return E_FAIL;
7045 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
7046 pTIIface->pTypeLib = pTypeLibImpl;
7047 pTIIface->index = 0;
7048 pTIIface->Name = NULL;
7049 pTIIface->dwHelpContext = -1;
7050 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7051 pTIIface->TypeAttr.lcid = lcid;
7052 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7053 pTIIface->TypeAttr.wMajorVerNum = 0;
7054 pTIIface->TypeAttr.wMinorVerNum = 0;
7055 pTIIface->TypeAttr.cbAlignment = 2;
7056 pTIIface->TypeAttr.cbSizeInstance = -1;
7057 pTIIface->TypeAttr.cbSizeVft = -1;
7058 pTIIface->TypeAttr.cFuncs = 0;
7059 pTIIface->TypeAttr.cImplTypes = 0;
7060 pTIIface->TypeAttr.cVars = 0;
7061 pTIIface->TypeAttr.wTypeFlags = 0;
7063 ppFuncDesc = &pTIIface->funclist;
7064 for(func = 0; func < pidata->cMembers; func++) {
7065 METHODDATA *md = pidata->pmethdata + func;
7066 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
7067 (*ppFuncDesc)->Name = SysAllocString(md->szName);
7068 (*ppFuncDesc)->funcdesc.memid = md->dispid;
7069 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
7070 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
7071 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
7072 (*ppFuncDesc)->funcdesc.callconv = md->cc;
7073 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
7074 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
7075 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
7076 (*ppFuncDesc)->funcdesc.cScodes = 0;
7077 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
7078 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7079 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7080 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7081 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7082 md->cArgs * sizeof(ELEMDESC));
7083 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7084 md->cArgs * sizeof(TLBParDesc));
7085 for(param = 0; param < md->cArgs; param++) {
7086 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7087 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7089 (*ppFuncDesc)->helpcontext = 0;
7090 (*ppFuncDesc)->HelpStringContext = 0;
7091 (*ppFuncDesc)->HelpString = NULL;
7092 (*ppFuncDesc)->Entry = NULL;
7093 (*ppFuncDesc)->ctCustData = 0;
7094 (*ppFuncDesc)->pCustData = NULL;
7095 (*ppFuncDesc)->next = NULL;
7096 pTIIface->TypeAttr.cFuncs++;
7097 ppFuncDesc = &(*ppFuncDesc)->next;
7100 dump_TypeInfo(pTIIface);
7102 pTypeLibImpl->pTypeInfo = pTIIface;
7103 pTypeLibImpl->TypeInfoCount++;
7105 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
7106 pTIClass->pTypeLib = pTypeLibImpl;
7107 pTIClass->index = 1;
7108 pTIClass->Name = NULL;
7109 pTIClass->dwHelpContext = -1;
7110 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7111 pTIClass->TypeAttr.lcid = lcid;
7112 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7113 pTIClass->TypeAttr.wMajorVerNum = 0;
7114 pTIClass->TypeAttr.wMinorVerNum = 0;
7115 pTIClass->TypeAttr.cbAlignment = 2;
7116 pTIClass->TypeAttr.cbSizeInstance = -1;
7117 pTIClass->TypeAttr.cbSizeVft = -1;
7118 pTIClass->TypeAttr.cFuncs = 0;
7119 pTIClass->TypeAttr.cImplTypes = 1;
7120 pTIClass->TypeAttr.cVars = 0;
7121 pTIClass->TypeAttr.wTypeFlags = 0;
7123 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
7124 pTIClass->impltypelist->hRef = 0;
7126 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
7127 ref->index = 0;
7128 ref->reference = 0;
7129 ref->pImpTLInfo = TLB_REF_INTERNAL;
7130 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7132 dump_TypeInfo(pTIClass);
7134 pTIIface->next = pTIClass;
7135 pTypeLibImpl->TypeInfoCount++;
7137 *pptinfo = (ITypeInfo*)pTIClass;
7139 ITypeInfo_AddRef(*pptinfo);
7140 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7142 return S_OK;
7146 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7148 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7150 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7153 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7155 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7157 return ITypeInfo_AddRef((ITypeInfo *)This);
7160 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7162 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7164 return ITypeInfo_Release((ITypeInfo *)This);
7167 static HRESULT WINAPI ITypeComp_fnBind(
7168 ITypeComp * iface,
7169 OLECHAR * szName,
7170 ULONG lHash,
7171 WORD wFlags,
7172 ITypeInfo ** ppTInfo,
7173 DESCKIND * pDescKind,
7174 BINDPTR * pBindPtr)
7176 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7177 const TLBFuncDesc *pFDesc;
7178 const TLBVarDesc *pVDesc;
7179 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7181 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7183 *pDescKind = DESCKIND_NONE;
7184 pBindPtr->lpfuncdesc = NULL;
7185 *ppTInfo = NULL;
7187 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
7188 if (!strcmpiW(pFDesc->Name, szName)) {
7189 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7190 break;
7191 else
7192 /* name found, but wrong flags */
7193 hr = TYPE_E_TYPEMISMATCH;
7196 if (pFDesc)
7198 HRESULT hr = TLB_AllocAndInitFuncDesc(
7199 &pFDesc->funcdesc,
7200 &pBindPtr->lpfuncdesc,
7201 This->TypeAttr.typekind == TKIND_DISPATCH);
7202 if (FAILED(hr))
7203 return hr;
7204 *pDescKind = DESCKIND_FUNCDESC;
7205 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7206 ITypeInfo_AddRef(*ppTInfo);
7207 return S_OK;
7208 } else {
7209 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7210 if (!strcmpiW(pVDesc->Name, szName)) {
7211 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7212 if (FAILED(hr))
7213 return hr;
7214 *pDescKind = DESCKIND_VARDESC;
7215 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7216 ITypeInfo_AddRef(*ppTInfo);
7217 return S_OK;
7221 /* FIXME: search each inherited interface, not just the first */
7222 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7223 /* recursive search */
7224 ITypeInfo *pTInfo;
7225 ITypeComp *pTComp;
7226 HRESULT hr;
7227 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7228 if (SUCCEEDED(hr))
7230 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7231 ITypeInfo_Release(pTInfo);
7233 if (SUCCEEDED(hr))
7235 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7236 ITypeComp_Release(pTComp);
7237 return hr;
7239 WARN("Could not search inherited interface!\n");
7241 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
7242 return hr;
7245 static HRESULT WINAPI ITypeComp_fnBindType(
7246 ITypeComp * iface,
7247 OLECHAR * szName,
7248 ULONG lHash,
7249 ITypeInfo ** ppTInfo,
7250 ITypeComp ** ppTComp)
7252 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7254 /* strange behaviour (does nothing) but like the
7255 * original */
7257 if (!ppTInfo || !ppTComp)
7258 return E_POINTER;
7260 *ppTInfo = NULL;
7261 *ppTComp = NULL;
7263 return S_OK;
7266 static const ITypeCompVtbl tcompvt =
7269 ITypeComp_fnQueryInterface,
7270 ITypeComp_fnAddRef,
7271 ITypeComp_fnRelease,
7273 ITypeComp_fnBind,
7274 ITypeComp_fnBindType