widl: Separate declaration and initialisation for indirect arguments.
[wine.git] / dlls / oleaut32 / typelib.c
blobfb572925be6c2326b82c660fa59b518e47bcdf5d
1 /*
2 * TYPELIB
4 * Copyright 1997 Marcus Meissner
5 * 1999 Rein Klazes
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 2005 Robert Shearman, for CodeWeavers
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 * --------------------------------------------------------------------------------------
25 * Known problems (2000, Francois Jacques)
27 * - Tested using OLEVIEW (Platform SDK tool) only.
29 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
30 * creating by doing a straight copy of the dispinterface instance and just changing
31 * its typekind. Pointed structures aren't copied - only the address of the pointers.
33 * - locale stuff is partially implemented but hasn't been tested.
35 * - typelib file is still read in its entirety, but it is released now.
37 * --------------------------------------------------------------------------------------
38 * Known problems left from previous implementation (1999, Rein Klazes) :
40 * -. Data structures are straightforward, but slow for look-ups.
41 * -. (related) nothing is hashed
42 * -. Most error return values are just guessed not checked with windows
43 * behaviour.
44 * -. lousy fatal error handling
48 #include "config.h"
49 #include "wine/port.h"
51 #include <stdlib.h>
52 #include <string.h>
53 #include <stdarg.h>
54 #include <stdio.h>
55 #include <ctype.h>
57 #define COBJMACROS
58 #define NONAMELESSUNION
59 #define NONAMELESSSTRUCT
61 #include "winerror.h"
62 #include "windef.h"
63 #include "winbase.h"
64 #include "winnls.h"
65 #include "winreg.h"
66 #include "winuser.h"
68 #include "wine/unicode.h"
69 #include "objbase.h"
70 #include "typelib.h"
71 #include "wine/debug.h"
72 #include "variant.h"
73 #include "wine/list.h"
75 WINE_DEFAULT_DEBUG_CHANNEL(ole);
76 WINE_DECLARE_DEBUG_CHANNEL(typelib);
78 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
79 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
81 /****************************************************************************
82 * FromLExxx
84 * Takes p_iVal (which is in little endian) and returns it
85 * in the host machine's byte order.
87 #ifdef WORDS_BIGENDIAN
88 static WORD FromLEWord(WORD p_iVal)
90 return (((p_iVal & 0x00FF) << 8) |
91 ((p_iVal & 0xFF00) >> 8));
95 static DWORD FromLEDWord(DWORD p_iVal)
97 return (((p_iVal & 0x000000FF) << 24) |
98 ((p_iVal & 0x0000FF00) << 8) |
99 ((p_iVal & 0x00FF0000) >> 8) |
100 ((p_iVal & 0xFF000000) >> 24));
102 #else
103 #define FromLEWord(X) (X)
104 #define FromLEDWord(X) (X)
105 #endif
107 #define DISPATCH_HREF_OFFSET 0x01000000
108 #define DISPATCH_HREF_MASK 0xff000000
110 /****************************************************************************
111 * FromLExxx
113 * Fix byte order in any structure if necessary
115 #ifdef WORDS_BIGENDIAN
116 static void FromLEWords(void *p_Val, int p_iSize)
118 WORD *Val = p_Val;
120 p_iSize /= sizeof(WORD);
122 while (p_iSize) {
123 *Val = FromLEWord(*Val);
124 Val++;
125 p_iSize--;
130 static void FromLEDWords(void *p_Val, int p_iSize)
132 DWORD *Val = p_Val;
134 p_iSize /= sizeof(DWORD);
136 while (p_iSize) {
137 *Val = FromLEDWord(*Val);
138 Val++;
139 p_iSize--;
142 #else
143 #define FromLEWords(X,Y) /*nothing*/
144 #define FromLEDWords(X,Y) /*nothing*/
145 #endif
148 * Find a typelib key which matches a requested maj.min version.
150 static BOOL find_typelib_key( REFGUID guid, WORD wMaj, WORD *wMin )
152 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
153 WCHAR buffer[60];
154 char key_name[16];
155 DWORD len, i;
156 INT best_min = -1;
157 HKEY hkey;
159 memcpy( buffer, typelibW, sizeof(typelibW) );
160 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
162 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
163 return FALSE;
165 len = sizeof(key_name);
166 i = 0;
167 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
169 INT v_maj, v_min;
171 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
173 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
175 if (wMaj == v_maj)
177 if (*wMin == v_min)
179 best_min = v_min;
180 break; /* exact match */
182 if (v_min > best_min) best_min = v_min;
185 len = sizeof(key_name);
187 RegCloseKey( hkey );
188 if (best_min >= 0)
190 *wMin = best_min;
191 return TRUE;
193 return FALSE;
196 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
197 /* buffer must be at least 60 characters long */
198 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
200 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
201 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
203 memcpy( buffer, TypelibW, sizeof(TypelibW) );
204 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
205 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
206 return buffer;
209 /* get the path of an interface key, in the form "Interface\\<guid>" */
210 /* buffer must be at least 50 characters long */
211 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
213 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
215 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
216 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
217 return buffer;
220 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
221 /* buffer must be at least 16 characters long */
222 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
224 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
225 static const WCHAR win16W[] = {'w','i','n','1','6',0};
226 static const WCHAR win32W[] = {'w','i','n','3','2',0};
228 sprintfW( buffer, LcidFormatW, lcid );
229 switch(syskind)
231 case SYS_WIN16: strcatW( buffer, win16W ); break;
232 case SYS_WIN32: strcatW( buffer, win32W ); break;
233 default:
234 TRACE("Typelib is for unsupported syskind %i\n", syskind);
235 return NULL;
237 return buffer;
240 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
243 /****************************************************************************
244 * QueryPathOfRegTypeLib [OLEAUT32.164]
246 * Gets the path to a registered type library.
248 * PARAMS
249 * guid [I] referenced guid
250 * wMaj [I] major version
251 * wMin [I] minor version
252 * lcid [I] locale id
253 * path [O] path of typelib
255 * RETURNS
256 * Success: S_OK.
257 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
258 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
259 * opened.
261 HRESULT WINAPI QueryPathOfRegTypeLib(
262 REFGUID guid,
263 WORD wMaj,
264 WORD wMin,
265 LCID lcid,
266 LPBSTR path )
268 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
269 LCID myLCID = lcid;
270 HKEY hkey;
271 WCHAR buffer[60];
272 WCHAR Path[MAX_PATH];
273 LONG res;
275 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
277 if (!find_typelib_key( guid, wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
278 get_typelib_key( guid, wMaj, wMin, buffer );
280 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
281 if (res == ERROR_FILE_NOT_FOUND)
283 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
284 return TYPE_E_LIBNOTREGISTERED;
286 else if (res != ERROR_SUCCESS)
288 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
289 return TYPE_E_REGISTRYACCESS;
292 while (hr != S_OK)
294 LONG dwPathLen = sizeof(Path);
296 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
298 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
300 if (!lcid)
301 break;
302 else if (myLCID == lcid)
304 /* try with sub-langid */
305 myLCID = SUBLANGID(lcid);
307 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
309 /* try with system langid */
310 myLCID = 0;
312 else
314 break;
317 else
319 *path = SysAllocString( Path );
320 hr = S_OK;
323 RegCloseKey( hkey );
324 TRACE_(typelib)("-- 0x%08x\n", hr);
325 return hr;
328 /******************************************************************************
329 * CreateTypeLib [OLEAUT32.160] creates a typelib
331 * RETURNS
332 * Success: S_OK
333 * Failure: Status
335 HRESULT WINAPI CreateTypeLib(
336 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
338 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
339 return E_FAIL;
342 /******************************************************************************
343 * LoadTypeLib [OLEAUT32.161]
345 * Loads a type library
347 * PARAMS
348 * szFile [I] Name of file to load from.
349 * pptLib [O] Pointer that receives ITypeLib object on success.
351 * RETURNS
352 * Success: S_OK
353 * Failure: Status
355 * SEE
356 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
358 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
360 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
361 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
364 /******************************************************************************
365 * LoadTypeLibEx [OLEAUT32.183]
367 * Loads and optionally registers a type library
369 * RETURNS
370 * Success: S_OK
371 * Failure: Status
373 HRESULT WINAPI LoadTypeLibEx(
374 LPCOLESTR szFile, /* [in] Name of file to load from */
375 REGKIND regkind, /* [in] Specify kind of registration */
376 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
378 WCHAR szPath[MAX_PATH+1];
379 HRESULT res;
381 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
383 *pptLib = NULL;
385 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
387 if (SUCCEEDED(res))
388 switch(regkind)
390 case REGKIND_DEFAULT:
391 /* don't register typelibs supplied with full path. Experimentation confirms the following */
392 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
393 (szFile[0] && (szFile[1] == ':'))) break;
394 /* else fall-through */
396 case REGKIND_REGISTER:
397 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
399 IUnknown_Release(*pptLib);
400 *pptLib = 0;
402 break;
403 case REGKIND_NONE:
404 break;
407 TRACE(" returns %08x\n",res);
408 return res;
411 /******************************************************************************
412 * LoadRegTypeLib [OLEAUT32.162]
414 * Loads a registered type library.
416 * PARAMS
417 * rguid [I] GUID of the registered type library.
418 * wVerMajor [I] major version.
419 * wVerMinor [I] minor version.
420 * lcid [I] locale ID.
421 * ppTLib [O] pointer that receives an ITypeLib object on success.
423 * RETURNS
424 * Success: S_OK.
425 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
426 * LoadTypeLib.
428 HRESULT WINAPI LoadRegTypeLib(
429 REFGUID rguid,
430 WORD wVerMajor,
431 WORD wVerMinor,
432 LCID lcid,
433 ITypeLib **ppTLib)
435 BSTR bstr=NULL;
436 HRESULT res;
438 *ppTLib = NULL;
440 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
442 if(SUCCEEDED(res))
444 res= LoadTypeLib(bstr, ppTLib);
445 SysFreeString(bstr);
448 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
450 return res;
454 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
455 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
456 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
457 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
458 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
459 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
461 /******************************************************************************
462 * RegisterTypeLib [OLEAUT32.163]
463 * Adds information about a type library to the System Registry
464 * NOTES
465 * Docs: ITypeLib FAR * ptlib
466 * Docs: OLECHAR FAR* szFullPath
467 * Docs: OLECHAR FAR* szHelpDir
469 * RETURNS
470 * Success: S_OK
471 * Failure: Status
473 HRESULT WINAPI RegisterTypeLib(
474 ITypeLib * ptlib, /* [in] Pointer to the library*/
475 OLECHAR * szFullPath, /* [in] full Path of the library*/
476 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
477 may be NULL*/
479 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
480 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
481 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
482 HRESULT res;
483 TLIBATTR *attr;
484 WCHAR keyName[60];
485 WCHAR tmp[16];
486 HKEY key, subKey;
487 UINT types, tidx;
488 TYPEKIND kind;
489 DWORD disposition;
491 if (ptlib == NULL || szFullPath == NULL)
492 return E_INVALIDARG;
494 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
495 return E_FAIL;
497 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
499 res = S_OK;
500 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
501 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
503 LPOLESTR doc;
505 /* Set the human-readable name of the typelib */
506 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
508 if (RegSetValueExW(key, NULL, 0, REG_SZ,
509 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
510 res = E_FAIL;
512 SysFreeString(doc);
514 else
515 res = E_FAIL;
517 /* Make up the name of the typelib path subkey */
518 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
520 /* Create the typelib path subkey */
521 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
522 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
524 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
525 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
526 res = E_FAIL;
528 RegCloseKey(subKey);
530 else
531 res = E_FAIL;
533 /* Create the flags subkey */
534 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
535 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
537 /* FIXME: is %u correct? */
538 static const WCHAR formatW[] = {'%','u',0};
539 WCHAR buf[20];
540 sprintfW(buf, formatW, attr->wLibFlags);
541 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
542 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
543 res = E_FAIL;
545 RegCloseKey(subKey);
547 else
548 res = E_FAIL;
550 /* create the helpdir subkey */
551 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
552 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
554 BOOL freeHelpDir = FALSE;
555 OLECHAR* pIndexStr;
557 /* if we created a new key, and helpDir was null, set the helpdir
558 to the directory which contains the typelib. However,
559 if we just opened an existing key, we leave the helpdir alone */
560 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
561 szHelpDir = SysAllocString(szFullPath);
562 pIndexStr = strrchrW(szHelpDir, '\\');
563 if (pIndexStr) {
564 *pIndexStr = 0;
566 freeHelpDir = TRUE;
569 /* if we have an szHelpDir, set it! */
570 if (szHelpDir != NULL) {
571 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
572 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
573 res = E_FAIL;
577 /* tidy up */
578 if (freeHelpDir) SysFreeString(szHelpDir);
579 RegCloseKey(subKey);
581 } else {
582 res = E_FAIL;
585 RegCloseKey(key);
587 else
588 res = E_FAIL;
590 /* register OLE Automation-compatible interfaces for this typelib */
591 types = ITypeLib_GetTypeInfoCount(ptlib);
592 for (tidx=0; tidx<types; tidx++) {
593 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
594 LPOLESTR name = NULL;
595 ITypeInfo *tinfo = NULL;
597 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
599 switch (kind) {
600 case TKIND_INTERFACE:
601 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
602 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
603 break;
605 case TKIND_DISPATCH:
606 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
607 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
608 break;
610 default:
611 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
612 break;
615 if (tinfo) {
616 TYPEATTR *tattr = NULL;
617 ITypeInfo_GetTypeAttr(tinfo, &tattr);
619 if (tattr) {
620 TRACE_(typelib)("guid=%s, flags=%04x (",
621 debugstr_guid(&tattr->guid),
622 tattr->wTypeFlags);
624 if (TRACE_ON(typelib)) {
625 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
626 XX(FAPPOBJECT);
627 XX(FCANCREATE);
628 XX(FLICENSED);
629 XX(FPREDECLID);
630 XX(FHIDDEN);
631 XX(FCONTROL);
632 XX(FDUAL);
633 XX(FNONEXTENSIBLE);
634 XX(FOLEAUTOMATION);
635 XX(FRESTRICTED);
636 XX(FAGGREGATABLE);
637 XX(FREPLACEABLE);
638 XX(FDISPATCHABLE);
639 XX(FREVERSEBIND);
640 XX(FPROXY);
641 #undef XX
642 MESSAGE("\n");
645 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL|TYPEFLAG_FDISPATCHABLE))
647 /* register interface<->typelib coupling */
648 get_interface_key( &tattr->guid, keyName );
649 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
650 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
652 if (name)
653 RegSetValueExW(key, NULL, 0, REG_SZ,
654 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
656 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
657 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
658 RegSetValueExW(subKey, NULL, 0, REG_SZ,
659 (const BYTE *)PSOA, sizeof PSOA);
660 RegCloseKey(subKey);
663 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
664 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
665 RegSetValueExW(subKey, NULL, 0, REG_SZ,
666 (const BYTE *)PSOA, sizeof PSOA);
667 RegCloseKey(subKey);
670 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
671 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
673 WCHAR buffer[40];
674 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
675 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
677 StringFromGUID2(&attr->guid, buffer, 40);
678 RegSetValueExW(subKey, NULL, 0, REG_SZ,
679 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
680 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
681 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
682 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
683 RegCloseKey(subKey);
686 RegCloseKey(key);
690 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
693 ITypeInfo_Release(tinfo);
696 SysFreeString(name);
700 ITypeLib_ReleaseTLibAttr(ptlib, attr);
702 return res;
706 /******************************************************************************
707 * UnRegisterTypeLib [OLEAUT32.186]
708 * Removes information about a type library from the System Registry
709 * NOTES
711 * RETURNS
712 * Success: S_OK
713 * Failure: Status
715 HRESULT WINAPI UnRegisterTypeLib(
716 REFGUID libid, /* [in] Guid of the library */
717 WORD wVerMajor, /* [in] major version */
718 WORD wVerMinor, /* [in] minor version */
719 LCID lcid, /* [in] locale id */
720 SYSKIND syskind)
722 BSTR tlibPath = NULL;
723 DWORD tmpLength;
724 WCHAR keyName[60];
725 WCHAR subKeyName[50];
726 int result = S_OK;
727 DWORD i = 0;
728 BOOL deleteOtherStuff;
729 HKEY key = NULL;
730 HKEY subKey = NULL;
731 TYPEATTR* typeAttr = NULL;
732 TYPEKIND kind;
733 ITypeInfo* typeInfo = NULL;
734 ITypeLib* typeLib = NULL;
735 int numTypes;
737 TRACE("(IID: %s)\n",debugstr_guid(libid));
739 /* Create the path to the key */
740 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
742 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
744 TRACE("Unsupported syskind %i\n", syskind);
745 result = E_INVALIDARG;
746 goto end;
749 /* get the path to the typelib on disk */
750 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
751 result = E_INVALIDARG;
752 goto end;
755 /* Try and open the key to the type library. */
756 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
757 result = E_INVALIDARG;
758 goto end;
761 /* Try and load the type library */
762 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
763 result = TYPE_E_INVALIDSTATE;
764 goto end;
767 /* remove any types registered with this typelib */
768 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
769 for (i=0; i<numTypes; i++) {
770 /* get the kind of type */
771 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
772 goto enddeleteloop;
775 /* skip non-interfaces, and get type info for the type */
776 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
777 goto enddeleteloop;
779 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
780 goto enddeleteloop;
782 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
783 goto enddeleteloop;
786 /* the path to the type */
787 get_interface_key( &typeAttr->guid, subKeyName );
789 /* Delete its bits */
790 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS) {
791 goto enddeleteloop;
793 RegDeleteKeyW(subKey, ProxyStubClsidW);
794 RegDeleteKeyW(subKey, ProxyStubClsid32W);
795 RegDeleteKeyW(subKey, TypeLibW);
796 RegCloseKey(subKey);
797 subKey = NULL;
798 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
800 enddeleteloop:
801 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
802 typeAttr = NULL;
803 if (typeInfo) ITypeInfo_Release(typeInfo);
804 typeInfo = NULL;
807 /* Now, delete the type library path subkey */
808 get_lcid_subkey( lcid, syskind, subKeyName );
809 RegDeleteKeyW(key, subKeyName);
810 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
811 RegDeleteKeyW(key, subKeyName);
813 /* check if there is anything besides the FLAGS/HELPDIR keys.
814 If there is, we don't delete them */
815 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
816 deleteOtherStuff = TRUE;
817 i = 0;
818 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
819 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
821 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
822 if (!strcmpW(subKeyName, FLAGSW)) continue;
823 if (!strcmpW(subKeyName, HELPDIRW)) continue;
824 deleteOtherStuff = FALSE;
825 break;
828 /* only delete the other parts of the key if we're absolutely sure */
829 if (deleteOtherStuff) {
830 RegDeleteKeyW(key, FLAGSW);
831 RegDeleteKeyW(key, HELPDIRW);
832 RegCloseKey(key);
833 key = NULL;
835 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
836 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
837 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
840 end:
841 if (tlibPath) SysFreeString(tlibPath);
842 if (typeLib) ITypeLib_Release(typeLib);
843 if (subKey) RegCloseKey(subKey);
844 if (key) RegCloseKey(key);
845 return result;
848 /*======================= ITypeLib implementation =======================*/
850 typedef struct tagTLBCustData
852 GUID guid;
853 VARIANT data;
854 struct tagTLBCustData* next;
855 } TLBCustData;
857 /* data structure for import typelibs */
858 typedef struct tagTLBImpLib
860 int offset; /* offset in the file (MSFT)
861 offset in nametable (SLTG)
862 just used to identify library while reading
863 data from file */
864 GUID guid; /* libid */
865 BSTR name; /* name */
867 LCID lcid; /* lcid of imported typelib */
869 WORD wVersionMajor; /* major version number */
870 WORD wVersionMinor; /* minor version number */
872 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
873 NULL if not yet loaded */
874 struct tagTLBImpLib * next;
875 } TLBImpLib;
877 /* internal ITypeLib data */
878 typedef struct tagITypeLibImpl
880 const ITypeLib2Vtbl *lpVtbl;
881 const ITypeCompVtbl *lpVtblTypeComp;
882 LONG ref;
883 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
885 /* strings can be stored in tlb as multibyte strings BUT they are *always*
886 * exported to the application as a UNICODE string.
888 BSTR Name;
889 BSTR DocString;
890 BSTR HelpFile;
891 BSTR HelpStringDll;
892 unsigned long dwHelpContext;
893 int TypeInfoCount; /* nr of typeinfo's in librarry */
894 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
895 int ctCustData; /* number of items in cust data list */
896 TLBCustData * pCustData; /* linked list to cust data */
897 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
898 int ctTypeDesc; /* number of items in type desc array */
899 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
900 library. Only used while reading MSFT
901 typelibs */
902 struct list ref_list; /* list of ref types in this typelib */
903 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
906 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
907 struct tagITypeLibImpl *next, *prev;
908 WCHAR *path;
909 INT index;
910 } ITypeLibImpl;
912 static const ITypeLib2Vtbl tlbvt;
913 static const ITypeCompVtbl tlbtcvt;
915 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
917 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
920 /* ITypeLib methods */
921 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
922 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
924 /*======================= ITypeInfo implementation =======================*/
926 /* data for referenced types */
927 typedef struct tagTLBRefType
929 INT index; /* Type index for internal ref or for external ref
930 it the format is SLTG. -2 indicates to
931 use guid */
933 GUID guid; /* guid of the referenced type */
934 /* if index == TLB_REF_USE_GUID */
936 HREFTYPE reference; /* The href of this ref */
937 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
938 TLB_REF_INTERNAL for internal refs
939 TLB_REF_NOT_FOUND for broken refs */
941 struct list entry;
942 } TLBRefType;
944 #define TLB_REF_USE_GUID -2
946 #define TLB_REF_INTERNAL (void*)-2
947 #define TLB_REF_NOT_FOUND (void*)-1
949 /* internal Parameter data */
950 typedef struct tagTLBParDesc
952 BSTR Name;
953 int ctCustData;
954 TLBCustData * pCustData; /* linked list to cust data */
955 } TLBParDesc;
957 /* internal Function data */
958 typedef struct tagTLBFuncDesc
960 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
961 BSTR Name; /* the name of this function */
962 TLBParDesc *pParamDesc; /* array with param names and custom data */
963 int helpcontext;
964 int HelpStringContext;
965 BSTR HelpString;
966 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
967 int ctCustData;
968 TLBCustData * pCustData; /* linked list to cust data; */
969 struct tagTLBFuncDesc * next;
970 } TLBFuncDesc;
972 /* internal Variable data */
973 typedef struct tagTLBVarDesc
975 VARDESC vardesc; /* lots of info on the variable and its attributes. */
976 BSTR Name; /* the name of this variable */
977 int HelpContext;
978 int HelpStringContext; /* FIXME: where? */
979 BSTR HelpString;
980 int ctCustData;
981 TLBCustData * pCustData;/* linked list to cust data; */
982 struct tagTLBVarDesc * next;
983 } TLBVarDesc;
985 /* internal implemented interface data */
986 typedef struct tagTLBImplType
988 HREFTYPE hRef; /* hRef of interface */
989 int implflags; /* IMPLFLAG_*s */
990 int ctCustData;
991 TLBCustData * pCustData;/* linked list to custom data; */
992 struct tagTLBImplType *next;
993 } TLBImplType;
995 /* internal TypeInfo data */
996 typedef struct tagITypeInfoImpl
998 const ITypeInfo2Vtbl *lpVtbl;
999 const ITypeCompVtbl *lpVtblTypeComp;
1000 LONG ref;
1001 BOOL no_free_data; /* don't free data structures */
1002 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1003 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1004 int index; /* index in this typelib; */
1005 HREFTYPE hreftype; /* hreftype for app object binding */
1006 /* type libs seem to store the doc strings in ascii
1007 * so why should we do it in unicode?
1009 BSTR Name;
1010 BSTR DocString;
1011 BSTR DllName;
1012 unsigned long dwHelpContext;
1013 unsigned long dwHelpStringContext;
1015 /* functions */
1016 TLBFuncDesc * funclist; /* linked list with function descriptions */
1018 /* variables */
1019 TLBVarDesc * varlist; /* linked list with variable descriptions */
1021 /* Implemented Interfaces */
1022 TLBImplType * impltypelist;
1024 int ctCustData;
1025 TLBCustData * pCustData; /* linked list to cust data; */
1026 struct tagITypeInfoImpl * next;
1027 } ITypeInfoImpl;
1029 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1031 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1034 static const ITypeInfo2Vtbl tinfvt;
1035 static const ITypeCompVtbl tcompvt;
1037 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
1039 typedef struct tagTLBContext
1041 unsigned int oStart; /* start of TLB in file */
1042 unsigned int pos; /* current pos */
1043 unsigned int length; /* total length */
1044 void *mapping; /* memory mapping */
1045 MSFT_SegDir * pTblDir;
1046 ITypeLibImpl* pLibInfo;
1047 } TLBContext;
1050 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1053 debug
1055 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1056 if (pTD->vt & VT_RESERVED)
1057 szVarType += strlen(strcpy(szVarType, "reserved | "));
1058 if (pTD->vt & VT_BYREF)
1059 szVarType += strlen(strcpy(szVarType, "ref to "));
1060 if (pTD->vt & VT_ARRAY)
1061 szVarType += strlen(strcpy(szVarType, "array of "));
1062 if (pTD->vt & VT_VECTOR)
1063 szVarType += strlen(strcpy(szVarType, "vector of "));
1064 switch(pTD->vt & VT_TYPEMASK) {
1065 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1066 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1067 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1068 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1069 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1070 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1071 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1072 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1073 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1074 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1075 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1076 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1077 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1078 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1079 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1080 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1081 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1082 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1083 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1084 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1085 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1086 pTD->u.hreftype); break;
1087 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1088 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1089 case VT_PTR: sprintf(szVarType, "ptr to ");
1090 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1091 break;
1092 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1093 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1094 break;
1095 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1096 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1097 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1098 break;
1100 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1104 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1105 char buf[200];
1106 USHORT flags = edesc->u.paramdesc.wParamFlags;
1107 dump_TypeDesc(&edesc->tdesc,buf);
1108 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1109 MESSAGE("\t\tu.paramdesc.wParamFlags");
1110 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1111 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1112 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1113 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1114 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1115 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1116 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1117 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1118 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1120 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1121 int i;
1122 MESSAGE("memid is %08x\n",funcdesc->memid);
1123 for (i=0;i<funcdesc->cParams;i++) {
1124 MESSAGE("Param %d:\n",i);
1125 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1127 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1128 switch (funcdesc->funckind) {
1129 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1130 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1131 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1132 case FUNC_STATIC: MESSAGE("static");break;
1133 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1134 default: MESSAGE("unknown");break;
1136 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1137 switch (funcdesc->invkind) {
1138 case INVOKE_FUNC: MESSAGE("func");break;
1139 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1140 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1141 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1143 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1144 switch (funcdesc->callconv) {
1145 case CC_CDECL: MESSAGE("cdecl");break;
1146 case CC_PASCAL: MESSAGE("pascal");break;
1147 case CC_STDCALL: MESSAGE("stdcall");break;
1148 case CC_SYSCALL: MESSAGE("syscall");break;
1149 default:break;
1151 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1152 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1153 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1155 MESSAGE("\telemdescFunc (return value type):\n");
1156 dump_ELEMDESC(&funcdesc->elemdescFunc);
1159 static const char * const typekind_desc[] =
1161 "TKIND_ENUM",
1162 "TKIND_RECORD",
1163 "TKIND_MODULE",
1164 "TKIND_INTERFACE",
1165 "TKIND_DISPATCH",
1166 "TKIND_COCLASS",
1167 "TKIND_ALIAS",
1168 "TKIND_UNION",
1169 "TKIND_MAX"
1172 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1174 int i;
1175 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1176 for (i=0;i<pfd->funcdesc.cParams;i++)
1177 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1180 dump_FUNCDESC(&(pfd->funcdesc));
1182 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1183 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1185 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1187 while (pfd)
1189 dump_TLBFuncDescOne(pfd);
1190 pfd = pfd->next;
1193 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1195 while (pvd)
1197 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1198 pvd = pvd->next;
1202 static void dump_TLBImpLib(const TLBImpLib *import)
1204 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1205 debugstr_w(import->name));
1206 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1207 import->wVersionMinor, import->lcid, import->offset);
1210 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1212 TLBRefType *ref;
1214 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1216 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1217 if(ref->index == -1)
1218 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1219 else
1220 TRACE_(typelib)("type no: %d\n", ref->index);
1222 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1224 TRACE_(typelib)("in lib\n");
1225 dump_TLBImpLib(ref->pImpTLInfo);
1230 static void dump_TLBImplType(const TLBImplType * impl)
1232 while (impl) {
1233 TRACE_(typelib)(
1234 "implementing/inheriting interface hRef = %x implflags %x\n",
1235 impl->hRef, impl->implflags);
1236 impl = impl->next;
1240 static void dump_Variant(const VARIANT * pvar)
1242 SYSTEMTIME st;
1244 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1246 if (pvar)
1248 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1249 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1251 TRACE(",%p", V_BYREF(pvar));
1253 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1255 TRACE(",%p", V_ARRAY(pvar));
1257 else switch (V_TYPE(pvar))
1259 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1260 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1261 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1262 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1263 case VT_INT:
1264 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1265 case VT_UINT:
1266 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1267 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1268 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1269 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1270 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1271 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1272 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1273 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1274 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1275 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1276 V_CY(pvar).s.Lo); break;
1277 case VT_DATE:
1278 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1279 TRACE(",<invalid>");
1280 else
1281 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1282 st.wHour, st.wMinute, st.wSecond);
1283 break;
1284 case VT_ERROR:
1285 case VT_VOID:
1286 case VT_USERDEFINED:
1287 case VT_EMPTY:
1288 case VT_NULL: break;
1289 default: TRACE(",?"); break;
1292 TRACE("}\n");
1295 static void dump_DispParms(const DISPPARAMS * pdp)
1297 int index;
1299 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1301 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1303 TRACE("named args:\n");
1304 for (index = 0; index < pdp->cNamedArgs; index++)
1305 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1308 if (pdp->cArgs && pdp->rgvarg)
1310 TRACE("args:\n");
1311 for (index = 0; index < pdp->cArgs; index++)
1312 dump_Variant( &pdp->rgvarg[index] );
1316 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1318 TRACE("%p ref=%u\n", pty, pty->ref);
1319 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1320 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1321 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1322 TRACE("fct:%u var:%u impl:%u\n",
1323 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1324 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1325 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1326 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1327 if (TRACE_ON(ole))
1328 dump_TLBFuncDesc(pty->funclist);
1329 dump_TLBVarDesc(pty->varlist);
1330 dump_TLBImplType(pty->impltypelist);
1333 static void dump_VARDESC(const VARDESC *v)
1335 MESSAGE("memid %d\n",v->memid);
1336 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1337 MESSAGE("oInst %d\n",v->u.oInst);
1338 dump_ELEMDESC(&(v->elemdescVar));
1339 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1340 MESSAGE("varkind %d\n",v->varkind);
1343 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1345 /* VT_LPWSTR is largest type that */
1346 /* may appear in type description*/
1347 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1348 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1349 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1350 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1351 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1352 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1353 {{0},30},{{0},31}
1356 static void TLB_abort(void)
1358 DebugBreak();
1361 static void * TLB_Alloc(unsigned size) __WINE_ALLOC_SIZE(1);
1362 static void * TLB_Alloc(unsigned size)
1364 void * ret;
1365 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1366 /* FIXME */
1367 ERR("cannot allocate memory\n");
1369 return ret;
1372 static void TLB_Free(void * ptr)
1374 HeapFree(GetProcessHeap(), 0, ptr);
1377 /* returns the size required for a deep copy of a typedesc into a
1378 * flat buffer */
1379 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1381 SIZE_T size = 0;
1383 if (alloc_initial_space)
1384 size += sizeof(TYPEDESC);
1386 switch (tdesc->vt)
1388 case VT_PTR:
1389 case VT_SAFEARRAY:
1390 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1391 break;
1392 case VT_CARRAY:
1393 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1394 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1395 break;
1397 return size;
1400 /* deep copy a typedesc into a flat buffer */
1401 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1403 if (!dest)
1405 dest = buffer;
1406 buffer = (char *)buffer + sizeof(TYPEDESC);
1409 *dest = *src;
1411 switch (src->vt)
1413 case VT_PTR:
1414 case VT_SAFEARRAY:
1415 dest->u.lptdesc = buffer;
1416 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1417 break;
1418 case VT_CARRAY:
1419 dest->u.lpadesc = buffer;
1420 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1421 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1422 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1423 break;
1425 return buffer;
1428 /* free custom data allocated by MSFT_CustData */
1429 static inline void TLB_FreeCustData(TLBCustData *pCustData)
1431 TLBCustData *pCustDataNext;
1432 for (; pCustData; pCustData = pCustDataNext)
1434 VariantClear(&pCustData->data);
1436 pCustDataNext = pCustData->next;
1437 TLB_Free(pCustData);
1441 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1443 DWORD len;
1444 BSTR ret;
1446 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1447 ret = SysAllocStringLen(NULL, len - 1);
1448 if (!ret) return ret;
1449 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1450 return ret;
1453 /**********************************************************************
1455 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1457 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1459 return pcx->pos;
1462 static inline void MSFT_Seek(TLBContext *pcx, long where)
1464 if (where != DO_NOT_SEEK)
1466 where += pcx->oStart;
1467 if (where > pcx->length)
1469 /* FIXME */
1470 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1471 TLB_abort();
1473 pcx->pos = where;
1477 /* read function */
1478 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1480 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1481 pcx->pos, count, pcx->oStart, pcx->length, where);
1483 MSFT_Seek(pcx, where);
1484 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1485 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1486 pcx->pos += count;
1487 return count;
1490 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1491 long where )
1493 DWORD ret;
1495 ret = MSFT_Read(buffer, count, pcx, where);
1496 FromLEDWords(buffer, ret);
1498 return ret;
1501 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1502 long where )
1504 DWORD ret;
1506 ret = MSFT_Read(buffer, count, pcx, where);
1507 FromLEWords(buffer, ret);
1509 return ret;
1512 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1514 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1515 memset(pGuid,0, sizeof(GUID));
1516 return;
1518 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1519 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1520 pGuid->Data2 = FromLEWord(pGuid->Data2);
1521 pGuid->Data3 = FromLEWord(pGuid->Data3);
1522 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1525 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1527 MSFT_NameIntro niName;
1529 if (offset < 0)
1531 ERR_(typelib)("bad offset %d\n", offset);
1532 return -1;
1535 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1536 pcx->pTblDir->pNametab.offset+offset);
1538 return niName.hreftype;
1541 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1543 char * name;
1544 MSFT_NameIntro niName;
1545 int lengthInChars;
1546 BSTR bstrName = NULL;
1548 if (offset < 0)
1550 ERR_(typelib)("bad offset %d\n", offset);
1551 return NULL;
1553 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1554 pcx->pTblDir->pNametab.offset+offset);
1555 niName.namelen &= 0xFF; /* FIXME: correct ? */
1556 name=TLB_Alloc((niName.namelen & 0xff) +1);
1557 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1558 name[niName.namelen & 0xff]='\0';
1560 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1561 name, -1, NULL, 0);
1563 /* no invalid characters in string */
1564 if (lengthInChars)
1566 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1568 /* don't check for invalid character since this has been done previously */
1569 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1571 TLB_Free(name);
1573 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1574 return bstrName;
1577 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1579 char * string;
1580 INT16 length;
1581 int lengthInChars;
1582 BSTR bstr = NULL;
1584 if(offset<0) return NULL;
1585 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1586 if(length <= 0) return 0;
1587 string=TLB_Alloc(length +1);
1588 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1589 string[length]='\0';
1591 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1592 string, -1, NULL, 0);
1594 /* no invalid characters in string */
1595 if (lengthInChars)
1597 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1599 /* don't check for invalid character since this has been done previously */
1600 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1602 TLB_Free(string);
1604 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1605 return bstr;
1608 * read a value and fill a VARIANT structure
1610 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1612 int size;
1614 TRACE_(typelib)("\n");
1616 if(offset <0) { /* data are packed in here */
1617 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1618 V_I4(pVar) = offset & 0x3ffffff;
1619 return;
1621 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1622 pcx->pTblDir->pCustData.offset + offset );
1623 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1624 switch (V_VT(pVar)){
1625 case VT_EMPTY: /* FIXME: is this right? */
1626 case VT_NULL: /* FIXME: is this right? */
1627 case VT_I2 : /* this should not happen */
1628 case VT_I4 :
1629 case VT_R4 :
1630 case VT_ERROR :
1631 case VT_BOOL :
1632 case VT_I1 :
1633 case VT_UI1 :
1634 case VT_UI2 :
1635 case VT_UI4 :
1636 case VT_INT :
1637 case VT_UINT :
1638 case VT_VOID : /* FIXME: is this right? */
1639 case VT_HRESULT :
1640 size=4; break;
1641 case VT_R8 :
1642 case VT_CY :
1643 case VT_DATE :
1644 case VT_I8 :
1645 case VT_UI8 :
1646 case VT_DECIMAL : /* FIXME: is this right? */
1647 case VT_FILETIME :
1648 size=8;break;
1649 /* pointer types with known behaviour */
1650 case VT_BSTR :{
1651 char * ptr;
1652 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1653 if(size < 0) {
1654 char next;
1655 DWORD origPos = MSFT_Tell(pcx), nullPos;
1657 do {
1658 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1659 } while (next);
1660 nullPos = MSFT_Tell(pcx);
1661 size = nullPos - origPos;
1662 MSFT_Seek(pcx, origPos);
1664 ptr=TLB_Alloc(size);/* allocate temp buffer */
1665 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1666 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1667 /* FIXME: do we need a AtoW conversion here? */
1668 V_UNION(pVar, bstrVal[size])='\0';
1669 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1670 TLB_Free(ptr);
1672 size=-4; break;
1673 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1674 case VT_DISPATCH :
1675 case VT_VARIANT :
1676 case VT_UNKNOWN :
1677 case VT_PTR :
1678 case VT_SAFEARRAY :
1679 case VT_CARRAY :
1680 case VT_USERDEFINED :
1681 case VT_LPSTR :
1682 case VT_LPWSTR :
1683 case VT_BLOB :
1684 case VT_STREAM :
1685 case VT_STORAGE :
1686 case VT_STREAMED_OBJECT :
1687 case VT_STORED_OBJECT :
1688 case VT_BLOB_OBJECT :
1689 case VT_CF :
1690 case VT_CLSID :
1691 default:
1692 size=0;
1693 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1694 V_VT(pVar));
1697 if(size>0) /* (big|small) endian correct? */
1698 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1699 return;
1702 * create a linked list with custom data
1704 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1706 MSFT_CDGuid entry;
1707 TLBCustData* pNew;
1708 int count=0;
1710 TRACE_(typelib)("\n");
1712 while(offset >=0){
1713 count++;
1714 pNew=TLB_Alloc(sizeof(TLBCustData));
1715 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1716 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1717 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1718 /* add new custom data at head of the list */
1719 pNew->next=*ppCustData;
1720 *ppCustData=pNew;
1721 offset = entry.next;
1723 return count;
1726 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1727 ITypeInfoImpl *pTI)
1729 if(type <0)
1730 pTd->vt=type & VT_TYPEMASK;
1731 else
1732 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1734 if(pTd->vt == VT_USERDEFINED)
1735 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1737 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1740 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1742 /* resolve referenced type if any */
1743 while (lpTypeDesc)
1745 switch (lpTypeDesc->vt)
1747 case VT_PTR:
1748 lpTypeDesc = lpTypeDesc->u.lptdesc;
1749 break;
1751 case VT_CARRAY:
1752 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1753 break;
1755 case VT_USERDEFINED:
1756 MSFT_DoRefType(pcx, pTI->pTypeLib,
1757 lpTypeDesc->u.hreftype);
1759 lpTypeDesc = NULL;
1760 break;
1762 default:
1763 lpTypeDesc = NULL;
1768 static void
1769 MSFT_DoFuncs(TLBContext* pcx,
1770 ITypeInfoImpl* pTI,
1771 int cFuncs,
1772 int cVars,
1773 int offset,
1774 TLBFuncDesc** pptfd)
1777 * member information is stored in a data structure at offset
1778 * indicated by the memoffset field of the typeinfo structure
1779 * There are several distinctive parts.
1780 * The first part starts with a field that holds the total length
1781 * of this (first) part excluding this field. Then follow the records,
1782 * for each member there is one record.
1784 * The first entry is always the length of the record (including this
1785 * length word).
1786 * The rest of the record depends on the type of the member. If there is
1787 * a field indicating the member type (function, variable, interface, etc)
1788 * I have not found it yet. At this time we depend on the information
1789 * in the type info and the usual order how things are stored.
1791 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1792 * for each member;
1794 * Third is an equal sized array with file offsets to the name entry
1795 * of each member.
1797 * The fourth and last (?) part is an array with offsets to the records
1798 * in the first part of this file segment.
1801 int infolen, nameoffset, reclength, nrattributes, i;
1802 int recoffset = offset + sizeof(INT);
1804 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1805 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1806 TLBFuncDesc *ptfd_prev = NULL;
1808 TRACE_(typelib)("\n");
1810 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1812 for ( i = 0; i < cFuncs ; i++ )
1814 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1816 /* name, eventually add to a hash table */
1817 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1818 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1820 /* nameoffset is sometimes -1 on the second half of a propget/propput
1821 * pair of functions */
1822 if ((nameoffset == -1) && (i > 0))
1823 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1824 else
1825 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1827 /* read the function information record */
1828 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1830 reclength &= 0xffff;
1832 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1834 /* do the attributes */
1835 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1836 / sizeof(int);
1838 if ( nrattributes > 0 )
1840 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1842 if ( nrattributes > 1 )
1844 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1845 pFuncRec->OptAttr[1]) ;
1847 if ( nrattributes > 2 )
1849 if ( pFuncRec->FKCCIC & 0x2000 )
1851 if (HIWORD(pFuncRec->OptAttr[2]) != 0)
1852 ERR("ordinal 0x%08x invalid, HIWORD != 0\n", pFuncRec->OptAttr[2]);
1853 (*pptfd)->Entry = (BSTR)pFuncRec->OptAttr[2];
1855 else
1857 (*pptfd)->Entry = MSFT_ReadString(pcx,
1858 pFuncRec->OptAttr[2]);
1860 if( nrattributes > 5 )
1862 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1864 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1866 MSFT_CustData(pcx,
1867 pFuncRec->OptAttr[6],
1868 &(*pptfd)->pCustData);
1872 else
1874 (*pptfd)->Entry = (BSTR)-1;
1879 /* fill the FuncDesc Structure */
1880 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1881 offset + infolen + ( i + 1) * sizeof(INT));
1883 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1884 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1885 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1886 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1887 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1888 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1889 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1891 MSFT_GetTdesc(pcx,
1892 pFuncRec->DataType,
1893 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1894 pTI);
1895 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1897 /* do the parameters/arguments */
1898 if(pFuncRec->nrargs)
1900 int j = 0;
1901 MSFT_ParameterInfo paraminfo;
1903 (*pptfd)->funcdesc.lprgelemdescParam =
1904 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1906 (*pptfd)->pParamDesc =
1907 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1909 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1910 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1912 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1914 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1916 MSFT_GetTdesc(pcx,
1917 paraminfo.DataType,
1918 &elemdesc->tdesc,
1919 pTI);
1921 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1923 /* name */
1924 if (paraminfo.oName == -1)
1925 /* this occurs for [propput] or [propget] methods, so
1926 * we should just set the name of the parameter to the
1927 * name of the method. */
1928 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1929 else
1930 (*pptfd)->pParamDesc[j].Name =
1931 MSFT_ReadName( pcx, paraminfo.oName );
1932 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1934 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1936 /* default value */
1937 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1938 (pFuncRec->FKCCIC & 0x1000) )
1940 INT* pInt = (INT *)((char *)pFuncRec +
1941 reclength -
1942 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1944 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1946 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1947 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1949 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1950 pInt[j], pcx);
1952 else
1953 elemdesc->u.paramdesc.pparamdescex = NULL;
1954 /* custom info */
1955 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1957 MSFT_CustData(pcx,
1958 pFuncRec->OptAttr[7+j],
1959 &(*pptfd)->pParamDesc[j].pCustData);
1962 /* SEEK value = jump to offset,
1963 * from there jump to the end of record,
1964 * go back by (j-1) arguments
1966 MSFT_ReadLEDWords( &paraminfo ,
1967 sizeof(MSFT_ParameterInfo), pcx,
1968 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1969 * sizeof(MSFT_ParameterInfo)));
1973 /* scode is not used: archaic win16 stuff FIXME: right? */
1974 (*pptfd)->funcdesc.cScodes = 0 ;
1975 (*pptfd)->funcdesc.lprgscode = NULL ;
1977 ptfd_prev = *pptfd;
1978 pptfd = & ((*pptfd)->next);
1979 recoffset += reclength;
1981 HeapFree(GetProcessHeap(), 0, recbuf);
1984 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1985 int cVars, int offset, TLBVarDesc ** pptvd)
1987 int infolen, nameoffset, reclength;
1988 char recbuf[256];
1989 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1990 int i;
1991 int recoffset;
1993 TRACE_(typelib)("\n");
1995 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1996 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1997 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1998 recoffset += offset+sizeof(INT);
1999 for(i=0;i<cVars;i++){
2000 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
2001 /* name, eventually add to a hash table */
2002 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2003 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2004 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
2005 /* read the variable information record */
2006 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
2007 reclength &=0xff;
2008 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
2009 /* Optional data */
2010 if(reclength >(6*sizeof(INT)) )
2011 (*pptvd)->HelpContext=pVarRec->HelpContext;
2012 if(reclength >(7*sizeof(INT)) )
2013 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
2014 if(reclength >(8*sizeof(INT)) )
2015 if(reclength >(9*sizeof(INT)) )
2016 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
2017 /* fill the VarDesc Structure */
2018 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
2019 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2020 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
2021 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
2022 MSFT_GetTdesc(pcx, pVarRec->DataType,
2023 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
2024 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2025 if(pVarRec->VarKind == VAR_CONST ){
2026 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
2027 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
2028 pVarRec->OffsValue, pcx);
2029 } else
2030 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
2031 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
2032 pptvd=&((*pptvd)->next);
2033 recoffset += reclength;
2036 /* fill in data for a hreftype (offset). When the referenced type is contained
2037 * in the typelib, it's just an (file) offset in the type info base dir.
2038 * If comes from import, it's an offset+1 in the ImpInfo table
2039 * */
2040 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2041 int offset)
2043 TLBRefType *ref;
2045 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2047 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2049 if(ref->reference == offset) return;
2052 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
2053 list_add_tail(&pTL->ref_list, &ref->entry);
2055 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2056 /* external typelib */
2057 MSFT_ImpInfo impinfo;
2058 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2060 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2062 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2063 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2064 while (pImpLib){ /* search the known offsets of all import libraries */
2065 if(pImpLib->offset==impinfo.oImpFile) break;
2066 pImpLib=pImpLib->next;
2068 if(pImpLib){
2069 ref->reference = offset;
2070 ref->pImpTLInfo = pImpLib;
2071 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2072 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2073 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2074 ref->index = TLB_REF_USE_GUID;
2075 } else
2076 ref->index = impinfo.oGuid;
2077 }else{
2078 ERR("Cannot find a reference\n");
2079 ref->reference = -1;
2080 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2082 }else{
2083 /* in this typelib */
2084 ref->index = MSFT_HREFTYPE_INDEX(offset);
2085 ref->reference = offset;
2086 ref->pImpTLInfo = TLB_REF_INTERNAL;
2090 /* process Implemented Interfaces of a com class */
2091 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2092 int offset)
2094 int i;
2095 MSFT_RefRecord refrec;
2096 TLBImplType **ppImpl = &pTI->impltypelist;
2098 TRACE_(typelib)("\n");
2100 for(i=0;i<count;i++){
2101 if(offset<0) break; /* paranoia */
2102 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2103 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2104 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2105 (*ppImpl)->hRef = refrec.reftype;
2106 (*ppImpl)->implflags=refrec.flags;
2107 (*ppImpl)->ctCustData=
2108 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2109 offset=refrec.onext;
2110 ppImpl=&((*ppImpl)->next);
2114 * process a typeinfo record
2116 static ITypeInfoImpl * MSFT_DoTypeInfo(
2117 TLBContext *pcx,
2118 int count,
2119 ITypeLibImpl * pLibInfo)
2121 MSFT_TypeInfoBase tiBase;
2122 ITypeInfoImpl *ptiRet;
2124 TRACE_(typelib)("count=%u\n", count);
2126 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2127 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2128 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2130 /* this is where we are coming from */
2131 ptiRet->pTypeLib = pLibInfo;
2132 ptiRet->index=count;
2133 /* fill in the typeattr fields */
2135 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2136 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2137 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2138 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2139 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2140 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2141 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2142 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2143 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2144 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2145 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2146 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2147 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2148 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2149 MSFT_GetTdesc(pcx, tiBase.datatype1,
2150 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2152 /* FIXME: */
2153 /* IDLDESC idldescType; *//* never saw this one != zero */
2155 /* name, eventually add to a hash table */
2156 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2157 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2158 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2159 /* help info */
2160 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2161 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2162 ptiRet->dwHelpContext=tiBase.helpcontext;
2164 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2165 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2167 /* note: InfoType's Help file and HelpStringDll come from the containing
2168 * library. Further HelpString and Docstring appear to be the same thing :(
2170 /* functions */
2171 if(ptiRet->TypeAttr.cFuncs >0 )
2172 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2173 ptiRet->TypeAttr.cVars,
2174 tiBase.memoffset, & ptiRet->funclist);
2175 /* variables */
2176 if(ptiRet->TypeAttr.cVars >0 )
2177 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2178 ptiRet->TypeAttr.cVars,
2179 tiBase.memoffset, & ptiRet->varlist);
2180 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2181 switch(ptiRet->TypeAttr.typekind)
2183 case TKIND_COCLASS:
2184 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2185 tiBase.datatype1);
2186 break;
2187 case TKIND_DISPATCH:
2188 /* This is not -1 when the interface is a non-base dual interface or
2189 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2190 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2191 not this interface.
2194 if (tiBase.datatype1 != -1)
2196 ptiRet->impltypelist = TLB_Alloc(sizeof(TLBImplType));
2197 ptiRet->impltypelist->hRef = tiBase.datatype1;
2198 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2200 break;
2201 default:
2202 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2203 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2204 ptiRet->impltypelist->hRef = tiBase.datatype1;
2205 break;
2208 ptiRet->ctCustData=
2209 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2211 TRACE_(typelib)("%s guid: %s kind:%s\n",
2212 debugstr_w(ptiRet->Name),
2213 debugstr_guid(&ptiRet->TypeAttr.guid),
2214 typekind_desc[ptiRet->TypeAttr.typekind]);
2216 return ptiRet;
2219 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2220 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2221 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2222 * tradeoff here.
2224 static ITypeLibImpl *tlb_cache_first;
2225 static CRITICAL_SECTION cache_section;
2226 static CRITICAL_SECTION_DEBUG cache_section_debug =
2228 0, 0, &cache_section,
2229 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2230 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2232 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2235 typedef struct TLB_PEFile
2237 const IUnknownVtbl *lpvtbl;
2238 LONG refs;
2239 HMODULE dll;
2240 HRSRC typelib_resource;
2241 HGLOBAL typelib_global;
2242 LPVOID typelib_base;
2243 } TLB_PEFile;
2245 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2247 if (IsEqualIID(riid, &IID_IUnknown))
2249 *ppv = iface;
2250 IUnknown_AddRef(iface);
2251 return S_OK;
2253 *ppv = NULL;
2254 return E_NOINTERFACE;
2257 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2259 TLB_PEFile *This = (TLB_PEFile *)iface;
2260 return InterlockedIncrement(&This->refs);
2263 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2265 TLB_PEFile *This = (TLB_PEFile *)iface;
2266 ULONG refs = InterlockedDecrement(&This->refs);
2267 if (!refs)
2269 if (This->typelib_global)
2270 FreeResource(This->typelib_global);
2271 if (This->dll)
2272 FreeLibrary(This->dll);
2273 HeapFree(GetProcessHeap(), 0, This);
2275 return refs;
2278 static const IUnknownVtbl TLB_PEFile_Vtable =
2280 TLB_PEFile_QueryInterface,
2281 TLB_PEFile_AddRef,
2282 TLB_PEFile_Release
2285 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2287 TLB_PEFile *This;
2289 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2290 if (!This)
2291 return E_OUTOFMEMORY;
2293 This->lpvtbl = &TLB_PEFile_Vtable;
2294 This->refs = 1;
2295 This->dll = NULL;
2296 This->typelib_resource = NULL;
2297 This->typelib_global = NULL;
2298 This->typelib_base = NULL;
2300 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2301 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2303 if (This->dll)
2305 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2306 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2307 if (This->typelib_resource)
2309 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2310 if (This->typelib_global)
2312 This->typelib_base = LockResource(This->typelib_global);
2314 if (This->typelib_base)
2316 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2317 *ppBase = This->typelib_base;
2318 *ppFile = (IUnknown *)&This->lpvtbl;
2319 return S_OK;
2325 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2326 return TYPE_E_CANTLOADLIBRARY;
2330 typedef struct TLB_Mapping
2332 const IUnknownVtbl *lpvtbl;
2333 LONG refs;
2334 HANDLE file;
2335 HANDLE mapping;
2336 LPVOID typelib_base;
2337 } TLB_Mapping;
2339 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2341 if (IsEqualIID(riid, &IID_IUnknown))
2343 *ppv = iface;
2344 IUnknown_AddRef(iface);
2345 return S_OK;
2347 *ppv = NULL;
2348 return E_NOINTERFACE;
2351 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2353 TLB_Mapping *This = (TLB_Mapping *)iface;
2354 return InterlockedIncrement(&This->refs);
2357 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2359 TLB_Mapping *This = (TLB_Mapping *)iface;
2360 ULONG refs = InterlockedDecrement(&This->refs);
2361 if (!refs)
2363 if (This->typelib_base)
2364 UnmapViewOfFile(This->typelib_base);
2365 if (This->mapping)
2366 CloseHandle(This->mapping);
2367 if (This->file != INVALID_HANDLE_VALUE)
2368 CloseHandle(This->file);
2369 HeapFree(GetProcessHeap(), 0, This);
2371 return refs;
2374 static const IUnknownVtbl TLB_Mapping_Vtable =
2376 TLB_Mapping_QueryInterface,
2377 TLB_Mapping_AddRef,
2378 TLB_Mapping_Release
2381 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2383 TLB_Mapping *This;
2385 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2386 if (!This)
2387 return E_OUTOFMEMORY;
2389 This->lpvtbl = &TLB_Mapping_Vtable;
2390 This->refs = 1;
2391 This->file = INVALID_HANDLE_VALUE;
2392 This->mapping = NULL;
2393 This->typelib_base = NULL;
2395 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2396 if (INVALID_HANDLE_VALUE != This->file)
2398 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2399 if (This->mapping)
2401 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2402 if(This->typelib_base)
2404 /* retrieve file size */
2405 *pdwTLBLength = GetFileSize(This->file, NULL);
2406 *ppBase = This->typelib_base;
2407 *ppFile = (IUnknown *)&This->lpvtbl;
2408 return S_OK;
2413 IUnknown_Release((IUnknown *)&This->lpvtbl);
2414 return TYPE_E_CANTLOADLIBRARY;
2417 /****************************************************************************
2418 * TLB_ReadTypeLib
2420 * find the type of the typelib file and map the typelib resource into
2421 * the memory
2423 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2424 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2425 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2427 ITypeLibImpl *entry;
2428 HRESULT ret;
2429 INT index = 1;
2430 LPWSTR index_str, file = (LPWSTR)pszFileName;
2431 LPVOID pBase = NULL;
2432 DWORD dwTLBLength = 0;
2433 IUnknown *pFile = NULL;
2435 *ppTypeLib = NULL;
2437 index_str = strrchrW(pszFileName, '\\');
2438 if(index_str && *++index_str != '\0')
2440 LPWSTR end_ptr;
2441 long idx = strtolW(index_str, &end_ptr, 10);
2442 if(*end_ptr == '\0')
2444 int str_len = index_str - pszFileName - 1;
2445 index = idx;
2446 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
2447 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2448 file[str_len] = 0;
2452 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2454 if(strchrW(file, '\\'))
2456 lstrcpyW(pszPath, file);
2458 else
2460 int len = GetSystemDirectoryW(pszPath, cchPath);
2461 pszPath[len] = '\\';
2462 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2466 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file);
2468 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2470 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2471 EnterCriticalSection(&cache_section);
2472 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2474 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2476 TRACE("cache hit\n");
2477 *ppTypeLib = (ITypeLib2*)entry;
2478 ITypeLib_AddRef(*ppTypeLib);
2479 LeaveCriticalSection(&cache_section);
2480 return S_OK;
2483 LeaveCriticalSection(&cache_section);
2485 /* now actually load and parse the typelib */
2487 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2488 if (ret == TYPE_E_CANTLOADLIBRARY)
2489 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2490 if (SUCCEEDED(ret))
2492 if (dwTLBLength >= 4)
2494 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2495 if (dwSignature == MSFT_SIGNATURE)
2496 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2497 else if (dwSignature == SLTG_SIGNATURE)
2498 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2499 else
2501 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2502 ret = TYPE_E_CANTLOADLIBRARY;
2505 else
2506 ret = TYPE_E_CANTLOADLIBRARY;
2507 IUnknown_Release(pFile);
2510 if(*ppTypeLib) {
2511 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2513 TRACE("adding to cache\n");
2514 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2515 lstrcpyW(impl->path, pszPath);
2516 /* We should really canonicalise the path here. */
2517 impl->index = index;
2519 /* FIXME: check if it has added already in the meantime */
2520 EnterCriticalSection(&cache_section);
2521 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2522 impl->prev = NULL;
2523 tlb_cache_first = impl;
2524 LeaveCriticalSection(&cache_section);
2525 ret = S_OK;
2526 } else
2527 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2529 return ret;
2532 /*================== ITypeLib(2) Methods ===================================*/
2534 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2536 ITypeLibImpl* pTypeLibImpl;
2538 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2539 if (!pTypeLibImpl) return NULL;
2541 pTypeLibImpl->lpVtbl = &tlbvt;
2542 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2543 pTypeLibImpl->ref = 1;
2545 list_init(&pTypeLibImpl->ref_list);
2546 pTypeLibImpl->dispatch_href = -1;
2548 return pTypeLibImpl;
2551 /****************************************************************************
2552 * ITypeLib2_Constructor_MSFT
2554 * loading an MSFT typelib from an in-memory image
2556 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2558 TLBContext cx;
2559 long lPSegDir;
2560 MSFT_Header tlbHeader;
2561 MSFT_SegDir tlbSegDir;
2562 ITypeLibImpl * pTypeLibImpl;
2564 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2566 pTypeLibImpl = TypeLibImpl_Constructor();
2567 if (!pTypeLibImpl) return NULL;
2569 /* get pointer to beginning of typelib data */
2570 cx.pos = 0;
2571 cx.oStart=0;
2572 cx.mapping = pLib;
2573 cx.pLibInfo = pTypeLibImpl;
2574 cx.length = dwTLBLength;
2576 /* read header */
2577 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2578 TRACE_(typelib)("header:\n");
2579 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2580 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2581 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2582 return NULL;
2584 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2586 /* there is a small amount of information here until the next important
2587 * part:
2588 * the segment directory . Try to calculate the amount of data */
2589 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2591 /* now read the segment directory */
2592 TRACE("read segment directory (at %ld)\n",lPSegDir);
2593 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2594 cx.pTblDir = &tlbSegDir;
2596 /* just check two entries */
2597 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2599 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2600 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2601 return NULL;
2604 /* now fill our internal data */
2605 /* TLIBATTR fields */
2606 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2608 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2609 /* Windows seems to have zero here, is this correct? */
2610 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2611 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2612 else
2613 pTypeLibImpl->LibAttr.lcid = 0;
2615 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2616 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2617 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2618 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2620 /* name, eventually add to a hash table */
2621 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2623 /* help info */
2624 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2625 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2627 if( tlbHeader.varflags & HELPDLLFLAG)
2629 int offset;
2630 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2631 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2634 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2636 /* custom data */
2637 if(tlbHeader.CustomDataOffset >= 0)
2639 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2642 /* fill in type descriptions */
2643 if(tlbSegDir.pTypdescTab.length > 0)
2645 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2646 INT16 td[4];
2647 pTypeLibImpl->ctTypeDesc = cTD;
2648 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2649 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2650 for(i=0; i<cTD; )
2652 /* FIXME: add several sanity checks here */
2653 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2654 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2656 /* FIXME: check safearray */
2657 if(td[3] < 0)
2658 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2659 else
2660 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2662 else if(td[0] == VT_CARRAY)
2664 /* array descr table here */
2665 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2667 else if(td[0] == VT_USERDEFINED)
2669 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2671 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2674 /* second time around to fill the array subscript info */
2675 for(i=0;i<cTD;i++)
2677 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2678 if(tlbSegDir.pArrayDescriptions.offset>0)
2680 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2681 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2683 if(td[1]<0)
2684 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2685 else
2686 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2688 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2690 for(j = 0; j<td[2]; j++)
2692 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2693 sizeof(INT), &cx, DO_NOT_SEEK);
2694 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2695 sizeof(INT), &cx, DO_NOT_SEEK);
2698 else
2700 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2701 ERR("didn't find array description data\n");
2706 /* imported type libs */
2707 if(tlbSegDir.pImpFiles.offset>0)
2709 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2710 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2711 UINT16 size;
2713 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2715 char *name;
2717 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2718 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2719 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2721 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2722 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2723 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2724 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2726 size >>= 2;
2727 name = TLB_Alloc(size+1);
2728 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2729 (*ppImpLib)->name = TLB_MultiByteToBSTR(name);
2731 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2732 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2734 ppImpLib = &(*ppImpLib)->next;
2738 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
2739 if(pTypeLibImpl->dispatch_href != -1)
2740 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
2742 /* type info's */
2743 if(tlbHeader.nrtypeinfos >= 0 )
2745 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2746 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2747 int i;
2749 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
2751 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2753 ppTI = &((*ppTI)->next);
2754 (pTypeLibImpl->TypeInfoCount)++;
2758 TRACE("(%p)\n", pTypeLibImpl);
2759 return (ITypeLib2*) pTypeLibImpl;
2763 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
2765 char b[3];
2766 int i;
2767 short s;
2769 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2770 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2771 return FALSE;
2774 guid->Data4[0] = s >> 8;
2775 guid->Data4[1] = s & 0xff;
2777 b[2] = '\0';
2778 for(i = 0; i < 6; i++) {
2779 memcpy(b, str + 24 + 2 * i, 2);
2780 guid->Data4[i + 2] = strtol(b, NULL, 16);
2782 return TRUE;
2785 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
2787 WORD bytelen;
2788 DWORD len;
2790 *pBstr = NULL;
2791 bytelen = *(const WORD*)ptr;
2792 if(bytelen == 0xffff) return 2;
2793 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2794 *pBstr = SysAllocStringLen(NULL, len - 1);
2795 if (*pBstr)
2796 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
2797 return bytelen + 2;
2800 static WORD SLTG_ReadStringA(const char *ptr, char **str)
2802 WORD bytelen;
2804 *str = NULL;
2805 bytelen = *(const WORD*)ptr;
2806 if(bytelen == 0xffff) return 2;
2807 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2808 memcpy(*str, ptr + 2, bytelen);
2809 (*str)[bytelen] = '\0';
2810 return bytelen + 2;
2813 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2815 char *ptr = pLibBlk;
2816 WORD w;
2818 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2819 FIXME("libblk magic = %04x\n", w);
2820 return 0;
2823 ptr += 6;
2824 if((w = *(WORD*)ptr) != 0xffff) {
2825 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2826 ptr += w;
2828 ptr += 2;
2830 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2832 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2834 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2835 ptr += 4;
2837 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2838 ptr += 2;
2840 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2841 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2842 else
2843 pTypeLibImpl->LibAttr.lcid = 0;
2844 ptr += 2;
2846 ptr += 4; /* skip res12 */
2848 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2849 ptr += 2;
2851 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2852 ptr += 2;
2854 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2855 ptr += 2;
2857 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2858 ptr += sizeof(GUID);
2860 return ptr - (char*)pLibBlk;
2863 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
2864 typedef struct
2866 unsigned int num;
2867 HREFTYPE refs[1];
2868 } sltg_ref_lookup_t;
2870 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
2871 HREFTYPE *typelib_ref)
2873 if(typeinfo_ref < table->num)
2875 *typelib_ref = table->refs[typeinfo_ref];
2876 return S_OK;
2879 ERR_(typelib)("Unable to find reference\n");
2880 *typelib_ref = -1;
2881 return E_FAIL;
2884 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
2886 BOOL done = FALSE;
2888 while(!done) {
2889 if((*pType & 0xe00) == 0xe00) {
2890 pTD->vt = VT_PTR;
2891 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2892 sizeof(TYPEDESC));
2893 pTD = pTD->u.lptdesc;
2895 switch(*pType & 0x3f) {
2896 case VT_PTR:
2897 pTD->vt = VT_PTR;
2898 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2899 sizeof(TYPEDESC));
2900 pTD = pTD->u.lptdesc;
2901 break;
2903 case VT_USERDEFINED:
2904 pTD->vt = VT_USERDEFINED;
2905 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
2906 done = TRUE;
2907 break;
2909 case VT_CARRAY:
2911 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2912 array */
2914 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2916 pTD->vt = VT_CARRAY;
2917 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2918 sizeof(ARRAYDESC) +
2919 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2920 pTD->u.lpadesc->cDims = pSA->cDims;
2921 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2922 pSA->cDims * sizeof(SAFEARRAYBOUND));
2924 pTD = &pTD->u.lpadesc->tdescElem;
2925 break;
2928 case VT_SAFEARRAY:
2930 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2931 useful? */
2933 pType++;
2934 pTD->vt = VT_SAFEARRAY;
2935 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2936 sizeof(TYPEDESC));
2937 pTD = pTD->u.lptdesc;
2938 break;
2940 default:
2941 pTD->vt = *pType & 0x3f;
2942 done = TRUE;
2943 break;
2945 pType++;
2947 return pType;
2950 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
2951 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
2953 /* Handle [in/out] first */
2954 if((*pType & 0xc000) == 0xc000)
2955 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2956 else if(*pType & 0x8000)
2957 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2958 else if(*pType & 0x4000)
2959 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2960 else
2961 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2963 if(*pType & 0x2000)
2964 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2966 if(*pType & 0x80)
2967 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2969 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
2973 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
2974 char *pNameTable)
2976 int ref;
2977 char *name;
2978 TLBRefType *ref_type;
2979 sltg_ref_lookup_t *table;
2980 HREFTYPE typelib_ref;
2982 if(pRef->magic != SLTG_REF_MAGIC) {
2983 FIXME("Ref magic = %x\n", pRef->magic);
2984 return NULL;
2986 name = ( (char*)pRef->names + pRef->number);
2988 table = HeapAlloc(GetProcessHeap(), 0, sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
2989 table->num = pRef->number >> 3;
2991 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
2993 /* We don't want the first href to be 0 */
2994 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
2996 for(ref = 0; ref < pRef->number >> 3; ref++) {
2997 char *refname;
2998 unsigned int lib_offs, type_num;
3000 ref_type = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref_type));
3002 name += SLTG_ReadStringA(name, &refname);
3003 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3004 FIXME_(typelib)("Can't sscanf ref\n");
3005 if(lib_offs != 0xffff) {
3006 TLBImpLib **import = &pTL->pImpLibs;
3008 while(*import) {
3009 if((*import)->offset == lib_offs)
3010 break;
3011 import = &(*import)->next;
3013 if(!*import) {
3014 char fname[MAX_PATH+1];
3015 int len;
3017 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3018 sizeof(**import));
3019 (*import)->offset = lib_offs;
3020 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3021 &(*import)->guid);
3022 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3023 &(*import)->wVersionMajor,
3024 &(*import)->wVersionMinor,
3025 &(*import)->lcid, fname) != 4) {
3026 FIXME_(typelib)("can't sscanf ref %s\n",
3027 pNameTable + lib_offs + 40);
3029 len = strlen(fname);
3030 if(fname[len-1] != '#')
3031 FIXME("fname = %s\n", fname);
3032 fname[len-1] = '\0';
3033 (*import)->name = TLB_MultiByteToBSTR(fname);
3035 ref_type->pImpTLInfo = *import;
3037 /* Store a reference to IDispatch */
3038 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
3039 pTL->dispatch_href = typelib_ref;
3041 } else { /* internal ref */
3042 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3044 ref_type->reference = typelib_ref;
3045 ref_type->index = type_num;
3047 HeapFree(GetProcessHeap(), 0, refname);
3048 list_add_tail(&pTL->ref_list, &ref_type->entry);
3050 table->refs[ref] = typelib_ref;
3051 typelib_ref += 4;
3053 if((BYTE)*name != SLTG_REF_MAGIC)
3054 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3055 dump_TLBRefType(pTL);
3056 return table;
3059 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3060 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3062 SLTG_ImplInfo *info;
3063 TLBImplType **ppImplType = &pTI->impltypelist;
3064 /* I don't really get this structure, usually it's 0x16 bytes
3065 long, but iuser.tlb contains some that are 0x18 bytes long.
3066 That's ok because we can use the next ptr to jump to the next
3067 one. But how do we know the length of the last one? The WORD
3068 at offs 0x8 might be the clue. For now I'm just assuming that
3069 the last one is the regular 0x16 bytes. */
3071 info = (SLTG_ImplInfo*)pBlk;
3072 while(1) {
3073 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3074 sizeof(**ppImplType));
3075 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef);
3076 (*ppImplType)->implflags = info->impltypeflags;
3077 pTI->TypeAttr.cImplTypes++;
3078 ppImplType = &(*ppImplType)->next;
3080 if(info->next == 0xffff)
3081 break;
3082 if(OneOnly)
3083 FIXME_(typelib)("Interface inheriting more than one interface\n");
3084 info = (SLTG_ImplInfo*)(pBlk + info->next);
3086 info++; /* see comment at top of function */
3087 return (char*)info;
3090 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3091 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3093 TLBVarDesc **ppVarDesc = &pTI->varlist;
3094 BSTR bstrPrevName = NULL;
3095 SLTG_Variable *pItem;
3096 unsigned short i;
3097 WORD *pType;
3099 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3100 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
3102 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3103 sizeof(**ppVarDesc));
3104 (*ppVarDesc)->vardesc.memid = pItem->memid;
3106 if (pItem->magic != SLTG_VAR_MAGIC &&
3107 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3108 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3109 return;
3112 if (pItem->name == 0xfffe)
3113 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
3114 else
3115 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3117 TRACE_(typelib)("name: %s\n", debugstr_w((*ppVarDesc)->Name));
3118 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3119 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3121 if(pItem->flags & 0x02)
3122 pType = &pItem->type;
3123 else
3124 pType = (WORD*)(pBlk + pItem->type);
3126 if (pItem->flags & ~0xda)
3127 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3129 SLTG_DoElem(pType, pBlk,
3130 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup);
3132 if (TRACE_ON(typelib)) {
3133 char buf[300];
3134 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3135 TRACE_(typelib)("elemdescVar: %s\n", buf);
3138 if (pItem->flags & 0x40) {
3139 TRACE_(typelib)("VAR_DISPATCH\n");
3140 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
3142 else if (pItem->flags & 0x10) {
3143 TRACE_(typelib)("VAR_CONST\n");
3144 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3145 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3146 sizeof(VARIANT));
3147 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3148 if (pItem->flags & 0x08)
3149 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) = pItem->byte_offs;
3150 else {
3151 switch ((*ppVarDesc)->vardesc.elemdescVar.tdesc.vt)
3153 case VT_LPSTR:
3154 case VT_LPWSTR:
3155 case VT_BSTR:
3157 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3158 BSTR str;
3159 TRACE_(typelib)("len = %u\n", len);
3160 if (len == 0xffff) {
3161 str = NULL;
3162 } else {
3163 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3164 str = SysAllocStringLen(NULL, alloc_len);
3165 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3167 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_BSTR;
3168 V_BSTR((*ppVarDesc)->vardesc.u.lpvarValue) = str;
3169 break;
3171 case VT_I2:
3172 case VT_UI2:
3173 case VT_I4:
3174 case VT_UI4:
3175 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
3176 *(INT*)(pBlk + pItem->byte_offs);
3177 break;
3178 default:
3179 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt);
3183 else {
3184 TRACE_(typelib)("VAR_PERINSTANCE\n");
3185 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3186 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3189 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3190 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
3192 if (pItem->flags & 0x80)
3193 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3195 bstrPrevName = (*ppVarDesc)->Name;
3196 ppVarDesc = &((*ppVarDesc)->next);
3198 pTI->TypeAttr.cVars = cVars;
3201 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3202 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3204 SLTG_Function *pFunc;
3205 unsigned short i;
3206 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3208 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3209 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3211 int param;
3212 WORD *pType, *pArg;
3214 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3215 sizeof(**ppFuncDesc));
3217 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3218 case SLTG_FUNCTION_MAGIC:
3219 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3220 break;
3221 case SLTG_DISPATCH_FUNCTION_MAGIC:
3222 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3223 break;
3224 case SLTG_STATIC_FUNCTION_MAGIC:
3225 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3226 break;
3227 default:
3228 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3229 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
3230 *ppFuncDesc = NULL;
3231 return;
3233 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3235 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3236 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3237 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3238 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3239 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3240 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3242 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3243 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3245 if(pFunc->retnextopt & 0x80)
3246 pType = &pFunc->rettype;
3247 else
3248 pType = (WORD*)(pBlk + pFunc->rettype);
3250 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3252 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3253 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3254 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3255 (*ppFuncDesc)->pParamDesc =
3256 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3257 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3259 pArg = (WORD*)(pBlk + pFunc->arg_off);
3261 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3262 char *paramName = pNameTable + *pArg;
3263 BOOL HaveOffs;
3264 /* If arg type follows then paramName points to the 2nd
3265 letter of the name, else the next WORD is an offset to
3266 the arg type and paramName points to the first letter.
3267 So let's take one char off paramName and see if we're
3268 pointing at an alpha-numeric char. However if *pArg is
3269 0xffff or 0xfffe then the param has no name, the former
3270 meaning that the next WORD is the type, the latter
3271 meaning that the next WORD is an offset to the type. */
3273 HaveOffs = FALSE;
3274 if(*pArg == 0xffff)
3275 paramName = NULL;
3276 else if(*pArg == 0xfffe) {
3277 paramName = NULL;
3278 HaveOffs = TRUE;
3280 else if(paramName[-1] && !isalnum(paramName[-1]))
3281 HaveOffs = TRUE;
3283 pArg++;
3285 if(HaveOffs) { /* the next word is an offset to type */
3286 pType = (WORD*)(pBlk + *pArg);
3287 SLTG_DoElem(pType, pBlk,
3288 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3289 pArg++;
3290 } else {
3291 if(paramName)
3292 paramName--;
3293 pArg = SLTG_DoElem(pArg, pBlk,
3294 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3297 /* Are we an optional param ? */
3298 if((*ppFuncDesc)->funcdesc.cParams - param <=
3299 (*ppFuncDesc)->funcdesc.cParamsOpt)
3300 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3302 if(paramName) {
3303 (*ppFuncDesc)->pParamDesc[param].Name =
3304 TLB_MultiByteToBSTR(paramName);
3305 } else {
3306 (*ppFuncDesc)->pParamDesc[param].Name =
3307 SysAllocString((*ppFuncDesc)->Name);
3311 ppFuncDesc = &((*ppFuncDesc)->next);
3312 if(pFunc->next == 0xffff) break;
3314 pTI->TypeAttr.cFuncs = cFuncs;
3317 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3318 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3319 SLTG_TypeInfoTail *pTITail)
3321 char *pFirstItem;
3322 sltg_ref_lookup_t *ref_lookup = NULL;
3324 if(pTIHeader->href_table != 0xffffffff) {
3325 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3326 pNameTable);
3329 pFirstItem = pBlk;
3331 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3332 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3334 HeapFree(GetProcessHeap(), 0, ref_lookup);
3338 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3339 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3340 const SLTG_TypeInfoTail *pTITail)
3342 char *pFirstItem;
3343 sltg_ref_lookup_t *ref_lookup = NULL;
3345 if(pTIHeader->href_table != 0xffffffff) {
3346 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3347 pNameTable);
3350 pFirstItem = pBlk;
3352 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3353 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3356 if (pTITail->funcs_off != 0xffff)
3357 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3359 HeapFree(GetProcessHeap(), 0, ref_lookup);
3361 if (TRACE_ON(typelib))
3362 dump_TLBFuncDesc(pTI->funclist);
3365 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3366 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3367 const SLTG_TypeInfoTail *pTITail)
3369 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3372 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3373 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3374 const SLTG_TypeInfoTail *pTITail)
3376 WORD *pType;
3377 sltg_ref_lookup_t *ref_lookup = NULL;
3379 if (pTITail->simple_alias) {
3380 /* if simple alias, no more processing required */
3381 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3382 return;
3385 if(pTIHeader->href_table != 0xffffffff) {
3386 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3387 pNameTable);
3390 /* otherwise it is an offset to a type */
3391 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3393 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3395 HeapFree(GetProcessHeap(), 0, ref_lookup);
3398 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3399 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3400 const SLTG_TypeInfoTail *pTITail)
3402 sltg_ref_lookup_t *ref_lookup = NULL;
3403 if (pTIHeader->href_table != 0xffffffff)
3404 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3405 pNameTable);
3407 if (pTITail->vars_off != 0xffff)
3408 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3410 if (pTITail->funcs_off != 0xffff)
3411 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3413 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3414 * of dispinterface functions including the IDispatch ones, so
3415 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3416 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3418 HeapFree(GetProcessHeap(), 0, ref_lookup);
3419 if (TRACE_ON(typelib))
3420 dump_TLBFuncDesc(pTI->funclist);
3423 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3424 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3425 const SLTG_TypeInfoTail *pTITail)
3427 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3430 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3431 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3432 const SLTG_TypeInfoTail *pTITail)
3434 sltg_ref_lookup_t *ref_lookup = NULL;
3435 if (pTIHeader->href_table != 0xffffffff)
3436 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3437 pNameTable);
3439 if (pTITail->vars_off != 0xffff)
3440 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3442 if (pTITail->funcs_off != 0xffff)
3443 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3444 HeapFree(GetProcessHeap(), 0, ref_lookup);
3445 if (TRACE_ON(typelib))
3446 dump_TypeInfo(pTI);
3449 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3450 managable copy of it into this */
3451 typedef struct {
3452 WORD small_no;
3453 char *index_name;
3454 char *other_name;
3455 WORD res1a;
3456 WORD name_offs;
3457 WORD more_bytes;
3458 char *extra;
3459 WORD res20;
3460 DWORD helpcontext;
3461 WORD res26;
3462 GUID uuid;
3463 } SLTG_InternalOtherTypeInfo;
3465 /****************************************************************************
3466 * ITypeLib2_Constructor_SLTG
3468 * loading a SLTG typelib from an in-memory image
3470 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3472 ITypeLibImpl *pTypeLibImpl;
3473 SLTG_Header *pHeader;
3474 SLTG_BlkEntry *pBlkEntry;
3475 SLTG_Magic *pMagic;
3476 SLTG_Index *pIndex;
3477 SLTG_Pad9 *pPad9;
3478 LPVOID pBlk, pFirstBlk;
3479 SLTG_LibBlk *pLibBlk;
3480 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3481 char *pAfterOTIBlks = NULL;
3482 char *pNameTable, *ptr;
3483 int i;
3484 DWORD len, order;
3485 ITypeInfoImpl **ppTypeInfoImpl;
3487 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3490 pTypeLibImpl = TypeLibImpl_Constructor();
3491 if (!pTypeLibImpl) return NULL;
3493 pHeader = pLib;
3495 TRACE_(typelib)("header:\n");
3496 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3497 pHeader->nrOfFileBlks );
3498 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3499 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3500 pHeader->SLTG_magic);
3501 return NULL;
3504 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3505 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3507 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3508 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3510 /* Next we have a magic block */
3511 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3513 /* Let's see if we're still in sync */
3514 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3515 sizeof(SLTG_COMPOBJ_MAGIC))) {
3516 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3517 return NULL;
3519 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3520 sizeof(SLTG_DIR_MAGIC))) {
3521 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
3522 return NULL;
3525 pIndex = (SLTG_Index*)(pMagic+1);
3527 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3529 pFirstBlk = (LPVOID)(pPad9 + 1);
3531 /* We'll set up a ptr to the main library block, which is the last one. */
3533 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3534 pBlkEntry[order].next != 0;
3535 order = pBlkEntry[order].next - 1, i++) {
3536 pBlk = (char*)pBlk + pBlkEntry[order].len;
3538 pLibBlk = pBlk;
3540 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3542 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3543 interspersed */
3545 len += 0x40;
3547 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3549 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3550 sizeof(*pOtherTypeInfoBlks) *
3551 pTypeLibImpl->TypeInfoCount);
3554 ptr = (char*)pLibBlk + len;
3556 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3557 WORD w, extra;
3558 len = 0;
3560 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3562 w = *(WORD*)(ptr + 2);
3563 if(w != 0xffff) {
3564 len += w;
3565 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3566 w+1);
3567 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3568 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3570 w = *(WORD*)(ptr + 4 + len);
3571 if(w != 0xffff) {
3572 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3573 len += w;
3574 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3575 w+1);
3576 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3577 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3579 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3580 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3581 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3582 if(extra) {
3583 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3584 extra);
3585 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3586 len += extra;
3588 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3589 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3590 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3591 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3592 len += sizeof(SLTG_OtherTypeInfo);
3593 ptr += len;
3596 pAfterOTIBlks = ptr;
3598 /* Skip this WORD and get the next DWORD */
3599 len = *(DWORD*)(pAfterOTIBlks + 2);
3601 /* Now add this to pLibBLk look at what we're pointing at and
3602 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3603 dust and we should be pointing at the beginning of the name
3604 table */
3606 pNameTable = (char*)pLibBlk + len;
3608 switch(*(WORD*)pNameTable) {
3609 case 0xffff:
3610 break;
3611 case 0x0200:
3612 pNameTable += 0x20;
3613 break;
3614 default:
3615 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
3616 break;
3619 pNameTable += 0x216;
3621 pNameTable += 2;
3623 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
3625 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3628 /* Hopefully we now have enough ptrs set up to actually read in
3629 some TypeInfos. It's not clear which order to do them in, so
3630 I'll just follow the links along the BlkEntry chain and read
3631 them in the order in which they are in the file */
3633 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3635 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3636 pBlkEntry[order].next != 0;
3637 order = pBlkEntry[order].next - 1, i++) {
3639 SLTG_TypeInfoHeader *pTIHeader;
3640 SLTG_TypeInfoTail *pTITail;
3641 SLTG_MemberHeader *pMemHeader;
3643 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3644 pOtherTypeInfoBlks[i].index_name)) {
3645 FIXME_(typelib)("Index strings don't match\n");
3646 return NULL;
3649 pTIHeader = pBlk;
3650 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3651 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3652 return NULL;
3654 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
3655 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3656 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3658 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3659 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3660 (*ppTypeInfoImpl)->index = i;
3661 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3662 pOtherTypeInfoBlks[i].name_offs +
3663 pNameTable);
3664 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3665 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
3666 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3667 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3668 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3669 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3670 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3672 if((pTIHeader->typeflags1 & 7) != 2)
3673 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
3674 if(pTIHeader->typeflags3 != 2)
3675 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
3677 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3678 debugstr_w((*ppTypeInfoImpl)->Name),
3679 typekind_desc[pTIHeader->typekind],
3680 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3681 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3683 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3685 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3687 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3688 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3689 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3691 switch(pTIHeader->typekind) {
3692 case TKIND_ENUM:
3693 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3694 pTIHeader, pTITail);
3695 break;
3697 case TKIND_RECORD:
3698 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3699 pTIHeader, pTITail);
3700 break;
3702 case TKIND_INTERFACE:
3703 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3704 pTIHeader, pTITail);
3705 break;
3707 case TKIND_COCLASS:
3708 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3709 pTIHeader, pTITail);
3710 break;
3712 case TKIND_ALIAS:
3713 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3714 pTIHeader, pTITail);
3715 break;
3717 case TKIND_DISPATCH:
3718 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3719 pTIHeader, pTITail);
3720 break;
3722 case TKIND_MODULE:
3723 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3724 pTIHeader, pTITail);
3725 break;
3727 default:
3728 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3729 break;
3733 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3734 but we've already set those */
3735 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3736 X(06);
3737 X(16);
3738 X(18);
3739 X(1a);
3740 X(1e);
3741 X(24);
3742 X(26);
3743 X(2a);
3744 X(2c);
3745 X(2e);
3746 X(30);
3747 X(32);
3748 X(34);
3750 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3751 pBlk = (char*)pBlk + pBlkEntry[order].len;
3754 if(i != pTypeLibImpl->TypeInfoCount) {
3755 FIXME("Somehow processed %d TypeInfos\n", i);
3756 return NULL;
3759 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3760 return (ITypeLib2*)pTypeLibImpl;
3763 /* ITypeLib::QueryInterface
3765 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3766 ITypeLib2 * iface,
3767 REFIID riid,
3768 VOID **ppvObject)
3770 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3772 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3774 *ppvObject=NULL;
3775 if(IsEqualIID(riid, &IID_IUnknown) ||
3776 IsEqualIID(riid,&IID_ITypeLib)||
3777 IsEqualIID(riid,&IID_ITypeLib2))
3779 *ppvObject = This;
3782 if(*ppvObject)
3784 ITypeLib2_AddRef(iface);
3785 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3786 return S_OK;
3788 TRACE("-- Interface: E_NOINTERFACE\n");
3789 return E_NOINTERFACE;
3792 /* ITypeLib::AddRef
3794 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3796 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3797 ULONG ref = InterlockedIncrement(&This->ref);
3799 TRACE("(%p)->ref was %u\n",This, ref - 1);
3801 return ref;
3804 /* ITypeLib::Release
3806 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3808 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3809 ULONG ref = InterlockedDecrement(&This->ref);
3811 TRACE("(%p)->(%u)\n",This, ref);
3813 if (!ref)
3815 TLBImpLib *pImpLib, *pImpLibNext;
3816 TLBCustData *pCustData, *pCustDataNext;
3817 TLBRefType *ref_type;
3818 void *cursor2;
3819 int i;
3821 /* remove cache entry */
3822 if(This->path)
3824 TRACE("removing from cache list\n");
3825 EnterCriticalSection(&cache_section);
3826 if (This->next) This->next->prev = This->prev;
3827 if (This->prev) This->prev->next = This->next;
3828 else tlb_cache_first = This->next;
3829 LeaveCriticalSection(&cache_section);
3830 HeapFree(GetProcessHeap(), 0, This->path);
3832 TRACE(" destroying ITypeLib(%p)\n",This);
3834 if (This->Name)
3836 SysFreeString(This->Name);
3837 This->Name = NULL;
3840 if (This->DocString)
3842 SysFreeString(This->DocString);
3843 This->DocString = NULL;
3846 if (This->HelpFile)
3848 SysFreeString(This->HelpFile);
3849 This->HelpFile = NULL;
3852 if (This->HelpStringDll)
3854 SysFreeString(This->HelpStringDll);
3855 This->HelpStringDll = NULL;
3858 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
3860 VariantClear(&pCustData->data);
3862 pCustDataNext = pCustData->next;
3863 TLB_Free(pCustData);
3866 for (i = 0; i < This->ctTypeDesc; i++)
3867 if (This->pTypeDesc[i].vt == VT_CARRAY)
3868 TLB_Free(This->pTypeDesc[i].u.lpadesc);
3870 TLB_Free(This->pTypeDesc);
3872 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
3874 if (pImpLib->pImpTypeLib)
3875 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
3876 SysFreeString(pImpLib->name);
3878 pImpLibNext = pImpLib->next;
3879 TLB_Free(pImpLib);
3882 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
3884 list_remove(&ref_type->entry);
3885 TLB_Free(ref_type);
3888 if (This->pTypeInfo) /* can be NULL */
3889 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3890 HeapFree(GetProcessHeap(),0,This);
3891 return 0;
3894 return ref;
3897 /* ITypeLib::GetTypeInfoCount
3899 * Returns the number of type descriptions in the type library
3901 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3903 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3904 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3905 return This->TypeInfoCount;
3908 /* ITypeLib::GetTypeInfo
3910 * retrieves the specified type description in the library.
3912 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3913 ITypeLib2 *iface,
3914 UINT index,
3915 ITypeInfo **ppTInfo)
3917 int i;
3919 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3920 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3922 TRACE("(%p)->(index=%d)\n", This, index);
3924 if (!ppTInfo) return E_INVALIDARG;
3926 /* search element n in list */
3927 for(i=0; i < index; i++)
3929 pTypeInfo = pTypeInfo->next;
3930 if (!pTypeInfo)
3932 TRACE("-- element not found\n");
3933 return TYPE_E_ELEMENTNOTFOUND;
3937 *ppTInfo = (ITypeInfo *) pTypeInfo;
3939 ITypeInfo_AddRef(*ppTInfo);
3940 TRACE("-- found (%p)\n",*ppTInfo);
3941 return S_OK;
3945 /* ITypeLibs::GetTypeInfoType
3947 * Retrieves the type of a type description.
3949 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3950 ITypeLib2 *iface,
3951 UINT index,
3952 TYPEKIND *pTKind)
3954 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3955 int i;
3956 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3958 if (ITypeLib2_fnGetTypeInfoCount(iface) < index + 1)
3959 return TYPE_E_ELEMENTNOTFOUND;
3961 TRACE("(%p) index %d\n", This, index);
3963 if(!pTKind) return E_INVALIDARG;
3965 /* search element n in list */
3966 for(i=0; i < index; i++)
3968 if(!pTInfo)
3970 TRACE("-- element not found\n");
3971 return TYPE_E_ELEMENTNOTFOUND;
3973 pTInfo = pTInfo->next;
3976 *pTKind = pTInfo->TypeAttr.typekind;
3977 TRACE("-- found Type (%d)\n", *pTKind);
3978 return S_OK;
3981 /* ITypeLib::GetTypeInfoOfGuid
3983 * Retrieves the type description that corresponds to the specified GUID.
3986 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3987 ITypeLib2 *iface,
3988 REFGUID guid,
3989 ITypeInfo **ppTInfo)
3991 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3992 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3994 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3996 if (!pTypeInfo)
3998 WARN("-- element not found\n");
3999 return TYPE_E_ELEMENTNOTFOUND;
4002 /* search linked list for guid */
4003 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
4005 pTypeInfo = pTypeInfo->next;
4007 if (!pTypeInfo)
4009 /* end of list reached */
4010 WARN("-- element not found\n");
4011 return TYPE_E_ELEMENTNOTFOUND;
4015 TRACE("-- found (%p, %s)\n",
4016 pTypeInfo,
4017 debugstr_w(pTypeInfo->Name));
4019 *ppTInfo = (ITypeInfo*)pTypeInfo;
4020 ITypeInfo_AddRef(*ppTInfo);
4021 return S_OK;
4024 /* ITypeLib::GetLibAttr
4026 * Retrieves the structure that contains the library's attributes.
4029 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4030 ITypeLib2 *iface,
4031 LPTLIBATTR *ppTLibAttr)
4033 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4034 TRACE("(%p)\n",This);
4035 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
4036 **ppTLibAttr = This->LibAttr;
4037 return S_OK;
4040 /* ITypeLib::GetTypeComp
4042 * Enables a client compiler to bind to a library's types, variables,
4043 * constants, and global functions.
4046 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4047 ITypeLib2 *iface,
4048 ITypeComp **ppTComp)
4050 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4052 TRACE("(%p)->(%p)\n",This,ppTComp);
4053 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4054 ITypeComp_AddRef(*ppTComp);
4056 return S_OK;
4059 /* ITypeLib::GetDocumentation
4061 * Retrieves the library's documentation string, the complete Help file name
4062 * and path, and the context identifier for the library Help topic in the Help
4063 * file.
4065 * On a successful return all non-null BSTR pointers will have been set,
4066 * possibly to NULL.
4068 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4069 ITypeLib2 *iface,
4070 INT index,
4071 BSTR *pBstrName,
4072 BSTR *pBstrDocString,
4073 DWORD *pdwHelpContext,
4074 BSTR *pBstrHelpFile)
4076 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4078 HRESULT result = E_INVALIDARG;
4080 ITypeInfo *pTInfo;
4083 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4084 This, index,
4085 pBstrName, pBstrDocString,
4086 pdwHelpContext, pBstrHelpFile);
4088 if(index<0)
4090 /* documentation for the typelib */
4091 if(pBstrName)
4093 if (This->Name)
4095 if(!(*pBstrName = SysAllocString(This->Name)))
4096 goto memerr1;
4098 else
4099 *pBstrName = NULL;
4101 if(pBstrDocString)
4103 if (This->DocString)
4105 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4106 goto memerr2;
4108 else if (This->Name)
4110 if(!(*pBstrDocString = SysAllocString(This->Name)))
4111 goto memerr2;
4113 else
4114 *pBstrDocString = NULL;
4116 if(pdwHelpContext)
4118 *pdwHelpContext = This->dwHelpContext;
4120 if(pBstrHelpFile)
4122 if (This->HelpFile)
4124 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4125 goto memerr3;
4127 else
4128 *pBstrHelpFile = NULL;
4131 result = S_OK;
4133 else
4135 /* for a typeinfo */
4136 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4138 if(SUCCEEDED(result))
4140 result = ITypeInfo_GetDocumentation(pTInfo,
4141 MEMBERID_NIL,
4142 pBstrName,
4143 pBstrDocString,
4144 pdwHelpContext, pBstrHelpFile);
4146 ITypeInfo_Release(pTInfo);
4149 return result;
4150 memerr3:
4151 if (pBstrDocString) SysFreeString (*pBstrDocString);
4152 memerr2:
4153 if (pBstrName) SysFreeString (*pBstrName);
4154 memerr1:
4155 return STG_E_INSUFFICIENTMEMORY;
4158 /* ITypeLib::IsName
4160 * Indicates whether a passed-in string contains the name of a type or member
4161 * described in the library.
4164 static HRESULT WINAPI ITypeLib2_fnIsName(
4165 ITypeLib2 *iface,
4166 LPOLESTR szNameBuf,
4167 ULONG lHashVal,
4168 BOOL *pfName)
4170 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4171 ITypeInfoImpl *pTInfo;
4172 TLBFuncDesc *pFInfo;
4173 TLBVarDesc *pVInfo;
4174 int i;
4175 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4177 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4178 pfName);
4180 *pfName=TRUE;
4181 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
4182 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4183 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4184 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4185 for(i=0;i<pFInfo->funcdesc.cParams;i++)
4186 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
4187 goto ITypeLib2_fnIsName_exit;
4189 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4190 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4193 *pfName=FALSE;
4195 ITypeLib2_fnIsName_exit:
4196 TRACE("(%p)slow! search for %s: %s found!\n", This,
4197 debugstr_w(szNameBuf), *pfName?"NOT":"");
4199 return S_OK;
4202 /* ITypeLib::FindName
4204 * Finds occurrences of a type description in a type library. This may be used
4205 * to quickly verify that a name exists in a type library.
4208 static HRESULT WINAPI ITypeLib2_fnFindName(
4209 ITypeLib2 *iface,
4210 LPOLESTR szNameBuf,
4211 ULONG lHashVal,
4212 ITypeInfo **ppTInfo,
4213 MEMBERID *rgMemId,
4214 UINT16 *pcFound)
4216 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4217 ITypeInfoImpl *pTInfo;
4218 TLBFuncDesc *pFInfo;
4219 TLBVarDesc *pVInfo;
4220 int i,j = 0;
4221 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4223 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
4224 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4225 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4226 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4227 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
4228 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
4229 goto ITypeLib2_fnFindName_exit;
4232 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4233 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4234 continue;
4235 ITypeLib2_fnFindName_exit:
4236 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4237 ppTInfo[j]=(LPTYPEINFO)pTInfo;
4238 j++;
4240 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4241 This, *pcFound, debugstr_w(szNameBuf), j);
4243 *pcFound=j;
4245 return S_OK;
4248 /* ITypeLib::ReleaseTLibAttr
4250 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4253 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4254 ITypeLib2 *iface,
4255 TLIBATTR *pTLibAttr)
4257 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4258 TRACE("freeing (%p)\n",This);
4259 HeapFree(GetProcessHeap(),0,pTLibAttr);
4263 /* ITypeLib2::GetCustData
4265 * gets the custom data
4267 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4268 ITypeLib2 * iface,
4269 REFGUID guid,
4270 VARIANT *pVarVal)
4272 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4273 TLBCustData *pCData;
4275 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4277 if( IsEqualIID(guid, &pCData->guid)) break;
4280 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4282 if(pCData)
4284 VariantInit( pVarVal);
4285 VariantCopy( pVarVal, &pCData->data);
4286 return S_OK;
4288 return E_INVALIDARG; /* FIXME: correct? */
4291 /* ITypeLib2::GetLibStatistics
4293 * Returns statistics about a type library that are required for efficient
4294 * sizing of hash tables.
4297 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4298 ITypeLib2 * iface,
4299 ULONG *pcUniqueNames,
4300 ULONG *pcchUniqueNames)
4302 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4304 FIXME("(%p): stub!\n", This);
4306 if(pcUniqueNames) *pcUniqueNames=1;
4307 if(pcchUniqueNames) *pcchUniqueNames=1;
4308 return S_OK;
4311 /* ITypeLib2::GetDocumentation2
4313 * Retrieves the library's documentation string, the complete Help file name
4314 * and path, the localization context to use, and the context ID for the
4315 * library Help topic in the Help file.
4318 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4319 ITypeLib2 * iface,
4320 INT index,
4321 LCID lcid,
4322 BSTR *pbstrHelpString,
4323 DWORD *pdwHelpStringContext,
4324 BSTR *pbstrHelpStringDll)
4326 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4327 HRESULT result;
4328 ITypeInfo *pTInfo;
4330 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4332 /* the help string should be obtained from the helpstringdll,
4333 * using the _DLLGetDocumentation function, based on the supplied
4334 * lcid. Nice to do sometime...
4336 if(index<0)
4338 /* documentation for the typelib */
4339 if(pbstrHelpString)
4340 *pbstrHelpString=SysAllocString(This->DocString);
4341 if(pdwHelpStringContext)
4342 *pdwHelpStringContext=This->dwHelpContext;
4343 if(pbstrHelpStringDll)
4344 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4346 result = S_OK;
4348 else
4350 /* for a typeinfo */
4351 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4353 if(SUCCEEDED(result))
4355 ITypeInfo2 * pTInfo2;
4356 result = ITypeInfo_QueryInterface(pTInfo,
4357 &IID_ITypeInfo2,
4358 (LPVOID*) &pTInfo2);
4360 if(SUCCEEDED(result))
4362 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4363 MEMBERID_NIL,
4364 lcid,
4365 pbstrHelpString,
4366 pdwHelpStringContext,
4367 pbstrHelpStringDll);
4369 ITypeInfo2_Release(pTInfo2);
4372 ITypeInfo_Release(pTInfo);
4375 return result;
4378 /* ITypeLib2::GetAllCustData
4380 * Gets all custom data items for the library.
4383 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4384 ITypeLib2 * iface,
4385 CUSTDATA *pCustData)
4387 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4388 TLBCustData *pCData;
4389 int i;
4390 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4391 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4392 if(pCustData->prgCustData ){
4393 pCustData->cCustData=This->ctCustData;
4394 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4395 pCustData->prgCustData[i].guid=pCData->guid;
4396 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4398 }else{
4399 ERR(" OUT OF MEMORY!\n");
4400 return E_OUTOFMEMORY;
4402 return S_OK;
4405 static const ITypeLib2Vtbl tlbvt = {
4406 ITypeLib2_fnQueryInterface,
4407 ITypeLib2_fnAddRef,
4408 ITypeLib2_fnRelease,
4409 ITypeLib2_fnGetTypeInfoCount,
4410 ITypeLib2_fnGetTypeInfo,
4411 ITypeLib2_fnGetTypeInfoType,
4412 ITypeLib2_fnGetTypeInfoOfGuid,
4413 ITypeLib2_fnGetLibAttr,
4414 ITypeLib2_fnGetTypeComp,
4415 ITypeLib2_fnGetDocumentation,
4416 ITypeLib2_fnIsName,
4417 ITypeLib2_fnFindName,
4418 ITypeLib2_fnReleaseTLibAttr,
4420 ITypeLib2_fnGetCustData,
4421 ITypeLib2_fnGetLibStatistics,
4422 ITypeLib2_fnGetDocumentation2,
4423 ITypeLib2_fnGetAllCustData
4427 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4429 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4431 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4434 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4436 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4438 return ITypeLib2_AddRef((ITypeLib2 *)This);
4441 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4443 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4445 return ITypeLib2_Release((ITypeLib2 *)This);
4448 static HRESULT WINAPI ITypeLibComp_fnBind(
4449 ITypeComp * iface,
4450 OLECHAR * szName,
4451 ULONG lHash,
4452 WORD wFlags,
4453 ITypeInfo ** ppTInfo,
4454 DESCKIND * pDescKind,
4455 BINDPTR * pBindPtr)
4457 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4458 ITypeInfoImpl *pTypeInfo;
4460 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4462 *pDescKind = DESCKIND_NONE;
4463 pBindPtr->lptcomp = NULL;
4464 *ppTInfo = NULL;
4466 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4468 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4470 /* FIXME: check wFlags here? */
4471 /* FIXME: we should use a hash table to look this info up using lHash
4472 * instead of an O(n) search */
4473 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4474 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4476 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4478 *pDescKind = DESCKIND_TYPECOMP;
4479 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4480 ITypeComp_AddRef(pBindPtr->lptcomp);
4481 TRACE("module or enum: %s\n", debugstr_w(szName));
4482 return S_OK;
4486 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4487 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4489 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4490 HRESULT hr;
4492 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4493 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4495 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4496 return S_OK;
4500 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4501 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4503 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4504 HRESULT hr;
4505 ITypeInfo *subtypeinfo;
4506 BINDPTR subbindptr;
4507 DESCKIND subdesckind;
4509 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4510 &subtypeinfo, &subdesckind, &subbindptr);
4511 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4513 TYPEDESC tdesc_appobject =
4516 (TYPEDESC *)pTypeInfo->hreftype
4518 VT_USERDEFINED
4520 const VARDESC vardesc_appobject =
4522 -2, /* memid */
4523 NULL, /* lpstrSchema */
4525 0 /* oInst */
4528 /* ELEMDESC */
4530 /* TYPEDESC */
4532 &tdesc_appobject
4534 VT_PTR
4537 0, /* wVarFlags */
4538 VAR_STATIC /* varkind */
4541 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4543 /* cleanup things filled in by Bind call so we can put our
4544 * application object data in there instead */
4545 switch (subdesckind)
4547 case DESCKIND_FUNCDESC:
4548 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4549 break;
4550 case DESCKIND_VARDESC:
4551 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4552 break;
4553 default:
4554 break;
4556 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4558 if (pTypeInfo->hreftype == -1)
4559 FIXME("no hreftype for interface %p\n", pTypeInfo);
4561 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4562 if (FAILED(hr))
4563 return hr;
4565 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4566 *ppTInfo = (ITypeInfo *)pTypeInfo;
4567 ITypeInfo_AddRef(*ppTInfo);
4568 return S_OK;
4573 TRACE("name not found %s\n", debugstr_w(szName));
4574 return S_OK;
4577 static HRESULT WINAPI ITypeLibComp_fnBindType(
4578 ITypeComp * iface,
4579 OLECHAR * szName,
4580 ULONG lHash,
4581 ITypeInfo ** ppTInfo,
4582 ITypeComp ** ppTComp)
4584 FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4585 return E_NOTIMPL;
4588 static const ITypeCompVtbl tlbtcvt =
4591 ITypeLibComp_fnQueryInterface,
4592 ITypeLibComp_fnAddRef,
4593 ITypeLibComp_fnRelease,
4595 ITypeLibComp_fnBind,
4596 ITypeLibComp_fnBindType
4599 /*================== ITypeInfo(2) Methods ===================================*/
4600 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4602 ITypeInfoImpl * pTypeInfoImpl;
4604 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4605 if (pTypeInfoImpl)
4607 pTypeInfoImpl->lpVtbl = &tinfvt;
4608 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4609 pTypeInfoImpl->ref=1;
4610 pTypeInfoImpl->hreftype = -1;
4611 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4612 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4614 TRACE("(%p)\n", pTypeInfoImpl);
4615 return (ITypeInfo2*) pTypeInfoImpl;
4618 /* ITypeInfo::QueryInterface
4620 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4621 ITypeInfo2 *iface,
4622 REFIID riid,
4623 VOID **ppvObject)
4625 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4627 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4629 *ppvObject=NULL;
4630 if(IsEqualIID(riid, &IID_IUnknown) ||
4631 IsEqualIID(riid,&IID_ITypeInfo)||
4632 IsEqualIID(riid,&IID_ITypeInfo2))
4633 *ppvObject = This;
4635 if(*ppvObject){
4636 ITypeInfo_AddRef(iface);
4637 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4638 return S_OK;
4640 TRACE("-- Interface: E_NOINTERFACE\n");
4641 return E_NOINTERFACE;
4644 /* ITypeInfo::AddRef
4646 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4648 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4649 ULONG ref = InterlockedIncrement(&This->ref);
4651 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4653 TRACE("(%p)->ref is %u\n",This, ref);
4654 return ref;
4657 /* ITypeInfo::Release
4659 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4661 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4662 ULONG ref = InterlockedDecrement(&This->ref);
4664 TRACE("(%p)->(%u)\n",This, ref);
4666 if (ref) {
4667 /* We don't release ITypeLib when ref=0 because
4668 it means that function is called by ITypeLib2_Release */
4669 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4670 } else {
4671 TLBFuncDesc *pFInfo, *pFInfoNext;
4672 TLBVarDesc *pVInfo, *pVInfoNext;
4673 TLBImplType *pImpl, *pImplNext;
4675 TRACE("destroying ITypeInfo(%p)\n",This);
4677 if (This->no_free_data)
4678 goto finish_free;
4680 if (This->Name)
4682 SysFreeString(This->Name);
4683 This->Name = 0;
4686 if (This->DocString)
4688 SysFreeString(This->DocString);
4689 This->DocString = 0;
4692 if (This->DllName)
4694 SysFreeString(This->DllName);
4695 This->DllName = 0;
4698 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4700 UINT i;
4701 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4703 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4704 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4706 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4707 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4709 SysFreeString(pFInfo->pParamDesc[i].Name);
4711 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4712 TLB_Free(pFInfo->pParamDesc);
4713 TLB_FreeCustData(pFInfo->pCustData);
4714 if (HIWORD(pFInfo->Entry) != 0 && pFInfo->Entry != (BSTR)-1)
4715 SysFreeString(pFInfo->Entry);
4716 SysFreeString(pFInfo->HelpString);
4717 SysFreeString(pFInfo->Name);
4719 pFInfoNext = pFInfo->next;
4720 TLB_Free(pFInfo);
4722 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
4724 if (pVInfo->vardesc.varkind == VAR_CONST)
4726 VariantClear(pVInfo->vardesc.u.lpvarValue);
4727 TLB_Free(pVInfo->vardesc.u.lpvarValue);
4729 TLB_FreeCustData(pVInfo->pCustData);
4730 SysFreeString(pVInfo->Name);
4731 pVInfoNext = pVInfo->next;
4732 TLB_Free(pVInfo);
4734 for(pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
4736 TLB_FreeCustData(pImpl->pCustData);
4737 pImplNext = pImpl->next;
4738 TLB_Free(pImpl);
4740 TLB_FreeCustData(This->pCustData);
4742 finish_free:
4743 if (This->next)
4745 ITypeInfo_Release((ITypeInfo*)This->next);
4748 HeapFree(GetProcessHeap(),0,This);
4749 return 0;
4751 return ref;
4754 /* ITypeInfo::GetTypeAttr
4756 * Retrieves a TYPEATTR structure that contains the attributes of the type
4757 * description.
4760 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4761 LPTYPEATTR *ppTypeAttr)
4763 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4764 SIZE_T size;
4766 TRACE("(%p)\n",This);
4768 size = sizeof(**ppTypeAttr);
4769 if (This->TypeAttr.typekind == TKIND_ALIAS)
4770 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4772 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4773 if (!*ppTypeAttr)
4774 return E_OUTOFMEMORY;
4776 **ppTypeAttr = This->TypeAttr;
4778 if (This->TypeAttr.typekind == TKIND_ALIAS)
4779 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4780 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4782 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4783 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4784 funcs */
4785 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4786 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4788 return S_OK;
4791 /* ITypeInfo::GetTypeComp
4793 * Retrieves the ITypeComp interface for the type description, which enables a
4794 * client compiler to bind to the type description's members.
4797 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4798 ITypeComp * *ppTComp)
4800 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4802 TRACE("(%p)->(%p)\n", This, ppTComp);
4804 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4805 ITypeComp_AddRef(*ppTComp);
4806 return S_OK;
4809 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4811 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4812 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4813 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4814 return size;
4817 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4819 *dest = *src;
4820 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4821 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4823 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4824 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4825 *buffer += sizeof(PARAMDESCEX);
4826 *pparamdescex_dest = *pparamdescex_src;
4827 VariantInit(&pparamdescex_dest->varDefaultValue);
4828 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4829 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4831 else
4832 dest->u.paramdesc.pparamdescex = NULL;
4833 return S_OK;
4836 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4838 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4839 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4842 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4844 FUNCDESC *dest;
4845 char *buffer;
4846 SIZE_T size = sizeof(*src);
4847 SHORT i;
4848 HRESULT hr;
4850 size += sizeof(*src->lprgscode) * src->cScodes;
4851 size += TLB_SizeElemDesc(&src->elemdescFunc);
4852 for (i = 0; i < src->cParams; i++)
4854 size += sizeof(ELEMDESC);
4855 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4858 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4859 if (!dest) return E_OUTOFMEMORY;
4861 *dest = *src;
4862 if (dispinterface) /* overwrite funckind */
4863 dest->funckind = FUNC_DISPATCH;
4864 buffer = (char *)(dest + 1);
4866 dest->lprgscode = (SCODE *)buffer;
4867 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4868 buffer += sizeof(*src->lprgscode) * src->cScodes;
4870 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4871 if (FAILED(hr))
4873 SysFreeString((BSTR)dest);
4874 return hr;
4877 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4878 buffer += sizeof(ELEMDESC) * src->cParams;
4879 for (i = 0; i < src->cParams; i++)
4881 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4882 if (FAILED(hr))
4883 break;
4885 if (FAILED(hr))
4887 /* undo the above actions */
4888 for (i = i - 1; i >= 0; i--)
4889 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4890 TLB_FreeElemDesc(&dest->elemdescFunc);
4891 SysFreeString((BSTR)dest);
4892 return hr;
4895 /* special treatment for dispinterfaces: this makes functions appear
4896 * to return their [retval] value when it is really returning an
4897 * HRESULT */
4898 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4900 if (dest->cParams &&
4901 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4903 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4904 if (elemdesc->tdesc.vt != VT_PTR)
4906 ERR("elemdesc should have started with VT_PTR instead of:\n");
4907 if (ERR_ON(ole))
4908 dump_ELEMDESC(elemdesc);
4909 return E_UNEXPECTED;
4912 /* copy last parameter to the return value. we are using a flat
4913 * buffer so there is no danger of leaking memory in
4914 * elemdescFunc */
4915 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4917 /* remove the last parameter */
4918 dest->cParams--;
4920 else
4921 /* otherwise this function is made to appear to have no return
4922 * value */
4923 dest->elemdescFunc.tdesc.vt = VT_VOID;
4927 *dest_ptr = dest;
4928 return S_OK;
4931 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4933 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4934 const TLBFuncDesc *pFDesc;
4935 int i;
4937 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4940 if (pFDesc)
4942 *ppFuncDesc = &pFDesc->funcdesc;
4943 return S_OK;
4946 return TYPE_E_ELEMENTNOTFOUND;
4949 /* internal function to make the inherited interfaces' methods appear
4950 * part of the interface */
4951 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
4952 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
4954 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4955 HRESULT hr;
4956 UINT implemented_funcs = 0;
4958 if (funcs)
4959 *funcs = 0;
4960 else
4961 *hrefoffset = DISPATCH_HREF_OFFSET;
4963 if(This->impltypelist)
4965 ITypeInfo *pSubTypeInfo;
4966 UINT sub_funcs;
4968 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
4969 if (FAILED(hr))
4970 return hr;
4972 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
4973 index,
4974 ppFuncDesc,
4975 &sub_funcs, hrefoffset);
4976 implemented_funcs += sub_funcs;
4977 ITypeInfo_Release(pSubTypeInfo);
4978 if (SUCCEEDED(hr))
4979 return hr;
4980 *hrefoffset += DISPATCH_HREF_OFFSET;
4983 if (funcs)
4984 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
4985 else
4986 *hrefoffset = 0;
4988 if (index < implemented_funcs)
4989 return E_INVALIDARG;
4990 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
4991 ppFuncDesc);
4994 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
4996 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
4997 while (TRUE)
4999 switch (pTypeDesc->vt)
5001 case VT_USERDEFINED:
5002 pTypeDesc->u.hreftype += hrefoffset;
5003 return;
5004 case VT_PTR:
5005 case VT_SAFEARRAY:
5006 pTypeDesc = pTypeDesc->u.lptdesc;
5007 break;
5008 case VT_CARRAY:
5009 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5010 break;
5011 default:
5012 return;
5017 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5019 SHORT i;
5020 for (i = 0; i < pFuncDesc->cParams; i++)
5021 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5022 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5025 /* ITypeInfo::GetFuncDesc
5027 * Retrieves the FUNCDESC structure that contains information about a
5028 * specified function.
5031 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5032 LPFUNCDESC *ppFuncDesc)
5034 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5035 const FUNCDESC *internal_funcdesc;
5036 HRESULT hr;
5037 UINT hrefoffset = 0;
5039 TRACE("(%p) index %d\n", This, index);
5041 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5042 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5043 &internal_funcdesc, NULL,
5044 &hrefoffset);
5045 else
5046 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5047 &internal_funcdesc);
5048 if (FAILED(hr))
5050 WARN("description for function %d not found\n", index);
5051 return hr;
5054 hr = TLB_AllocAndInitFuncDesc(
5055 internal_funcdesc,
5056 ppFuncDesc,
5057 This->TypeAttr.typekind == TKIND_DISPATCH);
5059 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5060 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5062 TRACE("-- 0x%08x\n", hr);
5063 return hr;
5066 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5068 VARDESC *dest;
5069 char *buffer;
5070 SIZE_T size = sizeof(*src);
5071 HRESULT hr;
5073 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5074 if (src->varkind == VAR_CONST)
5075 size += sizeof(VARIANT);
5076 size += TLB_SizeElemDesc(&src->elemdescVar);
5078 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5079 if (!dest) return E_OUTOFMEMORY;
5081 *dest = *src;
5082 buffer = (char *)(dest + 1);
5083 if (src->lpstrSchema)
5085 int len;
5086 dest->lpstrSchema = (LPOLESTR)buffer;
5087 len = strlenW(src->lpstrSchema);
5088 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5089 buffer += (len + 1) * sizeof(WCHAR);
5092 if (src->varkind == VAR_CONST)
5094 HRESULT hr;
5096 dest->u.lpvarValue = (VARIANT *)buffer;
5097 *dest->u.lpvarValue = *src->u.lpvarValue;
5098 buffer += sizeof(VARIANT);
5099 VariantInit(dest->u.lpvarValue);
5100 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5101 if (FAILED(hr))
5103 SysFreeString((BSTR)dest_ptr);
5104 return hr;
5107 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5108 if (FAILED(hr))
5110 if (src->varkind == VAR_CONST)
5111 VariantClear(dest->u.lpvarValue);
5112 SysFreeString((BSTR)dest);
5113 return hr;
5115 *dest_ptr = dest;
5116 return S_OK;
5119 /* ITypeInfo::GetVarDesc
5121 * Retrieves a VARDESC structure that describes the specified variable.
5124 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5125 LPVARDESC *ppVarDesc)
5127 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5128 int i;
5129 const TLBVarDesc *pVDesc;
5131 TRACE("(%p) index %d\n", This, index);
5133 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
5136 if (pVDesc)
5137 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5139 return E_INVALIDARG;
5142 /* ITypeInfo_GetNames
5144 * Retrieves the variable with the specified member ID (or the name of the
5145 * property or method and its parameters) that correspond to the specified
5146 * function ID.
5148 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5149 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5151 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5152 const TLBFuncDesc *pFDesc;
5153 const TLBVarDesc *pVDesc;
5154 int i;
5155 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5156 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
5157 if(pFDesc)
5159 /* function found, now return function and parameter names */
5160 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5162 if(!i)
5163 *rgBstrNames=SysAllocString(pFDesc->Name);
5164 else
5165 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5167 *pcNames=i;
5169 else
5171 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
5172 if(pVDesc)
5174 *rgBstrNames=SysAllocString(pVDesc->Name);
5175 *pcNames=1;
5177 else
5179 if(This->impltypelist &&
5180 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5181 /* recursive search */
5182 ITypeInfo *pTInfo;
5183 HRESULT result;
5184 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5185 &pTInfo);
5186 if(SUCCEEDED(result))
5188 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5189 ITypeInfo_Release(pTInfo);
5190 return result;
5192 WARN("Could not search inherited interface!\n");
5194 else
5196 WARN("no names found\n");
5198 *pcNames=0;
5199 return TYPE_E_ELEMENTNOTFOUND;
5202 return S_OK;
5206 /* ITypeInfo::GetRefTypeOfImplType
5208 * If a type description describes a COM class, it retrieves the type
5209 * description of the implemented interface types. For an interface,
5210 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5211 * if any exist.
5214 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5215 ITypeInfo2 *iface,
5216 UINT index,
5217 HREFTYPE *pRefType)
5219 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5220 int i;
5221 HRESULT hr = S_OK;
5222 const TLBImplType *pImpl = This->impltypelist;
5224 TRACE("(%p) index %d\n", This, index);
5225 if (TRACE_ON(ole)) dump_TypeInfo(This);
5227 if(index==(UINT)-1)
5229 /* only valid on dual interfaces;
5230 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5232 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5234 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
5235 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
5237 *pRefType = -1;
5239 else
5241 hr = TYPE_E_ELEMENTNOTFOUND;
5244 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5246 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5247 *pRefType = This->pTypeLib->dispatch_href;
5249 else
5251 /* get element n from linked list */
5252 for(i=0; pImpl && i<index; i++)
5254 pImpl = pImpl->next;
5257 if (pImpl)
5258 *pRefType = pImpl->hRef;
5259 else
5260 hr = TYPE_E_ELEMENTNOTFOUND;
5263 if(TRACE_ON(ole))
5265 if(SUCCEEDED(hr))
5266 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5267 else
5268 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5271 return hr;
5274 /* ITypeInfo::GetImplTypeFlags
5276 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5277 * or base interface in a type description.
5279 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5280 UINT index, INT *pImplTypeFlags)
5282 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5283 int i;
5284 TLBImplType *pImpl;
5286 TRACE("(%p) index %d\n", This, index);
5287 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5288 i++, pImpl=pImpl->next)
5290 if(i==index && pImpl){
5291 *pImplTypeFlags=pImpl->implflags;
5292 return S_OK;
5294 *pImplTypeFlags=0;
5295 return TYPE_E_ELEMENTNOTFOUND;
5298 /* GetIDsOfNames
5299 * Maps between member names and member IDs, and parameter names and
5300 * parameter IDs.
5302 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5303 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5305 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5306 const TLBFuncDesc *pFDesc;
5307 const TLBVarDesc *pVDesc;
5308 HRESULT ret=S_OK;
5309 int i;
5311 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5312 cNames);
5314 /* init out parameters in case of failure */
5315 for (i = 0; i < cNames; i++)
5316 pMemId[i] = MEMBERID_NIL;
5318 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5319 int j;
5320 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5321 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5322 for(i=1; i < cNames; i++){
5323 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5324 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5325 break;
5326 if( j<pFDesc->funcdesc.cParams)
5327 pMemId[i]=j;
5328 else
5329 ret=DISP_E_UNKNOWNNAME;
5331 TRACE("-- 0x%08x\n", ret);
5332 return ret;
5335 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5336 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5337 if(cNames) *pMemId=pVDesc->vardesc.memid;
5338 return ret;
5341 /* not found, see if it can be found in an inherited interface */
5342 if(This->impltypelist) {
5343 /* recursive search */
5344 ITypeInfo *pTInfo;
5345 ret=ITypeInfo_GetRefTypeInfo(iface,
5346 This->impltypelist->hRef, &pTInfo);
5347 if(SUCCEEDED(ret)){
5348 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5349 ITypeInfo_Release(pTInfo);
5350 return ret;
5352 WARN("Could not search inherited interface!\n");
5353 } else
5354 WARN("no names found\n");
5355 return DISP_E_UNKNOWNNAME;
5358 /* ITypeInfo::Invoke
5360 * Invokes a method, or accesses a property of an object, that implements the
5361 * interface described by the type description.
5363 DWORD
5364 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5365 DWORD res;
5367 if (TRACE_ON(ole)) {
5368 int i;
5369 TRACE("Calling %p(",func);
5370 for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
5371 TRACE(")\n");
5374 switch (callconv) {
5375 case CC_STDCALL:
5377 switch (nrargs) {
5378 case 0:
5379 res = func();
5380 break;
5381 case 1:
5382 res = func(args[0]);
5383 break;
5384 case 2:
5385 res = func(args[0],args[1]);
5386 break;
5387 case 3:
5388 res = func(args[0],args[1],args[2]);
5389 break;
5390 case 4:
5391 res = func(args[0],args[1],args[2],args[3]);
5392 break;
5393 case 5:
5394 res = func(args[0],args[1],args[2],args[3],args[4]);
5395 break;
5396 case 6:
5397 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
5398 break;
5399 case 7:
5400 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
5401 break;
5402 case 8:
5403 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
5404 break;
5405 case 9:
5406 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
5407 break;
5408 case 10:
5409 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
5410 break;
5411 case 11:
5412 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
5413 break;
5414 case 12:
5415 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11]);
5416 break;
5417 case 13:
5418 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12]);
5419 break;
5420 case 14:
5421 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13]);
5422 break;
5423 case 15:
5424 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14]);
5425 break;
5426 case 16:
5427 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15]);
5428 break;
5429 case 17:
5430 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16]);
5431 break;
5432 case 18:
5433 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17]);
5434 break;
5435 case 19:
5436 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18]);
5437 break;
5438 case 20:
5439 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19]);
5440 break;
5441 case 21:
5442 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20]);
5443 break;
5444 case 22:
5445 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21]);
5446 break;
5447 case 23:
5448 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22]);
5449 break;
5450 case 24:
5451 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23]);
5452 break;
5453 case 25:
5454 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24]);
5455 break;
5456 case 26:
5457 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25]);
5458 break;
5459 case 27:
5460 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26]);
5461 break;
5462 case 28:
5463 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26],args[27]);
5464 break;
5465 case 29:
5466 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26],args[27],args[28]);
5467 break;
5468 case 30:
5469 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26],args[27],args[28],args[29]);
5470 break;
5471 default:
5472 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
5473 res = -1;
5474 break;
5476 break;
5477 default:
5478 FIXME("unsupported calling convention %d\n",callconv);
5479 res = -1;
5480 break;
5482 TRACE("returns %08x\n",res);
5483 return res;
5486 /* The size of the argument on the stack in DWORD units (in all x86 call
5487 * convetions the arguments on the stack are DWORD-aligned)
5489 int _dispargsize(VARTYPE vt)
5491 switch (vt) {
5492 case VT_I8:
5493 case VT_UI8:
5494 return 8/sizeof(DWORD);
5495 case VT_R8:
5496 return sizeof(double)/sizeof(DWORD);
5497 case VT_DECIMAL:
5498 return (sizeof(DECIMAL)+3)/sizeof(DWORD);
5499 case VT_CY:
5500 return sizeof(CY)/sizeof(DWORD);
5501 case VT_DATE:
5502 return sizeof(DATE)/sizeof(DWORD);
5503 case VT_VARIANT:
5504 return (sizeof(VARIANT)+3)/sizeof(DWORD);
5505 case VT_RECORD:
5506 FIXME("VT_RECORD not implemented\n");
5507 return 1;
5508 default:
5509 return 1;
5513 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5515 HRESULT hr = S_OK;
5516 ITypeInfo *tinfo2 = NULL;
5517 TYPEATTR *tattr = NULL;
5519 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5520 if (hr)
5522 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5523 "hr = 0x%08x\n",
5524 tdesc->u.hreftype, hr);
5525 return hr;
5527 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5528 if (hr)
5530 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5531 ITypeInfo_Release(tinfo2);
5532 return hr;
5535 switch (tattr->typekind)
5537 case TKIND_ENUM:
5538 *vt |= VT_I4;
5539 break;
5541 case TKIND_ALIAS:
5542 tdesc = &tattr->tdescAlias;
5543 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5544 break;
5546 case TKIND_INTERFACE:
5547 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5548 *vt |= VT_DISPATCH;
5549 else
5550 *vt |= VT_UNKNOWN;
5551 break;
5553 case TKIND_DISPATCH:
5554 *vt |= VT_DISPATCH;
5555 break;
5557 case TKIND_COCLASS:
5558 *vt |= VT_DISPATCH;
5559 break;
5561 case TKIND_RECORD:
5562 FIXME("TKIND_RECORD unhandled.\n");
5563 hr = E_NOTIMPL;
5564 break;
5566 case TKIND_UNION:
5567 FIXME("TKIND_UNION unhandled.\n");
5568 hr = E_NOTIMPL;
5569 break;
5571 default:
5572 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5573 hr = E_NOTIMPL;
5574 break;
5576 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5577 ITypeInfo_Release(tinfo2);
5578 return hr;
5581 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5583 HRESULT hr = S_OK;
5585 /* enforce only one level of pointer indirection */
5586 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5588 tdesc = tdesc->u.lptdesc;
5590 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5591 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5592 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5593 if ((tdesc->vt == VT_USERDEFINED) ||
5594 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5596 VARTYPE vt_userdefined = 0;
5597 const TYPEDESC *tdesc_userdefined = tdesc;
5598 if (tdesc->vt == VT_PTR)
5600 vt_userdefined = VT_BYREF;
5601 tdesc_userdefined = tdesc->u.lptdesc;
5603 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5604 if ((hr == S_OK) &&
5605 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5606 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5608 *vt |= vt_userdefined;
5609 return S_OK;
5612 *vt = VT_BYREF;
5615 switch (tdesc->vt)
5617 case VT_HRESULT:
5618 *vt |= VT_ERROR;
5619 break;
5620 case VT_USERDEFINED:
5621 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5622 break;
5623 case VT_VOID:
5624 case VT_CARRAY:
5625 case VT_PTR:
5626 case VT_LPSTR:
5627 case VT_LPWSTR:
5628 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5629 hr = DISP_E_BADVARTYPE;
5630 break;
5631 case VT_SAFEARRAY:
5632 *vt |= VT_ARRAY;
5633 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5634 break;
5635 default:
5636 *vt |= tdesc->vt;
5637 break;
5639 return hr;
5642 /***********************************************************************
5643 * DispCallFunc (OLEAUT32.@)
5645 * Invokes a function of the specified calling convention, passing the
5646 * specified arguments and returns the result.
5648 * PARAMS
5649 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5650 * oVft [I] The offset in the vtable. See notes.
5651 * cc [I] Calling convention of the function to call.
5652 * vtReturn [I] The return type of the function.
5653 * cActuals [I] Number of parameters.
5654 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5655 * prgpvarg [I] The arguments to pass.
5656 * pvargResult [O] The return value of the function. Can be NULL.
5658 * RETURNS
5659 * Success: S_OK.
5660 * Failure: HRESULT code.
5662 * NOTES
5663 * The HRESULT return value of this function is not affected by the return
5664 * value of the user supplied function, which is returned in pvargResult.
5666 * If pvInstance is NULL then a non-object function is to be called and oVft
5667 * is the address of the function to call.
5669 * The cc parameter can be one of the following values:
5670 *|CC_FASTCALL
5671 *|CC_CDECL
5672 *|CC_PASCAL
5673 *|CC_STDCALL
5674 *|CC_FPFASTCALL
5675 *|CC_SYSCALL
5676 *|CC_MPWCDECL
5677 *|CC_MPWPASCAL
5680 HRESULT WINAPI
5681 DispCallFunc(
5682 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5683 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5685 int i, argsize, argspos;
5686 DWORD *args;
5687 HRESULT hres;
5689 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5690 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5691 pvargResult, V_VT(pvargResult));
5693 argsize = 0;
5694 if (pvInstance)
5695 argsize++; /* for This pointer */
5697 for (i=0;i<cActuals;i++)
5699 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_dispargsize(prgvt[i]));
5700 dump_Variant(prgpvarg[i]);
5701 argsize += _dispargsize(prgvt[i]);
5703 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5705 argspos = 0;
5706 if (pvInstance)
5708 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5709 argspos++;
5712 for (i=0;i<cActuals;i++)
5714 VARIANT *arg = prgpvarg[i];
5715 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5716 if (prgvt[i] == VT_VARIANT)
5717 memcpy(&args[argspos], arg, _dispargsize(prgvt[i]) * sizeof(DWORD));
5718 else
5719 memcpy(&args[argspos], &V_NONE(arg), _dispargsize(prgvt[i]) * sizeof(DWORD));
5720 argspos += _dispargsize(prgvt[i]);
5723 if (pvInstance)
5725 FARPROC *vtable = *(FARPROC**)pvInstance;
5726 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5728 else
5729 /* if we aren't invoking an object then the function pointer is stored
5730 * in oVft */
5731 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5733 if (pvargResult && (vtReturn != VT_EMPTY))
5735 TRACE("Method returned 0x%08x\n",hres);
5736 V_VT(pvargResult) = vtReturn;
5737 V_UI4(pvargResult) = hres;
5740 HeapFree(GetProcessHeap(),0,args);
5741 return S_OK;
5744 #define INVBUF_ELEMENT_SIZE \
5745 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5746 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5747 ((VARIANTARG *)(buffer))
5748 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5749 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5750 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5751 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5752 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5753 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5755 static HRESULT WINAPI ITypeInfo_fnInvoke(
5756 ITypeInfo2 *iface,
5757 VOID *pIUnk,
5758 MEMBERID memid,
5759 UINT16 wFlags,
5760 DISPPARAMS *pDispParams,
5761 VARIANT *pVarResult,
5762 EXCEPINFO *pExcepInfo,
5763 UINT *pArgErr)
5765 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5766 int i;
5767 unsigned int var_index;
5768 TYPEKIND type_kind;
5769 HRESULT hres;
5770 const TLBFuncDesc *pFuncInfo;
5772 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
5773 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5776 if (!pDispParams)
5778 ERR("NULL pDispParams not allowed\n");
5779 return E_INVALIDARG;
5782 dump_DispParms(pDispParams);
5784 if (pDispParams->cNamedArgs > pDispParams->cArgs)
5786 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
5787 pDispParams->cNamedArgs, pDispParams->cArgs);
5788 return E_INVALIDARG;
5791 /* we do this instead of using GetFuncDesc since it will return a fake
5792 * FUNCDESC for dispinterfaces and we want the real function description */
5793 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5794 if ((memid == pFuncInfo->funcdesc.memid) &&
5795 (wFlags & pFuncInfo->funcdesc.invkind))
5796 break;
5798 if (pFuncInfo) {
5799 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5801 if (TRACE_ON(ole))
5803 TRACE("invoking:\n");
5804 dump_TLBFuncDescOne(pFuncInfo);
5807 switch (func_desc->funckind) {
5808 case FUNC_PUREVIRTUAL:
5809 case FUNC_VIRTUAL: {
5810 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
5811 VARIANT varresult;
5812 VARIANT retval; /* pointer for storing byref retvals in */
5813 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
5814 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
5815 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
5816 UINT cNamedArgs = pDispParams->cNamedArgs;
5817 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
5819 hres = S_OK;
5821 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
5823 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
5825 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
5826 hres = DISP_E_PARAMNOTFOUND;
5827 goto func_fail;
5829 /* ignore the DISPID_PROPERTYPUT named argument from now on */
5830 cNamedArgs--;
5831 rgdispidNamedArgs++;
5834 if (func_desc->cParamsOpt < 0 && cNamedArgs)
5836 ERR("functions with the vararg attribute do not support named arguments\n");
5837 hres = DISP_E_NONAMEDARGS;
5838 goto func_fail;
5841 for (i = 0; i < func_desc->cParams; i++)
5843 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5844 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
5845 if (FAILED(hres))
5846 goto func_fail;
5849 TRACE("changing args\n");
5850 for (i = 0; i < func_desc->cParams; i++)
5852 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5853 VARIANTARG *src_arg;
5855 if (cNamedArgs)
5857 USHORT j;
5858 src_arg = NULL;
5859 for (j = 0; j < cNamedArgs; j++)
5860 if (rgdispidNamedArgs[j] == i)
5862 src_arg = &pDispParams->rgvarg[j];
5863 break;
5866 else
5867 src_arg = i < pDispParams->cArgs ? &pDispParams->rgvarg[pDispParams->cArgs - 1 - i] : NULL;
5869 if (wParamFlags & PARAMFLAG_FRETVAL)
5871 /* under most conditions the caller is not allowed to
5872 * pass in a dispparam arg in the index of what would be
5873 * the retval parameter. however, there is an exception
5874 * where the extra parameter is used in an extra
5875 * IDispatch::Invoke below */
5876 if ((i < pDispParams->cArgs) &&
5877 ((func_desc->cParams != 1) || !pVarResult ||
5878 !(func_desc->invkind & INVOKE_PROPERTYGET)))
5880 hres = DISP_E_BADPARAMCOUNT;
5881 break;
5884 /* note: this check is placed so that if the caller passes
5885 * in a VARIANTARG for the retval we just ignore it, like
5886 * native does */
5887 if (i == func_desc->cParams - 1)
5889 VARIANTARG *arg;
5890 arg = prgpvarg[i] = &rgvarg[i];
5891 memset(arg, 0, sizeof(*arg));
5892 V_VT(arg) = rgvt[i];
5893 memset(&retval, 0, sizeof(retval));
5894 V_BYREF(arg) = &retval;
5896 else
5898 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
5899 hres = E_UNEXPECTED;
5900 break;
5903 else if (src_arg)
5905 dump_Variant(src_arg);
5907 if (rgvt[i] == VT_VARIANT)
5908 hres = VariantCopy(&rgvarg[i], src_arg);
5909 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
5911 if (rgvt[i] == V_VT(src_arg))
5912 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
5913 else
5915 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5916 hres = VariantCopy(&missing_arg[i], src_arg);
5917 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
5919 V_VT(&rgvarg[i]) = rgvt[i];
5921 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
5923 SAFEARRAY *a;
5924 SAFEARRAYBOUND bound;
5925 VARIANT *v;
5926 LONG j;
5927 bound.lLbound = 0;
5928 bound.cElements = pDispParams->cArgs-i;
5929 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
5931 ERR("SafeArrayCreate failed\n");
5932 break;
5934 hres = SafeArrayAccessData(a, (LPVOID)&v);
5935 if (hres != S_OK)
5937 ERR("SafeArrayAccessData failed with %x\n", hres);
5938 break;
5940 for (j = 0; j < bound.cElements; j++)
5941 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
5942 hres = SafeArrayUnaccessData(a);
5943 if (hres != S_OK)
5945 ERR("SafeArrayUnaccessData failed with %x\n", hres);
5946 break;
5948 V_ARRAY(&rgvarg[i]) = a;
5949 V_VT(&rgvarg[i]) = rgvt[i];
5951 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
5953 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5954 V_VT(&missing_arg[i]) = V_VT(src_arg);
5955 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
5956 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
5957 V_VT(&rgvarg[i]) = rgvt[i];
5959 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
5961 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
5962 V_VT(&rgvarg[i]) = rgvt[i];
5964 else
5966 /* FIXME: this doesn't work for VT_BYREF arguments if
5967 * they are not the same type as in the paramdesc */
5968 V_VT(&rgvarg[i]) = V_VT(src_arg);
5969 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
5970 V_VT(&rgvarg[i]) = rgvt[i];
5973 if (FAILED(hres))
5975 ERR("failed to convert param %d to %s%s from %s%s\n", i,
5976 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
5977 debugstr_VT(src_arg), debugstr_VF(src_arg));
5978 break;
5980 prgpvarg[i] = &rgvarg[i];
5982 else if (wParamFlags & PARAMFLAG_FOPT)
5984 VARIANTARG *arg;
5985 arg = prgpvarg[i] = &rgvarg[i];
5986 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5988 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
5989 if (FAILED(hres))
5990 break;
5992 else
5994 VARIANTARG *missing_arg;
5995 /* if the function wants a pointer to a variant then
5996 * set that up, otherwise just pass the VT_ERROR in
5997 * the argument by value */
5998 if (rgvt[i] & VT_BYREF)
6000 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6001 V_VT(arg) = VT_VARIANT | VT_BYREF;
6002 V_VARIANTREF(arg) = missing_arg;
6004 else
6005 missing_arg = arg;
6006 V_VT(missing_arg) = VT_ERROR;
6007 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6010 else
6012 hres = DISP_E_BADPARAMCOUNT;
6013 break;
6016 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6018 /* VT_VOID is a special case for return types, so it is not
6019 * handled in the general function */
6020 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6021 V_VT(&varresult) = VT_EMPTY;
6022 else
6024 V_VT(&varresult) = 0;
6025 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6026 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6029 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6030 V_VT(&varresult), func_desc->cParams, rgvt,
6031 prgpvarg, &varresult);
6033 for (i = 0; i < func_desc->cParams; i++)
6035 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6036 if (wParamFlags & PARAMFLAG_FRETVAL)
6038 if (TRACE_ON(ole))
6040 TRACE("[retval] value: ");
6041 dump_Variant(prgpvarg[i]);
6044 if (pVarResult)
6046 VariantInit(pVarResult);
6047 /* deref return value */
6048 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6051 /* free data stored in varresult. Note that
6052 * VariantClear doesn't do what we want because we are
6053 * working with byref types. */
6054 /* FIXME: clear safearrays, bstrs, records and
6055 * variants here too */
6056 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
6057 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
6059 if(*V_UNKNOWNREF(prgpvarg[i]))
6060 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
6062 break;
6064 else if (i < pDispParams->cArgs)
6066 if (wParamFlags & PARAMFLAG_FOUT)
6068 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
6070 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
6071 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6073 if (FAILED(hres))
6075 ERR("failed to convert param %d to vt %d\n", i,
6076 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
6077 break;
6080 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6081 func_desc->cParamsOpt < 0 &&
6082 i == func_desc->cParams-1)
6084 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6085 LONG j, ubound;
6086 VARIANT *v;
6087 hres = SafeArrayGetUBound(a, 1, &ubound);
6088 if (hres != S_OK)
6090 ERR("SafeArrayGetUBound failed with %x\n", hres);
6091 break;
6093 hres = SafeArrayAccessData(a, (LPVOID)&v);
6094 if (hres != S_OK)
6096 ERR("SafeArrayAccessData failed with %x\n", hres);
6097 break;
6099 for (j = 0; j <= ubound; j++)
6100 VariantClear(&v[j]);
6101 hres = SafeArrayUnaccessData(a);
6102 if (hres != S_OK)
6104 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6105 break;
6108 VariantClear(&rgvarg[i]);
6110 else if (wParamFlags & PARAMFLAG_FOPT)
6112 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6113 VariantClear(&rgvarg[i]);
6117 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6119 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6120 hres = DISP_E_EXCEPTION;
6121 if (pExcepInfo)
6123 IErrorInfo *pErrorInfo;
6124 pExcepInfo->scode = V_ERROR(&varresult);
6125 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6127 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6128 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6129 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6130 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6132 IErrorInfo_Release(pErrorInfo);
6136 if (V_VT(&varresult) != VT_ERROR)
6138 TRACE("varresult value: ");
6139 dump_Variant(&varresult);
6141 if (pVarResult)
6143 VariantClear(pVarResult);
6144 *pVarResult = varresult;
6146 else
6147 VariantClear(&varresult);
6150 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6151 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6152 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6153 (pDispParams->cArgs != 0))
6155 if (V_VT(pVarResult) == VT_DISPATCH)
6157 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6158 /* Note: not VariantClear; we still need the dispatch
6159 * pointer to be valid */
6160 VariantInit(pVarResult);
6161 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6162 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6163 pDispParams, pVarResult, pExcepInfo, pArgErr);
6164 IDispatch_Release(pDispatch);
6166 else
6168 VariantClear(pVarResult);
6169 hres = DISP_E_NOTACOLLECTION;
6173 func_fail:
6174 HeapFree(GetProcessHeap(), 0, buffer);
6175 break;
6177 case FUNC_DISPATCH: {
6178 IDispatch *disp;
6180 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6181 if (SUCCEEDED(hres)) {
6182 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6183 hres = IDispatch_Invoke(
6184 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6185 pVarResult,pExcepInfo,pArgErr
6187 if (FAILED(hres))
6188 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6189 IDispatch_Release(disp);
6190 } else
6191 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6192 break;
6194 default:
6195 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6196 hres = E_FAIL;
6197 break;
6200 TRACE("-- 0x%08x\n", hres);
6201 return hres;
6203 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6204 VARDESC *var_desc;
6206 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6207 if(FAILED(hres)) return hres;
6209 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6210 dump_VARDESC(var_desc);
6211 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6212 return E_NOTIMPL;
6215 /* not found, look for it in inherited interfaces */
6216 ITypeInfo2_GetTypeKind(iface, &type_kind);
6217 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6218 if(This->impltypelist) {
6219 /* recursive search */
6220 ITypeInfo *pTInfo;
6221 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6222 if(SUCCEEDED(hres)){
6223 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6224 ITypeInfo_Release(pTInfo);
6225 return hres;
6227 WARN("Could not search inherited interface!\n");
6230 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6231 return DISP_E_MEMBERNOTFOUND;
6234 /* ITypeInfo::GetDocumentation
6236 * Retrieves the documentation string, the complete Help file name and path,
6237 * and the context ID for the Help topic for a specified type description.
6239 * (Can be tested by the Visual Basic Editor in Word for instance.)
6241 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6242 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6243 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6245 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6246 const TLBFuncDesc *pFDesc;
6247 const TLBVarDesc *pVDesc;
6248 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6249 " HelpContext(%p) HelpFile(%p)\n",
6250 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6251 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6252 if(pBstrName)
6253 *pBstrName=SysAllocString(This->Name);
6254 if(pBstrDocString)
6255 *pBstrDocString=SysAllocString(This->DocString);
6256 if(pdwHelpContext)
6257 *pdwHelpContext=This->dwHelpContext;
6258 if(pBstrHelpFile)
6259 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6260 return S_OK;
6261 }else {/* for a member */
6262 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6263 if(pFDesc->funcdesc.memid==memid){
6264 if(pBstrName)
6265 *pBstrName = SysAllocString(pFDesc->Name);
6266 if(pBstrDocString)
6267 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6268 if(pdwHelpContext)
6269 *pdwHelpContext=pFDesc->helpcontext;
6270 return S_OK;
6272 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6273 if(pVDesc->vardesc.memid==memid){
6274 if(pBstrName)
6275 *pBstrName = SysAllocString(pVDesc->Name);
6276 if(pBstrDocString)
6277 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6278 if(pdwHelpContext)
6279 *pdwHelpContext=pVDesc->HelpContext;
6280 return S_OK;
6284 if(This->impltypelist &&
6285 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6286 /* recursive search */
6287 ITypeInfo *pTInfo;
6288 HRESULT result;
6289 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6290 &pTInfo);
6291 if(SUCCEEDED(result)) {
6292 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6293 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6294 ITypeInfo_Release(pTInfo);
6295 return result;
6297 WARN("Could not search inherited interface!\n");
6300 WARN("member %d not found\n", memid);
6301 return TYPE_E_ELEMENTNOTFOUND;
6304 /* ITypeInfo::GetDllEntry
6306 * Retrieves a description or specification of an entry point for a function
6307 * in a DLL.
6309 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6310 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6311 WORD *pwOrdinal)
6313 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6314 const TLBFuncDesc *pFDesc;
6316 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6318 if (pBstrDllName) *pBstrDllName = NULL;
6319 if (pBstrName) *pBstrName = NULL;
6320 if (pwOrdinal) *pwOrdinal = 0;
6322 if (This->TypeAttr.typekind != TKIND_MODULE)
6323 return TYPE_E_BADMODULEKIND;
6325 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6326 if(pFDesc->funcdesc.memid==memid){
6327 dump_TypeInfo(This);
6328 if (TRACE_ON(ole))
6329 dump_TLBFuncDescOne(pFDesc);
6331 if (pBstrDllName)
6332 *pBstrDllName = SysAllocString(This->DllName);
6334 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6335 if (pBstrName)
6336 *pBstrName = SysAllocString(pFDesc->Entry);
6337 if (pwOrdinal)
6338 *pwOrdinal = -1;
6339 return S_OK;
6341 if (pBstrName)
6342 *pBstrName = NULL;
6343 if (pwOrdinal)
6344 *pwOrdinal = (DWORD)pFDesc->Entry;
6345 return S_OK;
6347 return TYPE_E_ELEMENTNOTFOUND;
6350 /* internal function to make the inherited interfaces' methods appear
6351 * part of the interface */
6352 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6353 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6355 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6356 HRESULT hr;
6358 TRACE("%p, 0x%x\n", iface, *hRefType);
6360 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK))
6362 ITypeInfo *pSubTypeInfo;
6364 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
6365 if (FAILED(hr))
6366 return hr;
6368 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6369 hRefType, ppTInfo);
6370 ITypeInfo_Release(pSubTypeInfo);
6371 if (SUCCEEDED(hr))
6372 return hr;
6374 *hRefType -= DISPATCH_HREF_OFFSET;
6376 if (!(*hRefType & DISPATCH_HREF_MASK))
6377 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6378 else
6379 return E_FAIL;
6382 /* ITypeInfo::GetRefTypeInfo
6384 * If a type description references other type descriptions, it retrieves
6385 * the referenced type descriptions.
6387 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6388 ITypeInfo2 *iface,
6389 HREFTYPE hRefType,
6390 ITypeInfo **ppTInfo)
6392 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6393 HRESULT result = E_FAIL;
6395 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6397 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6398 ITypeInfo_AddRef(*ppTInfo);
6399 result = S_OK;
6401 else if (hRefType == -1 &&
6402 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6403 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6405 /* when we meet a DUAL dispinterface, we must create the interface
6406 * version of it.
6408 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
6411 /* the interface version contains the same information as the dispinterface
6412 * copy the contents of the structs.
6414 *pTypeInfoImpl = *This;
6415 pTypeInfoImpl->ref = 0;
6417 /* change the type to interface */
6418 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6420 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6422 /* we use data structures from This, so we need to keep a reference
6423 * to it to stop it being destroyed and signal to the new instance to
6424 * not free its data structures when it is destroyed */
6425 pTypeInfoImpl->no_free_data = TRUE;
6426 pTypeInfoImpl->next = This;
6427 ITypeInfo_AddRef((ITypeInfo*) This);
6429 ITypeInfo_AddRef(*ppTInfo);
6431 result = S_OK;
6433 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6434 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6435 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6437 HREFTYPE href_dispatch = hRefType;
6438 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6439 } else {
6440 TLBRefType *ref_type;
6441 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6443 if(ref_type->reference == hRefType)
6444 break;
6446 if(&ref_type->entry == &This->pTypeLib->ref_list)
6448 FIXME("Can't find pRefType for ref %x\n", hRefType);
6449 goto end;
6451 if(hRefType != -1) {
6452 ITypeLib *pTLib = NULL;
6454 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6455 UINT Index;
6456 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6457 } else {
6458 if(ref_type->pImpTLInfo->pImpTypeLib) {
6459 TRACE("typeinfo in imported typelib that is already loaded\n");
6460 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6461 ITypeLib2_AddRef(pTLib);
6462 result = S_OK;
6463 } else {
6464 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6465 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6466 ref_type->pImpTLInfo->wVersionMajor,
6467 ref_type->pImpTLInfo->wVersionMinor,
6468 ref_type->pImpTLInfo->lcid,
6469 &pTLib);
6471 if(!SUCCEEDED(result)) {
6472 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6473 result=LoadTypeLib(libnam, &pTLib);
6474 SysFreeString(libnam);
6476 if(SUCCEEDED(result)) {
6477 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6478 ITypeLib2_AddRef(pTLib);
6482 if(SUCCEEDED(result)) {
6483 if(ref_type->index == TLB_REF_USE_GUID)
6484 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6485 &ref_type->guid,
6486 ppTInfo);
6487 else
6488 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6489 ppTInfo);
6491 if (pTLib != NULL)
6492 ITypeLib2_Release(pTLib);
6496 end:
6497 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6498 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6499 return result;
6502 /* ITypeInfo::AddressOfMember
6504 * Retrieves the addresses of static functions or variables, such as those
6505 * defined in a DLL.
6507 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6508 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6510 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6511 HRESULT hr;
6512 BSTR dll, entry;
6513 WORD ordinal;
6514 HMODULE module;
6516 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6518 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6519 if (FAILED(hr))
6520 return hr;
6522 module = LoadLibraryW(dll);
6523 if (!module)
6525 ERR("couldn't load %s\n", debugstr_w(dll));
6526 SysFreeString(dll);
6527 if (entry) SysFreeString(entry);
6528 return STG_E_FILENOTFOUND;
6530 /* FIXME: store library somewhere where we can free it */
6532 if (entry)
6534 LPSTR entryA;
6535 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6536 entryA = HeapAlloc(GetProcessHeap(), 0, len);
6537 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6539 *ppv = GetProcAddress(module, entryA);
6540 if (!*ppv)
6541 ERR("function not found %s\n", debugstr_a(entryA));
6543 HeapFree(GetProcessHeap(), 0, entryA);
6545 else
6547 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6548 if (!*ppv)
6549 ERR("function not found %d\n", ordinal);
6552 SysFreeString(dll);
6553 if (entry) SysFreeString(entry);
6555 if (!*ppv)
6556 return TYPE_E_DLLFUNCTIONNOTFOUND;
6558 return S_OK;
6561 /* ITypeInfo::CreateInstance
6563 * Creates a new instance of a type that describes a component object class
6564 * (coclass).
6566 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6567 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6569 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6570 HRESULT hr;
6571 TYPEATTR *pTA;
6573 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6575 *ppvObj = NULL;
6577 if(pOuterUnk)
6579 WARN("Not able to aggregate\n");
6580 return CLASS_E_NOAGGREGATION;
6583 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6584 if(FAILED(hr)) return hr;
6586 if(pTA->typekind != TKIND_COCLASS)
6588 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6589 hr = E_INVALIDARG;
6590 goto end;
6593 hr = S_FALSE;
6594 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6596 IUnknown *pUnk;
6597 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6598 TRACE("GetActiveObject rets %08x\n", hr);
6599 if(hr == S_OK)
6601 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6602 IUnknown_Release(pUnk);
6606 if(hr != S_OK)
6607 hr = CoCreateInstance(&pTA->guid, NULL,
6608 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6609 riid, ppvObj);
6611 end:
6612 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6613 return hr;
6616 /* ITypeInfo::GetMops
6618 * Retrieves marshalling information.
6620 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6621 BSTR *pBstrMops)
6623 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6624 FIXME("(%p) stub!\n", This);
6625 return S_OK;
6628 /* ITypeInfo::GetContainingTypeLib
6630 * Retrieves the containing type library and the index of the type description
6631 * within that type library.
6633 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6634 ITypeLib * *ppTLib, UINT *pIndex)
6636 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6638 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6639 if (pIndex) {
6640 *pIndex=This->index;
6641 TRACE("returning pIndex=%d\n", *pIndex);
6644 if (ppTLib) {
6645 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6646 ITypeLib2_AddRef(*ppTLib);
6647 TRACE("returning ppTLib=%p\n", *ppTLib);
6650 return S_OK;
6653 /* ITypeInfo::ReleaseTypeAttr
6655 * Releases a TYPEATTR previously returned by GetTypeAttr.
6658 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6659 TYPEATTR* pTypeAttr)
6661 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6662 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6663 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6666 /* ITypeInfo::ReleaseFuncDesc
6668 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6670 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6671 ITypeInfo2 *iface,
6672 FUNCDESC *pFuncDesc)
6674 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6675 SHORT i;
6677 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6679 for (i = 0; i < pFuncDesc->cParams; i++)
6680 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6681 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6683 SysFreeString((BSTR)pFuncDesc);
6686 /* ITypeInfo::ReleaseVarDesc
6688 * Releases a VARDESC previously returned by GetVarDesc.
6690 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6691 VARDESC *pVarDesc)
6693 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6694 TRACE("(%p)->(%p)\n", This, pVarDesc);
6696 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6697 if (pVarDesc->varkind == VAR_CONST)
6698 VariantClear(pVarDesc->u.lpvarValue);
6699 SysFreeString((BSTR)pVarDesc);
6702 /* ITypeInfo2::GetTypeKind
6704 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6707 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6708 TYPEKIND *pTypeKind)
6710 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6711 *pTypeKind=This->TypeAttr.typekind;
6712 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6713 return S_OK;
6716 /* ITypeInfo2::GetTypeFlags
6718 * Returns the type flags without any allocations. This returns a DWORD type
6719 * flag, which expands the type flags without growing the TYPEATTR (type
6720 * attribute).
6723 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6725 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6726 *pTypeFlags=This->TypeAttr.wTypeFlags;
6727 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6728 return S_OK;
6731 /* ITypeInfo2::GetFuncIndexOfMemId
6732 * Binds to a specific member based on a known DISPID, where the member name
6733 * is not known (for example, when binding to a default member).
6736 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
6737 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
6739 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6740 const TLBFuncDesc *pFuncInfo;
6741 int i;
6742 HRESULT result;
6744 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
6745 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
6746 break;
6747 if(pFuncInfo) {
6748 *pFuncIndex = i;
6749 result = S_OK;
6750 } else
6751 result = TYPE_E_ELEMENTNOTFOUND;
6753 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
6754 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6755 return result;
6758 /* TypeInfo2::GetVarIndexOfMemId
6760 * Binds to a specific member based on a known DISPID, where the member name
6761 * is not known (for example, when binding to a default member).
6764 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
6765 MEMBERID memid, UINT *pVarIndex)
6767 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6768 TLBVarDesc *pVarInfo;
6769 int i;
6770 HRESULT result;
6771 for(i=0, pVarInfo=This->varlist; pVarInfo &&
6772 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
6774 if(pVarInfo) {
6775 *pVarIndex = i;
6776 result = S_OK;
6777 } else
6778 result = TYPE_E_ELEMENTNOTFOUND;
6780 TRACE("(%p) memid 0x%08x -> %s\n", This,
6781 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6782 return result;
6785 /* ITypeInfo2::GetCustData
6787 * Gets the custom data
6789 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
6790 ITypeInfo2 * iface,
6791 REFGUID guid,
6792 VARIANT *pVarVal)
6794 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6795 TLBCustData *pCData;
6797 for(pCData=This->pCustData; pCData; pCData = pCData->next)
6798 if( IsEqualIID(guid, &pCData->guid)) break;
6800 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6802 if(pCData)
6804 VariantInit( pVarVal);
6805 VariantCopy( pVarVal, &pCData->data);
6806 return S_OK;
6808 return E_INVALIDARG; /* FIXME: correct? */
6811 /* ITypeInfo2::GetFuncCustData
6813 * Gets the custom data
6815 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
6816 ITypeInfo2 * iface,
6817 UINT index,
6818 REFGUID guid,
6819 VARIANT *pVarVal)
6821 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6822 TLBCustData *pCData=NULL;
6823 TLBFuncDesc * pFDesc;
6824 int i;
6825 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6826 pFDesc=pFDesc->next);
6828 if(pFDesc)
6829 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
6830 if( IsEqualIID(guid, &pCData->guid)) break;
6832 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6834 if(pCData){
6835 VariantInit( pVarVal);
6836 VariantCopy( pVarVal, &pCData->data);
6837 return S_OK;
6839 return E_INVALIDARG; /* FIXME: correct? */
6842 /* ITypeInfo2::GetParamCustData
6844 * Gets the custom data
6846 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
6847 ITypeInfo2 * iface,
6848 UINT indexFunc,
6849 UINT indexParam,
6850 REFGUID guid,
6851 VARIANT *pVarVal)
6853 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6854 TLBCustData *pCData=NULL;
6855 TLBFuncDesc * pFDesc;
6856 int i;
6858 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
6860 if(pFDesc && indexParam<pFDesc->funcdesc.cParams)
6861 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
6862 pCData = pCData->next)
6863 if( IsEqualIID(guid, &pCData->guid)) break;
6865 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6867 if(pCData)
6869 VariantInit( pVarVal);
6870 VariantCopy( pVarVal, &pCData->data);
6871 return S_OK;
6873 return E_INVALIDARG; /* FIXME: correct? */
6876 /* ITypeInfo2::GetVarCustData
6878 * Gets the custom data
6880 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
6881 ITypeInfo2 * iface,
6882 UINT index,
6883 REFGUID guid,
6884 VARIANT *pVarVal)
6886 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6887 TLBCustData *pCData=NULL;
6888 TLBVarDesc * pVDesc;
6889 int i;
6891 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
6893 if(pVDesc)
6895 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
6897 if( IsEqualIID(guid, &pCData->guid)) break;
6901 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6903 if(pCData)
6905 VariantInit( pVarVal);
6906 VariantCopy( pVarVal, &pCData->data);
6907 return S_OK;
6909 return E_INVALIDARG; /* FIXME: correct? */
6912 /* ITypeInfo2::GetImplCustData
6914 * Gets the custom data
6916 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6917 ITypeInfo2 * iface,
6918 UINT index,
6919 REFGUID guid,
6920 VARIANT *pVarVal)
6922 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6923 TLBCustData *pCData=NULL;
6924 TLBImplType * pRDesc;
6925 int i;
6927 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6929 if(pRDesc)
6931 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6933 if( IsEqualIID(guid, &pCData->guid)) break;
6937 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6939 if(pCData)
6941 VariantInit( pVarVal);
6942 VariantCopy( pVarVal, &pCData->data);
6943 return S_OK;
6945 return E_INVALIDARG; /* FIXME: correct? */
6948 /* ITypeInfo2::GetDocumentation2
6950 * Retrieves the documentation string, the complete Help file name and path,
6951 * the localization context to use, and the context ID for the library Help
6952 * topic in the Help file.
6955 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6956 ITypeInfo2 * iface,
6957 MEMBERID memid,
6958 LCID lcid,
6959 BSTR *pbstrHelpString,
6960 DWORD *pdwHelpStringContext,
6961 BSTR *pbstrHelpStringDll)
6963 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6964 const TLBFuncDesc *pFDesc;
6965 const TLBVarDesc *pVDesc;
6966 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
6967 "HelpStringContext(%p) HelpStringDll(%p)\n",
6968 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6969 pbstrHelpStringDll );
6970 /* the help string should be obtained from the helpstringdll,
6971 * using the _DLLGetDocumentation function, based on the supplied
6972 * lcid. Nice to do sometime...
6974 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6975 if(pbstrHelpString)
6976 *pbstrHelpString=SysAllocString(This->Name);
6977 if(pdwHelpStringContext)
6978 *pdwHelpStringContext=This->dwHelpStringContext;
6979 if(pbstrHelpStringDll)
6980 *pbstrHelpStringDll=
6981 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6982 return S_OK;
6983 }else {/* for a member */
6984 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6985 if(pFDesc->funcdesc.memid==memid){
6986 if(pbstrHelpString)
6987 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6988 if(pdwHelpStringContext)
6989 *pdwHelpStringContext=pFDesc->HelpStringContext;
6990 if(pbstrHelpStringDll)
6991 *pbstrHelpStringDll=
6992 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6993 return S_OK;
6995 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6996 if(pVDesc->vardesc.memid==memid){
6997 if(pbstrHelpString)
6998 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6999 if(pdwHelpStringContext)
7000 *pdwHelpStringContext=pVDesc->HelpStringContext;
7001 if(pbstrHelpStringDll)
7002 *pbstrHelpStringDll=
7003 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7004 return S_OK;
7007 return TYPE_E_ELEMENTNOTFOUND;
7010 /* ITypeInfo2::GetAllCustData
7012 * Gets all custom data items for the Type info.
7015 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7016 ITypeInfo2 * iface,
7017 CUSTDATA *pCustData)
7019 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7020 TLBCustData *pCData;
7021 int i;
7023 TRACE("(%p) returning %d items\n", This, This->ctCustData);
7025 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
7026 if(pCustData->prgCustData ){
7027 pCustData->cCustData=This->ctCustData;
7028 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
7029 pCustData->prgCustData[i].guid=pCData->guid;
7030 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
7032 }else{
7033 ERR(" OUT OF MEMORY!\n");
7034 return E_OUTOFMEMORY;
7036 return S_OK;
7039 /* ITypeInfo2::GetAllFuncCustData
7041 * Gets all custom data items for the specified Function
7044 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7045 ITypeInfo2 * iface,
7046 UINT index,
7047 CUSTDATA *pCustData)
7049 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7050 TLBCustData *pCData;
7051 TLBFuncDesc * pFDesc;
7052 int i;
7053 TRACE("(%p) index %d\n", This, index);
7054 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7055 pFDesc=pFDesc->next)
7057 if(pFDesc){
7058 pCustData->prgCustData =
7059 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
7060 if(pCustData->prgCustData ){
7061 pCustData->cCustData=pFDesc->ctCustData;
7062 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
7063 pCData = pCData->next){
7064 pCustData->prgCustData[i].guid=pCData->guid;
7065 VariantCopy(& pCustData->prgCustData[i].varValue,
7066 & pCData->data);
7068 }else{
7069 ERR(" OUT OF MEMORY!\n");
7070 return E_OUTOFMEMORY;
7072 return S_OK;
7074 return TYPE_E_ELEMENTNOTFOUND;
7077 /* ITypeInfo2::GetAllParamCustData
7079 * Gets all custom data items for the Functions
7082 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7083 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7085 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7086 TLBCustData *pCData=NULL;
7087 TLBFuncDesc * pFDesc;
7088 int i;
7089 TRACE("(%p) index %d\n", This, indexFunc);
7090 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
7091 pFDesc=pFDesc->next)
7093 if(pFDesc && indexParam<pFDesc->funcdesc.cParams){
7094 pCustData->prgCustData =
7095 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
7096 sizeof(CUSTDATAITEM));
7097 if(pCustData->prgCustData ){
7098 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
7099 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
7100 pCData; i++, pCData = pCData->next){
7101 pCustData->prgCustData[i].guid=pCData->guid;
7102 VariantCopy(& pCustData->prgCustData[i].varValue,
7103 & pCData->data);
7105 }else{
7106 ERR(" OUT OF MEMORY!\n");
7107 return E_OUTOFMEMORY;
7109 return S_OK;
7111 return TYPE_E_ELEMENTNOTFOUND;
7114 /* ITypeInfo2::GetAllVarCustData
7116 * Gets all custom data items for the specified Variable
7119 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7120 UINT index, CUSTDATA *pCustData)
7122 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7123 TLBCustData *pCData;
7124 TLBVarDesc * pVDesc;
7125 int i;
7126 TRACE("(%p) index %d\n", This, index);
7127 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
7128 pVDesc=pVDesc->next)
7130 if(pVDesc){
7131 pCustData->prgCustData =
7132 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
7133 if(pCustData->prgCustData ){
7134 pCustData->cCustData=pVDesc->ctCustData;
7135 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
7136 pCData = pCData->next){
7137 pCustData->prgCustData[i].guid=pCData->guid;
7138 VariantCopy(& pCustData->prgCustData[i].varValue,
7139 & pCData->data);
7141 }else{
7142 ERR(" OUT OF MEMORY!\n");
7143 return E_OUTOFMEMORY;
7145 return S_OK;
7147 return TYPE_E_ELEMENTNOTFOUND;
7150 /* ITypeInfo2::GetAllImplCustData
7152 * Gets all custom data items for the specified implementation type
7155 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7156 ITypeInfo2 * iface,
7157 UINT index,
7158 CUSTDATA *pCustData)
7160 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7161 TLBCustData *pCData;
7162 TLBImplType * pRDesc;
7163 int i;
7164 TRACE("(%p) index %d\n", This, index);
7165 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
7166 pRDesc=pRDesc->next)
7168 if(pRDesc){
7169 pCustData->prgCustData =
7170 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
7171 if(pCustData->prgCustData ){
7172 pCustData->cCustData=pRDesc->ctCustData;
7173 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
7174 pCData = pCData->next){
7175 pCustData->prgCustData[i].guid=pCData->guid;
7176 VariantCopy(& pCustData->prgCustData[i].varValue,
7177 & pCData->data);
7179 }else{
7180 ERR(" OUT OF MEMORY!\n");
7181 return E_OUTOFMEMORY;
7183 return S_OK;
7185 return TYPE_E_ELEMENTNOTFOUND;
7188 static const ITypeInfo2Vtbl tinfvt =
7191 ITypeInfo_fnQueryInterface,
7192 ITypeInfo_fnAddRef,
7193 ITypeInfo_fnRelease,
7195 ITypeInfo_fnGetTypeAttr,
7196 ITypeInfo_fnGetTypeComp,
7197 ITypeInfo_fnGetFuncDesc,
7198 ITypeInfo_fnGetVarDesc,
7199 ITypeInfo_fnGetNames,
7200 ITypeInfo_fnGetRefTypeOfImplType,
7201 ITypeInfo_fnGetImplTypeFlags,
7202 ITypeInfo_fnGetIDsOfNames,
7203 ITypeInfo_fnInvoke,
7204 ITypeInfo_fnGetDocumentation,
7205 ITypeInfo_fnGetDllEntry,
7206 ITypeInfo_fnGetRefTypeInfo,
7207 ITypeInfo_fnAddressOfMember,
7208 ITypeInfo_fnCreateInstance,
7209 ITypeInfo_fnGetMops,
7210 ITypeInfo_fnGetContainingTypeLib,
7211 ITypeInfo_fnReleaseTypeAttr,
7212 ITypeInfo_fnReleaseFuncDesc,
7213 ITypeInfo_fnReleaseVarDesc,
7215 ITypeInfo2_fnGetTypeKind,
7216 ITypeInfo2_fnGetTypeFlags,
7217 ITypeInfo2_fnGetFuncIndexOfMemId,
7218 ITypeInfo2_fnGetVarIndexOfMemId,
7219 ITypeInfo2_fnGetCustData,
7220 ITypeInfo2_fnGetFuncCustData,
7221 ITypeInfo2_fnGetParamCustData,
7222 ITypeInfo2_fnGetVarCustData,
7223 ITypeInfo2_fnGetImplTypeCustData,
7224 ITypeInfo2_fnGetDocumentation2,
7225 ITypeInfo2_fnGetAllCustData,
7226 ITypeInfo2_fnGetAllFuncCustData,
7227 ITypeInfo2_fnGetAllParamCustData,
7228 ITypeInfo2_fnGetAllVarCustData,
7229 ITypeInfo2_fnGetAllImplTypeCustData,
7232 /******************************************************************************
7233 * CreateDispTypeInfo [OLEAUT32.31]
7235 * Build type information for an object so it can be called through an
7236 * IDispatch interface.
7238 * RETURNS
7239 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7240 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7242 * NOTES
7243 * This call allows an objects methods to be accessed through IDispatch, by
7244 * building an ITypeInfo object that IDispatch can use to call through.
7246 HRESULT WINAPI CreateDispTypeInfo(
7247 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7248 LCID lcid, /* [I] Locale Id */
7249 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7251 ITypeInfoImpl *pTIClass, *pTIIface;
7252 ITypeLibImpl *pTypeLibImpl;
7253 int param, func;
7254 TLBFuncDesc **ppFuncDesc;
7255 TLBRefType *ref;
7257 TRACE("\n");
7258 pTypeLibImpl = TypeLibImpl_Constructor();
7259 if (!pTypeLibImpl) return E_FAIL;
7261 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
7262 pTIIface->pTypeLib = pTypeLibImpl;
7263 pTIIface->index = 0;
7264 pTIIface->Name = NULL;
7265 pTIIface->dwHelpContext = -1;
7266 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7267 pTIIface->TypeAttr.lcid = lcid;
7268 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7269 pTIIface->TypeAttr.wMajorVerNum = 0;
7270 pTIIface->TypeAttr.wMinorVerNum = 0;
7271 pTIIface->TypeAttr.cbAlignment = 2;
7272 pTIIface->TypeAttr.cbSizeInstance = -1;
7273 pTIIface->TypeAttr.cbSizeVft = -1;
7274 pTIIface->TypeAttr.cFuncs = 0;
7275 pTIIface->TypeAttr.cImplTypes = 0;
7276 pTIIface->TypeAttr.cVars = 0;
7277 pTIIface->TypeAttr.wTypeFlags = 0;
7279 ppFuncDesc = &pTIIface->funclist;
7280 for(func = 0; func < pidata->cMembers; func++) {
7281 METHODDATA *md = pidata->pmethdata + func;
7282 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
7283 (*ppFuncDesc)->Name = SysAllocString(md->szName);
7284 (*ppFuncDesc)->funcdesc.memid = md->dispid;
7285 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
7286 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
7287 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
7288 (*ppFuncDesc)->funcdesc.callconv = md->cc;
7289 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
7290 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
7291 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
7292 (*ppFuncDesc)->funcdesc.cScodes = 0;
7293 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
7294 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7295 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7296 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7297 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7298 md->cArgs * sizeof(ELEMDESC));
7299 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7300 md->cArgs * sizeof(TLBParDesc));
7301 for(param = 0; param < md->cArgs; param++) {
7302 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7303 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7305 (*ppFuncDesc)->helpcontext = 0;
7306 (*ppFuncDesc)->HelpStringContext = 0;
7307 (*ppFuncDesc)->HelpString = NULL;
7308 (*ppFuncDesc)->Entry = NULL;
7309 (*ppFuncDesc)->ctCustData = 0;
7310 (*ppFuncDesc)->pCustData = NULL;
7311 (*ppFuncDesc)->next = NULL;
7312 pTIIface->TypeAttr.cFuncs++;
7313 ppFuncDesc = &(*ppFuncDesc)->next;
7316 dump_TypeInfo(pTIIface);
7318 pTypeLibImpl->pTypeInfo = pTIIface;
7319 pTypeLibImpl->TypeInfoCount++;
7321 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
7322 pTIClass->pTypeLib = pTypeLibImpl;
7323 pTIClass->index = 1;
7324 pTIClass->Name = NULL;
7325 pTIClass->dwHelpContext = -1;
7326 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7327 pTIClass->TypeAttr.lcid = lcid;
7328 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7329 pTIClass->TypeAttr.wMajorVerNum = 0;
7330 pTIClass->TypeAttr.wMinorVerNum = 0;
7331 pTIClass->TypeAttr.cbAlignment = 2;
7332 pTIClass->TypeAttr.cbSizeInstance = -1;
7333 pTIClass->TypeAttr.cbSizeVft = -1;
7334 pTIClass->TypeAttr.cFuncs = 0;
7335 pTIClass->TypeAttr.cImplTypes = 1;
7336 pTIClass->TypeAttr.cVars = 0;
7337 pTIClass->TypeAttr.wTypeFlags = 0;
7339 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
7340 pTIClass->impltypelist->hRef = 0;
7342 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
7343 ref->index = 0;
7344 ref->reference = 0;
7345 ref->pImpTLInfo = TLB_REF_INTERNAL;
7346 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7348 dump_TypeInfo(pTIClass);
7350 pTIIface->next = pTIClass;
7351 pTypeLibImpl->TypeInfoCount++;
7353 *pptinfo = (ITypeInfo*)pTIClass;
7355 ITypeInfo_AddRef(*pptinfo);
7356 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7358 return S_OK;
7362 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7364 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7366 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7369 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7371 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7373 return ITypeInfo_AddRef((ITypeInfo *)This);
7376 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7378 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7380 return ITypeInfo_Release((ITypeInfo *)This);
7383 static HRESULT WINAPI ITypeComp_fnBind(
7384 ITypeComp * iface,
7385 OLECHAR * szName,
7386 ULONG lHash,
7387 WORD wFlags,
7388 ITypeInfo ** ppTInfo,
7389 DESCKIND * pDescKind,
7390 BINDPTR * pBindPtr)
7392 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7393 const TLBFuncDesc *pFDesc;
7394 const TLBVarDesc *pVDesc;
7395 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7397 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7399 *pDescKind = DESCKIND_NONE;
7400 pBindPtr->lpfuncdesc = NULL;
7401 *ppTInfo = NULL;
7403 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
7404 if (!strcmpiW(pFDesc->Name, szName)) {
7405 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7406 break;
7407 else
7408 /* name found, but wrong flags */
7409 hr = TYPE_E_TYPEMISMATCH;
7412 if (pFDesc)
7414 HRESULT hr = TLB_AllocAndInitFuncDesc(
7415 &pFDesc->funcdesc,
7416 &pBindPtr->lpfuncdesc,
7417 This->TypeAttr.typekind == TKIND_DISPATCH);
7418 if (FAILED(hr))
7419 return hr;
7420 *pDescKind = DESCKIND_FUNCDESC;
7421 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7422 ITypeInfo_AddRef(*ppTInfo);
7423 return S_OK;
7424 } else {
7425 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7426 if (!strcmpiW(pVDesc->Name, szName)) {
7427 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7428 if (FAILED(hr))
7429 return hr;
7430 *pDescKind = DESCKIND_VARDESC;
7431 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7432 ITypeInfo_AddRef(*ppTInfo);
7433 return S_OK;
7437 /* FIXME: search each inherited interface, not just the first */
7438 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7439 /* recursive search */
7440 ITypeInfo *pTInfo;
7441 ITypeComp *pTComp;
7442 HRESULT hr;
7443 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7444 if (SUCCEEDED(hr))
7446 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7447 ITypeInfo_Release(pTInfo);
7449 if (SUCCEEDED(hr))
7451 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7452 ITypeComp_Release(pTComp);
7453 return hr;
7455 WARN("Could not search inherited interface!\n");
7457 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
7458 return hr;
7461 static HRESULT WINAPI ITypeComp_fnBindType(
7462 ITypeComp * iface,
7463 OLECHAR * szName,
7464 ULONG lHash,
7465 ITypeInfo ** ppTInfo,
7466 ITypeComp ** ppTComp)
7468 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7470 /* strange behaviour (does nothing) but like the
7471 * original */
7473 if (!ppTInfo || !ppTComp)
7474 return E_POINTER;
7476 *ppTInfo = NULL;
7477 *ppTComp = NULL;
7479 return S_OK;
7482 static const ITypeCompVtbl tcompvt =
7485 ITypeComp_fnQueryInterface,
7486 ITypeComp_fnAddRef,
7487 ITypeComp_fnRelease,
7489 ITypeComp_fnBind,
7490 ITypeComp_fnBindType