save old text color during a call of DrawCaptionTempW
[wine/kumbayo.git] / dlls / oleaut32 / typelib.c
blobae4df69bab2eb70c422d3b8abaf5dbe3f864b4d6
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 /* free custom data allocated by MSFT_CustData */
1425 static inline void TLB_FreeCustData(TLBCustData *pCustData)
1427 TLBCustData *pCustDataNext;
1428 for (; pCustData; pCustData = pCustDataNext)
1430 VariantClear(&pCustData->data);
1432 pCustDataNext = pCustData->next;
1433 TLB_Free(pCustData);
1437 /**********************************************************************
1439 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1441 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1443 return pcx->pos;
1446 static inline void MSFT_Seek(TLBContext *pcx, long where)
1448 if (where != DO_NOT_SEEK)
1450 where += pcx->oStart;
1451 if (where > pcx->length)
1453 /* FIXME */
1454 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1455 TLB_abort();
1457 pcx->pos = where;
1461 /* read function */
1462 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1464 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1465 pcx->pos, count, pcx->oStart, pcx->length, where);
1467 MSFT_Seek(pcx, where);
1468 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1469 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1470 pcx->pos += count;
1471 return count;
1474 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1475 long where )
1477 DWORD ret;
1479 ret = MSFT_Read(buffer, count, pcx, where);
1480 FromLEDWords(buffer, ret);
1482 return ret;
1485 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1486 long where )
1488 DWORD ret;
1490 ret = MSFT_Read(buffer, count, pcx, where);
1491 FromLEWords(buffer, ret);
1493 return ret;
1496 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1498 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1499 memset(pGuid,0, sizeof(GUID));
1500 return;
1502 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1503 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1504 pGuid->Data2 = FromLEWord(pGuid->Data2);
1505 pGuid->Data3 = FromLEWord(pGuid->Data3);
1506 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1509 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1511 MSFT_NameIntro niName;
1513 if (offset < 0)
1515 ERR_(typelib)("bad offset %d\n", offset);
1516 return -1;
1519 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1520 pcx->pTblDir->pNametab.offset+offset);
1522 return niName.hreftype;
1525 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1527 char * name;
1528 MSFT_NameIntro niName;
1529 int lengthInChars;
1530 BSTR bstrName = NULL;
1532 if (offset < 0)
1534 ERR_(typelib)("bad offset %d\n", offset);
1535 return NULL;
1537 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1538 pcx->pTblDir->pNametab.offset+offset);
1539 niName.namelen &= 0xFF; /* FIXME: correct ? */
1540 name=TLB_Alloc((niName.namelen & 0xff) +1);
1541 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1542 name[niName.namelen & 0xff]='\0';
1544 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1545 name, -1, NULL, 0);
1547 /* no invalid characters in string */
1548 if (lengthInChars)
1550 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1552 /* don't check for invalid character since this has been done previously */
1553 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1555 TLB_Free(name);
1557 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1558 return bstrName;
1561 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1563 char * string;
1564 INT16 length;
1565 int lengthInChars;
1566 BSTR bstr = NULL;
1568 if(offset<0) return NULL;
1569 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1570 if(length <= 0) return 0;
1571 string=TLB_Alloc(length +1);
1572 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1573 string[length]='\0';
1575 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1576 string, -1, NULL, 0);
1578 /* no invalid characters in string */
1579 if (lengthInChars)
1581 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1583 /* don't check for invalid character since this has been done previously */
1584 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1586 TLB_Free(string);
1588 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1589 return bstr;
1592 * read a value and fill a VARIANT structure
1594 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1596 int size;
1598 TRACE_(typelib)("\n");
1600 if(offset <0) { /* data are packed in here */
1601 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1602 V_I4(pVar) = offset & 0x3ffffff;
1603 return;
1605 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1606 pcx->pTblDir->pCustData.offset + offset );
1607 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1608 switch (V_VT(pVar)){
1609 case VT_EMPTY: /* FIXME: is this right? */
1610 case VT_NULL: /* FIXME: is this right? */
1611 case VT_I2 : /* this should not happen */
1612 case VT_I4 :
1613 case VT_R4 :
1614 case VT_ERROR :
1615 case VT_BOOL :
1616 case VT_I1 :
1617 case VT_UI1 :
1618 case VT_UI2 :
1619 case VT_UI4 :
1620 case VT_INT :
1621 case VT_UINT :
1622 case VT_VOID : /* FIXME: is this right? */
1623 case VT_HRESULT :
1624 size=4; break;
1625 case VT_R8 :
1626 case VT_CY :
1627 case VT_DATE :
1628 case VT_I8 :
1629 case VT_UI8 :
1630 case VT_DECIMAL : /* FIXME: is this right? */
1631 case VT_FILETIME :
1632 size=8;break;
1633 /* pointer types with known behaviour */
1634 case VT_BSTR :{
1635 char * ptr;
1636 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1637 if(size < 0) {
1638 char next;
1639 DWORD origPos = MSFT_Tell(pcx), nullPos;
1641 do {
1642 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1643 } while (next);
1644 nullPos = MSFT_Tell(pcx);
1645 size = nullPos - origPos;
1646 MSFT_Seek(pcx, origPos);
1648 ptr=TLB_Alloc(size);/* allocate temp buffer */
1649 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1650 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1651 /* FIXME: do we need a AtoW conversion here? */
1652 V_UNION(pVar, bstrVal[size])='\0';
1653 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1654 TLB_Free(ptr);
1656 size=-4; break;
1657 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1658 case VT_DISPATCH :
1659 case VT_VARIANT :
1660 case VT_UNKNOWN :
1661 case VT_PTR :
1662 case VT_SAFEARRAY :
1663 case VT_CARRAY :
1664 case VT_USERDEFINED :
1665 case VT_LPSTR :
1666 case VT_LPWSTR :
1667 case VT_BLOB :
1668 case VT_STREAM :
1669 case VT_STORAGE :
1670 case VT_STREAMED_OBJECT :
1671 case VT_STORED_OBJECT :
1672 case VT_BLOB_OBJECT :
1673 case VT_CF :
1674 case VT_CLSID :
1675 default:
1676 size=0;
1677 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1678 V_VT(pVar));
1681 if(size>0) /* (big|small) endian correct? */
1682 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1683 return;
1686 * create a linked list with custom data
1688 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1690 MSFT_CDGuid entry;
1691 TLBCustData* pNew;
1692 int count=0;
1694 TRACE_(typelib)("\n");
1696 while(offset >=0){
1697 count++;
1698 pNew=TLB_Alloc(sizeof(TLBCustData));
1699 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1700 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1701 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1702 /* add new custom data at head of the list */
1703 pNew->next=*ppCustData;
1704 *ppCustData=pNew;
1705 offset = entry.next;
1707 return count;
1710 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1711 ITypeInfoImpl *pTI)
1713 if(type <0)
1714 pTd->vt=type & VT_TYPEMASK;
1715 else
1716 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1718 if(pTd->vt == VT_USERDEFINED)
1719 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1721 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1724 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1726 /* resolve referenced type if any */
1727 while (lpTypeDesc)
1729 switch (lpTypeDesc->vt)
1731 case VT_PTR:
1732 lpTypeDesc = lpTypeDesc->u.lptdesc;
1733 break;
1735 case VT_CARRAY:
1736 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1737 break;
1739 case VT_USERDEFINED:
1740 MSFT_DoRefType(pcx, pTI->pTypeLib,
1741 lpTypeDesc->u.hreftype);
1743 lpTypeDesc = NULL;
1744 break;
1746 default:
1747 lpTypeDesc = NULL;
1752 static void
1753 MSFT_DoFuncs(TLBContext* pcx,
1754 ITypeInfoImpl* pTI,
1755 int cFuncs,
1756 int cVars,
1757 int offset,
1758 TLBFuncDesc** pptfd)
1761 * member information is stored in a data structure at offset
1762 * indicated by the memoffset field of the typeinfo structure
1763 * There are several distinctive parts.
1764 * The first part starts with a field that holds the total length
1765 * of this (first) part excluding this field. Then follow the records,
1766 * for each member there is one record.
1768 * The first entry is always the length of the record (including this
1769 * length word).
1770 * The rest of the record depends on the type of the member. If there is
1771 * a field indicating the member type (function, variable, interface, etc)
1772 * I have not found it yet. At this time we depend on the information
1773 * in the type info and the usual order how things are stored.
1775 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1776 * for each member;
1778 * Third is an equal sized array with file offsets to the name entry
1779 * of each member.
1781 * The fourth and last (?) part is an array with offsets to the records
1782 * in the first part of this file segment.
1785 int infolen, nameoffset, reclength, nrattributes, i;
1786 int recoffset = offset + sizeof(INT);
1788 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1789 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1790 TLBFuncDesc *ptfd_prev = NULL;
1792 TRACE_(typelib)("\n");
1794 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1796 for ( i = 0; i < cFuncs ; i++ )
1798 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1800 /* name, eventually add to a hash table */
1801 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1802 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1804 /* nameoffset is sometimes -1 on the second half of a propget/propput
1805 * pair of functions */
1806 if ((nameoffset == -1) && (i > 0))
1807 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1808 else
1809 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1811 /* read the function information record */
1812 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1814 reclength &= 0xffff;
1816 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1818 /* do the attributes */
1819 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1820 / sizeof(int);
1822 if ( nrattributes > 0 )
1824 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1826 if ( nrattributes > 1 )
1828 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1829 pFuncRec->OptAttr[1]) ;
1831 if ( nrattributes > 2 )
1833 if ( pFuncRec->FKCCIC & 0x2000 )
1835 if (HIWORD(pFuncRec->OptAttr[2]) != 0)
1836 ERR("ordinal 0x%08x invalid, HIWORD != 0\n", pFuncRec->OptAttr[2]);
1837 (*pptfd)->Entry = (BSTR)pFuncRec->OptAttr[2];
1839 else
1841 (*pptfd)->Entry = MSFT_ReadString(pcx,
1842 pFuncRec->OptAttr[2]);
1844 if( nrattributes > 5 )
1846 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1848 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1850 MSFT_CustData(pcx,
1851 pFuncRec->OptAttr[6],
1852 &(*pptfd)->pCustData);
1856 else
1858 (*pptfd)->Entry = (BSTR)-1;
1863 /* fill the FuncDesc Structure */
1864 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1865 offset + infolen + ( i + 1) * sizeof(INT));
1867 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1868 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1869 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1870 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1871 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1872 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1873 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1875 MSFT_GetTdesc(pcx,
1876 pFuncRec->DataType,
1877 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1878 pTI);
1879 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1881 /* do the parameters/arguments */
1882 if(pFuncRec->nrargs)
1884 int j = 0;
1885 MSFT_ParameterInfo paraminfo;
1887 (*pptfd)->funcdesc.lprgelemdescParam =
1888 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1890 (*pptfd)->pParamDesc =
1891 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1893 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1894 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1896 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1898 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1900 MSFT_GetTdesc(pcx,
1901 paraminfo.DataType,
1902 &elemdesc->tdesc,
1903 pTI);
1905 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1907 /* name */
1908 if (paraminfo.oName == -1)
1909 /* this occurs for [propput] or [propget] methods, so
1910 * we should just set the name of the parameter to the
1911 * name of the method. */
1912 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1913 else
1914 (*pptfd)->pParamDesc[j].Name =
1915 MSFT_ReadName( pcx, paraminfo.oName );
1916 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1918 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1920 /* default value */
1921 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1922 (pFuncRec->FKCCIC & 0x1000) )
1924 INT* pInt = (INT *)((char *)pFuncRec +
1925 reclength -
1926 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1928 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1930 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1931 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1933 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1934 pInt[j], pcx);
1936 else
1937 elemdesc->u.paramdesc.pparamdescex = NULL;
1938 /* custom info */
1939 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1941 MSFT_CustData(pcx,
1942 pFuncRec->OptAttr[7+j],
1943 &(*pptfd)->pParamDesc[j].pCustData);
1946 /* SEEK value = jump to offset,
1947 * from there jump to the end of record,
1948 * go back by (j-1) arguments
1950 MSFT_ReadLEDWords( &paraminfo ,
1951 sizeof(MSFT_ParameterInfo), pcx,
1952 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1953 * sizeof(MSFT_ParameterInfo)));
1957 /* scode is not used: archaic win16 stuff FIXME: right? */
1958 (*pptfd)->funcdesc.cScodes = 0 ;
1959 (*pptfd)->funcdesc.lprgscode = NULL ;
1961 ptfd_prev = *pptfd;
1962 pptfd = & ((*pptfd)->next);
1963 recoffset += reclength;
1965 HeapFree(GetProcessHeap(), 0, recbuf);
1968 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1969 int cVars, int offset, TLBVarDesc ** pptvd)
1971 int infolen, nameoffset, reclength;
1972 char recbuf[256];
1973 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1974 int i;
1975 int recoffset;
1977 TRACE_(typelib)("\n");
1979 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1980 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1981 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1982 recoffset += offset+sizeof(INT);
1983 for(i=0;i<cVars;i++){
1984 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1985 /* name, eventually add to a hash table */
1986 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1987 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
1988 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1989 /* read the variable information record */
1990 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1991 reclength &=0xff;
1992 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1993 /* Optional data */
1994 if(reclength >(6*sizeof(INT)) )
1995 (*pptvd)->HelpContext=pVarRec->HelpContext;
1996 if(reclength >(7*sizeof(INT)) )
1997 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1998 if(reclength >(8*sizeof(INT)) )
1999 if(reclength >(9*sizeof(INT)) )
2000 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
2001 /* fill the VarDesc Structure */
2002 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
2003 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2004 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
2005 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
2006 MSFT_GetTdesc(pcx, pVarRec->DataType,
2007 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
2008 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2009 if(pVarRec->VarKind == VAR_CONST ){
2010 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
2011 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
2012 pVarRec->OffsValue, pcx);
2013 } else
2014 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
2015 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
2016 pptvd=&((*pptvd)->next);
2017 recoffset += reclength;
2020 /* fill in data for a hreftype (offset). When the referenced type is contained
2021 * in the typelib, it's just an (file) offset in the type info base dir.
2022 * If comes from import, it's an offset+1 in the ImpInfo table
2023 * */
2024 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2025 int offset)
2027 int j;
2028 TLBRefType *ref;
2030 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2032 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2034 if(ref->reference == offset) return;
2037 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
2038 list_add_tail(&pTL->ref_list, &ref->entry);
2040 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2041 /* external typelib */
2042 MSFT_ImpInfo impinfo;
2043 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2045 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2047 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2048 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2049 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
2050 if(pImpLib->offset==impinfo.oImpFile) break;
2051 pImpLib=pImpLib->next;
2053 if(pImpLib){
2054 ref->reference = offset;
2055 ref->pImpTLInfo = pImpLib;
2056 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2057 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2058 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2059 ref->index = TLB_REF_USE_GUID;
2060 } else
2061 ref->index = impinfo.oGuid;
2062 }else{
2063 ERR("Cannot find a reference\n");
2064 ref->reference = -1;
2065 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2067 }else{
2068 /* in this typelib */
2069 ref->index = MSFT_HREFTYPE_INDEX(offset);
2070 ref->reference = offset;
2071 ref->pImpTLInfo = TLB_REF_INTERNAL;
2075 /* process Implemented Interfaces of a com class */
2076 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2077 int offset)
2079 int i;
2080 MSFT_RefRecord refrec;
2081 TLBImplType **ppImpl = &pTI->impltypelist;
2083 TRACE_(typelib)("\n");
2085 for(i=0;i<count;i++){
2086 if(offset<0) break; /* paranoia */
2087 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2088 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2089 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2090 (*ppImpl)->hRef = refrec.reftype;
2091 (*ppImpl)->implflags=refrec.flags;
2092 (*ppImpl)->ctCustData=
2093 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2094 offset=refrec.onext;
2095 ppImpl=&((*ppImpl)->next);
2099 * process a typeinfo record
2101 static ITypeInfoImpl * MSFT_DoTypeInfo(
2102 TLBContext *pcx,
2103 int count,
2104 ITypeLibImpl * pLibInfo)
2106 MSFT_TypeInfoBase tiBase;
2107 ITypeInfoImpl *ptiRet;
2109 TRACE_(typelib)("count=%u\n", count);
2111 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2112 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2113 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2115 /* this is where we are coming from */
2116 ptiRet->pTypeLib = pLibInfo;
2117 ptiRet->index=count;
2118 /* fill in the typeattr fields */
2120 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2121 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2122 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2123 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2124 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2125 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2126 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2127 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2128 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2129 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2130 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2131 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2132 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2133 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2134 MSFT_GetTdesc(pcx, tiBase.datatype1,
2135 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2137 /* FIXME: */
2138 /* IDLDESC idldescType; *//* never saw this one != zero */
2140 /* name, eventually add to a hash table */
2141 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2142 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2143 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2144 /* help info */
2145 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2146 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2147 ptiRet->dwHelpContext=tiBase.helpcontext;
2149 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2150 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2152 /* note: InfoType's Help file and HelpStringDll come from the containing
2153 * library. Further HelpString and Docstring appear to be the same thing :(
2155 /* functions */
2156 if(ptiRet->TypeAttr.cFuncs >0 )
2157 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2158 ptiRet->TypeAttr.cVars,
2159 tiBase.memoffset, & ptiRet->funclist);
2160 /* variables */
2161 if(ptiRet->TypeAttr.cVars >0 )
2162 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2163 ptiRet->TypeAttr.cVars,
2164 tiBase.memoffset, & ptiRet->varlist);
2165 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2166 switch(ptiRet->TypeAttr.typekind)
2168 case TKIND_COCLASS:
2169 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2170 tiBase.datatype1);
2171 break;
2172 case TKIND_DISPATCH:
2173 /* This is not -1 when the interface is a non-base dual interface or
2174 when a dispinterface wraps an interface ie the idl 'dispinterface x {interface y;};'.
2175 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2176 not this interface.
2179 if (tiBase.datatype1 != -1)
2181 ptiRet->impltypelist = TLB_Alloc(sizeof(TLBImplType));
2182 ptiRet->impltypelist->hRef = tiBase.datatype1;
2183 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2185 break;
2186 default:
2187 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2188 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2189 ptiRet->impltypelist->hRef = tiBase.datatype1;
2190 break;
2193 ptiRet->ctCustData=
2194 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2196 TRACE_(typelib)("%s guid: %s kind:%s\n",
2197 debugstr_w(ptiRet->Name),
2198 debugstr_guid(&ptiRet->TypeAttr.guid),
2199 typekind_desc[ptiRet->TypeAttr.typekind]);
2201 return ptiRet;
2204 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2205 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2206 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2207 * tradeoff here.
2209 static ITypeLibImpl *tlb_cache_first;
2210 static CRITICAL_SECTION cache_section;
2211 static CRITICAL_SECTION_DEBUG cache_section_debug =
2213 0, 0, &cache_section,
2214 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2215 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2217 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2220 /****************************************************************************
2221 * TLB_ReadTypeLib
2223 * find the type of the typelib file and map the typelib resource into
2224 * the memory
2226 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2227 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2228 static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2230 ITypeLibImpl *entry;
2231 int ret = TYPE_E_CANTLOADLIBRARY;
2232 INT index = 1;
2233 HINSTANCE hinstDLL;
2234 LPWSTR index_str, file = (LPWSTR)pszFileName;
2236 *ppTypeLib = NULL;
2238 index_str = strrchrW(pszFileName, '\\');
2239 if(index_str && *++index_str != '\0')
2241 LPWSTR end_ptr;
2242 long idx = strtolW(index_str, &end_ptr, 10);
2243 if(*end_ptr == '\0')
2245 int str_len = index_str - pszFileName - 1;
2246 index = idx;
2247 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
2248 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2249 file[str_len] = 0;
2253 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2255 if(strchrW(file, '\\'))
2257 lstrcpyW(pszPath, file);
2259 else
2261 int len = GetSystemDirectoryW(pszPath, cchPath);
2262 pszPath[len] = '\\';
2263 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2267 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file);
2269 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2271 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2272 EnterCriticalSection(&cache_section);
2273 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2275 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2277 TRACE("cache hit\n");
2278 *ppTypeLib = (ITypeLib2*)entry;
2279 ITypeLib_AddRef(*ppTypeLib);
2280 LeaveCriticalSection(&cache_section);
2281 return S_OK;
2284 LeaveCriticalSection(&cache_section);
2286 /* now actually load and parse the typelib */
2288 hinstDLL = LoadLibraryExW(pszPath, 0, DONT_RESOLVE_DLL_REFERENCES |
2289 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2291 if (hinstDLL)
2293 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2294 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2295 if (hrsrc)
2297 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2298 if (hGlobal)
2300 LPVOID pBase = LockResource(hGlobal);
2301 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2303 if (pBase)
2305 /* try to load as incore resource */
2306 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2307 if (dwSignature == MSFT_SIGNATURE)
2308 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2309 else if (dwSignature == SLTG_SIGNATURE)
2310 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2311 else
2312 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2314 FreeResource( hGlobal );
2317 FreeLibrary(hinstDLL);
2319 else
2321 HANDLE hFile = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2322 if (INVALID_HANDLE_VALUE != hFile)
2324 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2325 if (hMapping)
2327 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2328 if(pBase)
2330 /* retrieve file size */
2331 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2332 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2334 if (dwSignature == MSFT_SIGNATURE)
2335 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2336 else if (dwSignature == SLTG_SIGNATURE)
2337 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2339 UnmapViewOfFile(pBase);
2341 CloseHandle(hMapping);
2343 CloseHandle(hFile);
2347 if(*ppTypeLib) {
2348 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2350 TRACE("adding to cache\n");
2351 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2352 lstrcpyW(impl->path, pszPath);
2353 /* We should really canonicalise the path here. */
2354 impl->index = index;
2356 /* FIXME: check if it has added already in the meantime */
2357 EnterCriticalSection(&cache_section);
2358 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2359 impl->prev = NULL;
2360 tlb_cache_first = impl;
2361 LeaveCriticalSection(&cache_section);
2362 ret = S_OK;
2363 } else
2364 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2366 return ret;
2369 /*================== ITypeLib(2) Methods ===================================*/
2371 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2373 ITypeLibImpl* pTypeLibImpl;
2375 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2376 if (!pTypeLibImpl) return NULL;
2378 pTypeLibImpl->lpVtbl = &tlbvt;
2379 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2380 pTypeLibImpl->ref = 1;
2382 list_init(&pTypeLibImpl->ref_list);
2383 pTypeLibImpl->dispatch_href = -1;
2385 return pTypeLibImpl;
2388 /****************************************************************************
2389 * ITypeLib2_Constructor_MSFT
2391 * loading an MSFT typelib from an in-memory image
2393 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2395 TLBContext cx;
2396 long lPSegDir;
2397 MSFT_Header tlbHeader;
2398 MSFT_SegDir tlbSegDir;
2399 ITypeLibImpl * pTypeLibImpl;
2401 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2403 pTypeLibImpl = TypeLibImpl_Constructor();
2404 if (!pTypeLibImpl) return NULL;
2406 /* get pointer to beginning of typelib data */
2407 cx.pos = 0;
2408 cx.oStart=0;
2409 cx.mapping = pLib;
2410 cx.pLibInfo = pTypeLibImpl;
2411 cx.length = dwTLBLength;
2413 /* read header */
2414 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2415 TRACE_(typelib)("header:\n");
2416 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2417 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2418 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2419 return NULL;
2421 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2423 /* there is a small amount of information here until the next important
2424 * part:
2425 * the segment directory . Try to calculate the amount of data */
2426 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2428 /* now read the segment directory */
2429 TRACE("read segment directory (at %ld)\n",lPSegDir);
2430 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2431 cx.pTblDir = &tlbSegDir;
2433 /* just check two entries */
2434 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2436 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2437 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2438 return NULL;
2441 /* now fill our internal data */
2442 /* TLIBATTR fields */
2443 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2445 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2446 /* Windows seems to have zero here, is this correct? */
2447 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2448 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2449 else
2450 pTypeLibImpl->LibAttr.lcid = 0;
2452 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2453 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2454 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2455 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2457 /* name, eventually add to a hash table */
2458 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2460 /* help info */
2461 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2462 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2464 if( tlbHeader.varflags & HELPDLLFLAG)
2466 int offset;
2467 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2468 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2471 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2473 /* custom data */
2474 if(tlbHeader.CustomDataOffset >= 0)
2476 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2479 /* fill in typedescriptions */
2480 if(tlbSegDir.pTypdescTab.length > 0)
2482 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2483 INT16 td[4];
2484 pTypeLibImpl->ctTypeDesc = cTD;
2485 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2486 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2487 for(i=0; i<cTD; )
2489 /* FIXME: add several sanity checks here */
2490 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2491 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2493 /* FIXME: check safearray */
2494 if(td[3] < 0)
2495 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2496 else
2497 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2499 else if(td[0] == VT_CARRAY)
2501 /* array descr table here */
2502 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2504 else if(td[0] == VT_USERDEFINED)
2506 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2508 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2511 /* second time around to fill the array subscript info */
2512 for(i=0;i<cTD;i++)
2514 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2515 if(tlbSegDir.pArrayDescriptions.offset>0)
2517 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2518 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2520 if(td[1]<0)
2521 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2522 else
2523 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2525 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2527 for(j = 0; j<td[2]; j++)
2529 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2530 sizeof(INT), &cx, DO_NOT_SEEK);
2531 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2532 sizeof(INT), &cx, DO_NOT_SEEK);
2535 else
2537 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2538 ERR("didn't find array description data\n");
2543 /* imported type libs */
2544 if(tlbSegDir.pImpFiles.offset>0)
2546 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2547 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2548 UINT16 size;
2550 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2552 char *name;
2553 DWORD len;
2555 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2556 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2557 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2559 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2560 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2561 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2562 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2564 size >>= 2;
2565 name = TLB_Alloc(size+1);
2566 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2567 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2568 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2569 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2570 TLB_Free(name);
2572 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2573 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2575 ppImpLib = &(*ppImpLib)->next;
2579 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
2580 if(pTypeLibImpl->dispatch_href != -1)
2581 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
2583 /* type info's */
2584 if(tlbHeader.nrtypeinfos >= 0 )
2586 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2587 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2588 int i;
2590 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2592 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2594 ppTI = &((*ppTI)->next);
2595 (pTypeLibImpl->TypeInfoCount)++;
2599 TRACE("(%p)\n", pTypeLibImpl);
2600 return (ITypeLib2*) pTypeLibImpl;
2604 static BSTR TLB_MultiByteToBSTR(const char *ptr)
2606 DWORD len;
2607 WCHAR *nameW;
2608 BSTR ret;
2610 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2611 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2612 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2613 ret = SysAllocString(nameW);
2614 HeapFree(GetProcessHeap(), 0, nameW);
2615 return ret;
2618 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
2620 char b[3];
2621 int i;
2622 short s;
2624 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2625 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2626 return FALSE;
2629 guid->Data4[0] = s >> 8;
2630 guid->Data4[1] = s & 0xff;
2632 b[2] = '\0';
2633 for(i = 0; i < 6; i++) {
2634 memcpy(b, str + 24 + 2 * i, 2);
2635 guid->Data4[i + 2] = strtol(b, NULL, 16);
2637 return TRUE;
2640 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
2642 WORD bytelen;
2643 DWORD len;
2644 WCHAR *nameW;
2646 *pBstr = NULL;
2647 bytelen = *(const WORD*)ptr;
2648 if(bytelen == 0xffff) return 2;
2649 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2650 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2651 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2652 *pBstr = SysAllocStringLen(nameW, len);
2653 HeapFree(GetProcessHeap(), 0, nameW);
2654 return bytelen + 2;
2657 static WORD SLTG_ReadStringA(const char *ptr, char **str)
2659 WORD bytelen;
2661 *str = NULL;
2662 bytelen = *(const WORD*)ptr;
2663 if(bytelen == 0xffff) return 2;
2664 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2665 memcpy(*str, ptr + 2, bytelen);
2666 (*str)[bytelen] = '\0';
2667 return bytelen + 2;
2670 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2672 char *ptr = pLibBlk;
2673 WORD w;
2675 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2676 FIXME("libblk magic = %04x\n", w);
2677 return 0;
2680 ptr += 6;
2681 if((w = *(WORD*)ptr) != 0xffff) {
2682 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2683 ptr += w;
2685 ptr += 2;
2687 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2689 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2691 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2692 ptr += 4;
2694 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2695 ptr += 2;
2697 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2698 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2699 else
2700 pTypeLibImpl->LibAttr.lcid = 0;
2701 ptr += 2;
2703 ptr += 4; /* skip res12 */
2705 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2706 ptr += 2;
2708 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2709 ptr += 2;
2711 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2712 ptr += 2;
2714 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2715 ptr += sizeof(GUID);
2717 return ptr - (char*)pLibBlk;
2720 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
2721 typedef struct
2723 unsigned int num;
2724 HREFTYPE refs[1];
2725 } sltg_ref_lookup_t;
2727 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
2728 HREFTYPE *typelib_ref)
2730 if(typeinfo_ref < table->num)
2732 *typelib_ref = table->refs[typeinfo_ref];
2733 return S_OK;
2736 ERR("Unable to find reference\n");
2737 *typelib_ref = -1;
2738 return E_FAIL;
2741 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
2743 BOOL done = FALSE;
2745 while(!done) {
2746 if((*pType & 0xe00) == 0xe00) {
2747 pTD->vt = VT_PTR;
2748 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2749 sizeof(TYPEDESC));
2750 pTD = pTD->u.lptdesc;
2752 switch(*pType & 0x3f) {
2753 case VT_PTR:
2754 pTD->vt = VT_PTR;
2755 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2756 sizeof(TYPEDESC));
2757 pTD = pTD->u.lptdesc;
2758 break;
2760 case VT_USERDEFINED:
2761 pTD->vt = VT_USERDEFINED;
2762 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
2763 done = TRUE;
2764 break;
2766 case VT_CARRAY:
2768 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2769 array */
2771 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2773 pTD->vt = VT_CARRAY;
2774 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2775 sizeof(ARRAYDESC) +
2776 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2777 pTD->u.lpadesc->cDims = pSA->cDims;
2778 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2779 pSA->cDims * sizeof(SAFEARRAYBOUND));
2781 pTD = &pTD->u.lpadesc->tdescElem;
2782 break;
2785 case VT_SAFEARRAY:
2787 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2788 useful? */
2790 pType++;
2791 pTD->vt = VT_SAFEARRAY;
2792 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2793 sizeof(TYPEDESC));
2794 pTD = pTD->u.lptdesc;
2795 break;
2797 default:
2798 pTD->vt = *pType & 0x3f;
2799 done = TRUE;
2800 break;
2802 pType++;
2804 return pType;
2807 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
2808 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
2810 /* Handle [in/out] first */
2811 if((*pType & 0xc000) == 0xc000)
2812 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2813 else if(*pType & 0x8000)
2814 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2815 else if(*pType & 0x4000)
2816 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2817 else
2818 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2820 if(*pType & 0x2000)
2821 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2823 if(*pType & 0x80)
2824 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2826 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
2830 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
2831 char *pNameTable)
2833 int ref;
2834 char *name;
2835 TLBRefType *ref_type;
2836 sltg_ref_lookup_t *table;
2837 HREFTYPE typelib_ref;
2839 if(pRef->magic != SLTG_REF_MAGIC) {
2840 FIXME("Ref magic = %x\n", pRef->magic);
2841 return NULL;
2843 name = ( (char*)(&pRef->names) + pRef->number);
2845 table = HeapAlloc(GetProcessHeap(), 0, sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
2846 table->num = pRef->number >> 3;
2848 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
2850 /* We don't want the first href to be 0 */
2851 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
2853 for(ref = 0; ref < pRef->number >> 3; ref++) {
2854 char *refname;
2855 unsigned int lib_offs, type_num;
2857 ref_type = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref_type));
2859 name += SLTG_ReadStringA(name, &refname);
2860 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2861 FIXME("Can't sscanf ref\n");
2862 if(lib_offs != 0xffff) {
2863 TLBImpLib **import = &pTL->pImpLibs;
2865 while(*import) {
2866 if((*import)->offset == lib_offs)
2867 break;
2868 import = &(*import)->next;
2870 if(!*import) {
2871 char fname[MAX_PATH+1];
2872 int len;
2874 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2875 sizeof(**import));
2876 (*import)->offset = lib_offs;
2877 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2878 &(*import)->guid);
2879 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
2880 &(*import)->wVersionMajor,
2881 &(*import)->wVersionMinor,
2882 &(*import)->lcid, fname) != 4) {
2883 FIXME("can't sscanf ref %s\n",
2884 pNameTable + lib_offs + 40);
2886 len = strlen(fname);
2887 if(fname[len-1] != '#')
2888 FIXME("fname = %s\n", fname);
2889 fname[len-1] = '\0';
2890 (*import)->name = TLB_MultiByteToBSTR(fname);
2892 ref_type->pImpTLInfo = *import;
2894 /* Store a reference to IDispatch */
2895 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
2896 pTL->dispatch_href = typelib_ref;
2898 } else { /* internal ref */
2899 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
2901 ref_type->reference = typelib_ref;
2902 ref_type->index = type_num;
2904 HeapFree(GetProcessHeap(), 0, refname);
2905 list_add_tail(&pTL->ref_list, &ref_type->entry);
2907 table->refs[ref] = typelib_ref;
2908 typelib_ref += 4;
2910 if((BYTE)*name != SLTG_REF_MAGIC)
2911 FIXME("End of ref block magic = %x\n", *name);
2912 dump_TLBRefType(pTL);
2913 return table;
2916 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2917 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
2919 SLTG_ImplInfo *info;
2920 TLBImplType **ppImplType = &pTI->impltypelist;
2921 /* I don't really get this structure, usually it's 0x16 bytes
2922 long, but iuser.tlb contains some that are 0x18 bytes long.
2923 That's ok because we can use the next ptr to jump to the next
2924 one. But how do we know the length of the last one? The WORD
2925 at offs 0x8 might be the clue. For now I'm just assuming that
2926 the last one is the regular 0x16 bytes. */
2928 info = (SLTG_ImplInfo*)pBlk;
2929 while(1) {
2930 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2931 sizeof(**ppImplType));
2932 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef);
2933 (*ppImplType)->implflags = info->impltypeflags;
2934 pTI->TypeAttr.cImplTypes++;
2935 ppImplType = &(*ppImplType)->next;
2937 if(info->next == 0xffff)
2938 break;
2939 if(OneOnly)
2940 FIXME("Interface inheriting more than one interface\n");
2941 info = (SLTG_ImplInfo*)(pBlk + info->next);
2943 info++; /* see comment at top of function */
2944 return (char*)info;
2947 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
2948 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
2950 TLBVarDesc **ppVarDesc = &pTI->varlist;
2951 BSTR bstrPrevName = NULL;
2952 SLTG_Variable *pItem;
2953 unsigned short i;
2954 WORD *pType;
2955 char buf[300];
2957 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
2958 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
2960 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2961 sizeof(**ppVarDesc));
2962 (*ppVarDesc)->vardesc.memid = pItem->memid;
2964 if (pItem->magic != SLTG_VAR_MAGIC &&
2965 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
2966 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
2967 return;
2970 if (pItem->name == 0xfffe)
2971 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
2972 else
2973 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2975 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
2976 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
2978 if (pItem->flags & 0x40) {
2979 TRACE_(typelib)("VAR_DISPATCH\n");
2980 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
2982 else if (pItem->flags & 0x10) {
2983 TRACE_(typelib)("VAR_CONST\n");
2984 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2985 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2986 sizeof(VARIANT));
2987 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2988 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2989 *(INT*)(pBlk + pItem->byte_offs);
2991 else {
2992 TRACE_(typelib)("VAR_PERINSTANCE\n");
2993 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2994 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2997 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
2998 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
3000 if (pItem->flags & 0x80)
3001 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3003 if(pItem->flags & 0x02)
3004 pType = &pItem->type;
3005 else
3006 pType = (WORD*)(pBlk + pItem->type);
3008 if (pItem->flags & ~0xd2)
3009 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xd2);
3011 SLTG_DoElem(pType, pBlk,
3012 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup);
3014 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3016 bstrPrevName = (*ppVarDesc)->Name;
3017 ppVarDesc = &((*ppVarDesc)->next);
3019 pTI->TypeAttr.cVars = cVars;
3022 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3023 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3025 SLTG_Function *pFunc;
3026 unsigned short i;
3027 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3029 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3030 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3032 int param;
3033 WORD *pType, *pArg;
3035 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3036 sizeof(**ppFuncDesc));
3038 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3039 case SLTG_FUNCTION_MAGIC:
3040 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3041 break;
3042 case SLTG_DISPATCH_FUNCTION_MAGIC:
3043 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3044 break;
3045 case SLTG_STATIC_FUNCTION_MAGIC:
3046 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3047 break;
3048 default:
3049 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3050 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
3051 *ppFuncDesc = NULL;
3052 return;
3054 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3056 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3057 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3058 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3059 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3060 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3061 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3063 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3064 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3066 if(pFunc->retnextopt & 0x80)
3067 pType = &pFunc->rettype;
3068 else
3069 pType = (WORD*)(pBlk + pFunc->rettype);
3071 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3073 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3074 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3075 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3076 (*ppFuncDesc)->pParamDesc =
3077 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3078 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3080 pArg = (WORD*)(pBlk + pFunc->arg_off);
3082 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3083 char *paramName = pNameTable + *pArg;
3084 BOOL HaveOffs;
3085 /* If arg type follows then paramName points to the 2nd
3086 letter of the name, else the next WORD is an offset to
3087 the arg type and paramName points to the first letter.
3088 So let's take one char off paramName and see if we're
3089 pointing at an alpha-numeric char. However if *pArg is
3090 0xffff or 0xfffe then the param has no name, the former
3091 meaning that the next WORD is the type, the latter
3092 meaning that the next WORD is an offset to the type. */
3094 HaveOffs = FALSE;
3095 if(*pArg == 0xffff)
3096 paramName = NULL;
3097 else if(*pArg == 0xfffe) {
3098 paramName = NULL;
3099 HaveOffs = TRUE;
3101 else if(paramName[-1] && !isalnum(paramName[-1]))
3102 HaveOffs = TRUE;
3104 pArg++;
3106 if(HaveOffs) { /* the next word is an offset to type */
3107 pType = (WORD*)(pBlk + *pArg);
3108 SLTG_DoElem(pType, pBlk,
3109 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3110 pArg++;
3111 } else {
3112 if(paramName)
3113 paramName--;
3114 pArg = SLTG_DoElem(pArg, pBlk,
3115 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3118 /* Are we an optional param ? */
3119 if((*ppFuncDesc)->funcdesc.cParams - param <=
3120 (*ppFuncDesc)->funcdesc.cParamsOpt)
3121 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3123 if(paramName) {
3124 (*ppFuncDesc)->pParamDesc[param].Name =
3125 TLB_MultiByteToBSTR(paramName);
3129 ppFuncDesc = &((*ppFuncDesc)->next);
3130 if(pFunc->next == 0xffff) break;
3132 pTI->TypeAttr.cFuncs = cFuncs;
3135 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3136 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3137 SLTG_TypeInfoTail *pTITail)
3139 char *pFirstItem, *pNextItem;
3140 sltg_ref_lookup_t *ref_lookup = NULL;
3142 if(pTIHeader->href_table != 0xffffffff) {
3143 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3144 pNameTable);
3147 pFirstItem = pNextItem = pBlk;
3149 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3150 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3152 HeapFree(GetProcessHeap(), 0, ref_lookup);
3156 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3157 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3158 const SLTG_TypeInfoTail *pTITail)
3160 char *pFirstItem, *pNextItem;
3161 sltg_ref_lookup_t *ref_lookup = NULL;
3163 if(pTIHeader->href_table != 0xffffffff) {
3164 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3165 pNameTable);
3168 pFirstItem = pNextItem = pBlk;
3170 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3171 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3174 if (pTITail->funcs_off != 0xffff)
3175 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3177 HeapFree(GetProcessHeap(), 0, ref_lookup);
3179 if (TRACE_ON(typelib))
3180 dump_TLBFuncDesc(pTI->funclist);
3183 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3184 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3185 const SLTG_TypeInfoTail *pTITail)
3187 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3190 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3191 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3192 const SLTG_TypeInfoTail *pTITail)
3194 WORD *pType;
3195 sltg_ref_lookup_t *ref_lookup = NULL;
3197 if (pTITail->simple_alias) {
3198 /* if simple alias, no more processing required */
3199 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3200 return;
3203 if(pTIHeader->href_table != 0xffffffff) {
3204 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3205 pNameTable);
3208 /* otherwise it is an offset to a type */
3209 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3211 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3213 HeapFree(GetProcessHeap(), 0, ref_lookup);
3216 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3217 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3218 const SLTG_TypeInfoTail *pTITail)
3220 sltg_ref_lookup_t *ref_lookup = NULL;
3221 if (pTIHeader->href_table != 0xffffffff)
3222 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3223 pNameTable);
3225 if (pTITail->vars_off != 0xffff)
3226 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3228 if (pTITail->funcs_off != 0xffff)
3229 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3231 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3232 * of dispinterface functons including the IDispatch ones, so
3233 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3234 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3236 HeapFree(GetProcessHeap(), 0, ref_lookup);
3237 if (TRACE_ON(typelib))
3238 dump_TLBFuncDesc(pTI->funclist);
3241 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3242 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3243 const SLTG_TypeInfoTail *pTITail)
3245 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3248 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3249 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3250 const SLTG_TypeInfoTail *pTITail)
3252 sltg_ref_lookup_t *ref_lookup = NULL;
3253 if (pTIHeader->href_table != 0xffffffff)
3254 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3255 pNameTable);
3257 if (pTITail->vars_off != 0xffff)
3258 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3260 if (pTITail->funcs_off != 0xffff)
3261 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3262 HeapFree(GetProcessHeap(), 0, ref_lookup);
3265 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3266 managable copy of it into this */
3267 typedef struct {
3268 WORD small_no;
3269 char *index_name;
3270 char *other_name;
3271 WORD res1a;
3272 WORD name_offs;
3273 WORD more_bytes;
3274 char *extra;
3275 WORD res20;
3276 DWORD helpcontext;
3277 WORD res26;
3278 GUID uuid;
3279 } SLTG_InternalOtherTypeInfo;
3281 /****************************************************************************
3282 * ITypeLib2_Constructor_SLTG
3284 * loading a SLTG typelib from an in-memory image
3286 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3288 ITypeLibImpl *pTypeLibImpl;
3289 SLTG_Header *pHeader;
3290 SLTG_BlkEntry *pBlkEntry;
3291 SLTG_Magic *pMagic;
3292 SLTG_Index *pIndex;
3293 SLTG_Pad9 *pPad9;
3294 LPVOID pBlk, pFirstBlk;
3295 SLTG_LibBlk *pLibBlk;
3296 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3297 char *pAfterOTIBlks = NULL;
3298 char *pNameTable, *ptr;
3299 int i;
3300 DWORD len, order;
3301 ITypeInfoImpl **ppTypeInfoImpl;
3303 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3306 pTypeLibImpl = TypeLibImpl_Constructor();
3307 if (!pTypeLibImpl) return NULL;
3309 pHeader = pLib;
3311 TRACE_(typelib)("header:\n");
3312 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3313 pHeader->nrOfFileBlks );
3314 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3315 FIXME("Header type magic 0x%08x not supported.\n",
3316 pHeader->SLTG_magic);
3317 return NULL;
3320 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3321 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3323 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3324 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3326 /* Next we have a magic block */
3327 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3329 /* Let's see if we're still in sync */
3330 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3331 sizeof(SLTG_COMPOBJ_MAGIC))) {
3332 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3333 return NULL;
3335 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3336 sizeof(SLTG_DIR_MAGIC))) {
3337 FIXME("dir magic = %s\n", pMagic->dir_magic);
3338 return NULL;
3341 pIndex = (SLTG_Index*)(pMagic+1);
3343 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3345 pFirstBlk = (LPVOID)(pPad9 + 1);
3347 /* We'll set up a ptr to the main library block, which is the last one. */
3349 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3350 pBlkEntry[order].next != 0;
3351 order = pBlkEntry[order].next - 1, i++) {
3352 pBlk = (char*)pBlk + pBlkEntry[order].len;
3354 pLibBlk = pBlk;
3356 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3358 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3359 interspersed */
3361 len += 0x40;
3363 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3365 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3366 sizeof(*pOtherTypeInfoBlks) *
3367 pTypeLibImpl->TypeInfoCount);
3370 ptr = (char*)pLibBlk + len;
3372 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3373 WORD w, extra;
3374 len = 0;
3376 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3378 w = *(WORD*)(ptr + 2);
3379 if(w != 0xffff) {
3380 len += w;
3381 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3382 w+1);
3383 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3384 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3386 w = *(WORD*)(ptr + 4 + len);
3387 if(w != 0xffff) {
3388 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3389 len += w;
3390 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3391 w+1);
3392 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3393 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3395 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3396 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3397 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3398 if(extra) {
3399 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3400 extra);
3401 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3402 len += extra;
3404 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3405 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3406 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3407 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3408 len += sizeof(SLTG_OtherTypeInfo);
3409 ptr += len;
3412 pAfterOTIBlks = ptr;
3414 /* Skip this WORD and get the next DWORD */
3415 len = *(DWORD*)(pAfterOTIBlks + 2);
3417 /* Now add this to pLibBLk look at what we're pointing at and
3418 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3419 dust and we should be pointing at the beginning of the name
3420 table */
3422 pNameTable = (char*)pLibBlk + len;
3424 switch(*(WORD*)pNameTable) {
3425 case 0xffff:
3426 break;
3427 case 0x0200:
3428 pNameTable += 0x20;
3429 break;
3430 default:
3431 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3432 break;
3435 pNameTable += 0x216;
3437 pNameTable += 2;
3439 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3441 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3444 /* Hopefully we now have enough ptrs set up to actually read in
3445 some TypeInfos. It's not clear which order to do them in, so
3446 I'll just follow the links along the BlkEntry chain and read
3447 them in the order in which they are in the file */
3449 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3451 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3452 pBlkEntry[order].next != 0;
3453 order = pBlkEntry[order].next - 1, i++) {
3455 SLTG_TypeInfoHeader *pTIHeader;
3456 SLTG_TypeInfoTail *pTITail;
3457 SLTG_MemberHeader *pMemHeader;
3459 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3460 pOtherTypeInfoBlks[i].index_name)) {
3461 FIXME("Index strings don't match\n");
3462 return NULL;
3465 pTIHeader = pBlk;
3466 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3467 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3468 return NULL;
3470 TRACE("pTIHeader->res06 = %x, pTIHeader->res0e = %x, pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3471 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3473 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3474 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3475 (*ppTypeInfoImpl)->index = i;
3476 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3477 pOtherTypeInfoBlks[i].name_offs +
3478 pNameTable);
3479 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3480 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3481 sizeof(GUID));
3482 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3483 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3484 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3485 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3486 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3488 if((pTIHeader->typeflags1 & 7) != 2)
3489 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3490 if(pTIHeader->typeflags3 != 2)
3491 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3493 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3494 debugstr_w((*ppTypeInfoImpl)->Name),
3495 typekind_desc[pTIHeader->typekind],
3496 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3497 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3499 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3501 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3503 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3504 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3505 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3507 switch(pTIHeader->typekind) {
3508 case TKIND_ENUM:
3509 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3510 pTIHeader, pTITail);
3511 break;
3513 case TKIND_RECORD:
3514 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3515 pTIHeader, pTITail);
3516 break;
3518 case TKIND_INTERFACE:
3519 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3520 pTIHeader, pTITail);
3521 break;
3523 case TKIND_COCLASS:
3524 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3525 pTIHeader, pTITail);
3526 break;
3528 case TKIND_ALIAS:
3529 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3530 pTIHeader, pTITail);
3531 break;
3533 case TKIND_DISPATCH:
3534 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3535 pTIHeader, pTITail);
3536 break;
3538 case TKIND_MODULE:
3539 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3540 pTIHeader, pTITail);
3541 break;
3543 default:
3544 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3545 break;
3549 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3550 but we've already set those */
3551 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3552 X(06);
3553 X(16);
3554 X(18);
3555 X(1a);
3556 X(1e);
3557 X(24);
3558 X(26);
3559 X(2a);
3560 X(2c);
3561 X(2e);
3562 X(30);
3563 X(32);
3564 X(34);
3566 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3567 pBlk = (char*)pBlk + pBlkEntry[order].len;
3570 if(i != pTypeLibImpl->TypeInfoCount) {
3571 FIXME("Somehow processed %d TypeInfos\n", i);
3572 return NULL;
3575 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3576 return (ITypeLib2*)pTypeLibImpl;
3579 /* ITypeLib::QueryInterface
3581 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3582 ITypeLib2 * iface,
3583 REFIID riid,
3584 VOID **ppvObject)
3586 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3588 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3590 *ppvObject=NULL;
3591 if(IsEqualIID(riid, &IID_IUnknown) ||
3592 IsEqualIID(riid,&IID_ITypeLib)||
3593 IsEqualIID(riid,&IID_ITypeLib2))
3595 *ppvObject = This;
3598 if(*ppvObject)
3600 ITypeLib2_AddRef(iface);
3601 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3602 return S_OK;
3604 TRACE("-- Interface: E_NOINTERFACE\n");
3605 return E_NOINTERFACE;
3608 /* ITypeLib::AddRef
3610 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3612 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3613 ULONG ref = InterlockedIncrement(&This->ref);
3615 TRACE("(%p)->ref was %u\n",This, ref - 1);
3617 return ref;
3620 /* ITypeLib::Release
3622 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3624 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3625 ULONG ref = InterlockedDecrement(&This->ref);
3627 TRACE("(%p)->(%u)\n",This, ref);
3629 if (!ref)
3631 TLBImpLib *pImpLib, *pImpLibNext;
3632 TLBCustData *pCustData, *pCustDataNext;
3633 TLBRefType *ref_type;
3634 void *cursor2;
3635 int i;
3637 /* remove cache entry */
3638 if(This->path)
3640 TRACE("removing from cache list\n");
3641 EnterCriticalSection(&cache_section);
3642 if (This->next) This->next->prev = This->prev;
3643 if (This->prev) This->prev->next = This->next;
3644 else tlb_cache_first = This->next;
3645 LeaveCriticalSection(&cache_section);
3646 HeapFree(GetProcessHeap(), 0, This->path);
3648 TRACE(" destroying ITypeLib(%p)\n",This);
3650 if (This->Name)
3652 SysFreeString(This->Name);
3653 This->Name = NULL;
3656 if (This->DocString)
3658 SysFreeString(This->DocString);
3659 This->DocString = NULL;
3662 if (This->HelpFile)
3664 SysFreeString(This->HelpFile);
3665 This->HelpFile = NULL;
3668 if (This->HelpStringDll)
3670 SysFreeString(This->HelpStringDll);
3671 This->HelpStringDll = NULL;
3674 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
3676 VariantClear(&pCustData->data);
3678 pCustDataNext = pCustData->next;
3679 TLB_Free(pCustData);
3682 for (i = 0; i < This->ctTypeDesc; i++)
3683 if (This->pTypeDesc[i].vt == VT_CARRAY)
3684 TLB_Free(This->pTypeDesc[i].u.lpadesc);
3686 TLB_Free(This->pTypeDesc);
3688 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
3690 if (pImpLib->pImpTypeLib)
3691 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
3692 TLB_Free(pImpLib->name);
3694 pImpLibNext = pImpLib->next;
3695 TLB_Free(pImpLib);
3698 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
3700 list_remove(&ref_type->entry);
3701 TLB_Free(ref_type);
3704 if (This->pTypeInfo) /* can be NULL */
3705 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3706 HeapFree(GetProcessHeap(),0,This);
3707 return 0;
3710 return ref;
3713 /* ITypeLib::GetTypeInfoCount
3715 * Returns the number of type descriptions in the type library
3717 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3719 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3720 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3721 return This->TypeInfoCount;
3724 /* ITypeLib::GetTypeInfo
3726 * retrieves the specified type description in the library.
3728 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3729 ITypeLib2 *iface,
3730 UINT index,
3731 ITypeInfo **ppTInfo)
3733 int i;
3735 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3736 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3738 TRACE("(%p)->(index=%d)\n", This, index);
3740 if (!ppTInfo) return E_INVALIDARG;
3742 /* search element n in list */
3743 for(i=0; i < index; i++)
3745 pTypeInfo = pTypeInfo->next;
3746 if (!pTypeInfo)
3748 TRACE("-- element not found\n");
3749 return TYPE_E_ELEMENTNOTFOUND;
3753 *ppTInfo = (ITypeInfo *) pTypeInfo;
3755 ITypeInfo_AddRef(*ppTInfo);
3756 TRACE("-- found (%p)\n",*ppTInfo);
3757 return S_OK;
3761 /* ITypeLibs::GetTypeInfoType
3763 * Retrieves the type of a type description.
3765 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3766 ITypeLib2 *iface,
3767 UINT index,
3768 TYPEKIND *pTKind)
3770 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3771 int i;
3772 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3774 if (ITypeLib2_fnGetTypeInfoCount(iface) < index + 1)
3775 return TYPE_E_ELEMENTNOTFOUND;
3777 TRACE("(%p) index %d\n", This, index);
3779 if(!pTKind) return E_INVALIDARG;
3781 /* search element n in list */
3782 for(i=0; i < index; i++)
3784 if(!pTInfo)
3786 TRACE("-- element not found\n");
3787 return TYPE_E_ELEMENTNOTFOUND;
3789 pTInfo = pTInfo->next;
3792 *pTKind = pTInfo->TypeAttr.typekind;
3793 TRACE("-- found Type (%d)\n", *pTKind);
3794 return S_OK;
3797 /* ITypeLib::GetTypeInfoOfGuid
3799 * Retrieves the type description that corresponds to the specified GUID.
3802 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3803 ITypeLib2 *iface,
3804 REFGUID guid,
3805 ITypeInfo **ppTInfo)
3807 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3808 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3810 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3812 if (!pTypeInfo)
3814 WARN("-- element not found\n");
3815 return TYPE_E_ELEMENTNOTFOUND;
3818 /* search linked list for guid */
3819 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3821 pTypeInfo = pTypeInfo->next;
3823 if (!pTypeInfo)
3825 /* end of list reached */
3826 WARN("-- element not found\n");
3827 return TYPE_E_ELEMENTNOTFOUND;
3831 TRACE("-- found (%p, %s)\n",
3832 pTypeInfo,
3833 debugstr_w(pTypeInfo->Name));
3835 *ppTInfo = (ITypeInfo*)pTypeInfo;
3836 ITypeInfo_AddRef(*ppTInfo);
3837 return S_OK;
3840 /* ITypeLib::GetLibAttr
3842 * Retrieves the structure that contains the library's attributes.
3845 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3846 ITypeLib2 *iface,
3847 LPTLIBATTR *ppTLibAttr)
3849 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3850 TRACE("(%p)\n",This);
3851 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3852 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3853 return S_OK;
3856 /* ITypeLib::GetTypeComp
3858 * Enables a client compiler to bind to a library's types, variables,
3859 * constants, and global functions.
3862 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3863 ITypeLib2 *iface,
3864 ITypeComp **ppTComp)
3866 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3868 TRACE("(%p)->(%p)\n",This,ppTComp);
3869 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3870 ITypeComp_AddRef(*ppTComp);
3872 return S_OK;
3875 /* ITypeLib::GetDocumentation
3877 * Retrieves the library's documentation string, the complete Help file name
3878 * and path, and the context identifier for the library Help topic in the Help
3879 * file.
3881 * On a successful return all non-null BSTR pointers will have been set,
3882 * possibly to NULL.
3884 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3885 ITypeLib2 *iface,
3886 INT index,
3887 BSTR *pBstrName,
3888 BSTR *pBstrDocString,
3889 DWORD *pdwHelpContext,
3890 BSTR *pBstrHelpFile)
3892 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3894 HRESULT result = E_INVALIDARG;
3896 ITypeInfo *pTInfo;
3899 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3900 This, index,
3901 pBstrName, pBstrDocString,
3902 pdwHelpContext, pBstrHelpFile);
3904 if(index<0)
3906 /* documentation for the typelib */
3907 if(pBstrName)
3909 if (This->Name)
3911 if(!(*pBstrName = SysAllocString(This->Name)))
3912 goto memerr1;
3914 else
3915 *pBstrName = NULL;
3917 if(pBstrDocString)
3919 if (This->DocString)
3921 if(!(*pBstrDocString = SysAllocString(This->DocString)))
3922 goto memerr2;
3924 else if (This->Name)
3926 if(!(*pBstrDocString = SysAllocString(This->Name)))
3927 goto memerr2;
3929 else
3930 *pBstrDocString = NULL;
3932 if(pdwHelpContext)
3934 *pdwHelpContext = This->dwHelpContext;
3936 if(pBstrHelpFile)
3938 if (This->HelpFile)
3940 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
3941 goto memerr3;
3943 else
3944 *pBstrHelpFile = NULL;
3947 result = S_OK;
3949 else
3951 /* for a typeinfo */
3952 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3954 if(SUCCEEDED(result))
3956 result = ITypeInfo_GetDocumentation(pTInfo,
3957 MEMBERID_NIL,
3958 pBstrName,
3959 pBstrDocString,
3960 pdwHelpContext, pBstrHelpFile);
3962 ITypeInfo_Release(pTInfo);
3965 return result;
3966 memerr3:
3967 if (pBstrDocString) SysFreeString (*pBstrDocString);
3968 memerr2:
3969 if (pBstrName) SysFreeString (*pBstrName);
3970 memerr1:
3971 return STG_E_INSUFFICIENTMEMORY;
3974 /* ITypeLib::IsName
3976 * Indicates whether a passed-in string contains the name of a type or member
3977 * described in the library.
3980 static HRESULT WINAPI ITypeLib2_fnIsName(
3981 ITypeLib2 *iface,
3982 LPOLESTR szNameBuf,
3983 ULONG lHashVal,
3984 BOOL *pfName)
3986 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3987 ITypeInfoImpl *pTInfo;
3988 TLBFuncDesc *pFInfo;
3989 TLBVarDesc *pVInfo;
3990 int i;
3991 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3993 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3994 pfName);
3996 *pfName=TRUE;
3997 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3998 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3999 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4000 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4001 for(i=0;i<pFInfo->funcdesc.cParams;i++)
4002 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
4003 goto ITypeLib2_fnIsName_exit;
4005 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4006 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4009 *pfName=FALSE;
4011 ITypeLib2_fnIsName_exit:
4012 TRACE("(%p)slow! search for %s: %s found!\n", This,
4013 debugstr_w(szNameBuf), *pfName?"NOT":"");
4015 return S_OK;
4018 /* ITypeLib::FindName
4020 * Finds occurrences of a type description in a type library. This may be used
4021 * to quickly verify that a name exists in a type library.
4024 static HRESULT WINAPI ITypeLib2_fnFindName(
4025 ITypeLib2 *iface,
4026 LPOLESTR szNameBuf,
4027 ULONG lHashVal,
4028 ITypeInfo **ppTInfo,
4029 MEMBERID *rgMemId,
4030 UINT16 *pcFound)
4032 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4033 ITypeInfoImpl *pTInfo;
4034 TLBFuncDesc *pFInfo;
4035 TLBVarDesc *pVInfo;
4036 int i,j = 0;
4037 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4039 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
4040 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4041 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4042 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4043 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
4044 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
4045 goto ITypeLib2_fnFindName_exit;
4048 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4049 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4050 continue;
4051 ITypeLib2_fnFindName_exit:
4052 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4053 ppTInfo[j]=(LPTYPEINFO)pTInfo;
4054 j++;
4056 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4057 This, *pcFound, debugstr_w(szNameBuf), j);
4059 *pcFound=j;
4061 return S_OK;
4064 /* ITypeLib::ReleaseTLibAttr
4066 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4069 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4070 ITypeLib2 *iface,
4071 TLIBATTR *pTLibAttr)
4073 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4074 TRACE("freeing (%p)\n",This);
4075 HeapFree(GetProcessHeap(),0,pTLibAttr);
4079 /* ITypeLib2::GetCustData
4081 * gets the custom data
4083 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4084 ITypeLib2 * iface,
4085 REFGUID guid,
4086 VARIANT *pVarVal)
4088 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4089 TLBCustData *pCData;
4091 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4093 if( IsEqualIID(guid, &pCData->guid)) break;
4096 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4098 if(pCData)
4100 VariantInit( pVarVal);
4101 VariantCopy( pVarVal, &pCData->data);
4102 return S_OK;
4104 return E_INVALIDARG; /* FIXME: correct? */
4107 /* ITypeLib2::GetLibStatistics
4109 * Returns statistics about a type library that are required for efficient
4110 * sizing of hash tables.
4113 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4114 ITypeLib2 * iface,
4115 ULONG *pcUniqueNames,
4116 ULONG *pcchUniqueNames)
4118 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4120 FIXME("(%p): stub!\n", This);
4122 if(pcUniqueNames) *pcUniqueNames=1;
4123 if(pcchUniqueNames) *pcchUniqueNames=1;
4124 return S_OK;
4127 /* ITypeLib2::GetDocumentation2
4129 * Retrieves the library's documentation string, the complete Help file name
4130 * and path, the localization context to use, and the context ID for the
4131 * library Help topic in the Help file.
4134 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4135 ITypeLib2 * iface,
4136 INT index,
4137 LCID lcid,
4138 BSTR *pbstrHelpString,
4139 DWORD *pdwHelpStringContext,
4140 BSTR *pbstrHelpStringDll)
4142 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4143 HRESULT result;
4144 ITypeInfo *pTInfo;
4146 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4148 /* the help string should be obtained from the helpstringdll,
4149 * using the _DLLGetDocumentation function, based on the supplied
4150 * lcid. Nice to do sometime...
4152 if(index<0)
4154 /* documentation for the typelib */
4155 if(pbstrHelpString)
4156 *pbstrHelpString=SysAllocString(This->DocString);
4157 if(pdwHelpStringContext)
4158 *pdwHelpStringContext=This->dwHelpContext;
4159 if(pbstrHelpStringDll)
4160 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4162 result = S_OK;
4164 else
4166 /* for a typeinfo */
4167 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4169 if(SUCCEEDED(result))
4171 ITypeInfo2 * pTInfo2;
4172 result = ITypeInfo_QueryInterface(pTInfo,
4173 &IID_ITypeInfo2,
4174 (LPVOID*) &pTInfo2);
4176 if(SUCCEEDED(result))
4178 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4179 MEMBERID_NIL,
4180 lcid,
4181 pbstrHelpString,
4182 pdwHelpStringContext,
4183 pbstrHelpStringDll);
4185 ITypeInfo2_Release(pTInfo2);
4188 ITypeInfo_Release(pTInfo);
4191 return result;
4194 /* ITypeLib2::GetAllCustData
4196 * Gets all custom data items for the library.
4199 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4200 ITypeLib2 * iface,
4201 CUSTDATA *pCustData)
4203 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4204 TLBCustData *pCData;
4205 int i;
4206 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4207 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4208 if(pCustData->prgCustData ){
4209 pCustData->cCustData=This->ctCustData;
4210 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4211 pCustData->prgCustData[i].guid=pCData->guid;
4212 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4214 }else{
4215 ERR(" OUT OF MEMORY!\n");
4216 return E_OUTOFMEMORY;
4218 return S_OK;
4221 static const ITypeLib2Vtbl tlbvt = {
4222 ITypeLib2_fnQueryInterface,
4223 ITypeLib2_fnAddRef,
4224 ITypeLib2_fnRelease,
4225 ITypeLib2_fnGetTypeInfoCount,
4226 ITypeLib2_fnGetTypeInfo,
4227 ITypeLib2_fnGetTypeInfoType,
4228 ITypeLib2_fnGetTypeInfoOfGuid,
4229 ITypeLib2_fnGetLibAttr,
4230 ITypeLib2_fnGetTypeComp,
4231 ITypeLib2_fnGetDocumentation,
4232 ITypeLib2_fnIsName,
4233 ITypeLib2_fnFindName,
4234 ITypeLib2_fnReleaseTLibAttr,
4236 ITypeLib2_fnGetCustData,
4237 ITypeLib2_fnGetLibStatistics,
4238 ITypeLib2_fnGetDocumentation2,
4239 ITypeLib2_fnGetAllCustData
4243 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4245 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4247 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4250 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4252 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4254 return ITypeLib2_AddRef((ITypeLib2 *)This);
4257 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4259 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4261 return ITypeLib2_Release((ITypeLib2 *)This);
4264 static HRESULT WINAPI ITypeLibComp_fnBind(
4265 ITypeComp * iface,
4266 OLECHAR * szName,
4267 ULONG lHash,
4268 WORD wFlags,
4269 ITypeInfo ** ppTInfo,
4270 DESCKIND * pDescKind,
4271 BINDPTR * pBindPtr)
4273 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4274 ITypeInfoImpl *pTypeInfo;
4276 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4278 *pDescKind = DESCKIND_NONE;
4279 pBindPtr->lptcomp = NULL;
4280 *ppTInfo = NULL;
4282 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4284 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4286 /* FIXME: check wFlags here? */
4287 /* FIXME: we should use a hash table to look this info up using lHash
4288 * instead of an O(n) search */
4289 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4290 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4292 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4294 *pDescKind = DESCKIND_TYPECOMP;
4295 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4296 ITypeComp_AddRef(pBindPtr->lptcomp);
4297 TRACE("module or enum: %s\n", debugstr_w(szName));
4298 return S_OK;
4302 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4303 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4305 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4306 HRESULT hr;
4308 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4309 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4311 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4312 return S_OK;
4316 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4317 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4319 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4320 HRESULT hr;
4321 ITypeInfo *subtypeinfo;
4322 BINDPTR subbindptr;
4323 DESCKIND subdesckind;
4325 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4326 &subtypeinfo, &subdesckind, &subbindptr);
4327 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4329 TYPEDESC tdesc_appobject =
4332 (TYPEDESC *)pTypeInfo->hreftype
4334 VT_USERDEFINED
4336 const VARDESC vardesc_appobject =
4338 -2, /* memid */
4339 NULL, /* lpstrSchema */
4341 0 /* oInst */
4344 /* ELEMDESC */
4346 /* TYPEDESC */
4348 &tdesc_appobject
4350 VT_PTR
4353 0, /* wVarFlags */
4354 VAR_STATIC /* varkind */
4357 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4359 /* cleanup things filled in by Bind call so we can put our
4360 * application object data in there instead */
4361 switch (subdesckind)
4363 case DESCKIND_FUNCDESC:
4364 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4365 break;
4366 case DESCKIND_VARDESC:
4367 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4368 break;
4369 default:
4370 break;
4372 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4374 if (pTypeInfo->hreftype == -1)
4375 FIXME("no hreftype for interface %p\n", pTypeInfo);
4377 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4378 if (FAILED(hr))
4379 return hr;
4381 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4382 *ppTInfo = (ITypeInfo *)pTypeInfo;
4383 ITypeInfo_AddRef(*ppTInfo);
4384 return S_OK;
4389 TRACE("name not found %s\n", debugstr_w(szName));
4390 return S_OK;
4393 static HRESULT WINAPI ITypeLibComp_fnBindType(
4394 ITypeComp * iface,
4395 OLECHAR * szName,
4396 ULONG lHash,
4397 ITypeInfo ** ppTInfo,
4398 ITypeComp ** ppTComp)
4400 FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4401 return E_NOTIMPL;
4404 static const ITypeCompVtbl tlbtcvt =
4407 ITypeLibComp_fnQueryInterface,
4408 ITypeLibComp_fnAddRef,
4409 ITypeLibComp_fnRelease,
4411 ITypeLibComp_fnBind,
4412 ITypeLibComp_fnBindType
4415 /*================== ITypeInfo(2) Methods ===================================*/
4416 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4418 ITypeInfoImpl * pTypeInfoImpl;
4420 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4421 if (pTypeInfoImpl)
4423 pTypeInfoImpl->lpVtbl = &tinfvt;
4424 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4425 pTypeInfoImpl->ref=1;
4426 pTypeInfoImpl->hreftype = -1;
4427 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4428 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4430 TRACE("(%p)\n", pTypeInfoImpl);
4431 return (ITypeInfo2*) pTypeInfoImpl;
4434 /* ITypeInfo::QueryInterface
4436 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4437 ITypeInfo2 *iface,
4438 REFIID riid,
4439 VOID **ppvObject)
4441 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4443 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4445 *ppvObject=NULL;
4446 if(IsEqualIID(riid, &IID_IUnknown) ||
4447 IsEqualIID(riid,&IID_ITypeInfo)||
4448 IsEqualIID(riid,&IID_ITypeInfo2))
4449 *ppvObject = This;
4451 if(*ppvObject){
4452 ITypeInfo_AddRef(iface);
4453 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4454 return S_OK;
4456 TRACE("-- Interface: E_NOINTERFACE\n");
4457 return E_NOINTERFACE;
4460 /* ITypeInfo::AddRef
4462 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4464 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4465 ULONG ref = InterlockedIncrement(&This->ref);
4467 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4469 TRACE("(%p)->ref is %u\n",This, ref);
4470 return ref;
4473 /* ITypeInfo::Release
4475 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4477 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4478 ULONG ref = InterlockedDecrement(&This->ref);
4480 TRACE("(%p)->(%u)\n",This, ref);
4482 if (ref) {
4483 /* We don't release ITypeLib when ref=0 because
4484 it means that function is called by ITypeLib2_Release */
4485 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4486 } else {
4487 TLBFuncDesc *pFInfo, *pFInfoNext;
4488 TLBVarDesc *pVInfo, *pVInfoNext;
4489 TLBImplType *pImpl, *pImplNext;
4491 TRACE("destroying ITypeInfo(%p)\n",This);
4493 if (This->no_free_data)
4494 goto finish_free;
4496 if (This->Name)
4498 SysFreeString(This->Name);
4499 This->Name = 0;
4502 if (This->DocString)
4504 SysFreeString(This->DocString);
4505 This->DocString = 0;
4508 if (This->DllName)
4510 SysFreeString(This->DllName);
4511 This->DllName = 0;
4514 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4516 UINT i;
4517 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4519 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4520 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4522 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4523 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4525 SysFreeString(pFInfo->pParamDesc[i].Name);
4527 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4528 TLB_Free(pFInfo->pParamDesc);
4529 TLB_FreeCustData(pFInfo->pCustData);
4530 if (HIWORD(pFInfo->Entry) != 0 && pFInfo->Entry != (BSTR)-1)
4531 SysFreeString(pFInfo->Entry);
4532 SysFreeString(pFInfo->HelpString);
4533 SysFreeString(pFInfo->Name);
4535 pFInfoNext = pFInfo->next;
4536 TLB_Free(pFInfo);
4538 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
4540 if (pVInfo->vardesc.varkind == VAR_CONST)
4542 VariantClear(pVInfo->vardesc.u.lpvarValue);
4543 TLB_Free(pVInfo->vardesc.u.lpvarValue);
4545 TLB_FreeCustData(pVInfo->pCustData);
4546 SysFreeString(pVInfo->Name);
4547 pVInfoNext = pVInfo->next;
4548 TLB_Free(pVInfo);
4550 for(pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
4552 TLB_FreeCustData(pImpl->pCustData);
4553 pImplNext = pImpl->next;
4554 TLB_Free(pImpl);
4556 TLB_FreeCustData(This->pCustData);
4558 finish_free:
4559 if (This->next)
4561 ITypeInfo_Release((ITypeInfo*)This->next);
4564 HeapFree(GetProcessHeap(),0,This);
4565 return 0;
4567 return ref;
4570 /* ITypeInfo::GetTypeAttr
4572 * Retrieves a TYPEATTR structure that contains the attributes of the type
4573 * description.
4576 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4577 LPTYPEATTR *ppTypeAttr)
4579 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4580 SIZE_T size;
4582 TRACE("(%p)\n",This);
4584 size = sizeof(**ppTypeAttr);
4585 if (This->TypeAttr.typekind == TKIND_ALIAS)
4586 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4588 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4589 if (!*ppTypeAttr)
4590 return E_OUTOFMEMORY;
4592 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4594 if (This->TypeAttr.typekind == TKIND_ALIAS)
4595 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4596 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4598 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4599 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4600 funcs */
4601 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4602 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4604 return S_OK;
4607 /* ITypeInfo::GetTypeComp
4609 * Retrieves the ITypeComp interface for the type description, which enables a
4610 * client compiler to bind to the type description's members.
4613 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4614 ITypeComp * *ppTComp)
4616 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4618 TRACE("(%p)->(%p)\n", This, ppTComp);
4620 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4621 ITypeComp_AddRef(*ppTComp);
4622 return S_OK;
4625 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4627 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4628 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4629 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4630 return size;
4633 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4635 memcpy(dest, src, sizeof(ELEMDESC));
4636 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4637 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4639 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4640 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4641 *buffer += sizeof(PARAMDESCEX);
4642 memcpy(pparamdescex_dest, pparamdescex_src, sizeof(PARAMDESCEX));
4643 VariantInit(&pparamdescex_dest->varDefaultValue);
4644 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4645 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4647 else
4648 dest->u.paramdesc.pparamdescex = NULL;
4649 return S_OK;
4652 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4654 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4655 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4658 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4660 FUNCDESC *dest;
4661 char *buffer;
4662 SIZE_T size = sizeof(*src);
4663 SHORT i;
4664 HRESULT hr;
4666 size += sizeof(*src->lprgscode) * src->cScodes;
4667 size += TLB_SizeElemDesc(&src->elemdescFunc);
4668 for (i = 0; i < src->cParams; i++)
4670 size += sizeof(ELEMDESC);
4671 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4674 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4675 if (!dest) return E_OUTOFMEMORY;
4677 memcpy(dest, src, sizeof(FUNCDESC));
4678 if (dispinterface) /* overwrite funckind */
4679 dest->funckind = FUNC_DISPATCH;
4680 buffer = (char *)(dest + 1);
4682 dest->lprgscode = (SCODE *)buffer;
4683 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4684 buffer += sizeof(*src->lprgscode) * src->cScodes;
4686 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4687 if (FAILED(hr))
4689 SysFreeString((BSTR)dest);
4690 return hr;
4693 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4694 buffer += sizeof(ELEMDESC) * src->cParams;
4695 for (i = 0; i < src->cParams; i++)
4697 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4698 if (FAILED(hr))
4699 break;
4701 if (FAILED(hr))
4703 /* undo the above actions */
4704 for (i = i - 1; i >= 0; i--)
4705 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4706 TLB_FreeElemDesc(&dest->elemdescFunc);
4707 SysFreeString((BSTR)dest);
4708 return hr;
4711 /* special treatment for dispinterfaces: this makes functions appear
4712 * to return their [retval] value when it is really returning an
4713 * HRESULT */
4714 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4716 if (dest->cParams &&
4717 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4719 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4720 if (elemdesc->tdesc.vt != VT_PTR)
4722 ERR("elemdesc should have started with VT_PTR instead of:\n");
4723 if (ERR_ON(ole))
4724 dump_ELEMDESC(elemdesc);
4725 return E_UNEXPECTED;
4728 /* copy last parameter to the return value. we are using a flat
4729 * buffer so there is no danger of leaking memory in
4730 * elemdescFunc */
4731 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4733 /* remove the last parameter */
4734 dest->cParams--;
4736 else
4737 /* otherwise this function is made to appear to have no return
4738 * value */
4739 dest->elemdescFunc.tdesc.vt = VT_VOID;
4743 *dest_ptr = dest;
4744 return S_OK;
4747 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4749 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4750 const TLBFuncDesc *pFDesc;
4751 int i;
4753 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4756 if (pFDesc)
4758 *ppFuncDesc = &pFDesc->funcdesc;
4759 return S_OK;
4762 return TYPE_E_ELEMENTNOTFOUND;
4765 /* internal function to make the inherited interfaces' methods appear
4766 * part of the interface */
4767 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
4768 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
4770 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4771 HRESULT hr;
4772 UINT implemented_funcs = 0;
4774 if (funcs)
4775 *funcs = 0;
4776 else
4777 *hrefoffset = DISPATCH_HREF_OFFSET;
4779 if(This->impltypelist)
4781 ITypeInfo *pSubTypeInfo;
4782 UINT sub_funcs;
4784 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
4785 if (FAILED(hr))
4786 return hr;
4788 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
4789 index,
4790 ppFuncDesc,
4791 &sub_funcs, hrefoffset);
4792 implemented_funcs += sub_funcs;
4793 ITypeInfo_Release(pSubTypeInfo);
4794 if (SUCCEEDED(hr))
4795 return hr;
4796 *hrefoffset += DISPATCH_HREF_OFFSET;
4799 if (funcs)
4800 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
4801 else
4802 *hrefoffset = 0;
4804 if (index < implemented_funcs)
4805 return E_INVALIDARG;
4806 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
4807 ppFuncDesc);
4810 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
4812 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
4813 while (TRUE)
4815 switch (pTypeDesc->vt)
4817 case VT_USERDEFINED:
4818 pTypeDesc->u.hreftype += hrefoffset;
4819 return;
4820 case VT_PTR:
4821 case VT_SAFEARRAY:
4822 pTypeDesc = pTypeDesc->u.lptdesc;
4823 break;
4824 case VT_CARRAY:
4825 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
4826 break;
4827 default:
4828 return;
4833 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
4835 SHORT i;
4836 for (i = 0; i < pFuncDesc->cParams; i++)
4837 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
4838 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
4841 /* ITypeInfo::GetFuncDesc
4843 * Retrieves the FUNCDESC structure that contains information about a
4844 * specified function.
4847 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4848 LPFUNCDESC *ppFuncDesc)
4850 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4851 const FUNCDESC *internal_funcdesc;
4852 HRESULT hr;
4853 UINT hrefoffset = 0;
4855 TRACE("(%p) index %d\n", This, index);
4857 if (This->TypeAttr.typekind == TKIND_DISPATCH)
4858 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
4859 &internal_funcdesc, NULL,
4860 &hrefoffset);
4861 else
4862 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
4863 &internal_funcdesc);
4864 if (FAILED(hr))
4866 WARN("description for function %d not found\n", index);
4867 return hr;
4870 hr = TLB_AllocAndInitFuncDesc(
4871 internal_funcdesc,
4872 ppFuncDesc,
4873 This->TypeAttr.typekind == TKIND_DISPATCH);
4875 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
4876 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
4878 TRACE("-- 0x%08x\n", hr);
4879 return hr;
4882 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
4884 VARDESC *dest;
4885 char *buffer;
4886 SIZE_T size = sizeof(*src);
4887 HRESULT hr;
4889 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
4890 if (src->varkind == VAR_CONST)
4891 size += sizeof(VARIANT);
4892 size += TLB_SizeElemDesc(&src->elemdescVar);
4894 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
4895 if (!dest) return E_OUTOFMEMORY;
4897 *dest = *src;
4898 buffer = (char *)(dest + 1);
4899 if (src->lpstrSchema)
4901 int len;
4902 dest->lpstrSchema = (LPOLESTR)buffer;
4903 len = strlenW(src->lpstrSchema);
4904 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
4905 buffer += (len + 1) * sizeof(WCHAR);
4908 if (src->varkind == VAR_CONST)
4910 HRESULT hr;
4912 dest->u.lpvarValue = (VARIANT *)buffer;
4913 *dest->u.lpvarValue = *src->u.lpvarValue;
4914 buffer += sizeof(VARIANT);
4915 VariantInit(dest->u.lpvarValue);
4916 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
4917 if (FAILED(hr))
4919 SysFreeString((BSTR)dest_ptr);
4920 return hr;
4923 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
4924 if (FAILED(hr))
4926 if (src->varkind == VAR_CONST)
4927 VariantClear(dest->u.lpvarValue);
4928 SysFreeString((BSTR)dest);
4929 return hr;
4931 *dest_ptr = dest;
4932 return S_OK;
4935 /* ITypeInfo::GetVarDesc
4937 * Retrieves a VARDESC structure that describes the specified variable.
4940 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4941 LPVARDESC *ppVarDesc)
4943 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4944 int i;
4945 const TLBVarDesc *pVDesc;
4947 TRACE("(%p) index %d\n", This, index);
4949 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4952 if (pVDesc)
4953 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
4955 return E_INVALIDARG;
4958 /* ITypeInfo_GetNames
4960 * Retrieves the variable with the specified member ID (or the name of the
4961 * property or method and its parameters) that correspond to the specified
4962 * function ID.
4964 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4965 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4967 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4968 const TLBFuncDesc *pFDesc;
4969 const TLBVarDesc *pVDesc;
4970 int i;
4971 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
4972 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4973 if(pFDesc)
4975 /* function found, now return function and parameter names */
4976 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4978 if(!i)
4979 *rgBstrNames=SysAllocString(pFDesc->Name);
4980 else
4981 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4983 *pcNames=i;
4985 else
4987 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4988 if(pVDesc)
4990 *rgBstrNames=SysAllocString(pVDesc->Name);
4991 *pcNames=1;
4993 else
4995 if(This->impltypelist &&
4996 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4997 /* recursive search */
4998 ITypeInfo *pTInfo;
4999 HRESULT result;
5000 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5001 &pTInfo);
5002 if(SUCCEEDED(result))
5004 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5005 ITypeInfo_Release(pTInfo);
5006 return result;
5008 WARN("Could not search inherited interface!\n");
5010 else
5012 WARN("no names found\n");
5014 *pcNames=0;
5015 return TYPE_E_ELEMENTNOTFOUND;
5018 return S_OK;
5022 /* ITypeInfo::GetRefTypeOfImplType
5024 * If a type description describes a COM class, it retrieves the type
5025 * description of the implemented interface types. For an interface,
5026 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5027 * if any exist.
5030 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5031 ITypeInfo2 *iface,
5032 UINT index,
5033 HREFTYPE *pRefType)
5035 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5036 int i;
5037 HRESULT hr = S_OK;
5038 const TLBImplType *pImpl = This->impltypelist;
5040 TRACE("(%p) index %d\n", This, index);
5041 if (TRACE_ON(ole)) dump_TypeInfo(This);
5043 if(index==(UINT)-1)
5045 /* only valid on dual interfaces;
5046 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5048 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5050 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
5051 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
5053 *pRefType = -1;
5055 else
5057 hr = TYPE_E_ELEMENTNOTFOUND;
5060 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5062 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5063 *pRefType = This->pTypeLib->dispatch_href;
5065 else
5067 /* get element n from linked list */
5068 for(i=0; pImpl && i<index; i++)
5070 pImpl = pImpl->next;
5073 if (pImpl)
5074 *pRefType = pImpl->hRef;
5075 else
5076 hr = TYPE_E_ELEMENTNOTFOUND;
5079 if(TRACE_ON(ole))
5081 if(SUCCEEDED(hr))
5082 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5083 else
5084 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5087 return hr;
5090 /* ITypeInfo::GetImplTypeFlags
5092 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5093 * or base interface in a type description.
5095 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5096 UINT index, INT *pImplTypeFlags)
5098 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5099 int i;
5100 TLBImplType *pImpl;
5102 TRACE("(%p) index %d\n", This, index);
5103 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5104 i++, pImpl=pImpl->next)
5106 if(i==index && pImpl){
5107 *pImplTypeFlags=pImpl->implflags;
5108 return S_OK;
5110 *pImplTypeFlags=0;
5111 return TYPE_E_ELEMENTNOTFOUND;
5114 /* GetIDsOfNames
5115 * Maps between member names and member IDs, and parameter names and
5116 * parameter IDs.
5118 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5119 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5121 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5122 const TLBFuncDesc *pFDesc;
5123 const TLBVarDesc *pVDesc;
5124 HRESULT ret=S_OK;
5125 int i;
5127 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5128 cNames);
5130 /* init out parameters in case of failure */
5131 for (i = 0; i < cNames; i++)
5132 pMemId[i] = MEMBERID_NIL;
5134 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5135 int j;
5136 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5137 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5138 for(i=1; i < cNames; i++){
5139 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5140 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5141 break;
5142 if( j<pFDesc->funcdesc.cParams)
5143 pMemId[i]=j;
5144 else
5145 ret=DISP_E_UNKNOWNNAME;
5147 TRACE("-- 0x%08x\n", ret);
5148 return ret;
5151 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5152 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5153 if(cNames) *pMemId=pVDesc->vardesc.memid;
5154 return ret;
5157 /* not found, see if it can be found in an inherited interface */
5158 if(This->impltypelist) {
5159 /* recursive search */
5160 ITypeInfo *pTInfo;
5161 ret=ITypeInfo_GetRefTypeInfo(iface,
5162 This->impltypelist->hRef, &pTInfo);
5163 if(SUCCEEDED(ret)){
5164 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5165 ITypeInfo_Release(pTInfo);
5166 return ret;
5168 WARN("Could not search inherited interface!\n");
5169 } else
5170 WARN("no names found\n");
5171 return DISP_E_UNKNOWNNAME;
5174 /* ITypeInfo::Invoke
5176 * Invokes a method, or accesses a property of an object, that implements the
5177 * interface described by the type description.
5179 DWORD
5180 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5181 DWORD res;
5183 if (TRACE_ON(ole)) {
5184 int i;
5185 TRACE("Calling %p(",func);
5186 for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
5187 TRACE(")\n");
5190 switch (callconv) {
5191 case CC_STDCALL:
5193 switch (nrargs) {
5194 case 0:
5195 res = func();
5196 break;
5197 case 1:
5198 res = func(args[0]);
5199 break;
5200 case 2:
5201 res = func(args[0],args[1]);
5202 break;
5203 case 3:
5204 res = func(args[0],args[1],args[2]);
5205 break;
5206 case 4:
5207 res = func(args[0],args[1],args[2],args[3]);
5208 break;
5209 case 5:
5210 res = func(args[0],args[1],args[2],args[3],args[4]);
5211 break;
5212 case 6:
5213 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
5214 break;
5215 case 7:
5216 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
5217 break;
5218 case 8:
5219 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
5220 break;
5221 case 9:
5222 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
5223 break;
5224 case 10:
5225 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
5226 break;
5227 case 11:
5228 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
5229 break;
5230 case 12:
5231 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]);
5232 break;
5233 case 13:
5234 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]);
5235 break;
5236 case 14:
5237 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]);
5238 break;
5239 case 15:
5240 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]);
5241 break;
5242 case 16:
5243 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]);
5244 break;
5245 case 17:
5246 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]);
5247 break;
5248 case 18:
5249 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]);
5250 break;
5251 case 19:
5252 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]);
5253 break;
5254 case 20:
5255 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]);
5256 break;
5257 case 21:
5258 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]);
5259 break;
5260 case 22:
5261 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]);
5262 break;
5263 case 23:
5264 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]);
5265 break;
5266 case 24:
5267 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]);
5268 break;
5269 case 25:
5270 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]);
5271 break;
5272 case 26:
5273 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]);
5274 break;
5275 case 27:
5276 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]);
5277 break;
5278 case 28:
5279 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]);
5280 break;
5281 case 29:
5282 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]);
5283 break;
5284 case 30:
5285 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]);
5286 break;
5287 default:
5288 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
5289 res = -1;
5290 break;
5292 break;
5293 default:
5294 FIXME("unsupported calling convention %d\n",callconv);
5295 res = -1;
5296 break;
5298 TRACE("returns %08x\n",res);
5299 return res;
5302 extern int _argsize(DWORD vt);
5304 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5306 HRESULT hr = S_OK;
5307 ITypeInfo *tinfo2 = NULL;
5308 TYPEATTR *tattr = NULL;
5310 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5311 if (hr)
5313 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5314 "hr = 0x%08x\n",
5315 tdesc->u.hreftype, hr);
5316 return hr;
5318 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5319 if (hr)
5321 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5322 ITypeInfo_Release(tinfo2);
5323 return hr;
5326 switch (tattr->typekind)
5328 case TKIND_ENUM:
5329 *vt |= VT_I4;
5330 break;
5332 case TKIND_ALIAS:
5333 tdesc = &tattr->tdescAlias;
5334 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5335 break;
5337 case TKIND_INTERFACE:
5338 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5339 *vt |= VT_DISPATCH;
5340 else
5341 *vt |= VT_UNKNOWN;
5342 break;
5344 case TKIND_DISPATCH:
5345 *vt |= VT_DISPATCH;
5346 break;
5348 case TKIND_COCLASS:
5349 *vt |= VT_DISPATCH;
5350 break;
5352 case TKIND_RECORD:
5353 FIXME("TKIND_RECORD unhandled.\n");
5354 hr = E_NOTIMPL;
5355 break;
5357 case TKIND_UNION:
5358 FIXME("TKIND_UNION unhandled.\n");
5359 hr = E_NOTIMPL;
5360 break;
5362 default:
5363 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5364 hr = E_NOTIMPL;
5365 break;
5367 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5368 ITypeInfo_Release(tinfo2);
5369 return hr;
5372 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5374 HRESULT hr = S_OK;
5376 /* enforce only one level of pointer indirection */
5377 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5379 tdesc = tdesc->u.lptdesc;
5381 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5382 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5383 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5384 if ((tdesc->vt == VT_USERDEFINED) ||
5385 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5387 VARTYPE vt_userdefined = 0;
5388 const TYPEDESC *tdesc_userdefined = tdesc;
5389 if (tdesc->vt == VT_PTR)
5391 vt_userdefined = VT_BYREF;
5392 tdesc_userdefined = tdesc->u.lptdesc;
5394 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5395 if ((hr == S_OK) &&
5396 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5397 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5399 *vt |= vt_userdefined;
5400 return S_OK;
5403 *vt = VT_BYREF;
5406 switch (tdesc->vt)
5408 case VT_HRESULT:
5409 *vt |= VT_ERROR;
5410 break;
5411 case VT_USERDEFINED:
5412 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5413 break;
5414 case VT_VOID:
5415 case VT_CARRAY:
5416 case VT_PTR:
5417 case VT_LPSTR:
5418 case VT_LPWSTR:
5419 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5420 hr = DISP_E_BADVARTYPE;
5421 break;
5422 case VT_SAFEARRAY:
5423 *vt |= VT_ARRAY;
5424 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5425 break;
5426 default:
5427 *vt |= tdesc->vt;
5428 break;
5430 return hr;
5433 /***********************************************************************
5434 * DispCallFunc (OLEAUT32.@)
5436 * Invokes a function of the specifed calling convention, passing the
5437 * specified arguments and returns the result.
5439 * PARAMS
5440 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5441 * oVft [I] The offset in the vtable. See notes.
5442 * cc [I] Calling convention of the function to call.
5443 * vtReturn [I] The return type of the function.
5444 * cActuals [I] Number of parameters.
5445 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5446 * prgpvarg [I] The arguments to pass.
5447 * pvargResult [O] The return value of the function. Can be NULL.
5449 * RETURNS
5450 * Success: S_OK.
5451 * Failure: HRESULT code.
5453 * NOTES
5454 * The HRESULT return value of this function is not affected by the return
5455 * value of the user supplied function, which is returned in pvargResult.
5457 * If pvInstance is NULL then a non-object function is to be called and oVft
5458 * is the address of the function to call.
5460 * The cc parameter can be one of the following values:
5461 *|CC_FASTCALL
5462 *|CC_CDECL
5463 *|CC_PASCAL
5464 *|CC_STDCALL
5465 *|CC_FPFASTCALL
5466 *|CC_SYSCALL
5467 *|CC_MPWCDECL
5468 *|CC_MPWPASCAL
5471 HRESULT WINAPI
5472 DispCallFunc(
5473 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5474 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5476 int i, argsize, argspos;
5477 DWORD *args;
5478 HRESULT hres;
5480 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5481 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5482 pvargResult, V_VT(pvargResult));
5484 argsize = 0;
5485 if (pvInstance)
5486 argsize++; /* for This pointer */
5488 for (i=0;i<cActuals;i++)
5490 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5491 dump_Variant(prgpvarg[i]);
5492 argsize += _argsize(prgvt[i]);
5494 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5496 argspos = 0;
5497 if (pvInstance)
5499 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5500 argspos++;
5503 for (i=0;i<cActuals;i++)
5505 VARIANT *arg = prgpvarg[i];
5506 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5507 if (prgvt[i] == VT_VARIANT)
5508 memcpy(&args[argspos], arg, _argsize(prgvt[i]) * sizeof(DWORD));
5509 else
5510 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5511 argspos += _argsize(prgvt[i]);
5514 if (pvInstance)
5516 FARPROC *vtable = *(FARPROC**)pvInstance;
5517 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5519 else
5520 /* if we aren't invoking an object then the function pointer is stored
5521 * in oVft */
5522 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5524 if (pvargResult && (vtReturn != VT_EMPTY))
5526 TRACE("Method returned 0x%08x\n",hres);
5527 V_VT(pvargResult) = vtReturn;
5528 V_UI4(pvargResult) = hres;
5531 HeapFree(GetProcessHeap(),0,args);
5532 return S_OK;
5535 #define INVBUF_ELEMENT_SIZE \
5536 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5537 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5538 ((VARIANTARG *)(buffer))
5539 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5540 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5541 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5542 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5543 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5544 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5546 static HRESULT WINAPI ITypeInfo_fnInvoke(
5547 ITypeInfo2 *iface,
5548 VOID *pIUnk,
5549 MEMBERID memid,
5550 UINT16 wFlags,
5551 DISPPARAMS *pDispParams,
5552 VARIANT *pVarResult,
5553 EXCEPINFO *pExcepInfo,
5554 UINT *pArgErr)
5556 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5557 int i;
5558 unsigned int var_index;
5559 TYPEKIND type_kind;
5560 HRESULT hres;
5561 const TLBFuncDesc *pFuncInfo;
5563 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
5564 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5567 if (!pDispParams)
5569 ERR("NULL pDispParams not allowed\n");
5570 return E_INVALIDARG;
5573 dump_DispParms(pDispParams);
5575 if (pDispParams->cNamedArgs > pDispParams->cArgs)
5577 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
5578 pDispParams->cNamedArgs, pDispParams->cArgs);
5579 return E_INVALIDARG;
5582 /* we do this instead of using GetFuncDesc since it will return a fake
5583 * FUNCDESC for dispinterfaces and we want the real function description */
5584 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5585 if ((memid == pFuncInfo->funcdesc.memid) &&
5586 (wFlags & pFuncInfo->funcdesc.invkind))
5587 break;
5589 if (pFuncInfo) {
5590 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5592 if (TRACE_ON(ole))
5594 TRACE("invoking:\n");
5595 dump_TLBFuncDescOne(pFuncInfo);
5598 switch (func_desc->funckind) {
5599 case FUNC_PUREVIRTUAL:
5600 case FUNC_VIRTUAL: {
5601 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
5602 VARIANT varresult;
5603 VARIANT retval; /* pointer for storing byref retvals in */
5604 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
5605 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
5606 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
5607 UINT cNamedArgs = pDispParams->cNamedArgs;
5608 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
5610 hres = S_OK;
5612 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
5614 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
5616 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
5617 hres = DISP_E_PARAMNOTFOUND;
5618 goto func_fail;
5620 /* ignore the DISPID_PROPERTYPUT named argument from now on */
5621 cNamedArgs--;
5622 rgdispidNamedArgs++;
5625 if (func_desc->cParamsOpt < 0 && cNamedArgs)
5627 ERR("functions with the vararg attribute do not support named arguments\n");
5628 hres = DISP_E_NONAMEDARGS;
5629 goto func_fail;
5632 for (i = 0; i < func_desc->cParams; i++)
5634 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5635 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
5636 if (FAILED(hres))
5637 goto func_fail;
5640 TRACE("changing args\n");
5641 for (i = 0; i < func_desc->cParams; i++)
5643 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5644 VARIANTARG *src_arg;
5646 if (cNamedArgs)
5648 USHORT j;
5649 src_arg = NULL;
5650 for (j = 0; j < cNamedArgs; j++)
5651 if (rgdispidNamedArgs[j] == i)
5653 src_arg = &pDispParams->rgvarg[j];
5654 break;
5657 else
5658 src_arg = i < pDispParams->cArgs ? &pDispParams->rgvarg[pDispParams->cArgs - 1 - i] : NULL;
5660 if (wParamFlags & PARAMFLAG_FRETVAL)
5662 /* under most conditions the caller is not allowed to
5663 * pass in a dispparam arg in the index of what would be
5664 * the retval parameter. however, there is an exception
5665 * where the extra parameter is used in an extra
5666 * IDispatch::Invoke below */
5667 if ((i < pDispParams->cArgs) &&
5668 ((func_desc->cParams != 1) || !pVarResult ||
5669 !(func_desc->invkind & INVOKE_PROPERTYGET)))
5671 hres = DISP_E_BADPARAMCOUNT;
5672 break;
5675 /* note: this check is placed so that if the caller passes
5676 * in a VARIANTARG for the retval we just ignore it, like
5677 * native does */
5678 if (i == func_desc->cParams - 1)
5680 VARIANTARG *arg;
5681 arg = prgpvarg[i] = &rgvarg[i];
5682 memset(arg, 0, sizeof(*arg));
5683 V_VT(arg) = rgvt[i];
5684 memset(&retval, 0, sizeof(retval));
5685 V_BYREF(arg) = &retval;
5687 else
5689 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
5690 hres = E_UNEXPECTED;
5691 break;
5694 else if (src_arg)
5696 dump_Variant(src_arg);
5698 if (rgvt[i] == VT_VARIANT)
5699 hres = VariantCopy(&rgvarg[i], src_arg);
5700 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
5702 if (rgvt[i] == V_VT(src_arg))
5703 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
5704 else
5706 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5707 hres = VariantCopy(&missing_arg[i], src_arg);
5708 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
5710 V_VT(&rgvarg[i]) = rgvt[i];
5712 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
5714 SAFEARRAY *a;
5715 SAFEARRAYBOUND bound;
5716 VARIANT *v;
5717 LONG j;
5718 bound.lLbound = 0;
5719 bound.cElements = pDispParams->cArgs-i;
5720 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
5722 ERR("SafeArrayCreate failed\n");
5723 break;
5725 hres = SafeArrayAccessData(a, (LPVOID)&v);
5726 if (hres != S_OK)
5728 ERR("SafeArrayAccessData failed with %x\n", hres);
5729 break;
5731 for (j = 0; j < bound.cElements; j++)
5732 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
5733 hres = SafeArrayUnaccessData(a);
5734 if (hres != S_OK)
5736 ERR("SafeArrayUnaccessData failed with %x\n", hres);
5737 break;
5739 V_ARRAY(&rgvarg[i]) = a;
5740 V_VT(&rgvarg[i]) = rgvt[i];
5742 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
5744 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5745 V_VT(&missing_arg[i]) = V_VT(src_arg);
5746 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
5747 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
5748 V_VT(&rgvarg[i]) = rgvt[i];
5750 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
5752 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
5753 V_VT(&rgvarg[i]) = rgvt[i];
5755 else
5757 /* FIXME: this doesn't work for VT_BYREF arguments if
5758 * they are not the same type as in the paramdesc */
5759 V_VT(&rgvarg[i]) = V_VT(src_arg);
5760 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
5761 V_VT(&rgvarg[i]) = rgvt[i];
5764 if (FAILED(hres))
5766 ERR("failed to convert param %d to %s%s from %s%s\n", i,
5767 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
5768 debugstr_VT(src_arg), debugstr_VF(src_arg));
5769 break;
5771 prgpvarg[i] = &rgvarg[i];
5773 else if (wParamFlags & PARAMFLAG_FOPT)
5775 VARIANTARG *arg;
5776 arg = prgpvarg[i] = &rgvarg[i];
5777 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5779 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
5780 if (FAILED(hres))
5781 break;
5783 else
5785 VARIANTARG *missing_arg;
5786 /* if the function wants a pointer to a variant then
5787 * set that up, otherwise just pass the VT_ERROR in
5788 * the argument by value */
5789 if (rgvt[i] & VT_BYREF)
5791 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
5792 V_VT(arg) = VT_VARIANT | VT_BYREF;
5793 V_VARIANTREF(arg) = missing_arg;
5795 else
5796 missing_arg = arg;
5797 V_VT(missing_arg) = VT_ERROR;
5798 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
5801 else
5803 hres = DISP_E_BADPARAMCOUNT;
5804 break;
5807 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5809 /* VT_VOID is a special case for return types, so it is not
5810 * handled in the general function */
5811 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
5812 V_VT(&varresult) = VT_EMPTY;
5813 else
5815 V_VT(&varresult) = 0;
5816 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
5817 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5820 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
5821 V_VT(&varresult), func_desc->cParams, rgvt,
5822 prgpvarg, &varresult);
5824 for (i = 0; i < func_desc->cParams; i++)
5826 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5827 if (wParamFlags & PARAMFLAG_FRETVAL)
5829 if (TRACE_ON(ole))
5831 TRACE("[retval] value: ");
5832 dump_Variant(prgpvarg[i]);
5835 if (pVarResult)
5837 VariantInit(pVarResult);
5838 /* deref return value */
5839 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
5842 /* free data stored in varresult. Note that
5843 * VariantClear doesn't do what we want because we are
5844 * working with byref types. */
5845 /* FIXME: clear safearrays, bstrs, records and
5846 * variants here too */
5847 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
5848 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
5850 if(*V_UNKNOWNREF(prgpvarg[i]))
5851 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
5853 break;
5855 else if (i < pDispParams->cArgs)
5857 if (wParamFlags & PARAMFLAG_FOUT)
5859 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5861 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
5862 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
5864 if (FAILED(hres))
5866 ERR("failed to convert param %d to vt %d\n", i,
5867 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
5868 break;
5871 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
5872 func_desc->cParamsOpt < 0 &&
5873 i == func_desc->cParams-1)
5875 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
5876 LONG j, ubound;
5877 VARIANT *v;
5878 hres = SafeArrayGetUBound(a, 1, &ubound);
5879 if (hres != S_OK)
5881 ERR("SafeArrayGetUBound failed with %x\n", hres);
5882 break;
5884 hres = SafeArrayAccessData(a, (LPVOID)&v);
5885 if (hres != S_OK)
5887 ERR("SafeArrayAccessData failed with %x\n", hres);
5888 break;
5890 for (j = 0; j <= ubound; j++)
5891 VariantClear(&v[j]);
5892 hres = SafeArrayUnaccessData(a);
5893 if (hres != S_OK)
5895 ERR("SafeArrayUnaccessData failed with %x\n", hres);
5896 break;
5899 VariantClear(&rgvarg[i]);
5901 else if (wParamFlags & PARAMFLAG_FOPT)
5903 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5904 VariantClear(&rgvarg[i]);
5908 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
5910 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
5911 hres = DISP_E_EXCEPTION;
5912 if (pExcepInfo)
5914 IErrorInfo *pErrorInfo;
5915 pExcepInfo->scode = V_ERROR(&varresult);
5916 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
5918 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
5919 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
5920 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
5921 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
5923 IErrorInfo_Release(pErrorInfo);
5927 if (V_VT(&varresult) != VT_ERROR)
5929 TRACE("varresult value: ");
5930 dump_Variant(&varresult);
5932 if (pVarResult)
5934 VariantClear(pVarResult);
5935 *pVarResult = varresult;
5937 else
5938 VariantClear(&varresult);
5941 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
5942 (func_desc->invkind & INVOKE_PROPERTYGET) &&
5943 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
5944 (pDispParams->cArgs != 0))
5946 if (V_VT(pVarResult) == VT_DISPATCH)
5948 IDispatch *pDispatch = V_DISPATCH(pVarResult);
5949 /* Note: not VariantClear; we still need the dispatch
5950 * pointer to be valid */
5951 VariantInit(pVarResult);
5952 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
5953 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
5954 pDispParams, pVarResult, pExcepInfo, pArgErr);
5955 IDispatch_Release(pDispatch);
5957 else
5959 VariantClear(pVarResult);
5960 hres = DISP_E_NOTACOLLECTION;
5964 func_fail:
5965 HeapFree(GetProcessHeap(), 0, buffer);
5966 break;
5968 case FUNC_DISPATCH: {
5969 IDispatch *disp;
5971 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5972 if (SUCCEEDED(hres)) {
5973 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5974 hres = IDispatch_Invoke(
5975 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
5976 pVarResult,pExcepInfo,pArgErr
5978 if (FAILED(hres))
5979 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
5980 IDispatch_Release(disp);
5981 } else
5982 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5983 break;
5985 default:
5986 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5987 hres = E_FAIL;
5988 break;
5991 TRACE("-- 0x%08x\n", hres);
5992 return hres;
5994 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5995 VARDESC *var_desc;
5997 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5998 if(FAILED(hres)) return hres;
6000 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6001 dump_VARDESC(var_desc);
6002 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6003 return E_NOTIMPL;
6006 /* not found, look for it in inherited interfaces */
6007 ITypeInfo2_GetTypeKind(iface, &type_kind);
6008 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6009 if(This->impltypelist) {
6010 /* recursive search */
6011 ITypeInfo *pTInfo;
6012 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6013 if(SUCCEEDED(hres)){
6014 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6015 ITypeInfo_Release(pTInfo);
6016 return hres;
6018 WARN("Could not search inherited interface!\n");
6021 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6022 return DISP_E_MEMBERNOTFOUND;
6025 /* ITypeInfo::GetDocumentation
6027 * Retrieves the documentation string, the complete Help file name and path,
6028 * and the context ID for the Help topic for a specified type description.
6030 * (Can be tested by the Visual Basic Editor in Word for instance.)
6032 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6033 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6034 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6036 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6037 const TLBFuncDesc *pFDesc;
6038 const TLBVarDesc *pVDesc;
6039 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6040 " HelpContext(%p) HelpFile(%p)\n",
6041 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6042 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6043 if(pBstrName)
6044 *pBstrName=SysAllocString(This->Name);
6045 if(pBstrDocString)
6046 *pBstrDocString=SysAllocString(This->DocString);
6047 if(pdwHelpContext)
6048 *pdwHelpContext=This->dwHelpContext;
6049 if(pBstrHelpFile)
6050 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6051 return S_OK;
6052 }else {/* for a member */
6053 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6054 if(pFDesc->funcdesc.memid==memid){
6055 if(pBstrName)
6056 *pBstrName = SysAllocString(pFDesc->Name);
6057 if(pBstrDocString)
6058 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6059 if(pdwHelpContext)
6060 *pdwHelpContext=pFDesc->helpcontext;
6061 return S_OK;
6063 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6064 if(pVDesc->vardesc.memid==memid){
6065 if(pBstrName)
6066 *pBstrName = SysAllocString(pVDesc->Name);
6067 if(pBstrDocString)
6068 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6069 if(pdwHelpContext)
6070 *pdwHelpContext=pVDesc->HelpContext;
6071 return S_OK;
6075 if(This->impltypelist &&
6076 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6077 /* recursive search */
6078 ITypeInfo *pTInfo;
6079 HRESULT result;
6080 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6081 &pTInfo);
6082 if(SUCCEEDED(result)) {
6083 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6084 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6085 ITypeInfo_Release(pTInfo);
6086 return result;
6088 WARN("Could not search inherited interface!\n");
6091 WARN("member %d not found\n", memid);
6092 return TYPE_E_ELEMENTNOTFOUND;
6095 /* ITypeInfo::GetDllEntry
6097 * Retrieves a description or specification of an entry point for a function
6098 * in a DLL.
6100 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6101 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6102 WORD *pwOrdinal)
6104 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6105 const TLBFuncDesc *pFDesc;
6107 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6109 if (pBstrDllName) *pBstrDllName = NULL;
6110 if (pBstrName) *pBstrName = NULL;
6111 if (pwOrdinal) *pwOrdinal = 0;
6113 if (This->TypeAttr.typekind != TKIND_MODULE)
6114 return TYPE_E_BADMODULEKIND;
6116 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6117 if(pFDesc->funcdesc.memid==memid){
6118 dump_TypeInfo(This);
6119 if (TRACE_ON(ole))
6120 dump_TLBFuncDescOne(pFDesc);
6122 if (pBstrDllName)
6123 *pBstrDllName = SysAllocString(This->DllName);
6125 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6126 if (pBstrName)
6127 *pBstrName = SysAllocString(pFDesc->Entry);
6128 if (pwOrdinal)
6129 *pwOrdinal = -1;
6130 return S_OK;
6132 if (pBstrName)
6133 *pBstrName = NULL;
6134 if (pwOrdinal)
6135 *pwOrdinal = (DWORD)pFDesc->Entry;
6136 return S_OK;
6138 return TYPE_E_ELEMENTNOTFOUND;
6141 /* internal function to make the inherited interfaces' methods appear
6142 * part of the interface */
6143 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6144 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6146 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6147 HRESULT hr;
6149 TRACE("%p, 0x%x\n", iface, *hRefType);
6151 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK))
6153 ITypeInfo *pSubTypeInfo;
6155 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
6156 if (FAILED(hr))
6157 return hr;
6159 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6160 hRefType, ppTInfo);
6161 ITypeInfo_Release(pSubTypeInfo);
6162 if (SUCCEEDED(hr))
6163 return hr;
6165 *hRefType -= DISPATCH_HREF_OFFSET;
6167 if (!(*hRefType & DISPATCH_HREF_MASK))
6168 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6169 else
6170 return E_FAIL;
6173 /* ITypeInfo::GetRefTypeInfo
6175 * If a type description references other type descriptions, it retrieves
6176 * the referenced type descriptions.
6178 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6179 ITypeInfo2 *iface,
6180 HREFTYPE hRefType,
6181 ITypeInfo **ppTInfo)
6183 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6184 HRESULT result = E_FAIL;
6186 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6188 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6189 ITypeInfo_AddRef(*ppTInfo);
6190 result = S_OK;
6192 else if (hRefType == -1 &&
6193 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6194 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6196 /* when we meet a DUAL dispinterface, we must create the interface
6197 * version of it.
6199 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
6202 /* the interface version contains the same information as the dispinterface
6203 * copy the contents of the structs.
6205 *pTypeInfoImpl = *This;
6206 pTypeInfoImpl->ref = 0;
6208 /* change the type to interface */
6209 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6211 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6213 /* we use data structures from This, so we need to keep a reference
6214 * to it to stop it being destroyed and signal to the new instance to
6215 * not free its data structures when it is destroyed */
6216 pTypeInfoImpl->no_free_data = TRUE;
6217 pTypeInfoImpl->next = This;
6218 ITypeInfo_AddRef((ITypeInfo*) This);
6220 ITypeInfo_AddRef(*ppTInfo);
6222 result = S_OK;
6224 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6225 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6226 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6228 HREFTYPE href_dispatch = hRefType;
6229 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6230 } else {
6231 TLBRefType *ref_type;
6232 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6234 if(ref_type->reference == hRefType)
6235 break;
6237 if(&ref_type->entry == &This->pTypeLib->ref_list)
6239 FIXME("Can't find pRefType for ref %x\n", hRefType);
6240 goto end;
6242 if(hRefType != -1) {
6243 ITypeLib *pTLib = NULL;
6245 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6246 UINT Index;
6247 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6248 } else {
6249 if(ref_type->pImpTLInfo->pImpTypeLib) {
6250 TRACE("typeinfo in imported typelib that is already loaded\n");
6251 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6252 ITypeLib2_AddRef((ITypeLib*) pTLib);
6253 result = S_OK;
6254 } else {
6255 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6256 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6257 ref_type->pImpTLInfo->wVersionMajor,
6258 ref_type->pImpTLInfo->wVersionMinor,
6259 ref_type->pImpTLInfo->lcid,
6260 &pTLib);
6262 if(!SUCCEEDED(result)) {
6263 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6264 result=LoadTypeLib(libnam, &pTLib);
6265 SysFreeString(libnam);
6267 if(SUCCEEDED(result)) {
6268 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6269 ITypeLib2_AddRef(pTLib);
6273 if(SUCCEEDED(result)) {
6274 if(ref_type->index == TLB_REF_USE_GUID)
6275 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6276 &ref_type->guid,
6277 ppTInfo);
6278 else
6279 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6280 ppTInfo);
6282 if (pTLib != NULL)
6283 ITypeLib2_Release(pTLib);
6287 end:
6288 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6289 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6290 return result;
6293 /* ITypeInfo::AddressOfMember
6295 * Retrieves the addresses of static functions or variables, such as those
6296 * defined in a DLL.
6298 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6299 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6301 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6302 HRESULT hr;
6303 BSTR dll, entry;
6304 WORD ordinal;
6305 HMODULE module;
6307 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6309 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6310 if (FAILED(hr))
6311 return hr;
6313 module = LoadLibraryW(dll);
6314 if (!module)
6316 ERR("couldn't load %s\n", debugstr_w(dll));
6317 SysFreeString(dll);
6318 if (entry) SysFreeString(entry);
6319 return STG_E_FILENOTFOUND;
6321 /* FIXME: store library somewhere where we can free it */
6323 if (entry)
6325 LPSTR entryA;
6326 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6327 entryA = HeapAlloc(GetProcessHeap(), 0, len);
6328 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6330 *ppv = GetProcAddress(module, entryA);
6331 if (!*ppv)
6332 ERR("function not found %s\n", debugstr_a(entryA));
6334 HeapFree(GetProcessHeap(), 0, entryA);
6336 else
6338 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6339 if (!*ppv)
6340 ERR("function not found %d\n", ordinal);
6343 SysFreeString(dll);
6344 if (entry) SysFreeString(entry);
6346 if (!*ppv)
6347 return TYPE_E_DLLFUNCTIONNOTFOUND;
6349 return S_OK;
6352 /* ITypeInfo::CreateInstance
6354 * Creates a new instance of a type that describes a component object class
6355 * (coclass).
6357 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6358 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6360 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6361 HRESULT hr;
6362 TYPEATTR *pTA;
6364 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6366 *ppvObj = NULL;
6368 if(pOuterUnk)
6370 WARN("Not able to aggregate\n");
6371 return CLASS_E_NOAGGREGATION;
6374 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6375 if(FAILED(hr)) return hr;
6377 if(pTA->typekind != TKIND_COCLASS)
6379 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6380 hr = E_INVALIDARG;
6381 goto end;
6384 hr = S_FALSE;
6385 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6387 IUnknown *pUnk;
6388 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6389 TRACE("GetActiveObject rets %08x\n", hr);
6390 if(hr == S_OK)
6392 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6393 IUnknown_Release(pUnk);
6397 if(hr != S_OK)
6398 hr = CoCreateInstance(&pTA->guid, NULL,
6399 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6400 riid, ppvObj);
6402 end:
6403 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6404 return hr;
6407 /* ITypeInfo::GetMops
6409 * Retrieves marshalling information.
6411 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6412 BSTR *pBstrMops)
6414 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6415 FIXME("(%p) stub!\n", This);
6416 return S_OK;
6419 /* ITypeInfo::GetContainingTypeLib
6421 * Retrieves the containing type library and the index of the type description
6422 * within that type library.
6424 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6425 ITypeLib * *ppTLib, UINT *pIndex)
6427 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6429 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6430 if (pIndex) {
6431 *pIndex=This->index;
6432 TRACE("returning pIndex=%d\n", *pIndex);
6435 if (ppTLib) {
6436 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6437 ITypeLib2_AddRef(*ppTLib);
6438 TRACE("returning ppTLib=%p\n", *ppTLib);
6441 return S_OK;
6444 /* ITypeInfo::ReleaseTypeAttr
6446 * Releases a TYPEATTR previously returned by GetTypeAttr.
6449 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6450 TYPEATTR* pTypeAttr)
6452 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6453 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6454 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6457 /* ITypeInfo::ReleaseFuncDesc
6459 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6461 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6462 ITypeInfo2 *iface,
6463 FUNCDESC *pFuncDesc)
6465 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6466 SHORT i;
6468 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6470 for (i = 0; i < pFuncDesc->cParams; i++)
6471 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6472 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6474 SysFreeString((BSTR)pFuncDesc);
6477 /* ITypeInfo::ReleaseVarDesc
6479 * Releases a VARDESC previously returned by GetVarDesc.
6481 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6482 VARDESC *pVarDesc)
6484 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6485 TRACE("(%p)->(%p)\n", This, pVarDesc);
6487 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6488 if (pVarDesc->varkind == VAR_CONST)
6489 VariantClear(pVarDesc->u.lpvarValue);
6490 SysFreeString((BSTR)pVarDesc);
6493 /* ITypeInfo2::GetTypeKind
6495 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6498 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6499 TYPEKIND *pTypeKind)
6501 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6502 *pTypeKind=This->TypeAttr.typekind;
6503 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6504 return S_OK;
6507 /* ITypeInfo2::GetTypeFlags
6509 * Returns the type flags without any allocations. This returns a DWORD type
6510 * flag, which expands the type flags without growing the TYPEATTR (type
6511 * attribute).
6514 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6516 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6517 *pTypeFlags=This->TypeAttr.wTypeFlags;
6518 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6519 return S_OK;
6522 /* ITypeInfo2::GetFuncIndexOfMemId
6523 * Binds to a specific member based on a known DISPID, where the member name
6524 * is not known (for example, when binding to a default member).
6527 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
6528 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
6530 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6531 const TLBFuncDesc *pFuncInfo;
6532 int i;
6533 HRESULT result;
6535 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
6536 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
6537 break;
6538 if(pFuncInfo) {
6539 *pFuncIndex = i;
6540 result = S_OK;
6541 } else
6542 result = TYPE_E_ELEMENTNOTFOUND;
6544 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
6545 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6546 return result;
6549 /* TypeInfo2::GetVarIndexOfMemId
6551 * Binds to a specific member based on a known DISPID, where the member name
6552 * is not known (for example, when binding to a default member).
6555 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
6556 MEMBERID memid, UINT *pVarIndex)
6558 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6559 TLBVarDesc *pVarInfo;
6560 int i;
6561 HRESULT result;
6562 for(i=0, pVarInfo=This->varlist; pVarInfo &&
6563 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
6565 if(pVarInfo) {
6566 *pVarIndex = i;
6567 result = S_OK;
6568 } else
6569 result = TYPE_E_ELEMENTNOTFOUND;
6571 TRACE("(%p) memid 0x%08x -> %s\n", This,
6572 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6573 return result;
6576 /* ITypeInfo2::GetCustData
6578 * Gets the custom data
6580 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
6581 ITypeInfo2 * iface,
6582 REFGUID guid,
6583 VARIANT *pVarVal)
6585 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6586 TLBCustData *pCData;
6588 for(pCData=This->pCustData; pCData; pCData = pCData->next)
6589 if( IsEqualIID(guid, &pCData->guid)) break;
6591 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6593 if(pCData)
6595 VariantInit( pVarVal);
6596 VariantCopy( pVarVal, &pCData->data);
6597 return S_OK;
6599 return E_INVALIDARG; /* FIXME: correct? */
6602 /* ITypeInfo2::GetFuncCustData
6604 * Gets the custom data
6606 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
6607 ITypeInfo2 * iface,
6608 UINT index,
6609 REFGUID guid,
6610 VARIANT *pVarVal)
6612 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6613 TLBCustData *pCData=NULL;
6614 TLBFuncDesc * pFDesc;
6615 int i;
6616 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6617 pFDesc=pFDesc->next);
6619 if(pFDesc)
6620 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
6621 if( IsEqualIID(guid, &pCData->guid)) break;
6623 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6625 if(pCData){
6626 VariantInit( pVarVal);
6627 VariantCopy( pVarVal, &pCData->data);
6628 return S_OK;
6630 return E_INVALIDARG; /* FIXME: correct? */
6633 /* ITypeInfo2::GetParamCustData
6635 * Gets the custom data
6637 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
6638 ITypeInfo2 * iface,
6639 UINT indexFunc,
6640 UINT indexParam,
6641 REFGUID guid,
6642 VARIANT *pVarVal)
6644 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6645 TLBCustData *pCData=NULL;
6646 TLBFuncDesc * pFDesc;
6647 int i;
6649 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
6651 if(pFDesc && indexParam<pFDesc->funcdesc.cParams)
6652 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
6653 pCData = pCData->next)
6654 if( IsEqualIID(guid, &pCData->guid)) break;
6656 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6658 if(pCData)
6660 VariantInit( pVarVal);
6661 VariantCopy( pVarVal, &pCData->data);
6662 return S_OK;
6664 return E_INVALIDARG; /* FIXME: correct? */
6667 /* ITypeInfo2::GetVarCustData
6669 * Gets the custom data
6671 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
6672 ITypeInfo2 * iface,
6673 UINT index,
6674 REFGUID guid,
6675 VARIANT *pVarVal)
6677 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6678 TLBCustData *pCData=NULL;
6679 TLBVarDesc * pVDesc;
6680 int i;
6682 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
6684 if(pVDesc)
6686 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
6688 if( IsEqualIID(guid, &pCData->guid)) break;
6692 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6694 if(pCData)
6696 VariantInit( pVarVal);
6697 VariantCopy( pVarVal, &pCData->data);
6698 return S_OK;
6700 return E_INVALIDARG; /* FIXME: correct? */
6703 /* ITypeInfo2::GetImplCustData
6705 * Gets the custom data
6707 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6708 ITypeInfo2 * iface,
6709 UINT index,
6710 REFGUID guid,
6711 VARIANT *pVarVal)
6713 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6714 TLBCustData *pCData=NULL;
6715 TLBImplType * pRDesc;
6716 int i;
6718 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6720 if(pRDesc)
6722 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6724 if( IsEqualIID(guid, &pCData->guid)) break;
6728 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6730 if(pCData)
6732 VariantInit( pVarVal);
6733 VariantCopy( pVarVal, &pCData->data);
6734 return S_OK;
6736 return E_INVALIDARG; /* FIXME: correct? */
6739 /* ITypeInfo2::GetDocumentation2
6741 * Retrieves the documentation string, the complete Help file name and path,
6742 * the localization context to use, and the context ID for the library Help
6743 * topic in the Help file.
6746 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6747 ITypeInfo2 * iface,
6748 MEMBERID memid,
6749 LCID lcid,
6750 BSTR *pbstrHelpString,
6751 DWORD *pdwHelpStringContext,
6752 BSTR *pbstrHelpStringDll)
6754 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6755 const TLBFuncDesc *pFDesc;
6756 const TLBVarDesc *pVDesc;
6757 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
6758 "HelpStringContext(%p) HelpStringDll(%p)\n",
6759 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6760 pbstrHelpStringDll );
6761 /* the help string should be obtained from the helpstringdll,
6762 * using the _DLLGetDocumentation function, based on the supplied
6763 * lcid. Nice to do sometime...
6765 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6766 if(pbstrHelpString)
6767 *pbstrHelpString=SysAllocString(This->Name);
6768 if(pdwHelpStringContext)
6769 *pdwHelpStringContext=This->dwHelpStringContext;
6770 if(pbstrHelpStringDll)
6771 *pbstrHelpStringDll=
6772 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6773 return S_OK;
6774 }else {/* for a member */
6775 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6776 if(pFDesc->funcdesc.memid==memid){
6777 if(pbstrHelpString)
6778 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6779 if(pdwHelpStringContext)
6780 *pdwHelpStringContext=pFDesc->HelpStringContext;
6781 if(pbstrHelpStringDll)
6782 *pbstrHelpStringDll=
6783 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6784 return S_OK;
6786 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6787 if(pVDesc->vardesc.memid==memid){
6788 if(pbstrHelpString)
6789 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6790 if(pdwHelpStringContext)
6791 *pdwHelpStringContext=pVDesc->HelpStringContext;
6792 if(pbstrHelpStringDll)
6793 *pbstrHelpStringDll=
6794 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6795 return S_OK;
6798 return TYPE_E_ELEMENTNOTFOUND;
6801 /* ITypeInfo2::GetAllCustData
6803 * Gets all custom data items for the Type info.
6806 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6807 ITypeInfo2 * iface,
6808 CUSTDATA *pCustData)
6810 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6811 TLBCustData *pCData;
6812 int i;
6814 TRACE("(%p) returning %d items\n", This, This->ctCustData);
6816 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6817 if(pCustData->prgCustData ){
6818 pCustData->cCustData=This->ctCustData;
6819 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
6820 pCustData->prgCustData[i].guid=pCData->guid;
6821 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
6823 }else{
6824 ERR(" OUT OF MEMORY!\n");
6825 return E_OUTOFMEMORY;
6827 return S_OK;
6830 /* ITypeInfo2::GetAllFuncCustData
6832 * Gets all custom data items for the specified Function
6835 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
6836 ITypeInfo2 * iface,
6837 UINT index,
6838 CUSTDATA *pCustData)
6840 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6841 TLBCustData *pCData;
6842 TLBFuncDesc * pFDesc;
6843 int i;
6844 TRACE("(%p) index %d\n", This, index);
6845 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6846 pFDesc=pFDesc->next)
6848 if(pFDesc){
6849 pCustData->prgCustData =
6850 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
6851 if(pCustData->prgCustData ){
6852 pCustData->cCustData=pFDesc->ctCustData;
6853 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
6854 pCData = pCData->next){
6855 pCustData->prgCustData[i].guid=pCData->guid;
6856 VariantCopy(& pCustData->prgCustData[i].varValue,
6857 & pCData->data);
6859 }else{
6860 ERR(" OUT OF MEMORY!\n");
6861 return E_OUTOFMEMORY;
6863 return S_OK;
6865 return TYPE_E_ELEMENTNOTFOUND;
6868 /* ITypeInfo2::GetAllParamCustData
6870 * Gets all custom data items for the Functions
6873 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
6874 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
6876 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6877 TLBCustData *pCData=NULL;
6878 TLBFuncDesc * pFDesc;
6879 int i;
6880 TRACE("(%p) index %d\n", This, indexFunc);
6881 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
6882 pFDesc=pFDesc->next)
6884 if(pFDesc && indexParam<pFDesc->funcdesc.cParams){
6885 pCustData->prgCustData =
6886 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
6887 sizeof(CUSTDATAITEM));
6888 if(pCustData->prgCustData ){
6889 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
6890 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
6891 pCData; i++, pCData = pCData->next){
6892 pCustData->prgCustData[i].guid=pCData->guid;
6893 VariantCopy(& pCustData->prgCustData[i].varValue,
6894 & pCData->data);
6896 }else{
6897 ERR(" OUT OF MEMORY!\n");
6898 return E_OUTOFMEMORY;
6900 return S_OK;
6902 return TYPE_E_ELEMENTNOTFOUND;
6905 /* ITypeInfo2::GetAllVarCustData
6907 * Gets all custom data items for the specified Variable
6910 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
6911 UINT index, CUSTDATA *pCustData)
6913 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6914 TLBCustData *pCData;
6915 TLBVarDesc * pVDesc;
6916 int i;
6917 TRACE("(%p) index %d\n", This, index);
6918 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
6919 pVDesc=pVDesc->next)
6921 if(pVDesc){
6922 pCustData->prgCustData =
6923 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
6924 if(pCustData->prgCustData ){
6925 pCustData->cCustData=pVDesc->ctCustData;
6926 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
6927 pCData = pCData->next){
6928 pCustData->prgCustData[i].guid=pCData->guid;
6929 VariantCopy(& pCustData->prgCustData[i].varValue,
6930 & pCData->data);
6932 }else{
6933 ERR(" OUT OF MEMORY!\n");
6934 return E_OUTOFMEMORY;
6936 return S_OK;
6938 return TYPE_E_ELEMENTNOTFOUND;
6941 /* ITypeInfo2::GetAllImplCustData
6943 * Gets all custom data items for the specified implementation type
6946 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
6947 ITypeInfo2 * iface,
6948 UINT index,
6949 CUSTDATA *pCustData)
6951 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6952 TLBCustData *pCData;
6953 TLBImplType * pRDesc;
6954 int i;
6955 TRACE("(%p) index %d\n", This, index);
6956 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
6957 pRDesc=pRDesc->next)
6959 if(pRDesc){
6960 pCustData->prgCustData =
6961 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
6962 if(pCustData->prgCustData ){
6963 pCustData->cCustData=pRDesc->ctCustData;
6964 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
6965 pCData = pCData->next){
6966 pCustData->prgCustData[i].guid=pCData->guid;
6967 VariantCopy(& pCustData->prgCustData[i].varValue,
6968 & pCData->data);
6970 }else{
6971 ERR(" OUT OF MEMORY!\n");
6972 return E_OUTOFMEMORY;
6974 return S_OK;
6976 return TYPE_E_ELEMENTNOTFOUND;
6979 static const ITypeInfo2Vtbl tinfvt =
6982 ITypeInfo_fnQueryInterface,
6983 ITypeInfo_fnAddRef,
6984 ITypeInfo_fnRelease,
6986 ITypeInfo_fnGetTypeAttr,
6987 ITypeInfo_fnGetTypeComp,
6988 ITypeInfo_fnGetFuncDesc,
6989 ITypeInfo_fnGetVarDesc,
6990 ITypeInfo_fnGetNames,
6991 ITypeInfo_fnGetRefTypeOfImplType,
6992 ITypeInfo_fnGetImplTypeFlags,
6993 ITypeInfo_fnGetIDsOfNames,
6994 ITypeInfo_fnInvoke,
6995 ITypeInfo_fnGetDocumentation,
6996 ITypeInfo_fnGetDllEntry,
6997 ITypeInfo_fnGetRefTypeInfo,
6998 ITypeInfo_fnAddressOfMember,
6999 ITypeInfo_fnCreateInstance,
7000 ITypeInfo_fnGetMops,
7001 ITypeInfo_fnGetContainingTypeLib,
7002 ITypeInfo_fnReleaseTypeAttr,
7003 ITypeInfo_fnReleaseFuncDesc,
7004 ITypeInfo_fnReleaseVarDesc,
7006 ITypeInfo2_fnGetTypeKind,
7007 ITypeInfo2_fnGetTypeFlags,
7008 ITypeInfo2_fnGetFuncIndexOfMemId,
7009 ITypeInfo2_fnGetVarIndexOfMemId,
7010 ITypeInfo2_fnGetCustData,
7011 ITypeInfo2_fnGetFuncCustData,
7012 ITypeInfo2_fnGetParamCustData,
7013 ITypeInfo2_fnGetVarCustData,
7014 ITypeInfo2_fnGetImplTypeCustData,
7015 ITypeInfo2_fnGetDocumentation2,
7016 ITypeInfo2_fnGetAllCustData,
7017 ITypeInfo2_fnGetAllFuncCustData,
7018 ITypeInfo2_fnGetAllParamCustData,
7019 ITypeInfo2_fnGetAllVarCustData,
7020 ITypeInfo2_fnGetAllImplTypeCustData,
7023 /******************************************************************************
7024 * CreateDispTypeInfo [OLEAUT32.31]
7026 * Build type information for an object so it can be called through an
7027 * IDispatch interface.
7029 * RETURNS
7030 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7031 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7033 * NOTES
7034 * This call allows an objects methods to be accessed through IDispatch, by
7035 * building an ITypeInfo object that IDispatch can use to call through.
7037 HRESULT WINAPI CreateDispTypeInfo(
7038 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7039 LCID lcid, /* [I] Locale Id */
7040 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7042 ITypeInfoImpl *pTIClass, *pTIIface;
7043 ITypeLibImpl *pTypeLibImpl;
7044 int param, func;
7045 TLBFuncDesc **ppFuncDesc;
7046 TLBRefType *ref;
7048 TRACE("\n");
7049 pTypeLibImpl = TypeLibImpl_Constructor();
7050 if (!pTypeLibImpl) return E_FAIL;
7052 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
7053 pTIIface->pTypeLib = pTypeLibImpl;
7054 pTIIface->index = 0;
7055 pTIIface->Name = NULL;
7056 pTIIface->dwHelpContext = -1;
7057 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7058 pTIIface->TypeAttr.lcid = lcid;
7059 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7060 pTIIface->TypeAttr.wMajorVerNum = 0;
7061 pTIIface->TypeAttr.wMinorVerNum = 0;
7062 pTIIface->TypeAttr.cbAlignment = 2;
7063 pTIIface->TypeAttr.cbSizeInstance = -1;
7064 pTIIface->TypeAttr.cbSizeVft = -1;
7065 pTIIface->TypeAttr.cFuncs = 0;
7066 pTIIface->TypeAttr.cImplTypes = 0;
7067 pTIIface->TypeAttr.cVars = 0;
7068 pTIIface->TypeAttr.wTypeFlags = 0;
7070 ppFuncDesc = &pTIIface->funclist;
7071 for(func = 0; func < pidata->cMembers; func++) {
7072 METHODDATA *md = pidata->pmethdata + func;
7073 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
7074 (*ppFuncDesc)->Name = SysAllocString(md->szName);
7075 (*ppFuncDesc)->funcdesc.memid = md->dispid;
7076 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
7077 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
7078 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
7079 (*ppFuncDesc)->funcdesc.callconv = md->cc;
7080 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
7081 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
7082 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
7083 (*ppFuncDesc)->funcdesc.cScodes = 0;
7084 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
7085 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7086 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7087 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7088 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7089 md->cArgs * sizeof(ELEMDESC));
7090 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7091 md->cArgs * sizeof(TLBParDesc));
7092 for(param = 0; param < md->cArgs; param++) {
7093 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7094 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7096 (*ppFuncDesc)->helpcontext = 0;
7097 (*ppFuncDesc)->HelpStringContext = 0;
7098 (*ppFuncDesc)->HelpString = NULL;
7099 (*ppFuncDesc)->Entry = NULL;
7100 (*ppFuncDesc)->ctCustData = 0;
7101 (*ppFuncDesc)->pCustData = NULL;
7102 (*ppFuncDesc)->next = NULL;
7103 pTIIface->TypeAttr.cFuncs++;
7104 ppFuncDesc = &(*ppFuncDesc)->next;
7107 dump_TypeInfo(pTIIface);
7109 pTypeLibImpl->pTypeInfo = pTIIface;
7110 pTypeLibImpl->TypeInfoCount++;
7112 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
7113 pTIClass->pTypeLib = pTypeLibImpl;
7114 pTIClass->index = 1;
7115 pTIClass->Name = NULL;
7116 pTIClass->dwHelpContext = -1;
7117 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7118 pTIClass->TypeAttr.lcid = lcid;
7119 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7120 pTIClass->TypeAttr.wMajorVerNum = 0;
7121 pTIClass->TypeAttr.wMinorVerNum = 0;
7122 pTIClass->TypeAttr.cbAlignment = 2;
7123 pTIClass->TypeAttr.cbSizeInstance = -1;
7124 pTIClass->TypeAttr.cbSizeVft = -1;
7125 pTIClass->TypeAttr.cFuncs = 0;
7126 pTIClass->TypeAttr.cImplTypes = 1;
7127 pTIClass->TypeAttr.cVars = 0;
7128 pTIClass->TypeAttr.wTypeFlags = 0;
7130 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
7131 pTIClass->impltypelist->hRef = 0;
7133 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
7134 ref->index = 0;
7135 ref->reference = 0;
7136 ref->pImpTLInfo = TLB_REF_INTERNAL;
7137 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7139 dump_TypeInfo(pTIClass);
7141 pTIIface->next = pTIClass;
7142 pTypeLibImpl->TypeInfoCount++;
7144 *pptinfo = (ITypeInfo*)pTIClass;
7146 ITypeInfo_AddRef(*pptinfo);
7147 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7149 return S_OK;
7153 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7155 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7157 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7160 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7162 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7164 return ITypeInfo_AddRef((ITypeInfo *)This);
7167 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7169 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7171 return ITypeInfo_Release((ITypeInfo *)This);
7174 static HRESULT WINAPI ITypeComp_fnBind(
7175 ITypeComp * iface,
7176 OLECHAR * szName,
7177 ULONG lHash,
7178 WORD wFlags,
7179 ITypeInfo ** ppTInfo,
7180 DESCKIND * pDescKind,
7181 BINDPTR * pBindPtr)
7183 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7184 const TLBFuncDesc *pFDesc;
7185 const TLBVarDesc *pVDesc;
7186 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7188 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7190 *pDescKind = DESCKIND_NONE;
7191 pBindPtr->lpfuncdesc = NULL;
7192 *ppTInfo = NULL;
7194 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
7195 if (!strcmpiW(pFDesc->Name, szName)) {
7196 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7197 break;
7198 else
7199 /* name found, but wrong flags */
7200 hr = TYPE_E_TYPEMISMATCH;
7203 if (pFDesc)
7205 HRESULT hr = TLB_AllocAndInitFuncDesc(
7206 &pFDesc->funcdesc,
7207 &pBindPtr->lpfuncdesc,
7208 This->TypeAttr.typekind == TKIND_DISPATCH);
7209 if (FAILED(hr))
7210 return hr;
7211 *pDescKind = DESCKIND_FUNCDESC;
7212 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7213 ITypeInfo_AddRef(*ppTInfo);
7214 return S_OK;
7215 } else {
7216 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7217 if (!strcmpiW(pVDesc->Name, szName)) {
7218 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7219 if (FAILED(hr))
7220 return hr;
7221 *pDescKind = DESCKIND_VARDESC;
7222 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7223 ITypeInfo_AddRef(*ppTInfo);
7224 return S_OK;
7228 /* FIXME: search each inherited interface, not just the first */
7229 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7230 /* recursive search */
7231 ITypeInfo *pTInfo;
7232 ITypeComp *pTComp;
7233 HRESULT hr;
7234 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7235 if (SUCCEEDED(hr))
7237 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7238 ITypeInfo_Release(pTInfo);
7240 if (SUCCEEDED(hr))
7242 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7243 ITypeComp_Release(pTComp);
7244 return hr;
7246 WARN("Could not search inherited interface!\n");
7248 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
7249 return hr;
7252 static HRESULT WINAPI ITypeComp_fnBindType(
7253 ITypeComp * iface,
7254 OLECHAR * szName,
7255 ULONG lHash,
7256 ITypeInfo ** ppTInfo,
7257 ITypeComp ** ppTComp)
7259 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7261 /* strange behaviour (does nothing) but like the
7262 * original */
7264 if (!ppTInfo || !ppTComp)
7265 return E_POINTER;
7267 *ppTInfo = NULL;
7268 *ppTComp = NULL;
7270 return S_OK;
7273 static const ITypeCompVtbl tcompvt =
7276 ITypeComp_fnQueryInterface,
7277 ITypeComp_fnAddRef,
7278 ITypeComp_fnRelease,
7280 ITypeComp_fnBind,
7281 ITypeComp_fnBindType