push 52c8025cfe276c5cfd77ca72ad5fc2909af0f7c3
[wine/hacks.git] / dlls / oleaut32 / typelib.c
blobceb229528b166e148478cc2d6b797f7a20e0c6a0
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_INT((*ppVarDesc)->vardesc.u.lpvarValue) = 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 case VT_INT:
3176 case VT_UINT:
3177 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) =
3178 *(INT*)(pBlk + pItem->byte_offs);
3179 break;
3180 default:
3181 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt);
3185 else {
3186 TRACE_(typelib)("VAR_PERINSTANCE\n");
3187 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3188 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3191 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3192 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
3194 if (pItem->flags & 0x80)
3195 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3197 bstrPrevName = (*ppVarDesc)->Name;
3198 ppVarDesc = &((*ppVarDesc)->next);
3200 pTI->TypeAttr.cVars = cVars;
3203 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3204 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3206 SLTG_Function *pFunc;
3207 unsigned short i;
3208 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3210 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3211 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3213 int param;
3214 WORD *pType, *pArg;
3216 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3217 sizeof(**ppFuncDesc));
3219 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3220 case SLTG_FUNCTION_MAGIC:
3221 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3222 break;
3223 case SLTG_DISPATCH_FUNCTION_MAGIC:
3224 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3225 break;
3226 case SLTG_STATIC_FUNCTION_MAGIC:
3227 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3228 break;
3229 default:
3230 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3231 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
3232 *ppFuncDesc = NULL;
3233 return;
3235 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3237 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3238 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3239 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3240 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3241 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3242 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3244 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3245 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3247 if(pFunc->retnextopt & 0x80)
3248 pType = &pFunc->rettype;
3249 else
3250 pType = (WORD*)(pBlk + pFunc->rettype);
3252 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3254 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3255 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3256 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3257 (*ppFuncDesc)->pParamDesc =
3258 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3259 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3261 pArg = (WORD*)(pBlk + pFunc->arg_off);
3263 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3264 char *paramName = pNameTable + *pArg;
3265 BOOL HaveOffs;
3266 /* If arg type follows then paramName points to the 2nd
3267 letter of the name, else the next WORD is an offset to
3268 the arg type and paramName points to the first letter.
3269 So let's take one char off paramName and see if we're
3270 pointing at an alpha-numeric char. However if *pArg is
3271 0xffff or 0xfffe then the param has no name, the former
3272 meaning that the next WORD is the type, the latter
3273 meaning that the next WORD is an offset to the type. */
3275 HaveOffs = FALSE;
3276 if(*pArg == 0xffff)
3277 paramName = NULL;
3278 else if(*pArg == 0xfffe) {
3279 paramName = NULL;
3280 HaveOffs = TRUE;
3282 else if(paramName[-1] && !isalnum(paramName[-1]))
3283 HaveOffs = TRUE;
3285 pArg++;
3287 if(HaveOffs) { /* the next word is an offset to type */
3288 pType = (WORD*)(pBlk + *pArg);
3289 SLTG_DoElem(pType, pBlk,
3290 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3291 pArg++;
3292 } else {
3293 if(paramName)
3294 paramName--;
3295 pArg = SLTG_DoElem(pArg, pBlk,
3296 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3299 /* Are we an optional param ? */
3300 if((*ppFuncDesc)->funcdesc.cParams - param <=
3301 (*ppFuncDesc)->funcdesc.cParamsOpt)
3302 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3304 if(paramName) {
3305 (*ppFuncDesc)->pParamDesc[param].Name =
3306 TLB_MultiByteToBSTR(paramName);
3307 } else {
3308 (*ppFuncDesc)->pParamDesc[param].Name =
3309 SysAllocString((*ppFuncDesc)->Name);
3313 ppFuncDesc = &((*ppFuncDesc)->next);
3314 if(pFunc->next == 0xffff) break;
3316 pTI->TypeAttr.cFuncs = cFuncs;
3319 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3320 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3321 SLTG_TypeInfoTail *pTITail)
3323 char *pFirstItem;
3324 sltg_ref_lookup_t *ref_lookup = NULL;
3326 if(pTIHeader->href_table != 0xffffffff) {
3327 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3328 pNameTable);
3331 pFirstItem = pBlk;
3333 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3334 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3336 HeapFree(GetProcessHeap(), 0, ref_lookup);
3340 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3341 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3342 const SLTG_TypeInfoTail *pTITail)
3344 char *pFirstItem;
3345 sltg_ref_lookup_t *ref_lookup = NULL;
3347 if(pTIHeader->href_table != 0xffffffff) {
3348 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3349 pNameTable);
3352 pFirstItem = pBlk;
3354 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3355 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3358 if (pTITail->funcs_off != 0xffff)
3359 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3361 HeapFree(GetProcessHeap(), 0, ref_lookup);
3363 if (TRACE_ON(typelib))
3364 dump_TLBFuncDesc(pTI->funclist);
3367 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3368 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3369 const SLTG_TypeInfoTail *pTITail)
3371 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3374 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3375 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3376 const SLTG_TypeInfoTail *pTITail)
3378 WORD *pType;
3379 sltg_ref_lookup_t *ref_lookup = NULL;
3381 if (pTITail->simple_alias) {
3382 /* if simple alias, no more processing required */
3383 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3384 return;
3387 if(pTIHeader->href_table != 0xffffffff) {
3388 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3389 pNameTable);
3392 /* otherwise it is an offset to a type */
3393 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3395 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3397 HeapFree(GetProcessHeap(), 0, ref_lookup);
3400 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3401 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3402 const SLTG_TypeInfoTail *pTITail)
3404 sltg_ref_lookup_t *ref_lookup = NULL;
3405 if (pTIHeader->href_table != 0xffffffff)
3406 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3407 pNameTable);
3409 if (pTITail->vars_off != 0xffff)
3410 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3412 if (pTITail->funcs_off != 0xffff)
3413 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3415 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3416 * of dispinterface functions including the IDispatch ones, so
3417 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3418 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3420 HeapFree(GetProcessHeap(), 0, ref_lookup);
3421 if (TRACE_ON(typelib))
3422 dump_TLBFuncDesc(pTI->funclist);
3425 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3426 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3427 const SLTG_TypeInfoTail *pTITail)
3429 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3432 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3433 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3434 const SLTG_TypeInfoTail *pTITail)
3436 sltg_ref_lookup_t *ref_lookup = NULL;
3437 if (pTIHeader->href_table != 0xffffffff)
3438 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3439 pNameTable);
3441 if (pTITail->vars_off != 0xffff)
3442 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3444 if (pTITail->funcs_off != 0xffff)
3445 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3446 HeapFree(GetProcessHeap(), 0, ref_lookup);
3447 if (TRACE_ON(typelib))
3448 dump_TypeInfo(pTI);
3451 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3452 managable copy of it into this */
3453 typedef struct {
3454 WORD small_no;
3455 char *index_name;
3456 char *other_name;
3457 WORD res1a;
3458 WORD name_offs;
3459 WORD more_bytes;
3460 char *extra;
3461 WORD res20;
3462 DWORD helpcontext;
3463 WORD res26;
3464 GUID uuid;
3465 } SLTG_InternalOtherTypeInfo;
3467 /****************************************************************************
3468 * ITypeLib2_Constructor_SLTG
3470 * loading a SLTG typelib from an in-memory image
3472 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3474 ITypeLibImpl *pTypeLibImpl;
3475 SLTG_Header *pHeader;
3476 SLTG_BlkEntry *pBlkEntry;
3477 SLTG_Magic *pMagic;
3478 SLTG_Index *pIndex;
3479 SLTG_Pad9 *pPad9;
3480 LPVOID pBlk, pFirstBlk;
3481 SLTG_LibBlk *pLibBlk;
3482 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3483 char *pAfterOTIBlks = NULL;
3484 char *pNameTable, *ptr;
3485 int i;
3486 DWORD len, order;
3487 ITypeInfoImpl **ppTypeInfoImpl;
3489 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3492 pTypeLibImpl = TypeLibImpl_Constructor();
3493 if (!pTypeLibImpl) return NULL;
3495 pHeader = pLib;
3497 TRACE_(typelib)("header:\n");
3498 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3499 pHeader->nrOfFileBlks );
3500 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3501 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3502 pHeader->SLTG_magic);
3503 return NULL;
3506 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3507 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3509 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3510 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3512 /* Next we have a magic block */
3513 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3515 /* Let's see if we're still in sync */
3516 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3517 sizeof(SLTG_COMPOBJ_MAGIC))) {
3518 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3519 return NULL;
3521 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3522 sizeof(SLTG_DIR_MAGIC))) {
3523 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
3524 return NULL;
3527 pIndex = (SLTG_Index*)(pMagic+1);
3529 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3531 pFirstBlk = (LPVOID)(pPad9 + 1);
3533 /* We'll set up a ptr to the main library block, which is the last one. */
3535 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3536 pBlkEntry[order].next != 0;
3537 order = pBlkEntry[order].next - 1, i++) {
3538 pBlk = (char*)pBlk + pBlkEntry[order].len;
3540 pLibBlk = pBlk;
3542 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3544 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3545 interspersed */
3547 len += 0x40;
3549 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3551 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3552 sizeof(*pOtherTypeInfoBlks) *
3553 pTypeLibImpl->TypeInfoCount);
3556 ptr = (char*)pLibBlk + len;
3558 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3559 WORD w, extra;
3560 len = 0;
3562 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3564 w = *(WORD*)(ptr + 2);
3565 if(w != 0xffff) {
3566 len += w;
3567 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3568 w+1);
3569 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3570 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3572 w = *(WORD*)(ptr + 4 + len);
3573 if(w != 0xffff) {
3574 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3575 len += w;
3576 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3577 w+1);
3578 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3579 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3581 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3582 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3583 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3584 if(extra) {
3585 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3586 extra);
3587 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3588 len += extra;
3590 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3591 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3592 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3593 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3594 len += sizeof(SLTG_OtherTypeInfo);
3595 ptr += len;
3598 pAfterOTIBlks = ptr;
3600 /* Skip this WORD and get the next DWORD */
3601 len = *(DWORD*)(pAfterOTIBlks + 2);
3603 /* Now add this to pLibBLk look at what we're pointing at and
3604 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3605 dust and we should be pointing at the beginning of the name
3606 table */
3608 pNameTable = (char*)pLibBlk + len;
3610 switch(*(WORD*)pNameTable) {
3611 case 0xffff:
3612 break;
3613 case 0x0200:
3614 pNameTable += 0x20;
3615 break;
3616 default:
3617 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
3618 break;
3621 pNameTable += 0x216;
3623 pNameTable += 2;
3625 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
3627 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3630 /* Hopefully we now have enough ptrs set up to actually read in
3631 some TypeInfos. It's not clear which order to do them in, so
3632 I'll just follow the links along the BlkEntry chain and read
3633 them in the order in which they are in the file */
3635 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3637 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3638 pBlkEntry[order].next != 0;
3639 order = pBlkEntry[order].next - 1, i++) {
3641 SLTG_TypeInfoHeader *pTIHeader;
3642 SLTG_TypeInfoTail *pTITail;
3643 SLTG_MemberHeader *pMemHeader;
3645 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3646 pOtherTypeInfoBlks[i].index_name)) {
3647 FIXME_(typelib)("Index strings don't match\n");
3648 return NULL;
3651 pTIHeader = pBlk;
3652 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3653 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3654 return NULL;
3656 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
3657 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3658 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3660 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3661 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3662 (*ppTypeInfoImpl)->index = i;
3663 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3664 pOtherTypeInfoBlks[i].name_offs +
3665 pNameTable);
3666 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3667 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
3668 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3669 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3670 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3671 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3672 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3674 if((pTIHeader->typeflags1 & 7) != 2)
3675 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
3676 if(pTIHeader->typeflags3 != 2)
3677 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
3679 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3680 debugstr_w((*ppTypeInfoImpl)->Name),
3681 typekind_desc[pTIHeader->typekind],
3682 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3683 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3685 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3687 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3689 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3690 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3691 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3693 switch(pTIHeader->typekind) {
3694 case TKIND_ENUM:
3695 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3696 pTIHeader, pTITail);
3697 break;
3699 case TKIND_RECORD:
3700 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3701 pTIHeader, pTITail);
3702 break;
3704 case TKIND_INTERFACE:
3705 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3706 pTIHeader, pTITail);
3707 break;
3709 case TKIND_COCLASS:
3710 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3711 pTIHeader, pTITail);
3712 break;
3714 case TKIND_ALIAS:
3715 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3716 pTIHeader, pTITail);
3717 break;
3719 case TKIND_DISPATCH:
3720 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3721 pTIHeader, pTITail);
3722 break;
3724 case TKIND_MODULE:
3725 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3726 pTIHeader, pTITail);
3727 break;
3729 default:
3730 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3731 break;
3735 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3736 but we've already set those */
3737 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3738 X(06);
3739 X(16);
3740 X(18);
3741 X(1a);
3742 X(1e);
3743 X(24);
3744 X(26);
3745 X(2a);
3746 X(2c);
3747 X(2e);
3748 X(30);
3749 X(32);
3750 X(34);
3752 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3753 pBlk = (char*)pBlk + pBlkEntry[order].len;
3756 if(i != pTypeLibImpl->TypeInfoCount) {
3757 FIXME("Somehow processed %d TypeInfos\n", i);
3758 return NULL;
3761 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3762 return (ITypeLib2*)pTypeLibImpl;
3765 /* ITypeLib::QueryInterface
3767 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3768 ITypeLib2 * iface,
3769 REFIID riid,
3770 VOID **ppvObject)
3772 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3774 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3776 *ppvObject=NULL;
3777 if(IsEqualIID(riid, &IID_IUnknown) ||
3778 IsEqualIID(riid,&IID_ITypeLib)||
3779 IsEqualIID(riid,&IID_ITypeLib2))
3781 *ppvObject = This;
3784 if(*ppvObject)
3786 ITypeLib2_AddRef(iface);
3787 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3788 return S_OK;
3790 TRACE("-- Interface: E_NOINTERFACE\n");
3791 return E_NOINTERFACE;
3794 /* ITypeLib::AddRef
3796 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3798 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3799 ULONG ref = InterlockedIncrement(&This->ref);
3801 TRACE("(%p)->ref was %u\n",This, ref - 1);
3803 return ref;
3806 /* ITypeLib::Release
3808 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3810 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3811 ULONG ref = InterlockedDecrement(&This->ref);
3813 TRACE("(%p)->(%u)\n",This, ref);
3815 if (!ref)
3817 TLBImpLib *pImpLib, *pImpLibNext;
3818 TLBCustData *pCustData, *pCustDataNext;
3819 TLBRefType *ref_type;
3820 void *cursor2;
3821 int i;
3823 /* remove cache entry */
3824 if(This->path)
3826 TRACE("removing from cache list\n");
3827 EnterCriticalSection(&cache_section);
3828 if (This->next) This->next->prev = This->prev;
3829 if (This->prev) This->prev->next = This->next;
3830 else tlb_cache_first = This->next;
3831 LeaveCriticalSection(&cache_section);
3832 HeapFree(GetProcessHeap(), 0, This->path);
3834 TRACE(" destroying ITypeLib(%p)\n",This);
3836 if (This->Name)
3838 SysFreeString(This->Name);
3839 This->Name = NULL;
3842 if (This->DocString)
3844 SysFreeString(This->DocString);
3845 This->DocString = NULL;
3848 if (This->HelpFile)
3850 SysFreeString(This->HelpFile);
3851 This->HelpFile = NULL;
3854 if (This->HelpStringDll)
3856 SysFreeString(This->HelpStringDll);
3857 This->HelpStringDll = NULL;
3860 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
3862 VariantClear(&pCustData->data);
3864 pCustDataNext = pCustData->next;
3865 TLB_Free(pCustData);
3868 for (i = 0; i < This->ctTypeDesc; i++)
3869 if (This->pTypeDesc[i].vt == VT_CARRAY)
3870 TLB_Free(This->pTypeDesc[i].u.lpadesc);
3872 TLB_Free(This->pTypeDesc);
3874 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
3876 if (pImpLib->pImpTypeLib)
3877 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
3878 SysFreeString(pImpLib->name);
3880 pImpLibNext = pImpLib->next;
3881 TLB_Free(pImpLib);
3884 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
3886 list_remove(&ref_type->entry);
3887 TLB_Free(ref_type);
3890 if (This->pTypeInfo) /* can be NULL */
3891 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3892 HeapFree(GetProcessHeap(),0,This);
3893 return 0;
3896 return ref;
3899 /* ITypeLib::GetTypeInfoCount
3901 * Returns the number of type descriptions in the type library
3903 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3905 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3906 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3907 return This->TypeInfoCount;
3910 /* ITypeLib::GetTypeInfo
3912 * retrieves the specified type description in the library.
3914 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3915 ITypeLib2 *iface,
3916 UINT index,
3917 ITypeInfo **ppTInfo)
3919 int i;
3921 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3922 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3924 TRACE("(%p)->(index=%d)\n", This, index);
3926 if (!ppTInfo) return E_INVALIDARG;
3928 /* search element n in list */
3929 for(i=0; i < index; i++)
3931 pTypeInfo = pTypeInfo->next;
3932 if (!pTypeInfo)
3934 TRACE("-- element not found\n");
3935 return TYPE_E_ELEMENTNOTFOUND;
3939 *ppTInfo = (ITypeInfo *) pTypeInfo;
3941 ITypeInfo_AddRef(*ppTInfo);
3942 TRACE("-- found (%p)\n",*ppTInfo);
3943 return S_OK;
3947 /* ITypeLibs::GetTypeInfoType
3949 * Retrieves the type of a type description.
3951 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3952 ITypeLib2 *iface,
3953 UINT index,
3954 TYPEKIND *pTKind)
3956 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3957 int i;
3958 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3960 if (ITypeLib2_fnGetTypeInfoCount(iface) < index + 1)
3961 return TYPE_E_ELEMENTNOTFOUND;
3963 TRACE("(%p) index %d\n", This, index);
3965 if(!pTKind) return E_INVALIDARG;
3967 /* search element n in list */
3968 for(i=0; i < index; i++)
3970 if(!pTInfo)
3972 TRACE("-- element not found\n");
3973 return TYPE_E_ELEMENTNOTFOUND;
3975 pTInfo = pTInfo->next;
3978 *pTKind = pTInfo->TypeAttr.typekind;
3979 TRACE("-- found Type (%d)\n", *pTKind);
3980 return S_OK;
3983 /* ITypeLib::GetTypeInfoOfGuid
3985 * Retrieves the type description that corresponds to the specified GUID.
3988 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3989 ITypeLib2 *iface,
3990 REFGUID guid,
3991 ITypeInfo **ppTInfo)
3993 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3994 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3996 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3998 if (!pTypeInfo)
4000 WARN("-- element not found\n");
4001 return TYPE_E_ELEMENTNOTFOUND;
4004 /* search linked list for guid */
4005 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
4007 pTypeInfo = pTypeInfo->next;
4009 if (!pTypeInfo)
4011 /* end of list reached */
4012 WARN("-- element not found\n");
4013 return TYPE_E_ELEMENTNOTFOUND;
4017 TRACE("-- found (%p, %s)\n",
4018 pTypeInfo,
4019 debugstr_w(pTypeInfo->Name));
4021 *ppTInfo = (ITypeInfo*)pTypeInfo;
4022 ITypeInfo_AddRef(*ppTInfo);
4023 return S_OK;
4026 /* ITypeLib::GetLibAttr
4028 * Retrieves the structure that contains the library's attributes.
4031 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4032 ITypeLib2 *iface,
4033 LPTLIBATTR *ppTLibAttr)
4035 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4036 TRACE("(%p)\n",This);
4037 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
4038 **ppTLibAttr = This->LibAttr;
4039 return S_OK;
4042 /* ITypeLib::GetTypeComp
4044 * Enables a client compiler to bind to a library's types, variables,
4045 * constants, and global functions.
4048 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4049 ITypeLib2 *iface,
4050 ITypeComp **ppTComp)
4052 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4054 TRACE("(%p)->(%p)\n",This,ppTComp);
4055 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4056 ITypeComp_AddRef(*ppTComp);
4058 return S_OK;
4061 /* ITypeLib::GetDocumentation
4063 * Retrieves the library's documentation string, the complete Help file name
4064 * and path, and the context identifier for the library Help topic in the Help
4065 * file.
4067 * On a successful return all non-null BSTR pointers will have been set,
4068 * possibly to NULL.
4070 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4071 ITypeLib2 *iface,
4072 INT index,
4073 BSTR *pBstrName,
4074 BSTR *pBstrDocString,
4075 DWORD *pdwHelpContext,
4076 BSTR *pBstrHelpFile)
4078 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4080 HRESULT result = E_INVALIDARG;
4082 ITypeInfo *pTInfo;
4085 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4086 This, index,
4087 pBstrName, pBstrDocString,
4088 pdwHelpContext, pBstrHelpFile);
4090 if(index<0)
4092 /* documentation for the typelib */
4093 if(pBstrName)
4095 if (This->Name)
4097 if(!(*pBstrName = SysAllocString(This->Name)))
4098 goto memerr1;
4100 else
4101 *pBstrName = NULL;
4103 if(pBstrDocString)
4105 if (This->DocString)
4107 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4108 goto memerr2;
4110 else if (This->Name)
4112 if(!(*pBstrDocString = SysAllocString(This->Name)))
4113 goto memerr2;
4115 else
4116 *pBstrDocString = NULL;
4118 if(pdwHelpContext)
4120 *pdwHelpContext = This->dwHelpContext;
4122 if(pBstrHelpFile)
4124 if (This->HelpFile)
4126 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4127 goto memerr3;
4129 else
4130 *pBstrHelpFile = NULL;
4133 result = S_OK;
4135 else
4137 /* for a typeinfo */
4138 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4140 if(SUCCEEDED(result))
4142 result = ITypeInfo_GetDocumentation(pTInfo,
4143 MEMBERID_NIL,
4144 pBstrName,
4145 pBstrDocString,
4146 pdwHelpContext, pBstrHelpFile);
4148 ITypeInfo_Release(pTInfo);
4151 return result;
4152 memerr3:
4153 if (pBstrDocString) SysFreeString (*pBstrDocString);
4154 memerr2:
4155 if (pBstrName) SysFreeString (*pBstrName);
4156 memerr1:
4157 return STG_E_INSUFFICIENTMEMORY;
4160 /* ITypeLib::IsName
4162 * Indicates whether a passed-in string contains the name of a type or member
4163 * described in the library.
4166 static HRESULT WINAPI ITypeLib2_fnIsName(
4167 ITypeLib2 *iface,
4168 LPOLESTR szNameBuf,
4169 ULONG lHashVal,
4170 BOOL *pfName)
4172 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4173 ITypeInfoImpl *pTInfo;
4174 TLBFuncDesc *pFInfo;
4175 TLBVarDesc *pVInfo;
4176 int i;
4177 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4179 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4180 pfName);
4182 *pfName=TRUE;
4183 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
4184 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4185 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4186 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4187 for(i=0;i<pFInfo->funcdesc.cParams;i++)
4188 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
4189 goto ITypeLib2_fnIsName_exit;
4191 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4192 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4195 *pfName=FALSE;
4197 ITypeLib2_fnIsName_exit:
4198 TRACE("(%p)slow! search for %s: %s found!\n", This,
4199 debugstr_w(szNameBuf), *pfName?"NOT":"");
4201 return S_OK;
4204 /* ITypeLib::FindName
4206 * Finds occurrences of a type description in a type library. This may be used
4207 * to quickly verify that a name exists in a type library.
4210 static HRESULT WINAPI ITypeLib2_fnFindName(
4211 ITypeLib2 *iface,
4212 LPOLESTR szNameBuf,
4213 ULONG lHashVal,
4214 ITypeInfo **ppTInfo,
4215 MEMBERID *rgMemId,
4216 UINT16 *pcFound)
4218 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4219 ITypeInfoImpl *pTInfo;
4220 TLBFuncDesc *pFInfo;
4221 TLBVarDesc *pVInfo;
4222 int i,j = 0;
4223 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4225 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
4226 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4227 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4228 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4229 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
4230 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
4231 goto ITypeLib2_fnFindName_exit;
4234 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4235 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4236 continue;
4237 ITypeLib2_fnFindName_exit:
4238 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4239 ppTInfo[j]=(LPTYPEINFO)pTInfo;
4240 j++;
4242 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4243 This, *pcFound, debugstr_w(szNameBuf), j);
4245 *pcFound=j;
4247 return S_OK;
4250 /* ITypeLib::ReleaseTLibAttr
4252 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4255 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4256 ITypeLib2 *iface,
4257 TLIBATTR *pTLibAttr)
4259 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4260 TRACE("freeing (%p)\n",This);
4261 HeapFree(GetProcessHeap(),0,pTLibAttr);
4265 /* ITypeLib2::GetCustData
4267 * gets the custom data
4269 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4270 ITypeLib2 * iface,
4271 REFGUID guid,
4272 VARIANT *pVarVal)
4274 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4275 TLBCustData *pCData;
4277 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4279 if( IsEqualIID(guid, &pCData->guid)) break;
4282 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4284 if(pCData)
4286 VariantInit( pVarVal);
4287 VariantCopy( pVarVal, &pCData->data);
4288 return S_OK;
4290 return E_INVALIDARG; /* FIXME: correct? */
4293 /* ITypeLib2::GetLibStatistics
4295 * Returns statistics about a type library that are required for efficient
4296 * sizing of hash tables.
4299 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4300 ITypeLib2 * iface,
4301 ULONG *pcUniqueNames,
4302 ULONG *pcchUniqueNames)
4304 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4306 FIXME("(%p): stub!\n", This);
4308 if(pcUniqueNames) *pcUniqueNames=1;
4309 if(pcchUniqueNames) *pcchUniqueNames=1;
4310 return S_OK;
4313 /* ITypeLib2::GetDocumentation2
4315 * Retrieves the library's documentation string, the complete Help file name
4316 * and path, the localization context to use, and the context ID for the
4317 * library Help topic in the Help file.
4320 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4321 ITypeLib2 * iface,
4322 INT index,
4323 LCID lcid,
4324 BSTR *pbstrHelpString,
4325 DWORD *pdwHelpStringContext,
4326 BSTR *pbstrHelpStringDll)
4328 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4329 HRESULT result;
4330 ITypeInfo *pTInfo;
4332 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4334 /* the help string should be obtained from the helpstringdll,
4335 * using the _DLLGetDocumentation function, based on the supplied
4336 * lcid. Nice to do sometime...
4338 if(index<0)
4340 /* documentation for the typelib */
4341 if(pbstrHelpString)
4342 *pbstrHelpString=SysAllocString(This->DocString);
4343 if(pdwHelpStringContext)
4344 *pdwHelpStringContext=This->dwHelpContext;
4345 if(pbstrHelpStringDll)
4346 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4348 result = S_OK;
4350 else
4352 /* for a typeinfo */
4353 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4355 if(SUCCEEDED(result))
4357 ITypeInfo2 * pTInfo2;
4358 result = ITypeInfo_QueryInterface(pTInfo,
4359 &IID_ITypeInfo2,
4360 (LPVOID*) &pTInfo2);
4362 if(SUCCEEDED(result))
4364 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4365 MEMBERID_NIL,
4366 lcid,
4367 pbstrHelpString,
4368 pdwHelpStringContext,
4369 pbstrHelpStringDll);
4371 ITypeInfo2_Release(pTInfo2);
4374 ITypeInfo_Release(pTInfo);
4377 return result;
4380 /* ITypeLib2::GetAllCustData
4382 * Gets all custom data items for the library.
4385 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4386 ITypeLib2 * iface,
4387 CUSTDATA *pCustData)
4389 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4390 TLBCustData *pCData;
4391 int i;
4392 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4393 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4394 if(pCustData->prgCustData ){
4395 pCustData->cCustData=This->ctCustData;
4396 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4397 pCustData->prgCustData[i].guid=pCData->guid;
4398 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4400 }else{
4401 ERR(" OUT OF MEMORY!\n");
4402 return E_OUTOFMEMORY;
4404 return S_OK;
4407 static const ITypeLib2Vtbl tlbvt = {
4408 ITypeLib2_fnQueryInterface,
4409 ITypeLib2_fnAddRef,
4410 ITypeLib2_fnRelease,
4411 ITypeLib2_fnGetTypeInfoCount,
4412 ITypeLib2_fnGetTypeInfo,
4413 ITypeLib2_fnGetTypeInfoType,
4414 ITypeLib2_fnGetTypeInfoOfGuid,
4415 ITypeLib2_fnGetLibAttr,
4416 ITypeLib2_fnGetTypeComp,
4417 ITypeLib2_fnGetDocumentation,
4418 ITypeLib2_fnIsName,
4419 ITypeLib2_fnFindName,
4420 ITypeLib2_fnReleaseTLibAttr,
4422 ITypeLib2_fnGetCustData,
4423 ITypeLib2_fnGetLibStatistics,
4424 ITypeLib2_fnGetDocumentation2,
4425 ITypeLib2_fnGetAllCustData
4429 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4431 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4433 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4436 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4438 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4440 return ITypeLib2_AddRef((ITypeLib2 *)This);
4443 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4445 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4447 return ITypeLib2_Release((ITypeLib2 *)This);
4450 static HRESULT WINAPI ITypeLibComp_fnBind(
4451 ITypeComp * iface,
4452 OLECHAR * szName,
4453 ULONG lHash,
4454 WORD wFlags,
4455 ITypeInfo ** ppTInfo,
4456 DESCKIND * pDescKind,
4457 BINDPTR * pBindPtr)
4459 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4460 ITypeInfoImpl *pTypeInfo;
4462 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4464 *pDescKind = DESCKIND_NONE;
4465 pBindPtr->lptcomp = NULL;
4466 *ppTInfo = NULL;
4468 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4470 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4472 /* FIXME: check wFlags here? */
4473 /* FIXME: we should use a hash table to look this info up using lHash
4474 * instead of an O(n) search */
4475 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4476 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4478 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4480 *pDescKind = DESCKIND_TYPECOMP;
4481 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4482 ITypeComp_AddRef(pBindPtr->lptcomp);
4483 TRACE("module or enum: %s\n", debugstr_w(szName));
4484 return S_OK;
4488 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4489 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4491 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4492 HRESULT hr;
4494 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4495 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4497 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4498 return S_OK;
4502 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4503 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4505 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4506 HRESULT hr;
4507 ITypeInfo *subtypeinfo;
4508 BINDPTR subbindptr;
4509 DESCKIND subdesckind;
4511 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4512 &subtypeinfo, &subdesckind, &subbindptr);
4513 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4515 TYPEDESC tdesc_appobject =
4518 (TYPEDESC *)pTypeInfo->hreftype
4520 VT_USERDEFINED
4522 const VARDESC vardesc_appobject =
4524 -2, /* memid */
4525 NULL, /* lpstrSchema */
4527 0 /* oInst */
4530 /* ELEMDESC */
4532 /* TYPEDESC */
4534 &tdesc_appobject
4536 VT_PTR
4539 0, /* wVarFlags */
4540 VAR_STATIC /* varkind */
4543 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4545 /* cleanup things filled in by Bind call so we can put our
4546 * application object data in there instead */
4547 switch (subdesckind)
4549 case DESCKIND_FUNCDESC:
4550 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4551 break;
4552 case DESCKIND_VARDESC:
4553 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4554 break;
4555 default:
4556 break;
4558 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4560 if (pTypeInfo->hreftype == -1)
4561 FIXME("no hreftype for interface %p\n", pTypeInfo);
4563 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4564 if (FAILED(hr))
4565 return hr;
4567 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4568 *ppTInfo = (ITypeInfo *)pTypeInfo;
4569 ITypeInfo_AddRef(*ppTInfo);
4570 return S_OK;
4575 TRACE("name not found %s\n", debugstr_w(szName));
4576 return S_OK;
4579 static HRESULT WINAPI ITypeLibComp_fnBindType(
4580 ITypeComp * iface,
4581 OLECHAR * szName,
4582 ULONG lHash,
4583 ITypeInfo ** ppTInfo,
4584 ITypeComp ** ppTComp)
4586 FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4587 return E_NOTIMPL;
4590 static const ITypeCompVtbl tlbtcvt =
4593 ITypeLibComp_fnQueryInterface,
4594 ITypeLibComp_fnAddRef,
4595 ITypeLibComp_fnRelease,
4597 ITypeLibComp_fnBind,
4598 ITypeLibComp_fnBindType
4601 /*================== ITypeInfo(2) Methods ===================================*/
4602 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4604 ITypeInfoImpl * pTypeInfoImpl;
4606 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4607 if (pTypeInfoImpl)
4609 pTypeInfoImpl->lpVtbl = &tinfvt;
4610 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4611 pTypeInfoImpl->ref=1;
4612 pTypeInfoImpl->hreftype = -1;
4613 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4614 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4616 TRACE("(%p)\n", pTypeInfoImpl);
4617 return (ITypeInfo2*) pTypeInfoImpl;
4620 /* ITypeInfo::QueryInterface
4622 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4623 ITypeInfo2 *iface,
4624 REFIID riid,
4625 VOID **ppvObject)
4627 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4629 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4631 *ppvObject=NULL;
4632 if(IsEqualIID(riid, &IID_IUnknown) ||
4633 IsEqualIID(riid,&IID_ITypeInfo)||
4634 IsEqualIID(riid,&IID_ITypeInfo2))
4635 *ppvObject = This;
4637 if(*ppvObject){
4638 ITypeInfo_AddRef(iface);
4639 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4640 return S_OK;
4642 TRACE("-- Interface: E_NOINTERFACE\n");
4643 return E_NOINTERFACE;
4646 /* ITypeInfo::AddRef
4648 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4650 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4651 ULONG ref = InterlockedIncrement(&This->ref);
4653 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4655 TRACE("(%p)->ref is %u\n",This, ref);
4656 return ref;
4659 /* ITypeInfo::Release
4661 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4663 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4664 ULONG ref = InterlockedDecrement(&This->ref);
4666 TRACE("(%p)->(%u)\n",This, ref);
4668 if (ref) {
4669 /* We don't release ITypeLib when ref=0 because
4670 it means that function is called by ITypeLib2_Release */
4671 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4672 } else {
4673 TLBFuncDesc *pFInfo, *pFInfoNext;
4674 TLBVarDesc *pVInfo, *pVInfoNext;
4675 TLBImplType *pImpl, *pImplNext;
4677 TRACE("destroying ITypeInfo(%p)\n",This);
4679 if (This->no_free_data)
4680 goto finish_free;
4682 if (This->Name)
4684 SysFreeString(This->Name);
4685 This->Name = 0;
4688 if (This->DocString)
4690 SysFreeString(This->DocString);
4691 This->DocString = 0;
4694 if (This->DllName)
4696 SysFreeString(This->DllName);
4697 This->DllName = 0;
4700 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4702 UINT i;
4703 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4705 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4706 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4708 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4709 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4711 SysFreeString(pFInfo->pParamDesc[i].Name);
4713 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4714 TLB_Free(pFInfo->pParamDesc);
4715 TLB_FreeCustData(pFInfo->pCustData);
4716 if (HIWORD(pFInfo->Entry) != 0 && pFInfo->Entry != (BSTR)-1)
4717 SysFreeString(pFInfo->Entry);
4718 SysFreeString(pFInfo->HelpString);
4719 SysFreeString(pFInfo->Name);
4721 pFInfoNext = pFInfo->next;
4722 TLB_Free(pFInfo);
4724 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
4726 if (pVInfo->vardesc.varkind == VAR_CONST)
4728 VariantClear(pVInfo->vardesc.u.lpvarValue);
4729 TLB_Free(pVInfo->vardesc.u.lpvarValue);
4731 TLB_FreeCustData(pVInfo->pCustData);
4732 SysFreeString(pVInfo->Name);
4733 pVInfoNext = pVInfo->next;
4734 TLB_Free(pVInfo);
4736 for(pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
4738 TLB_FreeCustData(pImpl->pCustData);
4739 pImplNext = pImpl->next;
4740 TLB_Free(pImpl);
4742 TLB_FreeCustData(This->pCustData);
4744 finish_free:
4745 if (This->next)
4747 ITypeInfo_Release((ITypeInfo*)This->next);
4750 HeapFree(GetProcessHeap(),0,This);
4751 return 0;
4753 return ref;
4756 /* ITypeInfo::GetTypeAttr
4758 * Retrieves a TYPEATTR structure that contains the attributes of the type
4759 * description.
4762 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4763 LPTYPEATTR *ppTypeAttr)
4765 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4766 SIZE_T size;
4768 TRACE("(%p)\n",This);
4770 size = sizeof(**ppTypeAttr);
4771 if (This->TypeAttr.typekind == TKIND_ALIAS)
4772 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4774 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4775 if (!*ppTypeAttr)
4776 return E_OUTOFMEMORY;
4778 **ppTypeAttr = This->TypeAttr;
4780 if (This->TypeAttr.typekind == TKIND_ALIAS)
4781 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4782 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4784 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4785 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4786 funcs */
4787 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4788 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4790 return S_OK;
4793 /* ITypeInfo::GetTypeComp
4795 * Retrieves the ITypeComp interface for the type description, which enables a
4796 * client compiler to bind to the type description's members.
4799 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4800 ITypeComp * *ppTComp)
4802 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4804 TRACE("(%p)->(%p)\n", This, ppTComp);
4806 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4807 ITypeComp_AddRef(*ppTComp);
4808 return S_OK;
4811 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4813 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4814 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4815 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4816 return size;
4819 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4821 *dest = *src;
4822 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4823 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4825 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4826 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4827 *buffer += sizeof(PARAMDESCEX);
4828 *pparamdescex_dest = *pparamdescex_src;
4829 VariantInit(&pparamdescex_dest->varDefaultValue);
4830 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4831 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4833 else
4834 dest->u.paramdesc.pparamdescex = NULL;
4835 return S_OK;
4838 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4840 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4841 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4844 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4846 FUNCDESC *dest;
4847 char *buffer;
4848 SIZE_T size = sizeof(*src);
4849 SHORT i;
4850 HRESULT hr;
4852 size += sizeof(*src->lprgscode) * src->cScodes;
4853 size += TLB_SizeElemDesc(&src->elemdescFunc);
4854 for (i = 0; i < src->cParams; i++)
4856 size += sizeof(ELEMDESC);
4857 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4860 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4861 if (!dest) return E_OUTOFMEMORY;
4863 *dest = *src;
4864 if (dispinterface) /* overwrite funckind */
4865 dest->funckind = FUNC_DISPATCH;
4866 buffer = (char *)(dest + 1);
4868 dest->lprgscode = (SCODE *)buffer;
4869 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4870 buffer += sizeof(*src->lprgscode) * src->cScodes;
4872 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4873 if (FAILED(hr))
4875 SysFreeString((BSTR)dest);
4876 return hr;
4879 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4880 buffer += sizeof(ELEMDESC) * src->cParams;
4881 for (i = 0; i < src->cParams; i++)
4883 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4884 if (FAILED(hr))
4885 break;
4887 if (FAILED(hr))
4889 /* undo the above actions */
4890 for (i = i - 1; i >= 0; i--)
4891 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4892 TLB_FreeElemDesc(&dest->elemdescFunc);
4893 SysFreeString((BSTR)dest);
4894 return hr;
4897 /* special treatment for dispinterfaces: this makes functions appear
4898 * to return their [retval] value when it is really returning an
4899 * HRESULT */
4900 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4902 if (dest->cParams &&
4903 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4905 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4906 if (elemdesc->tdesc.vt != VT_PTR)
4908 ERR("elemdesc should have started with VT_PTR instead of:\n");
4909 if (ERR_ON(ole))
4910 dump_ELEMDESC(elemdesc);
4911 return E_UNEXPECTED;
4914 /* copy last parameter to the return value. we are using a flat
4915 * buffer so there is no danger of leaking memory in
4916 * elemdescFunc */
4917 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4919 /* remove the last parameter */
4920 dest->cParams--;
4922 else
4923 /* otherwise this function is made to appear to have no return
4924 * value */
4925 dest->elemdescFunc.tdesc.vt = VT_VOID;
4929 *dest_ptr = dest;
4930 return S_OK;
4933 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4935 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4936 const TLBFuncDesc *pFDesc;
4937 int i;
4939 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4942 if (pFDesc)
4944 *ppFuncDesc = &pFDesc->funcdesc;
4945 return S_OK;
4948 return TYPE_E_ELEMENTNOTFOUND;
4951 /* internal function to make the inherited interfaces' methods appear
4952 * part of the interface */
4953 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
4954 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
4956 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4957 HRESULT hr;
4958 UINT implemented_funcs = 0;
4960 if (funcs)
4961 *funcs = 0;
4962 else
4963 *hrefoffset = DISPATCH_HREF_OFFSET;
4965 if(This->impltypelist)
4967 ITypeInfo *pSubTypeInfo;
4968 UINT sub_funcs;
4970 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
4971 if (FAILED(hr))
4972 return hr;
4974 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
4975 index,
4976 ppFuncDesc,
4977 &sub_funcs, hrefoffset);
4978 implemented_funcs += sub_funcs;
4979 ITypeInfo_Release(pSubTypeInfo);
4980 if (SUCCEEDED(hr))
4981 return hr;
4982 *hrefoffset += DISPATCH_HREF_OFFSET;
4985 if (funcs)
4986 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
4987 else
4988 *hrefoffset = 0;
4990 if (index < implemented_funcs)
4991 return E_INVALIDARG;
4992 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
4993 ppFuncDesc);
4996 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
4998 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
4999 while (TRUE)
5001 switch (pTypeDesc->vt)
5003 case VT_USERDEFINED:
5004 pTypeDesc->u.hreftype += hrefoffset;
5005 return;
5006 case VT_PTR:
5007 case VT_SAFEARRAY:
5008 pTypeDesc = pTypeDesc->u.lptdesc;
5009 break;
5010 case VT_CARRAY:
5011 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5012 break;
5013 default:
5014 return;
5019 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5021 SHORT i;
5022 for (i = 0; i < pFuncDesc->cParams; i++)
5023 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5024 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5027 /* ITypeInfo::GetFuncDesc
5029 * Retrieves the FUNCDESC structure that contains information about a
5030 * specified function.
5033 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5034 LPFUNCDESC *ppFuncDesc)
5036 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5037 const FUNCDESC *internal_funcdesc;
5038 HRESULT hr;
5039 UINT hrefoffset = 0;
5041 TRACE("(%p) index %d\n", This, index);
5043 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5044 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5045 &internal_funcdesc, NULL,
5046 &hrefoffset);
5047 else
5048 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5049 &internal_funcdesc);
5050 if (FAILED(hr))
5052 WARN("description for function %d not found\n", index);
5053 return hr;
5056 hr = TLB_AllocAndInitFuncDesc(
5057 internal_funcdesc,
5058 ppFuncDesc,
5059 This->TypeAttr.typekind == TKIND_DISPATCH);
5061 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5062 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5064 TRACE("-- 0x%08x\n", hr);
5065 return hr;
5068 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5070 VARDESC *dest;
5071 char *buffer;
5072 SIZE_T size = sizeof(*src);
5073 HRESULT hr;
5075 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5076 if (src->varkind == VAR_CONST)
5077 size += sizeof(VARIANT);
5078 size += TLB_SizeElemDesc(&src->elemdescVar);
5080 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5081 if (!dest) return E_OUTOFMEMORY;
5083 *dest = *src;
5084 buffer = (char *)(dest + 1);
5085 if (src->lpstrSchema)
5087 int len;
5088 dest->lpstrSchema = (LPOLESTR)buffer;
5089 len = strlenW(src->lpstrSchema);
5090 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5091 buffer += (len + 1) * sizeof(WCHAR);
5094 if (src->varkind == VAR_CONST)
5096 HRESULT hr;
5098 dest->u.lpvarValue = (VARIANT *)buffer;
5099 *dest->u.lpvarValue = *src->u.lpvarValue;
5100 buffer += sizeof(VARIANT);
5101 VariantInit(dest->u.lpvarValue);
5102 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5103 if (FAILED(hr))
5105 SysFreeString((BSTR)dest_ptr);
5106 return hr;
5109 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5110 if (FAILED(hr))
5112 if (src->varkind == VAR_CONST)
5113 VariantClear(dest->u.lpvarValue);
5114 SysFreeString((BSTR)dest);
5115 return hr;
5117 *dest_ptr = dest;
5118 return S_OK;
5121 /* ITypeInfo::GetVarDesc
5123 * Retrieves a VARDESC structure that describes the specified variable.
5126 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5127 LPVARDESC *ppVarDesc)
5129 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5130 int i;
5131 const TLBVarDesc *pVDesc;
5133 TRACE("(%p) index %d\n", This, index);
5135 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
5138 if (pVDesc)
5139 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5141 return E_INVALIDARG;
5144 /* ITypeInfo_GetNames
5146 * Retrieves the variable with the specified member ID (or the name of the
5147 * property or method and its parameters) that correspond to the specified
5148 * function ID.
5150 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5151 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5153 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5154 const TLBFuncDesc *pFDesc;
5155 const TLBVarDesc *pVDesc;
5156 int i;
5157 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5158 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
5159 if(pFDesc)
5161 /* function found, now return function and parameter names */
5162 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5164 if(!i)
5165 *rgBstrNames=SysAllocString(pFDesc->Name);
5166 else
5167 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5169 *pcNames=i;
5171 else
5173 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
5174 if(pVDesc)
5176 *rgBstrNames=SysAllocString(pVDesc->Name);
5177 *pcNames=1;
5179 else
5181 if(This->impltypelist &&
5182 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5183 /* recursive search */
5184 ITypeInfo *pTInfo;
5185 HRESULT result;
5186 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5187 &pTInfo);
5188 if(SUCCEEDED(result))
5190 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5191 ITypeInfo_Release(pTInfo);
5192 return result;
5194 WARN("Could not search inherited interface!\n");
5196 else
5198 WARN("no names found\n");
5200 *pcNames=0;
5201 return TYPE_E_ELEMENTNOTFOUND;
5204 return S_OK;
5208 /* ITypeInfo::GetRefTypeOfImplType
5210 * If a type description describes a COM class, it retrieves the type
5211 * description of the implemented interface types. For an interface,
5212 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5213 * if any exist.
5216 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5217 ITypeInfo2 *iface,
5218 UINT index,
5219 HREFTYPE *pRefType)
5221 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5222 int i;
5223 HRESULT hr = S_OK;
5224 const TLBImplType *pImpl = This->impltypelist;
5226 TRACE("(%p) index %d\n", This, index);
5227 if (TRACE_ON(ole)) dump_TypeInfo(This);
5229 if(index==(UINT)-1)
5231 /* only valid on dual interfaces;
5232 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5234 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5236 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
5237 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
5239 *pRefType = -1;
5241 else
5243 hr = TYPE_E_ELEMENTNOTFOUND;
5246 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5248 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5249 *pRefType = This->pTypeLib->dispatch_href;
5251 else
5253 /* get element n from linked list */
5254 for(i=0; pImpl && i<index; i++)
5256 pImpl = pImpl->next;
5259 if (pImpl)
5260 *pRefType = pImpl->hRef;
5261 else
5262 hr = TYPE_E_ELEMENTNOTFOUND;
5265 if(TRACE_ON(ole))
5267 if(SUCCEEDED(hr))
5268 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5269 else
5270 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5273 return hr;
5276 /* ITypeInfo::GetImplTypeFlags
5278 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5279 * or base interface in a type description.
5281 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5282 UINT index, INT *pImplTypeFlags)
5284 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5285 int i;
5286 TLBImplType *pImpl;
5288 TRACE("(%p) index %d\n", This, index);
5289 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5290 i++, pImpl=pImpl->next)
5292 if(i==index && pImpl){
5293 *pImplTypeFlags=pImpl->implflags;
5294 return S_OK;
5296 *pImplTypeFlags=0;
5297 return TYPE_E_ELEMENTNOTFOUND;
5300 /* GetIDsOfNames
5301 * Maps between member names and member IDs, and parameter names and
5302 * parameter IDs.
5304 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5305 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5307 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5308 const TLBFuncDesc *pFDesc;
5309 const TLBVarDesc *pVDesc;
5310 HRESULT ret=S_OK;
5311 int i;
5313 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5314 cNames);
5316 /* init out parameters in case of failure */
5317 for (i = 0; i < cNames; i++)
5318 pMemId[i] = MEMBERID_NIL;
5320 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5321 int j;
5322 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5323 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5324 for(i=1; i < cNames; i++){
5325 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5326 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5327 break;
5328 if( j<pFDesc->funcdesc.cParams)
5329 pMemId[i]=j;
5330 else
5331 ret=DISP_E_UNKNOWNNAME;
5333 TRACE("-- 0x%08x\n", ret);
5334 return ret;
5337 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5338 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5339 if(cNames) *pMemId=pVDesc->vardesc.memid;
5340 return ret;
5343 /* not found, see if it can be found in an inherited interface */
5344 if(This->impltypelist) {
5345 /* recursive search */
5346 ITypeInfo *pTInfo;
5347 ret=ITypeInfo_GetRefTypeInfo(iface,
5348 This->impltypelist->hRef, &pTInfo);
5349 if(SUCCEEDED(ret)){
5350 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5351 ITypeInfo_Release(pTInfo);
5352 return ret;
5354 WARN("Could not search inherited interface!\n");
5355 } else
5356 WARN("no names found\n");
5357 return DISP_E_UNKNOWNNAME;
5360 /* ITypeInfo::Invoke
5362 * Invokes a method, or accesses a property of an object, that implements the
5363 * interface described by the type description.
5365 DWORD
5366 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5367 DWORD res;
5369 if (TRACE_ON(ole)) {
5370 int i;
5371 TRACE("Calling %p(",func);
5372 for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
5373 TRACE(")\n");
5376 switch (callconv) {
5377 case CC_STDCALL:
5379 switch (nrargs) {
5380 case 0:
5381 res = func();
5382 break;
5383 case 1:
5384 res = func(args[0]);
5385 break;
5386 case 2:
5387 res = func(args[0],args[1]);
5388 break;
5389 case 3:
5390 res = func(args[0],args[1],args[2]);
5391 break;
5392 case 4:
5393 res = func(args[0],args[1],args[2],args[3]);
5394 break;
5395 case 5:
5396 res = func(args[0],args[1],args[2],args[3],args[4]);
5397 break;
5398 case 6:
5399 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
5400 break;
5401 case 7:
5402 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
5403 break;
5404 case 8:
5405 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
5406 break;
5407 case 9:
5408 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
5409 break;
5410 case 10:
5411 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
5412 break;
5413 case 11:
5414 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
5415 break;
5416 case 12:
5417 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]);
5418 break;
5419 case 13:
5420 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]);
5421 break;
5422 case 14:
5423 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]);
5424 break;
5425 case 15:
5426 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]);
5427 break;
5428 case 16:
5429 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]);
5430 break;
5431 case 17:
5432 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]);
5433 break;
5434 case 18:
5435 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]);
5436 break;
5437 case 19:
5438 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]);
5439 break;
5440 case 20:
5441 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]);
5442 break;
5443 case 21:
5444 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]);
5445 break;
5446 case 22:
5447 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]);
5448 break;
5449 case 23:
5450 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]);
5451 break;
5452 case 24:
5453 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]);
5454 break;
5455 case 25:
5456 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]);
5457 break;
5458 case 26:
5459 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]);
5460 break;
5461 case 27:
5462 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]);
5463 break;
5464 case 28:
5465 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]);
5466 break;
5467 case 29:
5468 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]);
5469 break;
5470 case 30:
5471 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]);
5472 break;
5473 default:
5474 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
5475 res = -1;
5476 break;
5478 break;
5479 default:
5480 FIXME("unsupported calling convention %d\n",callconv);
5481 res = -1;
5482 break;
5484 TRACE("returns %08x\n",res);
5485 return res;
5488 /* The size of the argument on the stack in DWORD units (in all x86 call
5489 * convetions the arguments on the stack are DWORD-aligned)
5491 int _dispargsize(VARTYPE vt)
5493 switch (vt) {
5494 case VT_I8:
5495 case VT_UI8:
5496 return 8/sizeof(DWORD);
5497 case VT_R8:
5498 return sizeof(double)/sizeof(DWORD);
5499 case VT_DECIMAL:
5500 return (sizeof(DECIMAL)+3)/sizeof(DWORD);
5501 case VT_CY:
5502 return sizeof(CY)/sizeof(DWORD);
5503 case VT_DATE:
5504 return sizeof(DATE)/sizeof(DWORD);
5505 case VT_VARIANT:
5506 return (sizeof(VARIANT)+3)/sizeof(DWORD);
5507 case VT_RECORD:
5508 FIXME("VT_RECORD not implemented\n");
5509 return 1;
5510 default:
5511 return 1;
5515 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5517 HRESULT hr = S_OK;
5518 ITypeInfo *tinfo2 = NULL;
5519 TYPEATTR *tattr = NULL;
5521 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5522 if (hr)
5524 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5525 "hr = 0x%08x\n",
5526 tdesc->u.hreftype, hr);
5527 return hr;
5529 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5530 if (hr)
5532 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5533 ITypeInfo_Release(tinfo2);
5534 return hr;
5537 switch (tattr->typekind)
5539 case TKIND_ENUM:
5540 *vt |= VT_I4;
5541 break;
5543 case TKIND_ALIAS:
5544 tdesc = &tattr->tdescAlias;
5545 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5546 break;
5548 case TKIND_INTERFACE:
5549 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5550 *vt |= VT_DISPATCH;
5551 else
5552 *vt |= VT_UNKNOWN;
5553 break;
5555 case TKIND_DISPATCH:
5556 *vt |= VT_DISPATCH;
5557 break;
5559 case TKIND_COCLASS:
5560 *vt |= VT_DISPATCH;
5561 break;
5563 case TKIND_RECORD:
5564 FIXME("TKIND_RECORD unhandled.\n");
5565 hr = E_NOTIMPL;
5566 break;
5568 case TKIND_UNION:
5569 FIXME("TKIND_UNION unhandled.\n");
5570 hr = E_NOTIMPL;
5571 break;
5573 default:
5574 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5575 hr = E_NOTIMPL;
5576 break;
5578 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5579 ITypeInfo_Release(tinfo2);
5580 return hr;
5583 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5585 HRESULT hr = S_OK;
5587 /* enforce only one level of pointer indirection */
5588 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5590 tdesc = tdesc->u.lptdesc;
5592 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5593 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5594 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5595 if ((tdesc->vt == VT_USERDEFINED) ||
5596 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5598 VARTYPE vt_userdefined = 0;
5599 const TYPEDESC *tdesc_userdefined = tdesc;
5600 if (tdesc->vt == VT_PTR)
5602 vt_userdefined = VT_BYREF;
5603 tdesc_userdefined = tdesc->u.lptdesc;
5605 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5606 if ((hr == S_OK) &&
5607 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5608 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5610 *vt |= vt_userdefined;
5611 return S_OK;
5614 *vt = VT_BYREF;
5617 switch (tdesc->vt)
5619 case VT_HRESULT:
5620 *vt |= VT_ERROR;
5621 break;
5622 case VT_USERDEFINED:
5623 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5624 break;
5625 case VT_VOID:
5626 case VT_CARRAY:
5627 case VT_PTR:
5628 case VT_LPSTR:
5629 case VT_LPWSTR:
5630 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5631 hr = DISP_E_BADVARTYPE;
5632 break;
5633 case VT_SAFEARRAY:
5634 *vt |= VT_ARRAY;
5635 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5636 break;
5637 default:
5638 *vt |= tdesc->vt;
5639 break;
5641 return hr;
5644 /***********************************************************************
5645 * DispCallFunc (OLEAUT32.@)
5647 * Invokes a function of the specified calling convention, passing the
5648 * specified arguments and returns the result.
5650 * PARAMS
5651 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5652 * oVft [I] The offset in the vtable. See notes.
5653 * cc [I] Calling convention of the function to call.
5654 * vtReturn [I] The return type of the function.
5655 * cActuals [I] Number of parameters.
5656 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5657 * prgpvarg [I] The arguments to pass.
5658 * pvargResult [O] The return value of the function. Can be NULL.
5660 * RETURNS
5661 * Success: S_OK.
5662 * Failure: HRESULT code.
5664 * NOTES
5665 * The HRESULT return value of this function is not affected by the return
5666 * value of the user supplied function, which is returned in pvargResult.
5668 * If pvInstance is NULL then a non-object function is to be called and oVft
5669 * is the address of the function to call.
5671 * The cc parameter can be one of the following values:
5672 *|CC_FASTCALL
5673 *|CC_CDECL
5674 *|CC_PASCAL
5675 *|CC_STDCALL
5676 *|CC_FPFASTCALL
5677 *|CC_SYSCALL
5678 *|CC_MPWCDECL
5679 *|CC_MPWPASCAL
5682 HRESULT WINAPI
5683 DispCallFunc(
5684 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5685 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5687 int i, argsize, argspos;
5688 DWORD *args;
5689 HRESULT hres;
5691 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5692 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5693 pvargResult, V_VT(pvargResult));
5695 argsize = 0;
5696 if (pvInstance)
5697 argsize++; /* for This pointer */
5699 for (i=0;i<cActuals;i++)
5701 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_dispargsize(prgvt[i]));
5702 dump_Variant(prgpvarg[i]);
5703 argsize += _dispargsize(prgvt[i]);
5705 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5707 argspos = 0;
5708 if (pvInstance)
5710 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5711 argspos++;
5714 for (i=0;i<cActuals;i++)
5716 VARIANT *arg = prgpvarg[i];
5717 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5718 if (prgvt[i] == VT_VARIANT)
5719 memcpy(&args[argspos], arg, _dispargsize(prgvt[i]) * sizeof(DWORD));
5720 else
5721 memcpy(&args[argspos], &V_NONE(arg), _dispargsize(prgvt[i]) * sizeof(DWORD));
5722 argspos += _dispargsize(prgvt[i]);
5725 if (pvInstance)
5727 FARPROC *vtable = *(FARPROC**)pvInstance;
5728 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5730 else
5731 /* if we aren't invoking an object then the function pointer is stored
5732 * in oVft */
5733 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5735 if (pvargResult && (vtReturn != VT_EMPTY))
5737 TRACE("Method returned 0x%08x\n",hres);
5738 V_VT(pvargResult) = vtReturn;
5739 V_UI4(pvargResult) = hres;
5742 HeapFree(GetProcessHeap(),0,args);
5743 return S_OK;
5746 #define INVBUF_ELEMENT_SIZE \
5747 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5748 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5749 ((VARIANTARG *)(buffer))
5750 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5751 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5752 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5753 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5754 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5755 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5757 static HRESULT WINAPI ITypeInfo_fnInvoke(
5758 ITypeInfo2 *iface,
5759 VOID *pIUnk,
5760 MEMBERID memid,
5761 UINT16 wFlags,
5762 DISPPARAMS *pDispParams,
5763 VARIANT *pVarResult,
5764 EXCEPINFO *pExcepInfo,
5765 UINT *pArgErr)
5767 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5768 int i;
5769 unsigned int var_index;
5770 TYPEKIND type_kind;
5771 HRESULT hres;
5772 const TLBFuncDesc *pFuncInfo;
5774 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
5775 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5778 if (!pDispParams)
5780 ERR("NULL pDispParams not allowed\n");
5781 return E_INVALIDARG;
5784 dump_DispParms(pDispParams);
5786 if (pDispParams->cNamedArgs > pDispParams->cArgs)
5788 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
5789 pDispParams->cNamedArgs, pDispParams->cArgs);
5790 return E_INVALIDARG;
5793 /* we do this instead of using GetFuncDesc since it will return a fake
5794 * FUNCDESC for dispinterfaces and we want the real function description */
5795 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5796 if ((memid == pFuncInfo->funcdesc.memid) &&
5797 (wFlags & pFuncInfo->funcdesc.invkind))
5798 break;
5800 if (pFuncInfo) {
5801 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5803 if (TRACE_ON(ole))
5805 TRACE("invoking:\n");
5806 dump_TLBFuncDescOne(pFuncInfo);
5809 switch (func_desc->funckind) {
5810 case FUNC_PUREVIRTUAL:
5811 case FUNC_VIRTUAL: {
5812 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
5813 VARIANT varresult;
5814 VARIANT retval; /* pointer for storing byref retvals in */
5815 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
5816 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
5817 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
5818 UINT cNamedArgs = pDispParams->cNamedArgs;
5819 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
5821 hres = S_OK;
5823 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
5825 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
5827 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
5828 hres = DISP_E_PARAMNOTFOUND;
5829 goto func_fail;
5831 /* ignore the DISPID_PROPERTYPUT named argument from now on */
5832 cNamedArgs--;
5833 rgdispidNamedArgs++;
5836 if (func_desc->cParamsOpt < 0 && cNamedArgs)
5838 ERR("functions with the vararg attribute do not support named arguments\n");
5839 hres = DISP_E_NONAMEDARGS;
5840 goto func_fail;
5843 for (i = 0; i < func_desc->cParams; i++)
5845 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5846 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
5847 if (FAILED(hres))
5848 goto func_fail;
5851 TRACE("changing args\n");
5852 for (i = 0; i < func_desc->cParams; i++)
5854 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5855 VARIANTARG *src_arg;
5857 if (cNamedArgs)
5859 USHORT j;
5860 src_arg = NULL;
5861 for (j = 0; j < cNamedArgs; j++)
5862 if (rgdispidNamedArgs[j] == i)
5864 src_arg = &pDispParams->rgvarg[j];
5865 break;
5868 else
5869 src_arg = i < pDispParams->cArgs ? &pDispParams->rgvarg[pDispParams->cArgs - 1 - i] : NULL;
5871 if (wParamFlags & PARAMFLAG_FRETVAL)
5873 /* under most conditions the caller is not allowed to
5874 * pass in a dispparam arg in the index of what would be
5875 * the retval parameter. however, there is an exception
5876 * where the extra parameter is used in an extra
5877 * IDispatch::Invoke below */
5878 if ((i < pDispParams->cArgs) &&
5879 ((func_desc->cParams != 1) || !pVarResult ||
5880 !(func_desc->invkind & INVOKE_PROPERTYGET)))
5882 hres = DISP_E_BADPARAMCOUNT;
5883 break;
5886 /* note: this check is placed so that if the caller passes
5887 * in a VARIANTARG for the retval we just ignore it, like
5888 * native does */
5889 if (i == func_desc->cParams - 1)
5891 VARIANTARG *arg;
5892 arg = prgpvarg[i] = &rgvarg[i];
5893 memset(arg, 0, sizeof(*arg));
5894 V_VT(arg) = rgvt[i];
5895 memset(&retval, 0, sizeof(retval));
5896 V_BYREF(arg) = &retval;
5898 else
5900 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
5901 hres = E_UNEXPECTED;
5902 break;
5905 else if (src_arg)
5907 dump_Variant(src_arg);
5909 if (rgvt[i] == VT_VARIANT)
5910 hres = VariantCopy(&rgvarg[i], src_arg);
5911 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
5913 if (rgvt[i] == V_VT(src_arg))
5914 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
5915 else
5917 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5918 hres = VariantCopy(&missing_arg[i], src_arg);
5919 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
5921 V_VT(&rgvarg[i]) = rgvt[i];
5923 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
5925 SAFEARRAY *a;
5926 SAFEARRAYBOUND bound;
5927 VARIANT *v;
5928 LONG j;
5929 bound.lLbound = 0;
5930 bound.cElements = pDispParams->cArgs-i;
5931 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
5933 ERR("SafeArrayCreate failed\n");
5934 break;
5936 hres = SafeArrayAccessData(a, (LPVOID)&v);
5937 if (hres != S_OK)
5939 ERR("SafeArrayAccessData failed with %x\n", hres);
5940 break;
5942 for (j = 0; j < bound.cElements; j++)
5943 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
5944 hres = SafeArrayUnaccessData(a);
5945 if (hres != S_OK)
5947 ERR("SafeArrayUnaccessData failed with %x\n", hres);
5948 break;
5950 V_ARRAY(&rgvarg[i]) = a;
5951 V_VT(&rgvarg[i]) = rgvt[i];
5953 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
5955 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5956 V_VT(&missing_arg[i]) = V_VT(src_arg);
5957 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
5958 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
5959 V_VT(&rgvarg[i]) = rgvt[i];
5961 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
5963 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
5964 V_VT(&rgvarg[i]) = rgvt[i];
5966 else
5968 /* FIXME: this doesn't work for VT_BYREF arguments if
5969 * they are not the same type as in the paramdesc */
5970 V_VT(&rgvarg[i]) = V_VT(src_arg);
5971 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
5972 V_VT(&rgvarg[i]) = rgvt[i];
5975 if (FAILED(hres))
5977 ERR("failed to convert param %d to %s%s from %s%s\n", i,
5978 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
5979 debugstr_VT(src_arg), debugstr_VF(src_arg));
5980 break;
5982 prgpvarg[i] = &rgvarg[i];
5984 else if (wParamFlags & PARAMFLAG_FOPT)
5986 VARIANTARG *arg;
5987 arg = prgpvarg[i] = &rgvarg[i];
5988 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5990 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
5991 if (FAILED(hres))
5992 break;
5994 else
5996 VARIANTARG *missing_arg;
5997 /* if the function wants a pointer to a variant then
5998 * set that up, otherwise just pass the VT_ERROR in
5999 * the argument by value */
6000 if (rgvt[i] & VT_BYREF)
6002 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6003 V_VT(arg) = VT_VARIANT | VT_BYREF;
6004 V_VARIANTREF(arg) = missing_arg;
6006 else
6007 missing_arg = arg;
6008 V_VT(missing_arg) = VT_ERROR;
6009 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6012 else
6014 hres = DISP_E_BADPARAMCOUNT;
6015 break;
6018 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6020 /* VT_VOID is a special case for return types, so it is not
6021 * handled in the general function */
6022 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6023 V_VT(&varresult) = VT_EMPTY;
6024 else
6026 V_VT(&varresult) = 0;
6027 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6028 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6031 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6032 V_VT(&varresult), func_desc->cParams, rgvt,
6033 prgpvarg, &varresult);
6035 for (i = 0; i < func_desc->cParams; i++)
6037 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6038 if (wParamFlags & PARAMFLAG_FRETVAL)
6040 if (TRACE_ON(ole))
6042 TRACE("[retval] value: ");
6043 dump_Variant(prgpvarg[i]);
6046 if (pVarResult)
6048 VariantInit(pVarResult);
6049 /* deref return value */
6050 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6053 /* free data stored in varresult. Note that
6054 * VariantClear doesn't do what we want because we are
6055 * working with byref types. */
6056 /* FIXME: clear safearrays, bstrs, records and
6057 * variants here too */
6058 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
6059 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
6061 if(*V_UNKNOWNREF(prgpvarg[i]))
6062 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
6064 break;
6066 else if (i < pDispParams->cArgs)
6068 if (wParamFlags & PARAMFLAG_FOUT)
6070 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
6072 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
6073 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6075 if (FAILED(hres))
6077 ERR("failed to convert param %d to vt %d\n", i,
6078 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
6079 break;
6082 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6083 func_desc->cParamsOpt < 0 &&
6084 i == func_desc->cParams-1)
6086 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6087 LONG j, ubound;
6088 VARIANT *v;
6089 hres = SafeArrayGetUBound(a, 1, &ubound);
6090 if (hres != S_OK)
6092 ERR("SafeArrayGetUBound failed with %x\n", hres);
6093 break;
6095 hres = SafeArrayAccessData(a, (LPVOID)&v);
6096 if (hres != S_OK)
6098 ERR("SafeArrayAccessData failed with %x\n", hres);
6099 break;
6101 for (j = 0; j <= ubound; j++)
6102 VariantClear(&v[j]);
6103 hres = SafeArrayUnaccessData(a);
6104 if (hres != S_OK)
6106 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6107 break;
6110 VariantClear(&rgvarg[i]);
6112 else if (wParamFlags & PARAMFLAG_FOPT)
6114 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6115 VariantClear(&rgvarg[i]);
6119 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6121 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6122 hres = DISP_E_EXCEPTION;
6123 if (pExcepInfo)
6125 IErrorInfo *pErrorInfo;
6126 pExcepInfo->scode = V_ERROR(&varresult);
6127 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6129 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6130 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6131 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6132 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6134 IErrorInfo_Release(pErrorInfo);
6138 if (V_VT(&varresult) != VT_ERROR)
6140 TRACE("varresult value: ");
6141 dump_Variant(&varresult);
6143 if (pVarResult)
6145 VariantClear(pVarResult);
6146 *pVarResult = varresult;
6148 else
6149 VariantClear(&varresult);
6152 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6153 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6154 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6155 (pDispParams->cArgs != 0))
6157 if (V_VT(pVarResult) == VT_DISPATCH)
6159 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6160 /* Note: not VariantClear; we still need the dispatch
6161 * pointer to be valid */
6162 VariantInit(pVarResult);
6163 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6164 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6165 pDispParams, pVarResult, pExcepInfo, pArgErr);
6166 IDispatch_Release(pDispatch);
6168 else
6170 VariantClear(pVarResult);
6171 hres = DISP_E_NOTACOLLECTION;
6175 func_fail:
6176 HeapFree(GetProcessHeap(), 0, buffer);
6177 break;
6179 case FUNC_DISPATCH: {
6180 IDispatch *disp;
6182 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6183 if (SUCCEEDED(hres)) {
6184 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6185 hres = IDispatch_Invoke(
6186 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6187 pVarResult,pExcepInfo,pArgErr
6189 if (FAILED(hres))
6190 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6191 IDispatch_Release(disp);
6192 } else
6193 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6194 break;
6196 default:
6197 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6198 hres = E_FAIL;
6199 break;
6202 TRACE("-- 0x%08x\n", hres);
6203 return hres;
6205 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6206 VARDESC *var_desc;
6208 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6209 if(FAILED(hres)) return hres;
6211 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6212 dump_VARDESC(var_desc);
6213 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6214 return E_NOTIMPL;
6217 /* not found, look for it in inherited interfaces */
6218 ITypeInfo2_GetTypeKind(iface, &type_kind);
6219 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6220 if(This->impltypelist) {
6221 /* recursive search */
6222 ITypeInfo *pTInfo;
6223 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6224 if(SUCCEEDED(hres)){
6225 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6226 ITypeInfo_Release(pTInfo);
6227 return hres;
6229 WARN("Could not search inherited interface!\n");
6232 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6233 return DISP_E_MEMBERNOTFOUND;
6236 /* ITypeInfo::GetDocumentation
6238 * Retrieves the documentation string, the complete Help file name and path,
6239 * and the context ID for the Help topic for a specified type description.
6241 * (Can be tested by the Visual Basic Editor in Word for instance.)
6243 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6244 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6245 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6247 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6248 const TLBFuncDesc *pFDesc;
6249 const TLBVarDesc *pVDesc;
6250 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6251 " HelpContext(%p) HelpFile(%p)\n",
6252 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6253 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6254 if(pBstrName)
6255 *pBstrName=SysAllocString(This->Name);
6256 if(pBstrDocString)
6257 *pBstrDocString=SysAllocString(This->DocString);
6258 if(pdwHelpContext)
6259 *pdwHelpContext=This->dwHelpContext;
6260 if(pBstrHelpFile)
6261 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6262 return S_OK;
6263 }else {/* for a member */
6264 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6265 if(pFDesc->funcdesc.memid==memid){
6266 if(pBstrName)
6267 *pBstrName = SysAllocString(pFDesc->Name);
6268 if(pBstrDocString)
6269 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6270 if(pdwHelpContext)
6271 *pdwHelpContext=pFDesc->helpcontext;
6272 return S_OK;
6274 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6275 if(pVDesc->vardesc.memid==memid){
6276 if(pBstrName)
6277 *pBstrName = SysAllocString(pVDesc->Name);
6278 if(pBstrDocString)
6279 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6280 if(pdwHelpContext)
6281 *pdwHelpContext=pVDesc->HelpContext;
6282 return S_OK;
6286 if(This->impltypelist &&
6287 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6288 /* recursive search */
6289 ITypeInfo *pTInfo;
6290 HRESULT result;
6291 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6292 &pTInfo);
6293 if(SUCCEEDED(result)) {
6294 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6295 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6296 ITypeInfo_Release(pTInfo);
6297 return result;
6299 WARN("Could not search inherited interface!\n");
6302 WARN("member %d not found\n", memid);
6303 return TYPE_E_ELEMENTNOTFOUND;
6306 /* ITypeInfo::GetDllEntry
6308 * Retrieves a description or specification of an entry point for a function
6309 * in a DLL.
6311 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6312 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6313 WORD *pwOrdinal)
6315 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6316 const TLBFuncDesc *pFDesc;
6318 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6320 if (pBstrDllName) *pBstrDllName = NULL;
6321 if (pBstrName) *pBstrName = NULL;
6322 if (pwOrdinal) *pwOrdinal = 0;
6324 if (This->TypeAttr.typekind != TKIND_MODULE)
6325 return TYPE_E_BADMODULEKIND;
6327 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6328 if(pFDesc->funcdesc.memid==memid){
6329 dump_TypeInfo(This);
6330 if (TRACE_ON(ole))
6331 dump_TLBFuncDescOne(pFDesc);
6333 if (pBstrDllName)
6334 *pBstrDllName = SysAllocString(This->DllName);
6336 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6337 if (pBstrName)
6338 *pBstrName = SysAllocString(pFDesc->Entry);
6339 if (pwOrdinal)
6340 *pwOrdinal = -1;
6341 return S_OK;
6343 if (pBstrName)
6344 *pBstrName = NULL;
6345 if (pwOrdinal)
6346 *pwOrdinal = (DWORD)pFDesc->Entry;
6347 return S_OK;
6349 return TYPE_E_ELEMENTNOTFOUND;
6352 /* internal function to make the inherited interfaces' methods appear
6353 * part of the interface */
6354 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6355 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6357 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6358 HRESULT hr;
6360 TRACE("%p, 0x%x\n", iface, *hRefType);
6362 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK))
6364 ITypeInfo *pSubTypeInfo;
6366 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
6367 if (FAILED(hr))
6368 return hr;
6370 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6371 hRefType, ppTInfo);
6372 ITypeInfo_Release(pSubTypeInfo);
6373 if (SUCCEEDED(hr))
6374 return hr;
6376 *hRefType -= DISPATCH_HREF_OFFSET;
6378 if (!(*hRefType & DISPATCH_HREF_MASK))
6379 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6380 else
6381 return E_FAIL;
6384 /* ITypeInfo::GetRefTypeInfo
6386 * If a type description references other type descriptions, it retrieves
6387 * the referenced type descriptions.
6389 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6390 ITypeInfo2 *iface,
6391 HREFTYPE hRefType,
6392 ITypeInfo **ppTInfo)
6394 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6395 HRESULT result = E_FAIL;
6397 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6399 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6400 ITypeInfo_AddRef(*ppTInfo);
6401 result = S_OK;
6403 else if (hRefType == -1 &&
6404 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6405 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6407 /* when we meet a DUAL dispinterface, we must create the interface
6408 * version of it.
6410 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
6413 /* the interface version contains the same information as the dispinterface
6414 * copy the contents of the structs.
6416 *pTypeInfoImpl = *This;
6417 pTypeInfoImpl->ref = 0;
6419 /* change the type to interface */
6420 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6422 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6424 /* we use data structures from This, so we need to keep a reference
6425 * to it to stop it being destroyed and signal to the new instance to
6426 * not free its data structures when it is destroyed */
6427 pTypeInfoImpl->no_free_data = TRUE;
6428 pTypeInfoImpl->next = This;
6429 ITypeInfo_AddRef((ITypeInfo*) This);
6431 ITypeInfo_AddRef(*ppTInfo);
6433 result = S_OK;
6435 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6436 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6437 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6439 HREFTYPE href_dispatch = hRefType;
6440 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6441 } else {
6442 TLBRefType *ref_type;
6443 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6445 if(ref_type->reference == hRefType)
6446 break;
6448 if(&ref_type->entry == &This->pTypeLib->ref_list)
6450 FIXME("Can't find pRefType for ref %x\n", hRefType);
6451 goto end;
6453 if(hRefType != -1) {
6454 ITypeLib *pTLib = NULL;
6456 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6457 UINT Index;
6458 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6459 } else {
6460 if(ref_type->pImpTLInfo->pImpTypeLib) {
6461 TRACE("typeinfo in imported typelib that is already loaded\n");
6462 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6463 ITypeLib2_AddRef(pTLib);
6464 result = S_OK;
6465 } else {
6466 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6467 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6468 ref_type->pImpTLInfo->wVersionMajor,
6469 ref_type->pImpTLInfo->wVersionMinor,
6470 ref_type->pImpTLInfo->lcid,
6471 &pTLib);
6473 if(!SUCCEEDED(result)) {
6474 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6475 result=LoadTypeLib(libnam, &pTLib);
6476 SysFreeString(libnam);
6478 if(SUCCEEDED(result)) {
6479 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6480 ITypeLib2_AddRef(pTLib);
6484 if(SUCCEEDED(result)) {
6485 if(ref_type->index == TLB_REF_USE_GUID)
6486 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6487 &ref_type->guid,
6488 ppTInfo);
6489 else
6490 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6491 ppTInfo);
6493 if (pTLib != NULL)
6494 ITypeLib2_Release(pTLib);
6498 end:
6499 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6500 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6501 return result;
6504 /* ITypeInfo::AddressOfMember
6506 * Retrieves the addresses of static functions or variables, such as those
6507 * defined in a DLL.
6509 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6510 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6512 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6513 HRESULT hr;
6514 BSTR dll, entry;
6515 WORD ordinal;
6516 HMODULE module;
6518 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6520 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6521 if (FAILED(hr))
6522 return hr;
6524 module = LoadLibraryW(dll);
6525 if (!module)
6527 ERR("couldn't load %s\n", debugstr_w(dll));
6528 SysFreeString(dll);
6529 if (entry) SysFreeString(entry);
6530 return STG_E_FILENOTFOUND;
6532 /* FIXME: store library somewhere where we can free it */
6534 if (entry)
6536 LPSTR entryA;
6537 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6538 entryA = HeapAlloc(GetProcessHeap(), 0, len);
6539 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6541 *ppv = GetProcAddress(module, entryA);
6542 if (!*ppv)
6543 ERR("function not found %s\n", debugstr_a(entryA));
6545 HeapFree(GetProcessHeap(), 0, entryA);
6547 else
6549 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6550 if (!*ppv)
6551 ERR("function not found %d\n", ordinal);
6554 SysFreeString(dll);
6555 if (entry) SysFreeString(entry);
6557 if (!*ppv)
6558 return TYPE_E_DLLFUNCTIONNOTFOUND;
6560 return S_OK;
6563 /* ITypeInfo::CreateInstance
6565 * Creates a new instance of a type that describes a component object class
6566 * (coclass).
6568 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6569 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6571 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6572 HRESULT hr;
6573 TYPEATTR *pTA;
6575 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6577 *ppvObj = NULL;
6579 if(pOuterUnk)
6581 WARN("Not able to aggregate\n");
6582 return CLASS_E_NOAGGREGATION;
6585 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6586 if(FAILED(hr)) return hr;
6588 if(pTA->typekind != TKIND_COCLASS)
6590 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6591 hr = E_INVALIDARG;
6592 goto end;
6595 hr = S_FALSE;
6596 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6598 IUnknown *pUnk;
6599 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6600 TRACE("GetActiveObject rets %08x\n", hr);
6601 if(hr == S_OK)
6603 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6604 IUnknown_Release(pUnk);
6608 if(hr != S_OK)
6609 hr = CoCreateInstance(&pTA->guid, NULL,
6610 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6611 riid, ppvObj);
6613 end:
6614 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6615 return hr;
6618 /* ITypeInfo::GetMops
6620 * Retrieves marshalling information.
6622 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6623 BSTR *pBstrMops)
6625 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6626 FIXME("(%p) stub!\n", This);
6627 return S_OK;
6630 /* ITypeInfo::GetContainingTypeLib
6632 * Retrieves the containing type library and the index of the type description
6633 * within that type library.
6635 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6636 ITypeLib * *ppTLib, UINT *pIndex)
6638 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6640 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6641 if (pIndex) {
6642 *pIndex=This->index;
6643 TRACE("returning pIndex=%d\n", *pIndex);
6646 if (ppTLib) {
6647 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6648 ITypeLib2_AddRef(*ppTLib);
6649 TRACE("returning ppTLib=%p\n", *ppTLib);
6652 return S_OK;
6655 /* ITypeInfo::ReleaseTypeAttr
6657 * Releases a TYPEATTR previously returned by GetTypeAttr.
6660 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6661 TYPEATTR* pTypeAttr)
6663 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6664 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6665 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6668 /* ITypeInfo::ReleaseFuncDesc
6670 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6672 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6673 ITypeInfo2 *iface,
6674 FUNCDESC *pFuncDesc)
6676 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6677 SHORT i;
6679 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6681 for (i = 0; i < pFuncDesc->cParams; i++)
6682 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6683 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6685 SysFreeString((BSTR)pFuncDesc);
6688 /* ITypeInfo::ReleaseVarDesc
6690 * Releases a VARDESC previously returned by GetVarDesc.
6692 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6693 VARDESC *pVarDesc)
6695 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6696 TRACE("(%p)->(%p)\n", This, pVarDesc);
6698 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6699 if (pVarDesc->varkind == VAR_CONST)
6700 VariantClear(pVarDesc->u.lpvarValue);
6701 SysFreeString((BSTR)pVarDesc);
6704 /* ITypeInfo2::GetTypeKind
6706 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6709 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6710 TYPEKIND *pTypeKind)
6712 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6713 *pTypeKind=This->TypeAttr.typekind;
6714 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6715 return S_OK;
6718 /* ITypeInfo2::GetTypeFlags
6720 * Returns the type flags without any allocations. This returns a DWORD type
6721 * flag, which expands the type flags without growing the TYPEATTR (type
6722 * attribute).
6725 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6727 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6728 *pTypeFlags=This->TypeAttr.wTypeFlags;
6729 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6730 return S_OK;
6733 /* ITypeInfo2::GetFuncIndexOfMemId
6734 * Binds to a specific member based on a known DISPID, where the member name
6735 * is not known (for example, when binding to a default member).
6738 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
6739 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
6741 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6742 const TLBFuncDesc *pFuncInfo;
6743 int i;
6744 HRESULT result;
6746 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
6747 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
6748 break;
6749 if(pFuncInfo) {
6750 *pFuncIndex = i;
6751 result = S_OK;
6752 } else
6753 result = TYPE_E_ELEMENTNOTFOUND;
6755 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
6756 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6757 return result;
6760 /* TypeInfo2::GetVarIndexOfMemId
6762 * Binds to a specific member based on a known DISPID, where the member name
6763 * is not known (for example, when binding to a default member).
6766 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
6767 MEMBERID memid, UINT *pVarIndex)
6769 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6770 TLBVarDesc *pVarInfo;
6771 int i;
6772 HRESULT result;
6773 for(i=0, pVarInfo=This->varlist; pVarInfo &&
6774 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
6776 if(pVarInfo) {
6777 *pVarIndex = i;
6778 result = S_OK;
6779 } else
6780 result = TYPE_E_ELEMENTNOTFOUND;
6782 TRACE("(%p) memid 0x%08x -> %s\n", This,
6783 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6784 return result;
6787 /* ITypeInfo2::GetCustData
6789 * Gets the custom data
6791 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
6792 ITypeInfo2 * iface,
6793 REFGUID guid,
6794 VARIANT *pVarVal)
6796 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6797 TLBCustData *pCData;
6799 for(pCData=This->pCustData; pCData; pCData = pCData->next)
6800 if( IsEqualIID(guid, &pCData->guid)) break;
6802 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6804 if(pCData)
6806 VariantInit( pVarVal);
6807 VariantCopy( pVarVal, &pCData->data);
6808 return S_OK;
6810 return E_INVALIDARG; /* FIXME: correct? */
6813 /* ITypeInfo2::GetFuncCustData
6815 * Gets the custom data
6817 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
6818 ITypeInfo2 * iface,
6819 UINT index,
6820 REFGUID guid,
6821 VARIANT *pVarVal)
6823 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6824 TLBCustData *pCData=NULL;
6825 TLBFuncDesc * pFDesc;
6826 int i;
6827 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6828 pFDesc=pFDesc->next);
6830 if(pFDesc)
6831 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
6832 if( IsEqualIID(guid, &pCData->guid)) break;
6834 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6836 if(pCData){
6837 VariantInit( pVarVal);
6838 VariantCopy( pVarVal, &pCData->data);
6839 return S_OK;
6841 return E_INVALIDARG; /* FIXME: correct? */
6844 /* ITypeInfo2::GetParamCustData
6846 * Gets the custom data
6848 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
6849 ITypeInfo2 * iface,
6850 UINT indexFunc,
6851 UINT indexParam,
6852 REFGUID guid,
6853 VARIANT *pVarVal)
6855 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6856 TLBCustData *pCData=NULL;
6857 TLBFuncDesc * pFDesc;
6858 int i;
6860 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
6862 if(pFDesc && indexParam<pFDesc->funcdesc.cParams)
6863 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
6864 pCData = pCData->next)
6865 if( IsEqualIID(guid, &pCData->guid)) break;
6867 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6869 if(pCData)
6871 VariantInit( pVarVal);
6872 VariantCopy( pVarVal, &pCData->data);
6873 return S_OK;
6875 return E_INVALIDARG; /* FIXME: correct? */
6878 /* ITypeInfo2::GetVarCustData
6880 * Gets the custom data
6882 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
6883 ITypeInfo2 * iface,
6884 UINT index,
6885 REFGUID guid,
6886 VARIANT *pVarVal)
6888 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6889 TLBCustData *pCData=NULL;
6890 TLBVarDesc * pVDesc;
6891 int i;
6893 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
6895 if(pVDesc)
6897 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
6899 if( IsEqualIID(guid, &pCData->guid)) break;
6903 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6905 if(pCData)
6907 VariantInit( pVarVal);
6908 VariantCopy( pVarVal, &pCData->data);
6909 return S_OK;
6911 return E_INVALIDARG; /* FIXME: correct? */
6914 /* ITypeInfo2::GetImplCustData
6916 * Gets the custom data
6918 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6919 ITypeInfo2 * iface,
6920 UINT index,
6921 REFGUID guid,
6922 VARIANT *pVarVal)
6924 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6925 TLBCustData *pCData=NULL;
6926 TLBImplType * pRDesc;
6927 int i;
6929 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6931 if(pRDesc)
6933 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6935 if( IsEqualIID(guid, &pCData->guid)) break;
6939 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6941 if(pCData)
6943 VariantInit( pVarVal);
6944 VariantCopy( pVarVal, &pCData->data);
6945 return S_OK;
6947 return E_INVALIDARG; /* FIXME: correct? */
6950 /* ITypeInfo2::GetDocumentation2
6952 * Retrieves the documentation string, the complete Help file name and path,
6953 * the localization context to use, and the context ID for the library Help
6954 * topic in the Help file.
6957 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6958 ITypeInfo2 * iface,
6959 MEMBERID memid,
6960 LCID lcid,
6961 BSTR *pbstrHelpString,
6962 DWORD *pdwHelpStringContext,
6963 BSTR *pbstrHelpStringDll)
6965 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6966 const TLBFuncDesc *pFDesc;
6967 const TLBVarDesc *pVDesc;
6968 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
6969 "HelpStringContext(%p) HelpStringDll(%p)\n",
6970 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6971 pbstrHelpStringDll );
6972 /* the help string should be obtained from the helpstringdll,
6973 * using the _DLLGetDocumentation function, based on the supplied
6974 * lcid. Nice to do sometime...
6976 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6977 if(pbstrHelpString)
6978 *pbstrHelpString=SysAllocString(This->Name);
6979 if(pdwHelpStringContext)
6980 *pdwHelpStringContext=This->dwHelpStringContext;
6981 if(pbstrHelpStringDll)
6982 *pbstrHelpStringDll=
6983 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6984 return S_OK;
6985 }else {/* for a member */
6986 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6987 if(pFDesc->funcdesc.memid==memid){
6988 if(pbstrHelpString)
6989 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6990 if(pdwHelpStringContext)
6991 *pdwHelpStringContext=pFDesc->HelpStringContext;
6992 if(pbstrHelpStringDll)
6993 *pbstrHelpStringDll=
6994 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6995 return S_OK;
6997 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6998 if(pVDesc->vardesc.memid==memid){
6999 if(pbstrHelpString)
7000 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
7001 if(pdwHelpStringContext)
7002 *pdwHelpStringContext=pVDesc->HelpStringContext;
7003 if(pbstrHelpStringDll)
7004 *pbstrHelpStringDll=
7005 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7006 return S_OK;
7009 return TYPE_E_ELEMENTNOTFOUND;
7012 /* ITypeInfo2::GetAllCustData
7014 * Gets all custom data items for the Type info.
7017 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7018 ITypeInfo2 * iface,
7019 CUSTDATA *pCustData)
7021 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7022 TLBCustData *pCData;
7023 int i;
7025 TRACE("(%p) returning %d items\n", This, This->ctCustData);
7027 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
7028 if(pCustData->prgCustData ){
7029 pCustData->cCustData=This->ctCustData;
7030 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
7031 pCustData->prgCustData[i].guid=pCData->guid;
7032 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
7034 }else{
7035 ERR(" OUT OF MEMORY!\n");
7036 return E_OUTOFMEMORY;
7038 return S_OK;
7041 /* ITypeInfo2::GetAllFuncCustData
7043 * Gets all custom data items for the specified Function
7046 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7047 ITypeInfo2 * iface,
7048 UINT index,
7049 CUSTDATA *pCustData)
7051 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7052 TLBCustData *pCData;
7053 TLBFuncDesc * pFDesc;
7054 int i;
7055 TRACE("(%p) index %d\n", This, index);
7056 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7057 pFDesc=pFDesc->next)
7059 if(pFDesc){
7060 pCustData->prgCustData =
7061 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
7062 if(pCustData->prgCustData ){
7063 pCustData->cCustData=pFDesc->ctCustData;
7064 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
7065 pCData = pCData->next){
7066 pCustData->prgCustData[i].guid=pCData->guid;
7067 VariantCopy(& pCustData->prgCustData[i].varValue,
7068 & pCData->data);
7070 }else{
7071 ERR(" OUT OF MEMORY!\n");
7072 return E_OUTOFMEMORY;
7074 return S_OK;
7076 return TYPE_E_ELEMENTNOTFOUND;
7079 /* ITypeInfo2::GetAllParamCustData
7081 * Gets all custom data items for the Functions
7084 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7085 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7087 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7088 TLBCustData *pCData=NULL;
7089 TLBFuncDesc * pFDesc;
7090 int i;
7091 TRACE("(%p) index %d\n", This, indexFunc);
7092 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
7093 pFDesc=pFDesc->next)
7095 if(pFDesc && indexParam<pFDesc->funcdesc.cParams){
7096 pCustData->prgCustData =
7097 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
7098 sizeof(CUSTDATAITEM));
7099 if(pCustData->prgCustData ){
7100 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
7101 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
7102 pCData; i++, pCData = pCData->next){
7103 pCustData->prgCustData[i].guid=pCData->guid;
7104 VariantCopy(& pCustData->prgCustData[i].varValue,
7105 & pCData->data);
7107 }else{
7108 ERR(" OUT OF MEMORY!\n");
7109 return E_OUTOFMEMORY;
7111 return S_OK;
7113 return TYPE_E_ELEMENTNOTFOUND;
7116 /* ITypeInfo2::GetAllVarCustData
7118 * Gets all custom data items for the specified Variable
7121 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7122 UINT index, CUSTDATA *pCustData)
7124 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7125 TLBCustData *pCData;
7126 TLBVarDesc * pVDesc;
7127 int i;
7128 TRACE("(%p) index %d\n", This, index);
7129 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
7130 pVDesc=pVDesc->next)
7132 if(pVDesc){
7133 pCustData->prgCustData =
7134 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
7135 if(pCustData->prgCustData ){
7136 pCustData->cCustData=pVDesc->ctCustData;
7137 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
7138 pCData = pCData->next){
7139 pCustData->prgCustData[i].guid=pCData->guid;
7140 VariantCopy(& pCustData->prgCustData[i].varValue,
7141 & pCData->data);
7143 }else{
7144 ERR(" OUT OF MEMORY!\n");
7145 return E_OUTOFMEMORY;
7147 return S_OK;
7149 return TYPE_E_ELEMENTNOTFOUND;
7152 /* ITypeInfo2::GetAllImplCustData
7154 * Gets all custom data items for the specified implementation type
7157 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7158 ITypeInfo2 * iface,
7159 UINT index,
7160 CUSTDATA *pCustData)
7162 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7163 TLBCustData *pCData;
7164 TLBImplType * pRDesc;
7165 int i;
7166 TRACE("(%p) index %d\n", This, index);
7167 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
7168 pRDesc=pRDesc->next)
7170 if(pRDesc){
7171 pCustData->prgCustData =
7172 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
7173 if(pCustData->prgCustData ){
7174 pCustData->cCustData=pRDesc->ctCustData;
7175 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
7176 pCData = pCData->next){
7177 pCustData->prgCustData[i].guid=pCData->guid;
7178 VariantCopy(& pCustData->prgCustData[i].varValue,
7179 & pCData->data);
7181 }else{
7182 ERR(" OUT OF MEMORY!\n");
7183 return E_OUTOFMEMORY;
7185 return S_OK;
7187 return TYPE_E_ELEMENTNOTFOUND;
7190 static const ITypeInfo2Vtbl tinfvt =
7193 ITypeInfo_fnQueryInterface,
7194 ITypeInfo_fnAddRef,
7195 ITypeInfo_fnRelease,
7197 ITypeInfo_fnGetTypeAttr,
7198 ITypeInfo_fnGetTypeComp,
7199 ITypeInfo_fnGetFuncDesc,
7200 ITypeInfo_fnGetVarDesc,
7201 ITypeInfo_fnGetNames,
7202 ITypeInfo_fnGetRefTypeOfImplType,
7203 ITypeInfo_fnGetImplTypeFlags,
7204 ITypeInfo_fnGetIDsOfNames,
7205 ITypeInfo_fnInvoke,
7206 ITypeInfo_fnGetDocumentation,
7207 ITypeInfo_fnGetDllEntry,
7208 ITypeInfo_fnGetRefTypeInfo,
7209 ITypeInfo_fnAddressOfMember,
7210 ITypeInfo_fnCreateInstance,
7211 ITypeInfo_fnGetMops,
7212 ITypeInfo_fnGetContainingTypeLib,
7213 ITypeInfo_fnReleaseTypeAttr,
7214 ITypeInfo_fnReleaseFuncDesc,
7215 ITypeInfo_fnReleaseVarDesc,
7217 ITypeInfo2_fnGetTypeKind,
7218 ITypeInfo2_fnGetTypeFlags,
7219 ITypeInfo2_fnGetFuncIndexOfMemId,
7220 ITypeInfo2_fnGetVarIndexOfMemId,
7221 ITypeInfo2_fnGetCustData,
7222 ITypeInfo2_fnGetFuncCustData,
7223 ITypeInfo2_fnGetParamCustData,
7224 ITypeInfo2_fnGetVarCustData,
7225 ITypeInfo2_fnGetImplTypeCustData,
7226 ITypeInfo2_fnGetDocumentation2,
7227 ITypeInfo2_fnGetAllCustData,
7228 ITypeInfo2_fnGetAllFuncCustData,
7229 ITypeInfo2_fnGetAllParamCustData,
7230 ITypeInfo2_fnGetAllVarCustData,
7231 ITypeInfo2_fnGetAllImplTypeCustData,
7234 /******************************************************************************
7235 * CreateDispTypeInfo [OLEAUT32.31]
7237 * Build type information for an object so it can be called through an
7238 * IDispatch interface.
7240 * RETURNS
7241 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7242 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7244 * NOTES
7245 * This call allows an objects methods to be accessed through IDispatch, by
7246 * building an ITypeInfo object that IDispatch can use to call through.
7248 HRESULT WINAPI CreateDispTypeInfo(
7249 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7250 LCID lcid, /* [I] Locale Id */
7251 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7253 ITypeInfoImpl *pTIClass, *pTIIface;
7254 ITypeLibImpl *pTypeLibImpl;
7255 int param, func;
7256 TLBFuncDesc **ppFuncDesc;
7257 TLBRefType *ref;
7259 TRACE("\n");
7260 pTypeLibImpl = TypeLibImpl_Constructor();
7261 if (!pTypeLibImpl) return E_FAIL;
7263 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
7264 pTIIface->pTypeLib = pTypeLibImpl;
7265 pTIIface->index = 0;
7266 pTIIface->Name = NULL;
7267 pTIIface->dwHelpContext = -1;
7268 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7269 pTIIface->TypeAttr.lcid = lcid;
7270 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7271 pTIIface->TypeAttr.wMajorVerNum = 0;
7272 pTIIface->TypeAttr.wMinorVerNum = 0;
7273 pTIIface->TypeAttr.cbAlignment = 2;
7274 pTIIface->TypeAttr.cbSizeInstance = -1;
7275 pTIIface->TypeAttr.cbSizeVft = -1;
7276 pTIIface->TypeAttr.cFuncs = 0;
7277 pTIIface->TypeAttr.cImplTypes = 0;
7278 pTIIface->TypeAttr.cVars = 0;
7279 pTIIface->TypeAttr.wTypeFlags = 0;
7281 ppFuncDesc = &pTIIface->funclist;
7282 for(func = 0; func < pidata->cMembers; func++) {
7283 METHODDATA *md = pidata->pmethdata + func;
7284 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
7285 (*ppFuncDesc)->Name = SysAllocString(md->szName);
7286 (*ppFuncDesc)->funcdesc.memid = md->dispid;
7287 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
7288 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
7289 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
7290 (*ppFuncDesc)->funcdesc.callconv = md->cc;
7291 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
7292 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
7293 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
7294 (*ppFuncDesc)->funcdesc.cScodes = 0;
7295 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
7296 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7297 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7298 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7299 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7300 md->cArgs * sizeof(ELEMDESC));
7301 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7302 md->cArgs * sizeof(TLBParDesc));
7303 for(param = 0; param < md->cArgs; param++) {
7304 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7305 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7307 (*ppFuncDesc)->helpcontext = 0;
7308 (*ppFuncDesc)->HelpStringContext = 0;
7309 (*ppFuncDesc)->HelpString = NULL;
7310 (*ppFuncDesc)->Entry = NULL;
7311 (*ppFuncDesc)->ctCustData = 0;
7312 (*ppFuncDesc)->pCustData = NULL;
7313 (*ppFuncDesc)->next = NULL;
7314 pTIIface->TypeAttr.cFuncs++;
7315 ppFuncDesc = &(*ppFuncDesc)->next;
7318 dump_TypeInfo(pTIIface);
7320 pTypeLibImpl->pTypeInfo = pTIIface;
7321 pTypeLibImpl->TypeInfoCount++;
7323 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
7324 pTIClass->pTypeLib = pTypeLibImpl;
7325 pTIClass->index = 1;
7326 pTIClass->Name = NULL;
7327 pTIClass->dwHelpContext = -1;
7328 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7329 pTIClass->TypeAttr.lcid = lcid;
7330 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7331 pTIClass->TypeAttr.wMajorVerNum = 0;
7332 pTIClass->TypeAttr.wMinorVerNum = 0;
7333 pTIClass->TypeAttr.cbAlignment = 2;
7334 pTIClass->TypeAttr.cbSizeInstance = -1;
7335 pTIClass->TypeAttr.cbSizeVft = -1;
7336 pTIClass->TypeAttr.cFuncs = 0;
7337 pTIClass->TypeAttr.cImplTypes = 1;
7338 pTIClass->TypeAttr.cVars = 0;
7339 pTIClass->TypeAttr.wTypeFlags = 0;
7341 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
7342 pTIClass->impltypelist->hRef = 0;
7344 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
7345 ref->index = 0;
7346 ref->reference = 0;
7347 ref->pImpTLInfo = TLB_REF_INTERNAL;
7348 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7350 dump_TypeInfo(pTIClass);
7352 pTIIface->next = pTIClass;
7353 pTypeLibImpl->TypeInfoCount++;
7355 *pptinfo = (ITypeInfo*)pTIClass;
7357 ITypeInfo_AddRef(*pptinfo);
7358 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7360 return S_OK;
7364 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7366 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7368 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7371 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7373 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7375 return ITypeInfo_AddRef((ITypeInfo *)This);
7378 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7380 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7382 return ITypeInfo_Release((ITypeInfo *)This);
7385 static HRESULT WINAPI ITypeComp_fnBind(
7386 ITypeComp * iface,
7387 OLECHAR * szName,
7388 ULONG lHash,
7389 WORD wFlags,
7390 ITypeInfo ** ppTInfo,
7391 DESCKIND * pDescKind,
7392 BINDPTR * pBindPtr)
7394 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7395 const TLBFuncDesc *pFDesc;
7396 const TLBVarDesc *pVDesc;
7397 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7399 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7401 *pDescKind = DESCKIND_NONE;
7402 pBindPtr->lpfuncdesc = NULL;
7403 *ppTInfo = NULL;
7405 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
7406 if (!strcmpiW(pFDesc->Name, szName)) {
7407 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7408 break;
7409 else
7410 /* name found, but wrong flags */
7411 hr = TYPE_E_TYPEMISMATCH;
7414 if (pFDesc)
7416 HRESULT hr = TLB_AllocAndInitFuncDesc(
7417 &pFDesc->funcdesc,
7418 &pBindPtr->lpfuncdesc,
7419 This->TypeAttr.typekind == TKIND_DISPATCH);
7420 if (FAILED(hr))
7421 return hr;
7422 *pDescKind = DESCKIND_FUNCDESC;
7423 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7424 ITypeInfo_AddRef(*ppTInfo);
7425 return S_OK;
7426 } else {
7427 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7428 if (!strcmpiW(pVDesc->Name, szName)) {
7429 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7430 if (FAILED(hr))
7431 return hr;
7432 *pDescKind = DESCKIND_VARDESC;
7433 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7434 ITypeInfo_AddRef(*ppTInfo);
7435 return S_OK;
7439 /* FIXME: search each inherited interface, not just the first */
7440 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7441 /* recursive search */
7442 ITypeInfo *pTInfo;
7443 ITypeComp *pTComp;
7444 HRESULT hr;
7445 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7446 if (SUCCEEDED(hr))
7448 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7449 ITypeInfo_Release(pTInfo);
7451 if (SUCCEEDED(hr))
7453 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7454 ITypeComp_Release(pTComp);
7455 return hr;
7457 WARN("Could not search inherited interface!\n");
7459 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
7460 return hr;
7463 static HRESULT WINAPI ITypeComp_fnBindType(
7464 ITypeComp * iface,
7465 OLECHAR * szName,
7466 ULONG lHash,
7467 ITypeInfo ** ppTInfo,
7468 ITypeComp ** ppTComp)
7470 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7472 /* strange behaviour (does nothing) but like the
7473 * original */
7475 if (!ppTInfo || !ppTComp)
7476 return E_POINTER;
7478 *ppTInfo = NULL;
7479 *ppTComp = NULL;
7481 return S_OK;
7484 static const ITypeCompVtbl tcompvt =
7487 ITypeComp_fnQueryInterface,
7488 ITypeComp_fnAddRef,
7489 ITypeComp_fnRelease,
7491 ITypeComp_fnBind,
7492 ITypeComp_fnBindType