quartz: Handle state changes in direct sound renderer correctly.
[wine/multimedia.git] / dlls / oleaut32 / typelib.c
blob06c464d801df239b682d6524b012e1f55a448d9b
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"
67 #include "lzexpand.h"
69 #include "wine/unicode.h"
70 #include "objbase.h"
71 #include "typelib.h"
72 #include "wine/debug.h"
73 #include "variant.h"
74 #include "wine/list.h"
76 WINE_DEFAULT_DEBUG_CHANNEL(ole);
77 WINE_DECLARE_DEBUG_CHANNEL(typelib);
79 typedef struct
81 WORD offset;
82 WORD length;
83 WORD flags;
84 WORD id;
85 WORD handle;
86 WORD usage;
87 } NE_NAMEINFO;
89 typedef struct
91 WORD type_id; /* Type identifier */
92 WORD count; /* Number of resources of this type */
93 DWORD resloader; /* SetResourceHandler() */
95 * Name info array.
97 } NE_TYPEINFO;
99 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
100 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
102 /****************************************************************************
103 * FromLExxx
105 * Takes p_iVal (which is in little endian) and returns it
106 * in the host machine's byte order.
108 #ifdef WORDS_BIGENDIAN
109 static WORD FromLEWord(WORD p_iVal)
111 return (((p_iVal & 0x00FF) << 8) |
112 ((p_iVal & 0xFF00) >> 8));
116 static DWORD FromLEDWord(DWORD p_iVal)
118 return (((p_iVal & 0x000000FF) << 24) |
119 ((p_iVal & 0x0000FF00) << 8) |
120 ((p_iVal & 0x00FF0000) >> 8) |
121 ((p_iVal & 0xFF000000) >> 24));
123 #else
124 #define FromLEWord(X) (X)
125 #define FromLEDWord(X) (X)
126 #endif
128 #define DISPATCH_HREF_OFFSET 0x01000000
129 #define DISPATCH_HREF_MASK 0xff000000
131 /****************************************************************************
132 * FromLExxx
134 * Fix byte order in any structure if necessary
136 #ifdef WORDS_BIGENDIAN
137 static void FromLEWords(void *p_Val, int p_iSize)
139 WORD *Val = p_Val;
141 p_iSize /= sizeof(WORD);
143 while (p_iSize) {
144 *Val = FromLEWord(*Val);
145 Val++;
146 p_iSize--;
151 static void FromLEDWords(void *p_Val, int p_iSize)
153 DWORD *Val = p_Val;
155 p_iSize /= sizeof(DWORD);
157 while (p_iSize) {
158 *Val = FromLEDWord(*Val);
159 Val++;
160 p_iSize--;
163 #else
164 #define FromLEWords(X,Y) /*nothing*/
165 #define FromLEDWords(X,Y) /*nothing*/
166 #endif
169 * Find a typelib key which matches a requested maj.min version.
171 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
173 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
174 WCHAR buffer[60];
175 char key_name[16];
176 DWORD len, i;
177 INT best_maj = -1, best_min = -1;
178 HKEY hkey;
180 memcpy( buffer, typelibW, sizeof(typelibW) );
181 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
183 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
184 return FALSE;
186 len = sizeof(key_name);
187 i = 0;
188 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
190 INT v_maj, v_min;
192 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
194 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
196 if (*wMaj == 0xffff && *wMin == 0xffff)
198 if (v_maj > best_maj) best_maj = v_maj;
199 if (v_min > best_min) best_min = v_min;
201 else if (*wMaj == v_maj)
203 best_maj = v_maj;
205 if (*wMin == v_min)
207 best_min = v_min;
208 break; /* exact match */
210 if (*wMin != 0xffff && v_min > best_min) best_min = v_min;
213 len = sizeof(key_name);
215 RegCloseKey( hkey );
217 TRACE("found best_maj %d, best_min %d\n", best_maj, best_min);
219 if (*wMaj == 0xffff && *wMin == 0xffff)
221 if (best_maj >= 0 && best_min >= 0)
223 *wMaj = best_maj;
224 *wMin = best_min;
225 return TRUE;
229 if (*wMaj == best_maj && best_min >= 0)
231 *wMin = best_min;
232 return TRUE;
234 return FALSE;
237 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
238 /* buffer must be at least 60 characters long */
239 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
241 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
242 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
244 memcpy( buffer, TypelibW, sizeof(TypelibW) );
245 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
246 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
247 return buffer;
250 /* get the path of an interface key, in the form "Interface\\<guid>" */
251 /* buffer must be at least 50 characters long */
252 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
254 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
256 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
257 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
258 return buffer;
261 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
262 /* buffer must be at least 16 characters long */
263 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
265 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
266 static const WCHAR win16W[] = {'w','i','n','1','6',0};
267 static const WCHAR win32W[] = {'w','i','n','3','2',0};
268 static const WCHAR win64W[] = {'w','i','n','6','4',0};
270 sprintfW( buffer, LcidFormatW, lcid );
271 switch(syskind)
273 case SYS_WIN16: strcatW( buffer, win16W ); break;
274 case SYS_WIN32: strcatW( buffer, win32W ); break;
275 case SYS_WIN64: strcatW( buffer, win64W ); break;
276 default:
277 TRACE("Typelib is for unsupported syskind %i\n", syskind);
278 return NULL;
280 return buffer;
283 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
286 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
287 static HRESULT query_typelib_path( REFGUID guid, WORD wMaj, WORD wMin,
288 SYSKIND syskind, LCID lcid, LPBSTR path )
290 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
291 LCID myLCID = lcid;
292 HKEY hkey;
293 WCHAR buffer[60];
294 WCHAR Path[MAX_PATH];
295 LONG res;
297 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
299 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
300 get_typelib_key( guid, wMaj, wMin, buffer );
302 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
303 if (res == ERROR_FILE_NOT_FOUND)
305 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
306 return TYPE_E_LIBNOTREGISTERED;
308 else if (res != ERROR_SUCCESS)
310 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
311 return TYPE_E_REGISTRYACCESS;
314 while (hr != S_OK)
316 LONG dwPathLen = sizeof(Path);
318 get_lcid_subkey( myLCID, syskind, buffer );
320 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
322 if (!lcid)
323 break;
324 else if (myLCID == lcid)
326 /* try with sub-langid */
327 myLCID = SUBLANGID(lcid);
329 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
331 /* try with system langid */
332 myLCID = 0;
334 else
336 break;
339 else
341 *path = SysAllocString( Path );
342 hr = S_OK;
345 RegCloseKey( hkey );
346 TRACE_(typelib)("-- 0x%08x\n", hr);
347 return hr;
350 /****************************************************************************
351 * QueryPathOfRegTypeLib [OLEAUT32.164]
353 * Gets the path to a registered type library.
355 * PARAMS
356 * guid [I] referenced guid
357 * wMaj [I] major version
358 * wMin [I] minor version
359 * lcid [I] locale id
360 * path [O] path of typelib
362 * RETURNS
363 * Success: S_OK.
364 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
365 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
366 * opened.
368 HRESULT WINAPI QueryPathOfRegTypeLib( REFGUID guid, WORD wMaj, WORD wMin, LCID lcid, LPBSTR path )
370 #ifdef _WIN64
371 HRESULT hres = query_typelib_path( guid, wMaj, wMin, SYS_WIN64, lcid, path );
372 if(SUCCEEDED(hres))
373 return hres;
374 #endif
375 return query_typelib_path( guid, wMaj, wMin, SYS_WIN32, lcid, path );
378 /******************************************************************************
379 * CreateTypeLib [OLEAUT32.160] creates a typelib
381 * RETURNS
382 * Success: S_OK
383 * Failure: Status
385 HRESULT WINAPI CreateTypeLib(
386 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
388 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
389 return E_FAIL;
392 /******************************************************************************
393 * LoadTypeLib [OLEAUT32.161]
395 * Loads a type library
397 * PARAMS
398 * szFile [I] Name of file to load from.
399 * pptLib [O] Pointer that receives ITypeLib object on success.
401 * RETURNS
402 * Success: S_OK
403 * Failure: Status
405 * SEE
406 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
408 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
410 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
411 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
414 /******************************************************************************
415 * LoadTypeLibEx [OLEAUT32.183]
417 * Loads and optionally registers a type library
419 * RETURNS
420 * Success: S_OK
421 * Failure: Status
423 HRESULT WINAPI LoadTypeLibEx(
424 LPCOLESTR szFile, /* [in] Name of file to load from */
425 REGKIND regkind, /* [in] Specify kind of registration */
426 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
428 WCHAR szPath[MAX_PATH+1];
429 HRESULT res;
431 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
433 *pptLib = NULL;
435 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
437 if (SUCCEEDED(res))
438 switch(regkind)
440 case REGKIND_DEFAULT:
441 /* don't register typelibs supplied with full path. Experimentation confirms the following */
442 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
443 (szFile[0] && (szFile[1] == ':'))) break;
444 /* else fall-through */
446 case REGKIND_REGISTER:
447 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
449 IUnknown_Release(*pptLib);
450 *pptLib = 0;
452 break;
453 case REGKIND_NONE:
454 break;
457 TRACE(" returns %08x\n",res);
458 return res;
461 /******************************************************************************
462 * LoadRegTypeLib [OLEAUT32.162]
464 * Loads a registered type library.
466 * PARAMS
467 * rguid [I] GUID of the registered type library.
468 * wVerMajor [I] major version.
469 * wVerMinor [I] minor version.
470 * lcid [I] locale ID.
471 * ppTLib [O] pointer that receives an ITypeLib object on success.
473 * RETURNS
474 * Success: S_OK.
475 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
476 * LoadTypeLib.
478 HRESULT WINAPI LoadRegTypeLib(
479 REFGUID rguid,
480 WORD wVerMajor,
481 WORD wVerMinor,
482 LCID lcid,
483 ITypeLib **ppTLib)
485 BSTR bstr=NULL;
486 HRESULT res;
488 *ppTLib = NULL;
490 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
492 if(SUCCEEDED(res))
494 res= LoadTypeLib(bstr, ppTLib);
495 SysFreeString(bstr);
498 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
500 return res;
504 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
505 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
506 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
507 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
508 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
509 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
511 /******************************************************************************
512 * RegisterTypeLib [OLEAUT32.163]
513 * Adds information about a type library to the System Registry
514 * NOTES
515 * Docs: ITypeLib FAR * ptlib
516 * Docs: OLECHAR FAR* szFullPath
517 * Docs: OLECHAR FAR* szHelpDir
519 * RETURNS
520 * Success: S_OK
521 * Failure: Status
523 HRESULT WINAPI RegisterTypeLib(
524 ITypeLib * ptlib, /* [in] Pointer to the library*/
525 OLECHAR * szFullPath, /* [in] full Path of the library*/
526 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
527 may be NULL*/
529 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
530 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
531 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
532 HRESULT res;
533 TLIBATTR *attr;
534 WCHAR keyName[60];
535 WCHAR tmp[16];
536 HKEY key, subKey;
537 UINT types, tidx;
538 TYPEKIND kind;
539 DWORD disposition;
541 if (ptlib == NULL || szFullPath == NULL)
542 return E_INVALIDARG;
544 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
545 return E_FAIL;
547 #ifdef _WIN64
548 if (attr->syskind != SYS_WIN64) return TYPE_E_BADMODULEKIND;
549 #else
550 if (attr->syskind != SYS_WIN32 && attr->syskind != SYS_WIN16) return TYPE_E_BADMODULEKIND;
551 #endif
553 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
555 res = S_OK;
556 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
557 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
559 LPOLESTR doc;
561 /* Set the human-readable name of the typelib */
562 if (FAILED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
563 res = E_FAIL;
564 else if (doc)
566 if (RegSetValueExW(key, NULL, 0, REG_SZ,
567 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
568 res = E_FAIL;
570 SysFreeString(doc);
573 /* Make up the name of the typelib path subkey */
574 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
576 /* Create the typelib path subkey */
577 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
578 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
580 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
581 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
582 res = E_FAIL;
584 RegCloseKey(subKey);
586 else
587 res = E_FAIL;
589 /* Create the flags subkey */
590 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
591 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
593 /* FIXME: is %u correct? */
594 static const WCHAR formatW[] = {'%','u',0};
595 WCHAR buf[20];
596 sprintfW(buf, formatW, attr->wLibFlags);
597 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
598 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
599 res = E_FAIL;
601 RegCloseKey(subKey);
603 else
604 res = E_FAIL;
606 /* create the helpdir subkey */
607 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
608 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
610 BOOL freeHelpDir = FALSE;
611 OLECHAR* pIndexStr;
613 /* if we created a new key, and helpDir was null, set the helpdir
614 to the directory which contains the typelib. However,
615 if we just opened an existing key, we leave the helpdir alone */
616 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
617 szHelpDir = SysAllocString(szFullPath);
618 pIndexStr = strrchrW(szHelpDir, '\\');
619 if (pIndexStr) {
620 *pIndexStr = 0;
622 freeHelpDir = TRUE;
625 /* if we have an szHelpDir, set it! */
626 if (szHelpDir != NULL) {
627 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
628 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
629 res = E_FAIL;
633 /* tidy up */
634 if (freeHelpDir) SysFreeString(szHelpDir);
635 RegCloseKey(subKey);
637 } else {
638 res = E_FAIL;
641 RegCloseKey(key);
643 else
644 res = E_FAIL;
646 /* register OLE Automation-compatible interfaces for this typelib */
647 types = ITypeLib_GetTypeInfoCount(ptlib);
648 for (tidx=0; tidx<types; tidx++) {
649 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
650 LPOLESTR name = NULL;
651 ITypeInfo *tinfo = NULL;
653 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
655 switch (kind) {
656 case TKIND_INTERFACE:
657 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
658 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
659 break;
661 case TKIND_DISPATCH:
662 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
663 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
664 break;
666 default:
667 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
668 break;
671 if (tinfo) {
672 TYPEATTR *tattr = NULL;
673 ITypeInfo_GetTypeAttr(tinfo, &tattr);
675 if (tattr) {
676 TRACE_(typelib)("guid=%s, flags=%04x (",
677 debugstr_guid(&tattr->guid),
678 tattr->wTypeFlags);
680 if (TRACE_ON(typelib)) {
681 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
682 XX(FAPPOBJECT);
683 XX(FCANCREATE);
684 XX(FLICENSED);
685 XX(FPREDECLID);
686 XX(FHIDDEN);
687 XX(FCONTROL);
688 XX(FDUAL);
689 XX(FNONEXTENSIBLE);
690 XX(FOLEAUTOMATION);
691 XX(FRESTRICTED);
692 XX(FAGGREGATABLE);
693 XX(FREPLACEABLE);
694 XX(FDISPATCHABLE);
695 XX(FREVERSEBIND);
696 XX(FPROXY);
697 #undef XX
698 MESSAGE("\n");
701 /* Register all dispinterfaces (which includes dual interfaces) and
702 oleautomation interfaces */
703 if ((kind == TKIND_INTERFACE && (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
704 kind == TKIND_DISPATCH)
706 /* register interface<->typelib coupling */
707 get_interface_key( &tattr->guid, keyName );
708 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
709 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
711 if (name)
712 RegSetValueExW(key, NULL, 0, REG_SZ,
713 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
715 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
716 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
717 RegSetValueExW(subKey, NULL, 0, REG_SZ,
718 (const BYTE *)PSOA, sizeof PSOA);
719 RegCloseKey(subKey);
722 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
723 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
724 RegSetValueExW(subKey, NULL, 0, REG_SZ,
725 (const BYTE *)PSOA, sizeof PSOA);
726 RegCloseKey(subKey);
729 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
730 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
732 WCHAR buffer[40];
733 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
734 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
736 StringFromGUID2(&attr->guid, buffer, 40);
737 RegSetValueExW(subKey, NULL, 0, REG_SZ,
738 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
739 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
740 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
741 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
742 RegCloseKey(subKey);
745 RegCloseKey(key);
749 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
752 ITypeInfo_Release(tinfo);
755 SysFreeString(name);
759 ITypeLib_ReleaseTLibAttr(ptlib, attr);
761 return res;
765 /******************************************************************************
766 * UnRegisterTypeLib [OLEAUT32.186]
767 * Removes information about a type library from the System Registry
768 * NOTES
770 * RETURNS
771 * Success: S_OK
772 * Failure: Status
774 HRESULT WINAPI UnRegisterTypeLib(
775 REFGUID libid, /* [in] Guid of the library */
776 WORD wVerMajor, /* [in] major version */
777 WORD wVerMinor, /* [in] minor version */
778 LCID lcid, /* [in] locale id */
779 SYSKIND syskind)
781 BSTR tlibPath = NULL;
782 DWORD tmpLength;
783 WCHAR keyName[60];
784 WCHAR subKeyName[50];
785 int result = S_OK;
786 DWORD i = 0;
787 BOOL deleteOtherStuff;
788 HKEY key = NULL;
789 HKEY subKey = NULL;
790 TYPEATTR* typeAttr = NULL;
791 TYPEKIND kind;
792 ITypeInfo* typeInfo = NULL;
793 ITypeLib* typeLib = NULL;
794 int numTypes;
796 TRACE("(IID: %s)\n",debugstr_guid(libid));
798 /* Create the path to the key */
799 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
801 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
803 TRACE("Unsupported syskind %i\n", syskind);
804 result = E_INVALIDARG;
805 goto end;
808 /* get the path to the typelib on disk */
809 if (query_typelib_path(libid, wVerMajor, wVerMinor, syskind, lcid, &tlibPath) != S_OK) {
810 result = E_INVALIDARG;
811 goto end;
814 /* Try and open the key to the type library. */
815 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
816 result = E_INVALIDARG;
817 goto end;
820 /* Try and load the type library */
821 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
822 result = TYPE_E_INVALIDSTATE;
823 goto end;
826 /* remove any types registered with this typelib */
827 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
828 for (i=0; i<numTypes; i++) {
829 /* get the kind of type */
830 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
831 goto enddeleteloop;
834 /* skip non-interfaces, and get type info for the type */
835 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
836 goto enddeleteloop;
838 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
839 goto enddeleteloop;
841 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
842 goto enddeleteloop;
845 if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
846 kind == TKIND_DISPATCH)
848 /* the path to the type */
849 get_interface_key( &typeAttr->guid, subKeyName );
851 /* Delete its bits */
852 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS)
853 goto enddeleteloop;
855 RegDeleteKeyW(subKey, ProxyStubClsidW);
856 RegDeleteKeyW(subKey, ProxyStubClsid32W);
857 RegDeleteKeyW(subKey, TypeLibW);
858 RegCloseKey(subKey);
859 subKey = NULL;
860 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
863 enddeleteloop:
864 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
865 typeAttr = NULL;
866 if (typeInfo) ITypeInfo_Release(typeInfo);
867 typeInfo = NULL;
870 /* Now, delete the type library path subkey */
871 get_lcid_subkey( lcid, syskind, subKeyName );
872 RegDeleteKeyW(key, subKeyName);
873 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
874 RegDeleteKeyW(key, subKeyName);
876 /* check if there is anything besides the FLAGS/HELPDIR keys.
877 If there is, we don't delete them */
878 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
879 deleteOtherStuff = TRUE;
880 i = 0;
881 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
882 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
884 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
885 if (!strcmpW(subKeyName, FLAGSW)) continue;
886 if (!strcmpW(subKeyName, HELPDIRW)) continue;
887 deleteOtherStuff = FALSE;
888 break;
891 /* only delete the other parts of the key if we're absolutely sure */
892 if (deleteOtherStuff) {
893 RegDeleteKeyW(key, FLAGSW);
894 RegDeleteKeyW(key, HELPDIRW);
895 RegCloseKey(key);
896 key = NULL;
898 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
899 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
900 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
903 end:
904 SysFreeString(tlibPath);
905 if (typeLib) ITypeLib_Release(typeLib);
906 if (subKey) RegCloseKey(subKey);
907 if (key) RegCloseKey(key);
908 return result;
911 /******************************************************************************
912 * RegisterTypeLibForUser [OLEAUT32.442]
913 * Adds information about a type library to the user registry
914 * NOTES
915 * Docs: ITypeLib FAR * ptlib
916 * Docs: OLECHAR FAR* szFullPath
917 * Docs: OLECHAR FAR* szHelpDir
919 * RETURNS
920 * Success: S_OK
921 * Failure: Status
923 HRESULT WINAPI RegisterTypeLibForUser(
924 ITypeLib * ptlib, /* [in] Pointer to the library*/
925 OLECHAR * szFullPath, /* [in] full Path of the library*/
926 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
927 may be NULL*/
929 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib,
930 debugstr_w(szFullPath), debugstr_w(szHelpDir));
931 return RegisterTypeLib(ptlib, szFullPath, szHelpDir);
934 /******************************************************************************
935 * UnRegisterTypeLibForUser [OLEAUT32.443]
936 * Removes information about a type library from the user registry
938 * RETURNS
939 * Success: S_OK
940 * Failure: Status
942 HRESULT WINAPI UnRegisterTypeLibForUser(
943 REFGUID libid, /* [in] GUID of the library */
944 WORD wVerMajor, /* [in] major version */
945 WORD wVerMinor, /* [in] minor version */
946 LCID lcid, /* [in] locale id */
947 SYSKIND syskind)
949 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
950 debugstr_guid(libid), wVerMajor, wVerMinor, lcid, syskind);
951 return UnRegisterTypeLib(libid, wVerMajor, wVerMinor, lcid, syskind);
954 /*======================= ITypeLib implementation =======================*/
956 typedef struct tagTLBCustData
958 GUID guid;
959 VARIANT data;
960 struct tagTLBCustData* next;
961 } TLBCustData;
963 /* data structure for import typelibs */
964 typedef struct tagTLBImpLib
966 int offset; /* offset in the file (MSFT)
967 offset in nametable (SLTG)
968 just used to identify library while reading
969 data from file */
970 GUID guid; /* libid */
971 BSTR name; /* name */
973 LCID lcid; /* lcid of imported typelib */
975 WORD wVersionMajor; /* major version number */
976 WORD wVersionMinor; /* minor version number */
978 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
979 NULL if not yet loaded */
980 struct tagTLBImpLib * next;
981 } TLBImpLib;
983 /* internal ITypeLib data */
984 typedef struct tagITypeLibImpl
986 const ITypeLib2Vtbl *lpVtbl;
987 const ITypeCompVtbl *lpVtblTypeComp;
988 LONG ref;
989 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
990 LCID lcid;
992 /* strings can be stored in tlb as multibyte strings BUT they are *always*
993 * exported to the application as a UNICODE string.
995 BSTR Name;
996 BSTR DocString;
997 BSTR HelpFile;
998 BSTR HelpStringDll;
999 DWORD dwHelpContext;
1000 int TypeInfoCount; /* nr of typeinfo's in librarry */
1001 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
1002 int ctCustData; /* number of items in cust data list */
1003 TLBCustData * pCustData; /* linked list to cust data */
1004 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
1005 int ctTypeDesc; /* number of items in type desc array */
1006 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1007 library. Only used while reading MSFT
1008 typelibs */
1009 struct list ref_list; /* list of ref types in this typelib */
1010 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1013 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1014 struct tagITypeLibImpl *next, *prev;
1015 WCHAR *path;
1016 INT index;
1017 } ITypeLibImpl;
1019 static const ITypeLib2Vtbl tlbvt;
1020 static const ITypeCompVtbl tlbtcvt;
1022 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1024 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
1027 /* ITypeLib methods */
1028 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1029 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1031 /*======================= ITypeInfo implementation =======================*/
1033 /* data for referenced types */
1034 typedef struct tagTLBRefType
1036 INT index; /* Type index for internal ref or for external ref
1037 it the format is SLTG. -2 indicates to
1038 use guid */
1040 GUID guid; /* guid of the referenced type */
1041 /* if index == TLB_REF_USE_GUID */
1043 HREFTYPE reference; /* The href of this ref */
1044 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1045 TLB_REF_INTERNAL for internal refs
1046 TLB_REF_NOT_FOUND for broken refs */
1048 struct list entry;
1049 } TLBRefType;
1051 #define TLB_REF_USE_GUID -2
1053 #define TLB_REF_INTERNAL (void*)-2
1054 #define TLB_REF_NOT_FOUND (void*)-1
1056 /* internal Parameter data */
1057 typedef struct tagTLBParDesc
1059 BSTR Name;
1060 int ctCustData;
1061 TLBCustData * pCustData; /* linked list to cust data */
1062 } TLBParDesc;
1064 /* internal Function data */
1065 typedef struct tagTLBFuncDesc
1067 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1068 BSTR Name; /* the name of this function */
1069 TLBParDesc *pParamDesc; /* array with param names and custom data */
1070 int helpcontext;
1071 int HelpStringContext;
1072 BSTR HelpString;
1073 BSTR Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1074 int ctCustData;
1075 TLBCustData * pCustData; /* linked list to cust data; */
1076 struct tagTLBFuncDesc * next;
1077 } TLBFuncDesc;
1079 /* internal Variable data */
1080 typedef struct tagTLBVarDesc
1082 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1083 BSTR Name; /* the name of this variable */
1084 int HelpContext;
1085 int HelpStringContext; /* FIXME: where? */
1086 BSTR HelpString;
1087 int ctCustData;
1088 TLBCustData * pCustData;/* linked list to cust data; */
1089 struct tagTLBVarDesc * next;
1090 } TLBVarDesc;
1092 /* internal implemented interface data */
1093 typedef struct tagTLBImplType
1095 HREFTYPE hRef; /* hRef of interface */
1096 int implflags; /* IMPLFLAG_*s */
1097 int ctCustData;
1098 TLBCustData * pCustData;/* linked list to custom data; */
1099 struct tagTLBImplType *next;
1100 } TLBImplType;
1102 /* internal TypeInfo data */
1103 typedef struct tagITypeInfoImpl
1105 const ITypeInfo2Vtbl *lpVtbl;
1106 const ITypeCompVtbl *lpVtblTypeComp;
1107 LONG ref;
1108 BOOL not_attached_to_typelib;
1109 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1110 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1111 int index; /* index in this typelib; */
1112 HREFTYPE hreftype; /* hreftype for app object binding */
1113 /* type libs seem to store the doc strings in ascii
1114 * so why should we do it in unicode?
1116 BSTR Name;
1117 BSTR DocString;
1118 BSTR DllName;
1119 DWORD dwHelpContext;
1120 DWORD dwHelpStringContext;
1122 /* functions */
1123 TLBFuncDesc * funclist; /* linked list with function descriptions */
1125 /* variables */
1126 TLBVarDesc * varlist; /* linked list with variable descriptions */
1128 /* Implemented Interfaces */
1129 TLBImplType * impltypelist;
1131 int ctCustData;
1132 TLBCustData * pCustData; /* linked list to cust data; */
1133 struct tagITypeInfoImpl * next;
1134 } ITypeInfoImpl;
1136 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1138 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1141 static const ITypeInfo2Vtbl tinfvt;
1142 static const ITypeCompVtbl tcompvt;
1144 static ITypeInfo2 * ITypeInfo_Constructor(void);
1145 static void ITypeInfo_fnDestroy(ITypeInfoImpl *This);
1147 typedef struct tagTLBContext
1149 unsigned int oStart; /* start of TLB in file */
1150 unsigned int pos; /* current pos */
1151 unsigned int length; /* total length */
1152 void *mapping; /* memory mapping */
1153 MSFT_SegDir * pTblDir;
1154 ITypeLibImpl* pLibInfo;
1155 } TLBContext;
1158 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1161 debug
1163 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1164 if (pTD->vt & VT_RESERVED)
1165 szVarType += strlen(strcpy(szVarType, "reserved | "));
1166 if (pTD->vt & VT_BYREF)
1167 szVarType += strlen(strcpy(szVarType, "ref to "));
1168 if (pTD->vt & VT_ARRAY)
1169 szVarType += strlen(strcpy(szVarType, "array of "));
1170 if (pTD->vt & VT_VECTOR)
1171 szVarType += strlen(strcpy(szVarType, "vector of "));
1172 switch(pTD->vt & VT_TYPEMASK) {
1173 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1174 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1175 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1176 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1177 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1178 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1179 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1180 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1181 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1182 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1183 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1184 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1185 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1186 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1187 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1188 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1189 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1190 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1191 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1192 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1193 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1194 pTD->u.hreftype); break;
1195 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1196 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1197 case VT_PTR: sprintf(szVarType, "ptr to ");
1198 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1199 break;
1200 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1201 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1202 break;
1203 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1204 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1205 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1206 break;
1208 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1212 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1213 char buf[200];
1214 USHORT flags = edesc->u.paramdesc.wParamFlags;
1215 dump_TypeDesc(&edesc->tdesc,buf);
1216 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1217 MESSAGE("\t\tu.paramdesc.wParamFlags");
1218 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1219 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1220 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1221 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1222 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1223 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1224 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1225 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1226 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1228 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1229 int i;
1230 MESSAGE("memid is %08x\n",funcdesc->memid);
1231 for (i=0;i<funcdesc->cParams;i++) {
1232 MESSAGE("Param %d:\n",i);
1233 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1235 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1236 switch (funcdesc->funckind) {
1237 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1238 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1239 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1240 case FUNC_STATIC: MESSAGE("static");break;
1241 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1242 default: MESSAGE("unknown");break;
1244 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1245 switch (funcdesc->invkind) {
1246 case INVOKE_FUNC: MESSAGE("func");break;
1247 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1248 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1249 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1251 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1252 switch (funcdesc->callconv) {
1253 case CC_CDECL: MESSAGE("cdecl");break;
1254 case CC_PASCAL: MESSAGE("pascal");break;
1255 case CC_STDCALL: MESSAGE("stdcall");break;
1256 case CC_SYSCALL: MESSAGE("syscall");break;
1257 default:break;
1259 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1260 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1261 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1263 MESSAGE("\telemdescFunc (return value type):\n");
1264 dump_ELEMDESC(&funcdesc->elemdescFunc);
1267 static const char * const typekind_desc[] =
1269 "TKIND_ENUM",
1270 "TKIND_RECORD",
1271 "TKIND_MODULE",
1272 "TKIND_INTERFACE",
1273 "TKIND_DISPATCH",
1274 "TKIND_COCLASS",
1275 "TKIND_ALIAS",
1276 "TKIND_UNION",
1277 "TKIND_MAX"
1280 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1282 int i;
1283 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1284 for (i=0;i<pfd->funcdesc.cParams;i++)
1285 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1288 dump_FUNCDESC(&(pfd->funcdesc));
1290 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1291 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1293 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1295 while (pfd)
1297 dump_TLBFuncDescOne(pfd);
1298 pfd = pfd->next;
1301 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1303 while (pvd)
1305 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1306 pvd = pvd->next;
1310 static void dump_TLBImpLib(const TLBImpLib *import)
1312 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1313 debugstr_w(import->name));
1314 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1315 import->wVersionMinor, import->lcid, import->offset);
1318 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1320 TLBRefType *ref;
1322 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1324 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1325 if(ref->index == -1)
1326 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1327 else
1328 TRACE_(typelib)("type no: %d\n", ref->index);
1330 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1332 TRACE_(typelib)("in lib\n");
1333 dump_TLBImpLib(ref->pImpTLInfo);
1338 static void dump_TLBImplType(const TLBImplType * impl)
1340 while (impl) {
1341 TRACE_(typelib)(
1342 "implementing/inheriting interface hRef = %x implflags %x\n",
1343 impl->hRef, impl->implflags);
1344 impl = impl->next;
1348 static void dump_Variant(const VARIANT * pvar)
1350 SYSTEMTIME st;
1352 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1354 if (pvar)
1356 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1357 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1359 TRACE(",%p", V_BYREF(pvar));
1361 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1363 TRACE(",%p", V_ARRAY(pvar));
1365 else switch (V_TYPE(pvar))
1367 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1368 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1369 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1370 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1371 case VT_INT:
1372 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1373 case VT_UINT:
1374 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1375 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1376 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1377 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1378 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1379 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1380 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1381 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1382 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1383 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1384 V_CY(pvar).s.Lo); break;
1385 case VT_DATE:
1386 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1387 TRACE(",<invalid>");
1388 else
1389 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1390 st.wHour, st.wMinute, st.wSecond);
1391 break;
1392 case VT_ERROR:
1393 case VT_VOID:
1394 case VT_USERDEFINED:
1395 case VT_EMPTY:
1396 case VT_NULL: break;
1397 default: TRACE(",?"); break;
1400 TRACE("}\n");
1403 static void dump_DispParms(const DISPPARAMS * pdp)
1405 unsigned int index;
1407 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1409 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1411 TRACE("named args:\n");
1412 for (index = 0; index < pdp->cNamedArgs; index++)
1413 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1416 if (pdp->cArgs && pdp->rgvarg)
1418 TRACE("args:\n");
1419 for (index = 0; index < pdp->cArgs; index++)
1420 dump_Variant( &pdp->rgvarg[index] );
1424 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1426 TRACE("%p ref=%u\n", pty, pty->ref);
1427 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1428 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1429 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1430 TRACE("fct:%u var:%u impl:%u\n",
1431 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1432 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1433 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1434 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1435 if (TRACE_ON(ole))
1436 dump_TLBFuncDesc(pty->funclist);
1437 dump_TLBVarDesc(pty->varlist);
1438 dump_TLBImplType(pty->impltypelist);
1441 static void dump_VARDESC(const VARDESC *v)
1443 MESSAGE("memid %d\n",v->memid);
1444 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1445 MESSAGE("oInst %d\n",v->u.oInst);
1446 dump_ELEMDESC(&(v->elemdescVar));
1447 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1448 MESSAGE("varkind %d\n",v->varkind);
1451 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1453 /* VT_LPWSTR is largest type that */
1454 /* may appear in type description*/
1455 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1456 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1457 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1458 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1459 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1460 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1461 {{0},30},{{0},31}
1464 static void TLB_abort(void)
1466 DebugBreak();
1469 static void * TLB_Alloc(unsigned size) __WINE_ALLOC_SIZE(1);
1470 static void * TLB_Alloc(unsigned size)
1472 void * ret;
1473 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1474 /* FIXME */
1475 ERR("cannot allocate memory\n");
1477 return ret;
1480 static void TLB_Free(void * ptr)
1482 HeapFree(GetProcessHeap(), 0, ptr);
1485 /* returns the size required for a deep copy of a typedesc into a
1486 * flat buffer */
1487 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1489 SIZE_T size = 0;
1491 if (alloc_initial_space)
1492 size += sizeof(TYPEDESC);
1494 switch (tdesc->vt)
1496 case VT_PTR:
1497 case VT_SAFEARRAY:
1498 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1499 break;
1500 case VT_CARRAY:
1501 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1502 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1503 break;
1505 return size;
1508 /* deep copy a typedesc into a flat buffer */
1509 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1511 if (!dest)
1513 dest = buffer;
1514 buffer = (char *)buffer + sizeof(TYPEDESC);
1517 *dest = *src;
1519 switch (src->vt)
1521 case VT_PTR:
1522 case VT_SAFEARRAY:
1523 dest->u.lptdesc = buffer;
1524 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1525 break;
1526 case VT_CARRAY:
1527 dest->u.lpadesc = buffer;
1528 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1529 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1530 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1531 break;
1533 return buffer;
1536 /* free custom data allocated by MSFT_CustData */
1537 static inline void TLB_FreeCustData(TLBCustData *pCustData)
1539 TLBCustData *pCustDataNext;
1540 for (; pCustData; pCustData = pCustDataNext)
1542 VariantClear(&pCustData->data);
1544 pCustDataNext = pCustData->next;
1545 TLB_Free(pCustData);
1549 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1551 DWORD len;
1552 BSTR ret;
1554 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1555 ret = SysAllocStringLen(NULL, len - 1);
1556 if (!ret) return ret;
1557 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1558 return ret;
1561 /**********************************************************************
1563 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1565 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1567 return pcx->pos;
1570 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
1572 if (where != DO_NOT_SEEK)
1574 where += pcx->oStart;
1575 if (where > pcx->length)
1577 /* FIXME */
1578 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
1579 TLB_abort();
1581 pcx->pos = where;
1585 /* read function */
1586 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
1588 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
1589 pcx->pos, count, pcx->oStart, pcx->length, where);
1591 MSFT_Seek(pcx, where);
1592 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1593 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1594 pcx->pos += count;
1595 return count;
1598 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1599 LONG where )
1601 DWORD ret;
1603 ret = MSFT_Read(buffer, count, pcx, where);
1604 FromLEDWords(buffer, ret);
1606 return ret;
1609 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1610 LONG where )
1612 DWORD ret;
1614 ret = MSFT_Read(buffer, count, pcx, where);
1615 FromLEWords(buffer, ret);
1617 return ret;
1620 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1622 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1623 memset(pGuid,0, sizeof(GUID));
1624 return;
1626 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1627 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1628 pGuid->Data2 = FromLEWord(pGuid->Data2);
1629 pGuid->Data3 = FromLEWord(pGuid->Data3);
1630 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1633 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1635 MSFT_NameIntro niName;
1637 if (offset < 0)
1639 ERR_(typelib)("bad offset %d\n", offset);
1640 return -1;
1643 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1644 pcx->pTblDir->pNametab.offset+offset);
1646 return niName.hreftype;
1649 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1651 char * name;
1652 MSFT_NameIntro niName;
1653 int lengthInChars;
1654 BSTR bstrName = NULL;
1656 if (offset < 0)
1658 ERR_(typelib)("bad offset %d\n", offset);
1659 return NULL;
1661 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1662 pcx->pTblDir->pNametab.offset+offset);
1663 niName.namelen &= 0xFF; /* FIXME: correct ? */
1664 name=TLB_Alloc((niName.namelen & 0xff) +1);
1665 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1666 name[niName.namelen & 0xff]='\0';
1668 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1669 name, -1, NULL, 0);
1671 /* no invalid characters in string */
1672 if (lengthInChars)
1674 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1676 /* don't check for invalid character since this has been done previously */
1677 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1679 TLB_Free(name);
1681 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1682 return bstrName;
1685 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1687 char * string;
1688 INT16 length;
1689 int lengthInChars;
1690 BSTR bstr = NULL;
1692 if(offset<0) return NULL;
1693 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1694 if(length <= 0) return 0;
1695 string=TLB_Alloc(length +1);
1696 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1697 string[length]='\0';
1699 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1700 string, -1, NULL, 0);
1702 /* no invalid characters in string */
1703 if (lengthInChars)
1705 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1707 /* don't check for invalid character since this has been done previously */
1708 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1710 TLB_Free(string);
1712 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1713 return bstr;
1716 * read a value and fill a VARIANT structure
1718 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1720 int size;
1722 TRACE_(typelib)("\n");
1724 if(offset <0) { /* data are packed in here */
1725 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1726 V_I4(pVar) = offset & 0x3ffffff;
1727 return;
1729 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1730 pcx->pTblDir->pCustData.offset + offset );
1731 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1732 switch (V_VT(pVar)){
1733 case VT_EMPTY: /* FIXME: is this right? */
1734 case VT_NULL: /* FIXME: is this right? */
1735 case VT_I2 : /* this should not happen */
1736 case VT_I4 :
1737 case VT_R4 :
1738 case VT_ERROR :
1739 case VT_BOOL :
1740 case VT_I1 :
1741 case VT_UI1 :
1742 case VT_UI2 :
1743 case VT_UI4 :
1744 case VT_INT :
1745 case VT_UINT :
1746 case VT_VOID : /* FIXME: is this right? */
1747 case VT_HRESULT :
1748 size=4; break;
1749 case VT_R8 :
1750 case VT_CY :
1751 case VT_DATE :
1752 case VT_I8 :
1753 case VT_UI8 :
1754 case VT_DECIMAL : /* FIXME: is this right? */
1755 case VT_FILETIME :
1756 size=8;break;
1757 /* pointer types with known behaviour */
1758 case VT_BSTR :{
1759 char * ptr;
1760 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1761 if(size < 0) {
1762 char next;
1763 DWORD origPos = MSFT_Tell(pcx), nullPos;
1765 do {
1766 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1767 } while (next);
1768 nullPos = MSFT_Tell(pcx);
1769 size = nullPos - origPos;
1770 MSFT_Seek(pcx, origPos);
1772 ptr=TLB_Alloc(size);/* allocate temp buffer */
1773 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1774 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1775 /* FIXME: do we need a AtoW conversion here? */
1776 V_UNION(pVar, bstrVal[size])='\0';
1777 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1778 TLB_Free(ptr);
1780 size=-4; break;
1781 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1782 case VT_DISPATCH :
1783 case VT_VARIANT :
1784 case VT_UNKNOWN :
1785 case VT_PTR :
1786 case VT_SAFEARRAY :
1787 case VT_CARRAY :
1788 case VT_USERDEFINED :
1789 case VT_LPSTR :
1790 case VT_LPWSTR :
1791 case VT_BLOB :
1792 case VT_STREAM :
1793 case VT_STORAGE :
1794 case VT_STREAMED_OBJECT :
1795 case VT_STORED_OBJECT :
1796 case VT_BLOB_OBJECT :
1797 case VT_CF :
1798 case VT_CLSID :
1799 default:
1800 size=0;
1801 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1802 V_VT(pVar));
1805 if(size>0) /* (big|small) endian correct? */
1806 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1807 return;
1810 * create a linked list with custom data
1812 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1814 MSFT_CDGuid entry;
1815 TLBCustData* pNew;
1816 int count=0;
1818 TRACE_(typelib)("\n");
1820 while(offset >=0){
1821 count++;
1822 pNew=TLB_Alloc(sizeof(TLBCustData));
1823 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1824 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1825 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1826 /* add new custom data at head of the list */
1827 pNew->next=*ppCustData;
1828 *ppCustData=pNew;
1829 offset = entry.next;
1831 return count;
1834 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1835 ITypeInfoImpl *pTI)
1837 if(type <0)
1838 pTd->vt=type & VT_TYPEMASK;
1839 else
1840 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1842 if(pTd->vt == VT_USERDEFINED)
1843 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1845 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1848 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1850 /* resolve referenced type if any */
1851 while (lpTypeDesc)
1853 switch (lpTypeDesc->vt)
1855 case VT_PTR:
1856 lpTypeDesc = lpTypeDesc->u.lptdesc;
1857 break;
1859 case VT_CARRAY:
1860 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1861 break;
1863 case VT_USERDEFINED:
1864 MSFT_DoRefType(pcx, pTI->pTypeLib,
1865 lpTypeDesc->u.hreftype);
1867 lpTypeDesc = NULL;
1868 break;
1870 default:
1871 lpTypeDesc = NULL;
1876 static void
1877 MSFT_DoFuncs(TLBContext* pcx,
1878 ITypeInfoImpl* pTI,
1879 int cFuncs,
1880 int cVars,
1881 int offset,
1882 TLBFuncDesc** pptfd)
1885 * member information is stored in a data structure at offset
1886 * indicated by the memoffset field of the typeinfo structure
1887 * There are several distinctive parts.
1888 * The first part starts with a field that holds the total length
1889 * of this (first) part excluding this field. Then follow the records,
1890 * for each member there is one record.
1892 * The first entry is always the length of the record (including this
1893 * length word).
1894 * The rest of the record depends on the type of the member. If there is
1895 * a field indicating the member type (function, variable, interface, etc)
1896 * I have not found it yet. At this time we depend on the information
1897 * in the type info and the usual order how things are stored.
1899 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1900 * for each member;
1902 * Third is an equal sized array with file offsets to the name entry
1903 * of each member.
1905 * The fourth and last (?) part is an array with offsets to the records
1906 * in the first part of this file segment.
1909 int infolen, nameoffset, reclength, nrattributes, i;
1910 int recoffset = offset + sizeof(INT);
1912 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1913 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1914 TLBFuncDesc *ptfd_prev = NULL;
1916 TRACE_(typelib)("\n");
1918 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1920 for ( i = 0; i < cFuncs ; i++ )
1922 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1924 /* name, eventually add to a hash table */
1925 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1926 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1928 /* nameoffset is sometimes -1 on the second half of a propget/propput
1929 * pair of functions */
1930 if ((nameoffset == -1) && (i > 0))
1931 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1932 else
1933 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1935 /* read the function information record */
1936 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1938 reclength &= 0xffff;
1940 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1942 /* do the attributes */
1943 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1944 / sizeof(int);
1946 if ( nrattributes > 0 )
1948 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1950 if ( nrattributes > 1 )
1952 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1953 pFuncRec->OptAttr[1]) ;
1955 if ( nrattributes > 2 )
1957 if ( pFuncRec->FKCCIC & 0x2000 )
1959 if (!IS_INTRESOURCE(pFuncRec->OptAttr[2]))
1960 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->OptAttr[2]);
1961 (*pptfd)->Entry = (BSTR)(DWORD_PTR)LOWORD(pFuncRec->OptAttr[2]);
1963 else
1965 (*pptfd)->Entry = MSFT_ReadString(pcx,
1966 pFuncRec->OptAttr[2]);
1968 if( nrattributes > 5 )
1970 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1972 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1974 MSFT_CustData(pcx,
1975 pFuncRec->OptAttr[6],
1976 &(*pptfd)->pCustData);
1980 else
1982 (*pptfd)->Entry = (BSTR)-1;
1987 /* fill the FuncDesc Structure */
1988 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1989 offset + infolen + ( i + 1) * sizeof(INT));
1991 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1992 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1993 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1994 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1995 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1996 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset;
1997 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1999 MSFT_GetTdesc(pcx,
2000 pFuncRec->DataType,
2001 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
2002 pTI);
2003 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
2005 /* do the parameters/arguments */
2006 if(pFuncRec->nrargs)
2008 int j = 0;
2009 MSFT_ParameterInfo paraminfo;
2011 (*pptfd)->funcdesc.lprgelemdescParam =
2012 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
2014 (*pptfd)->pParamDesc =
2015 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
2017 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2018 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2020 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2022 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
2024 MSFT_GetTdesc(pcx,
2025 paraminfo.DataType,
2026 &elemdesc->tdesc,
2027 pTI);
2029 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2031 /* name */
2032 if (paraminfo.oName == -1)
2033 /* this occurs for [propput] or [propget] methods, so
2034 * we should just set the name of the parameter to the
2035 * name of the method. */
2036 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
2037 else
2038 (*pptfd)->pParamDesc[j].Name =
2039 MSFT_ReadName( pcx, paraminfo.oName );
2040 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
2042 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
2044 /* default value */
2045 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2046 (pFuncRec->FKCCIC & 0x1000) )
2048 INT* pInt = (INT *)((char *)pFuncRec +
2049 reclength -
2050 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
2052 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2054 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
2055 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2057 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2058 pInt[j], pcx);
2060 else
2061 elemdesc->u.paramdesc.pparamdescex = NULL;
2062 /* custom info */
2063 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
2065 MSFT_CustData(pcx,
2066 pFuncRec->OptAttr[7+j],
2067 &(*pptfd)->pParamDesc[j].pCustData);
2070 /* SEEK value = jump to offset,
2071 * from there jump to the end of record,
2072 * go back by (j-1) arguments
2074 MSFT_ReadLEDWords( &paraminfo ,
2075 sizeof(MSFT_ParameterInfo), pcx,
2076 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2077 * sizeof(MSFT_ParameterInfo)));
2081 /* scode is not used: archaic win16 stuff FIXME: right? */
2082 (*pptfd)->funcdesc.cScodes = 0 ;
2083 (*pptfd)->funcdesc.lprgscode = NULL ;
2085 ptfd_prev = *pptfd;
2086 pptfd = & ((*pptfd)->next);
2087 recoffset += reclength;
2089 HeapFree(GetProcessHeap(), 0, recbuf);
2092 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2093 int cVars, int offset, TLBVarDesc ** pptvd)
2095 int infolen, nameoffset, reclength;
2096 char recbuf[256];
2097 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
2098 int i;
2099 int recoffset;
2101 TRACE_(typelib)("\n");
2103 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2104 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2105 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2106 recoffset += offset+sizeof(INT);
2107 for(i=0;i<cVars;i++){
2108 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
2109 /* name, eventually add to a hash table */
2110 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2111 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2112 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
2113 /* read the variable information record */
2114 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
2115 reclength &=0xff;
2116 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
2117 /* Optional data */
2118 if(reclength >(6*sizeof(INT)) )
2119 (*pptvd)->HelpContext=pVarRec->HelpContext;
2120 if(reclength >(7*sizeof(INT)) )
2121 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
2122 if(reclength >(8*sizeof(INT)) )
2123 if(reclength >(9*sizeof(INT)) )
2124 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
2125 /* fill the VarDesc Structure */
2126 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
2127 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2128 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
2129 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
2130 MSFT_GetTdesc(pcx, pVarRec->DataType,
2131 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
2132 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2133 if(pVarRec->VarKind == VAR_CONST ){
2134 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
2135 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
2136 pVarRec->OffsValue, pcx);
2137 } else
2138 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
2139 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
2140 pptvd=&((*pptvd)->next);
2141 recoffset += reclength;
2144 /* fill in data for a hreftype (offset). When the referenced type is contained
2145 * in the typelib, it's just an (file) offset in the type info base dir.
2146 * If comes from import, it's an offset+1 in the ImpInfo table
2147 * */
2148 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2149 int offset)
2151 TLBRefType *ref;
2153 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2155 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2157 if(ref->reference == offset) return;
2160 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
2161 list_add_tail(&pTL->ref_list, &ref->entry);
2163 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2164 /* external typelib */
2165 MSFT_ImpInfo impinfo;
2166 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2168 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2170 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2171 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2172 while (pImpLib){ /* search the known offsets of all import libraries */
2173 if(pImpLib->offset==impinfo.oImpFile) break;
2174 pImpLib=pImpLib->next;
2176 if(pImpLib){
2177 ref->reference = offset;
2178 ref->pImpTLInfo = pImpLib;
2179 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2180 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2181 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2182 ref->index = TLB_REF_USE_GUID;
2183 } else
2184 ref->index = impinfo.oGuid;
2185 }else{
2186 ERR("Cannot find a reference\n");
2187 ref->reference = -1;
2188 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2190 }else{
2191 /* in this typelib */
2192 ref->index = MSFT_HREFTYPE_INDEX(offset);
2193 ref->reference = offset;
2194 ref->pImpTLInfo = TLB_REF_INTERNAL;
2198 /* process Implemented Interfaces of a com class */
2199 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2200 int offset)
2202 int i;
2203 MSFT_RefRecord refrec;
2204 TLBImplType **ppImpl = &pTI->impltypelist;
2206 TRACE_(typelib)("\n");
2208 for(i=0;i<count;i++){
2209 if(offset<0) break; /* paranoia */
2210 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2211 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2212 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2213 (*ppImpl)->hRef = refrec.reftype;
2214 (*ppImpl)->implflags=refrec.flags;
2215 (*ppImpl)->ctCustData=
2216 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2217 offset=refrec.onext;
2218 ppImpl=&((*ppImpl)->next);
2222 * process a typeinfo record
2224 static ITypeInfoImpl * MSFT_DoTypeInfo(
2225 TLBContext *pcx,
2226 int count,
2227 ITypeLibImpl * pLibInfo)
2229 MSFT_TypeInfoBase tiBase;
2230 ITypeInfoImpl *ptiRet;
2232 TRACE_(typelib)("count=%u\n", count);
2234 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2235 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2236 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2238 /* this is where we are coming from */
2239 ptiRet->pTypeLib = pLibInfo;
2240 ptiRet->index=count;
2241 /* fill in the typeattr fields */
2243 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2244 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2245 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2246 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2247 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2248 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2249 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2250 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2251 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2252 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2253 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2254 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2255 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2256 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2257 MSFT_GetTdesc(pcx, tiBase.datatype1,
2258 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2260 /* FIXME: */
2261 /* IDLDESC idldescType; *//* never saw this one != zero */
2263 /* name, eventually add to a hash table */
2264 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2265 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2266 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2267 /* help info */
2268 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2269 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2270 ptiRet->dwHelpContext=tiBase.helpcontext;
2272 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2273 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2275 /* note: InfoType's Help file and HelpStringDll come from the containing
2276 * library. Further HelpString and Docstring appear to be the same thing :(
2278 /* functions */
2279 if(ptiRet->TypeAttr.cFuncs >0 )
2280 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2281 ptiRet->TypeAttr.cVars,
2282 tiBase.memoffset, & ptiRet->funclist);
2283 /* variables */
2284 if(ptiRet->TypeAttr.cVars >0 )
2285 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2286 ptiRet->TypeAttr.cVars,
2287 tiBase.memoffset, & ptiRet->varlist);
2288 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2289 switch(ptiRet->TypeAttr.typekind)
2291 case TKIND_COCLASS:
2292 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2293 tiBase.datatype1);
2294 break;
2295 case TKIND_DISPATCH:
2296 /* This is not -1 when the interface is a non-base dual interface or
2297 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2298 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2299 not this interface.
2302 if (tiBase.datatype1 != -1)
2304 ptiRet->impltypelist = TLB_Alloc(sizeof(TLBImplType));
2305 ptiRet->impltypelist->hRef = tiBase.datatype1;
2306 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2308 break;
2309 default:
2310 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2311 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2312 ptiRet->impltypelist->hRef = tiBase.datatype1;
2313 break;
2316 ptiRet->ctCustData=
2317 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2319 TRACE_(typelib)("%s guid: %s kind:%s\n",
2320 debugstr_w(ptiRet->Name),
2321 debugstr_guid(&ptiRet->TypeAttr.guid),
2322 typekind_desc[ptiRet->TypeAttr.typekind]);
2323 if (TRACE_ON(typelib))
2324 dump_TypeInfo(ptiRet);
2326 return ptiRet;
2329 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2330 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2331 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2332 * tradeoff here.
2334 static ITypeLibImpl *tlb_cache_first;
2335 static CRITICAL_SECTION cache_section;
2336 static CRITICAL_SECTION_DEBUG cache_section_debug =
2338 0, 0, &cache_section,
2339 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2340 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2342 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2345 typedef struct TLB_PEFile
2347 const IUnknownVtbl *lpvtbl;
2348 LONG refs;
2349 HMODULE dll;
2350 HRSRC typelib_resource;
2351 HGLOBAL typelib_global;
2352 LPVOID typelib_base;
2353 } TLB_PEFile;
2355 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2357 if (IsEqualIID(riid, &IID_IUnknown))
2359 *ppv = iface;
2360 IUnknown_AddRef(iface);
2361 return S_OK;
2363 *ppv = NULL;
2364 return E_NOINTERFACE;
2367 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2369 TLB_PEFile *This = (TLB_PEFile *)iface;
2370 return InterlockedIncrement(&This->refs);
2373 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2375 TLB_PEFile *This = (TLB_PEFile *)iface;
2376 ULONG refs = InterlockedDecrement(&This->refs);
2377 if (!refs)
2379 if (This->typelib_global)
2380 FreeResource(This->typelib_global);
2381 if (This->dll)
2382 FreeLibrary(This->dll);
2383 HeapFree(GetProcessHeap(), 0, This);
2385 return refs;
2388 static const IUnknownVtbl TLB_PEFile_Vtable =
2390 TLB_PEFile_QueryInterface,
2391 TLB_PEFile_AddRef,
2392 TLB_PEFile_Release
2395 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2397 TLB_PEFile *This;
2399 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2400 if (!This)
2401 return E_OUTOFMEMORY;
2403 This->lpvtbl = &TLB_PEFile_Vtable;
2404 This->refs = 1;
2405 This->dll = NULL;
2406 This->typelib_resource = NULL;
2407 This->typelib_global = NULL;
2408 This->typelib_base = NULL;
2410 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2411 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2413 if (This->dll)
2415 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2416 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2417 if (This->typelib_resource)
2419 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2420 if (This->typelib_global)
2422 This->typelib_base = LockResource(This->typelib_global);
2424 if (This->typelib_base)
2426 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2427 *ppBase = This->typelib_base;
2428 *ppFile = (IUnknown *)&This->lpvtbl;
2429 return S_OK;
2435 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2436 return TYPE_E_CANTLOADLIBRARY;
2439 typedef struct TLB_NEFile
2441 const IUnknownVtbl *lpvtbl;
2442 LONG refs;
2443 LPVOID typelib_base;
2444 } TLB_NEFile;
2446 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2448 if (IsEqualIID(riid, &IID_IUnknown))
2450 *ppv = iface;
2451 IUnknown_AddRef(iface);
2452 return S_OK;
2454 *ppv = NULL;
2455 return E_NOINTERFACE;
2458 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2460 TLB_NEFile *This = (TLB_NEFile *)iface;
2461 return InterlockedIncrement(&This->refs);
2464 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2466 TLB_NEFile *This = (TLB_NEFile *)iface;
2467 ULONG refs = InterlockedDecrement(&This->refs);
2468 if (!refs)
2470 HeapFree(GetProcessHeap(), 0, This->typelib_base);
2471 HeapFree(GetProcessHeap(), 0, This);
2473 return refs;
2476 static const IUnknownVtbl TLB_NEFile_Vtable =
2478 TLB_NEFile_QueryInterface,
2479 TLB_NEFile_AddRef,
2480 TLB_NEFile_Release
2483 /***********************************************************************
2484 * read_xx_header [internal]
2486 static int read_xx_header( HFILE lzfd )
2488 IMAGE_DOS_HEADER mzh;
2489 char magic[3];
2491 LZSeek( lzfd, 0, SEEK_SET );
2492 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2493 return 0;
2494 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2495 return 0;
2497 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2498 if ( 2 != LZRead( lzfd, magic, 2 ) )
2499 return 0;
2501 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2503 if ( magic[0] == 'N' && magic[1] == 'E' )
2504 return IMAGE_OS2_SIGNATURE;
2505 if ( magic[0] == 'P' && magic[1] == 'E' )
2506 return IMAGE_NT_SIGNATURE;
2508 magic[2] = '\0';
2509 WARN("Can't handle %s files.\n", magic );
2510 return 0;
2514 /***********************************************************************
2515 * find_ne_resource [internal]
2517 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2518 DWORD *resLen, DWORD *resOff )
2520 IMAGE_OS2_HEADER nehd;
2521 NE_TYPEINFO *typeInfo;
2522 NE_NAMEINFO *nameInfo;
2523 DWORD nehdoffset;
2524 LPBYTE resTab;
2525 DWORD resTabSize;
2526 int count;
2528 /* Read in NE header */
2529 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2530 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2532 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2533 if ( !resTabSize )
2535 TRACE("No resources in NE dll\n" );
2536 return FALSE;
2539 /* Read in resource table */
2540 resTab = HeapAlloc( GetProcessHeap(), 0, resTabSize );
2541 if ( !resTab ) return FALSE;
2543 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2544 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2546 HeapFree( GetProcessHeap(), 0, resTab );
2547 return FALSE;
2550 /* Find resource */
2551 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2553 if (!IS_INTRESOURCE(typeid)) /* named type */
2555 BYTE len = strlen( typeid );
2556 while (typeInfo->type_id)
2558 if (!(typeInfo->type_id & 0x8000))
2560 BYTE *p = resTab + typeInfo->type_id;
2561 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2563 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2564 typeInfo->count * sizeof(NE_NAMEINFO));
2567 else /* numeric type id */
2569 WORD id = LOWORD(typeid) | 0x8000;
2570 while (typeInfo->type_id)
2572 if (typeInfo->type_id == id) goto found_type;
2573 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2574 typeInfo->count * sizeof(NE_NAMEINFO));
2577 TRACE("No typeid entry found for %p\n", typeid );
2578 HeapFree( GetProcessHeap(), 0, resTab );
2579 return FALSE;
2581 found_type:
2582 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2584 if (!IS_INTRESOURCE(resid)) /* named resource */
2586 BYTE len = strlen( resid );
2587 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2589 BYTE *p = resTab + nameInfo->id;
2590 if (nameInfo->id & 0x8000) continue;
2591 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2594 else /* numeric resource id */
2596 WORD id = LOWORD(resid) | 0x8000;
2597 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2598 if (nameInfo->id == id) goto found_name;
2600 TRACE("No resid entry found for %p\n", typeid );
2601 HeapFree( GetProcessHeap(), 0, resTab );
2602 return FALSE;
2604 found_name:
2605 /* Return resource data */
2606 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2607 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2609 HeapFree( GetProcessHeap(), 0, resTab );
2610 return TRUE;
2613 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
2615 HFILE lzfd = -1;
2616 OFSTRUCT ofs;
2617 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2618 TLB_NEFile *This = NULL;
2620 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2621 if (!This) return E_OUTOFMEMORY;
2623 This->lpvtbl = &TLB_NEFile_Vtable;
2624 This->refs = 1;
2625 This->typelib_base = NULL;
2627 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
2628 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
2630 DWORD reslen, offset;
2631 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
2633 This->typelib_base = HeapAlloc(GetProcessHeap(), 0, reslen);
2634 if( !This->typelib_base )
2635 hr = E_OUTOFMEMORY;
2636 else
2638 LZSeek( lzfd, offset, SEEK_SET );
2639 reslen = LZRead( lzfd, This->typelib_base, reslen );
2640 LZClose( lzfd );
2641 *ppBase = This->typelib_base;
2642 *pdwTLBLength = reslen;
2643 *ppFile = (IUnknown *)&This->lpvtbl;
2644 return S_OK;
2649 if( lzfd >= 0) LZClose( lzfd );
2650 TLB_NEFile_Release((IUnknown *)&This->lpvtbl);
2651 return hr;
2654 typedef struct TLB_Mapping
2656 const IUnknownVtbl *lpvtbl;
2657 LONG refs;
2658 HANDLE file;
2659 HANDLE mapping;
2660 LPVOID typelib_base;
2661 } TLB_Mapping;
2663 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2665 if (IsEqualIID(riid, &IID_IUnknown))
2667 *ppv = iface;
2668 IUnknown_AddRef(iface);
2669 return S_OK;
2671 *ppv = NULL;
2672 return E_NOINTERFACE;
2675 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2677 TLB_Mapping *This = (TLB_Mapping *)iface;
2678 return InterlockedIncrement(&This->refs);
2681 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2683 TLB_Mapping *This = (TLB_Mapping *)iface;
2684 ULONG refs = InterlockedDecrement(&This->refs);
2685 if (!refs)
2687 if (This->typelib_base)
2688 UnmapViewOfFile(This->typelib_base);
2689 if (This->mapping)
2690 CloseHandle(This->mapping);
2691 if (This->file != INVALID_HANDLE_VALUE)
2692 CloseHandle(This->file);
2693 HeapFree(GetProcessHeap(), 0, This);
2695 return refs;
2698 static const IUnknownVtbl TLB_Mapping_Vtable =
2700 TLB_Mapping_QueryInterface,
2701 TLB_Mapping_AddRef,
2702 TLB_Mapping_Release
2705 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2707 TLB_Mapping *This;
2709 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2710 if (!This)
2711 return E_OUTOFMEMORY;
2713 This->lpvtbl = &TLB_Mapping_Vtable;
2714 This->refs = 1;
2715 This->file = INVALID_HANDLE_VALUE;
2716 This->mapping = NULL;
2717 This->typelib_base = NULL;
2719 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2720 if (INVALID_HANDLE_VALUE != This->file)
2722 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2723 if (This->mapping)
2725 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2726 if(This->typelib_base)
2728 /* retrieve file size */
2729 *pdwTLBLength = GetFileSize(This->file, NULL);
2730 *ppBase = This->typelib_base;
2731 *ppFile = (IUnknown *)&This->lpvtbl;
2732 return S_OK;
2737 IUnknown_Release((IUnknown *)&This->lpvtbl);
2738 return TYPE_E_CANTLOADLIBRARY;
2741 /****************************************************************************
2742 * TLB_ReadTypeLib
2744 * find the type of the typelib file and map the typelib resource into
2745 * the memory
2747 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2748 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2749 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2751 ITypeLibImpl *entry;
2752 HRESULT ret;
2753 INT index = 1;
2754 LPWSTR index_str, file = (LPWSTR)pszFileName;
2755 LPVOID pBase = NULL;
2756 DWORD dwTLBLength = 0;
2757 IUnknown *pFile = NULL;
2759 *ppTypeLib = NULL;
2761 index_str = strrchrW(pszFileName, '\\');
2762 if(index_str && *++index_str != '\0')
2764 LPWSTR end_ptr;
2765 LONG idx = strtolW(index_str, &end_ptr, 10);
2766 if(*end_ptr == '\0')
2768 int str_len = index_str - pszFileName - 1;
2769 index = idx;
2770 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
2771 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2772 file[str_len] = 0;
2776 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2778 if(strchrW(file, '\\'))
2780 lstrcpyW(pszPath, file);
2782 else
2784 int len = GetSystemDirectoryW(pszPath, cchPath);
2785 pszPath[len] = '\\';
2786 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2790 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file);
2792 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2794 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2795 EnterCriticalSection(&cache_section);
2796 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2798 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2800 TRACE("cache hit\n");
2801 *ppTypeLib = (ITypeLib2*)entry;
2802 ITypeLib_AddRef(*ppTypeLib);
2803 LeaveCriticalSection(&cache_section);
2804 return S_OK;
2807 LeaveCriticalSection(&cache_section);
2809 /* now actually load and parse the typelib */
2811 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2812 if (ret == TYPE_E_CANTLOADLIBRARY)
2813 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2814 if (ret == TYPE_E_CANTLOADLIBRARY)
2815 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2816 if (SUCCEEDED(ret))
2818 if (dwTLBLength >= 4)
2820 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2821 if (dwSignature == MSFT_SIGNATURE)
2822 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2823 else if (dwSignature == SLTG_SIGNATURE)
2824 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2825 else
2827 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2828 ret = TYPE_E_CANTLOADLIBRARY;
2831 else
2832 ret = TYPE_E_CANTLOADLIBRARY;
2833 IUnknown_Release(pFile);
2836 if(*ppTypeLib) {
2837 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2839 TRACE("adding to cache\n");
2840 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2841 lstrcpyW(impl->path, pszPath);
2842 /* We should really canonicalise the path here. */
2843 impl->index = index;
2845 /* FIXME: check if it has added already in the meantime */
2846 EnterCriticalSection(&cache_section);
2847 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2848 impl->prev = NULL;
2849 tlb_cache_first = impl;
2850 LeaveCriticalSection(&cache_section);
2851 ret = S_OK;
2852 } else
2853 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2855 return ret;
2858 /*================== ITypeLib(2) Methods ===================================*/
2860 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2862 ITypeLibImpl* pTypeLibImpl;
2864 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2865 if (!pTypeLibImpl) return NULL;
2867 pTypeLibImpl->lpVtbl = &tlbvt;
2868 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2869 pTypeLibImpl->ref = 1;
2871 list_init(&pTypeLibImpl->ref_list);
2872 pTypeLibImpl->dispatch_href = -1;
2874 return pTypeLibImpl;
2877 /****************************************************************************
2878 * ITypeLib2_Constructor_MSFT
2880 * loading an MSFT typelib from an in-memory image
2882 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2884 TLBContext cx;
2885 LONG lPSegDir;
2886 MSFT_Header tlbHeader;
2887 MSFT_SegDir tlbSegDir;
2888 ITypeLibImpl * pTypeLibImpl;
2890 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2892 pTypeLibImpl = TypeLibImpl_Constructor();
2893 if (!pTypeLibImpl) return NULL;
2895 /* get pointer to beginning of typelib data */
2896 cx.pos = 0;
2897 cx.oStart=0;
2898 cx.mapping = pLib;
2899 cx.pLibInfo = pTypeLibImpl;
2900 cx.length = dwTLBLength;
2902 /* read header */
2903 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2904 TRACE_(typelib)("header:\n");
2905 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2906 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2907 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2908 return NULL;
2910 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2912 /* there is a small amount of information here until the next important
2913 * part:
2914 * the segment directory . Try to calculate the amount of data */
2915 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2917 /* now read the segment directory */
2918 TRACE("read segment directory (at %d)\n",lPSegDir);
2919 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2920 cx.pTblDir = &tlbSegDir;
2922 /* just check two entries */
2923 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2925 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
2926 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2927 return NULL;
2930 /* now fill our internal data */
2931 /* TLIBATTR fields */
2932 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2934 pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid2;
2935 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2936 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2937 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2938 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2940 pTypeLibImpl->lcid = tlbHeader.lcid;
2942 /* name, eventually add to a hash table */
2943 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2945 /* help info */
2946 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2947 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2949 if( tlbHeader.varflags & HELPDLLFLAG)
2951 int offset;
2952 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2953 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2956 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2958 /* custom data */
2959 if(tlbHeader.CustomDataOffset >= 0)
2961 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2964 /* fill in type descriptions */
2965 if(tlbSegDir.pTypdescTab.length > 0)
2967 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2968 INT16 td[4];
2969 pTypeLibImpl->ctTypeDesc = cTD;
2970 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2971 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2972 for(i=0; i<cTD; )
2974 /* FIXME: add several sanity checks here */
2975 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2976 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2978 /* FIXME: check safearray */
2979 if(td[3] < 0)
2980 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2981 else
2982 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2984 else if(td[0] == VT_CARRAY)
2986 /* array descr table here */
2987 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
2989 else if(td[0] == VT_USERDEFINED)
2991 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2993 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2996 /* second time around to fill the array subscript info */
2997 for(i=0;i<cTD;i++)
2999 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3000 if(tlbSegDir.pArrayDescriptions.offset>0)
3002 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3003 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3005 if(td[1]<0)
3006 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3007 else
3008 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3010 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3012 for(j = 0; j<td[2]; j++)
3014 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3015 sizeof(INT), &cx, DO_NOT_SEEK);
3016 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3017 sizeof(INT), &cx, DO_NOT_SEEK);
3020 else
3022 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3023 ERR("didn't find array description data\n");
3028 /* imported type libs */
3029 if(tlbSegDir.pImpFiles.offset>0)
3031 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
3032 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3033 UINT16 size;
3035 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3037 char *name;
3039 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
3040 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
3041 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3043 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3044 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3045 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3046 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3048 size >>= 2;
3049 name = TLB_Alloc(size+1);
3050 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3051 (*ppImpLib)->name = TLB_MultiByteToBSTR(name);
3052 TLB_Free(name);
3054 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
3055 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3057 ppImpLib = &(*ppImpLib)->next;
3061 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3062 if(pTypeLibImpl->dispatch_href != -1)
3063 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
3065 /* type info's */
3066 if(tlbHeader.nrtypeinfos >= 0 )
3068 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
3069 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
3070 int i;
3072 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3074 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3076 ppTI = &((*ppTI)->next);
3077 (pTypeLibImpl->TypeInfoCount)++;
3081 TRACE("(%p)\n", pTypeLibImpl);
3082 return (ITypeLib2*) pTypeLibImpl;
3086 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3088 char b[3];
3089 int i;
3090 short s;
3092 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3093 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3094 return FALSE;
3097 guid->Data4[0] = s >> 8;
3098 guid->Data4[1] = s & 0xff;
3100 b[2] = '\0';
3101 for(i = 0; i < 6; i++) {
3102 memcpy(b, str + 24 + 2 * i, 2);
3103 guid->Data4[i + 2] = strtol(b, NULL, 16);
3105 return TRUE;
3108 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
3110 WORD bytelen;
3111 DWORD len;
3113 *pBstr = NULL;
3114 bytelen = *(const WORD*)ptr;
3115 if(bytelen == 0xffff) return 2;
3116 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3117 *pBstr = SysAllocStringLen(NULL, len);
3118 if (*pBstr)
3119 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
3120 return bytelen + 2;
3123 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3125 WORD bytelen;
3127 *str = NULL;
3128 bytelen = *(const WORD*)ptr;
3129 if(bytelen == 0xffff) return 2;
3130 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
3131 memcpy(*str, ptr + 2, bytelen);
3132 (*str)[bytelen] = '\0';
3133 return bytelen + 2;
3136 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3138 char *ptr = pLibBlk;
3139 WORD w;
3141 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3142 FIXME("libblk magic = %04x\n", w);
3143 return 0;
3146 ptr += 6;
3147 if((w = *(WORD*)ptr) != 0xffff) {
3148 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3149 ptr += w;
3151 ptr += 2;
3153 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
3155 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
3157 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3158 ptr += 4;
3160 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
3161 ptr += 2;
3163 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3164 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3165 else
3166 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = 0;
3167 ptr += 2;
3169 ptr += 4; /* skip res12 */
3171 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
3172 ptr += 2;
3174 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
3175 ptr += 2;
3177 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
3178 ptr += 2;
3180 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
3181 ptr += sizeof(GUID);
3183 return ptr - (char*)pLibBlk;
3186 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3187 typedef struct
3189 unsigned int num;
3190 HREFTYPE refs[1];
3191 } sltg_ref_lookup_t;
3193 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3194 HREFTYPE *typelib_ref)
3196 if(table && typeinfo_ref < table->num)
3198 *typelib_ref = table->refs[typeinfo_ref];
3199 return S_OK;
3202 ERR_(typelib)("Unable to find reference\n");
3203 *typelib_ref = -1;
3204 return E_FAIL;
3207 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3209 BOOL done = FALSE;
3211 while(!done) {
3212 if((*pType & 0xe00) == 0xe00) {
3213 pTD->vt = VT_PTR;
3214 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3215 sizeof(TYPEDESC));
3216 pTD = pTD->u.lptdesc;
3218 switch(*pType & 0x3f) {
3219 case VT_PTR:
3220 pTD->vt = VT_PTR;
3221 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3222 sizeof(TYPEDESC));
3223 pTD = pTD->u.lptdesc;
3224 break;
3226 case VT_USERDEFINED:
3227 pTD->vt = VT_USERDEFINED;
3228 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3229 done = TRUE;
3230 break;
3232 case VT_CARRAY:
3234 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3235 array */
3237 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3239 pTD->vt = VT_CARRAY;
3240 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3241 sizeof(ARRAYDESC) +
3242 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3243 pTD->u.lpadesc->cDims = pSA->cDims;
3244 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3245 pSA->cDims * sizeof(SAFEARRAYBOUND));
3247 pTD = &pTD->u.lpadesc->tdescElem;
3248 break;
3251 case VT_SAFEARRAY:
3253 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3254 useful? */
3256 pType++;
3257 pTD->vt = VT_SAFEARRAY;
3258 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3259 sizeof(TYPEDESC));
3260 pTD = pTD->u.lptdesc;
3261 break;
3263 default:
3264 pTD->vt = *pType & 0x3f;
3265 done = TRUE;
3266 break;
3268 pType++;
3270 return pType;
3273 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3274 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3276 /* Handle [in/out] first */
3277 if((*pType & 0xc000) == 0xc000)
3278 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3279 else if(*pType & 0x8000)
3280 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3281 else if(*pType & 0x4000)
3282 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3283 else
3284 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3286 if(*pType & 0x2000)
3287 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3289 if(*pType & 0x80)
3290 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3292 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3296 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3297 char *pNameTable)
3299 unsigned int ref;
3300 char *name;
3301 TLBRefType *ref_type;
3302 sltg_ref_lookup_t *table;
3303 HREFTYPE typelib_ref;
3305 if(pRef->magic != SLTG_REF_MAGIC) {
3306 FIXME("Ref magic = %x\n", pRef->magic);
3307 return NULL;
3309 name = ( (char*)pRef->names + pRef->number);
3311 table = HeapAlloc(GetProcessHeap(), 0, sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3312 table->num = pRef->number >> 3;
3314 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3316 /* We don't want the first href to be 0 */
3317 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3319 for(ref = 0; ref < pRef->number >> 3; ref++) {
3320 char *refname;
3321 unsigned int lib_offs, type_num;
3323 ref_type = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref_type));
3325 name += SLTG_ReadStringA(name, &refname);
3326 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3327 FIXME_(typelib)("Can't sscanf ref\n");
3328 if(lib_offs != 0xffff) {
3329 TLBImpLib **import = &pTL->pImpLibs;
3331 while(*import) {
3332 if((*import)->offset == lib_offs)
3333 break;
3334 import = &(*import)->next;
3336 if(!*import) {
3337 char fname[MAX_PATH+1];
3338 int len;
3340 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3341 sizeof(**import));
3342 (*import)->offset = lib_offs;
3343 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3344 &(*import)->guid);
3345 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3346 &(*import)->wVersionMajor,
3347 &(*import)->wVersionMinor,
3348 &(*import)->lcid, fname) != 4) {
3349 FIXME_(typelib)("can't sscanf ref %s\n",
3350 pNameTable + lib_offs + 40);
3352 len = strlen(fname);
3353 if(fname[len-1] != '#')
3354 FIXME("fname = %s\n", fname);
3355 fname[len-1] = '\0';
3356 (*import)->name = TLB_MultiByteToBSTR(fname);
3358 ref_type->pImpTLInfo = *import;
3360 /* Store a reference to IDispatch */
3361 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
3362 pTL->dispatch_href = typelib_ref;
3364 } else { /* internal ref */
3365 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3367 ref_type->reference = typelib_ref;
3368 ref_type->index = type_num;
3370 HeapFree(GetProcessHeap(), 0, refname);
3371 list_add_tail(&pTL->ref_list, &ref_type->entry);
3373 table->refs[ref] = typelib_ref;
3374 typelib_ref += 4;
3376 if((BYTE)*name != SLTG_REF_MAGIC)
3377 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3378 dump_TLBRefType(pTL);
3379 return table;
3382 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3383 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3385 SLTG_ImplInfo *info;
3386 TLBImplType **ppImplType = &pTI->impltypelist;
3387 /* I don't really get this structure, usually it's 0x16 bytes
3388 long, but iuser.tlb contains some that are 0x18 bytes long.
3389 That's ok because we can use the next ptr to jump to the next
3390 one. But how do we know the length of the last one? The WORD
3391 at offs 0x8 might be the clue. For now I'm just assuming that
3392 the last one is the regular 0x16 bytes. */
3394 info = (SLTG_ImplInfo*)pBlk;
3395 while(1) {
3396 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3397 sizeof(**ppImplType));
3398 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef);
3399 (*ppImplType)->implflags = info->impltypeflags;
3400 pTI->TypeAttr.cImplTypes++;
3401 ppImplType = &(*ppImplType)->next;
3403 if(info->next == 0xffff)
3404 break;
3405 if(OneOnly)
3406 FIXME_(typelib)("Interface inheriting more than one interface\n");
3407 info = (SLTG_ImplInfo*)(pBlk + info->next);
3409 info++; /* see comment at top of function */
3410 return (char*)info;
3413 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3414 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3416 TLBVarDesc **ppVarDesc = &pTI->varlist;
3417 BSTR bstrPrevName = NULL;
3418 SLTG_Variable *pItem;
3419 unsigned short i;
3420 WORD *pType;
3422 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3423 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
3425 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3426 sizeof(**ppVarDesc));
3427 (*ppVarDesc)->vardesc.memid = pItem->memid;
3429 if (pItem->magic != SLTG_VAR_MAGIC &&
3430 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3431 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3432 return;
3435 if (pItem->name == 0xfffe)
3436 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
3437 else
3438 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3440 TRACE_(typelib)("name: %s\n", debugstr_w((*ppVarDesc)->Name));
3441 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3442 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3444 if(pItem->flags & 0x02)
3445 pType = &pItem->type;
3446 else
3447 pType = (WORD*)(pBlk + pItem->type);
3449 if (pItem->flags & ~0xda)
3450 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3452 SLTG_DoElem(pType, pBlk,
3453 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup);
3455 if (TRACE_ON(typelib)) {
3456 char buf[300];
3457 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3458 TRACE_(typelib)("elemdescVar: %s\n", buf);
3461 if (pItem->flags & 0x40) {
3462 TRACE_(typelib)("VAR_DISPATCH\n");
3463 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
3465 else if (pItem->flags & 0x10) {
3466 TRACE_(typelib)("VAR_CONST\n");
3467 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3468 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3469 sizeof(VARIANT));
3470 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3471 if (pItem->flags & 0x08)
3472 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) = pItem->byte_offs;
3473 else {
3474 switch ((*ppVarDesc)->vardesc.elemdescVar.tdesc.vt)
3476 case VT_LPSTR:
3477 case VT_LPWSTR:
3478 case VT_BSTR:
3480 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3481 BSTR str;
3482 TRACE_(typelib)("len = %u\n", len);
3483 if (len == 0xffff) {
3484 str = NULL;
3485 } else {
3486 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3487 str = SysAllocStringLen(NULL, alloc_len);
3488 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3490 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_BSTR;
3491 V_BSTR((*ppVarDesc)->vardesc.u.lpvarValue) = str;
3492 break;
3494 case VT_I2:
3495 case VT_UI2:
3496 case VT_I4:
3497 case VT_UI4:
3498 case VT_INT:
3499 case VT_UINT:
3500 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) =
3501 *(INT*)(pBlk + pItem->byte_offs);
3502 break;
3503 default:
3504 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt);
3508 else {
3509 TRACE_(typelib)("VAR_PERINSTANCE\n");
3510 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3511 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3514 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3515 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
3517 if (pItem->flags & 0x80)
3518 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3520 bstrPrevName = (*ppVarDesc)->Name;
3521 ppVarDesc = &((*ppVarDesc)->next);
3523 pTI->TypeAttr.cVars = cVars;
3526 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3527 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3529 SLTG_Function *pFunc;
3530 unsigned short i;
3531 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3533 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3534 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3536 int param;
3537 WORD *pType, *pArg;
3539 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3540 sizeof(**ppFuncDesc));
3542 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3543 case SLTG_FUNCTION_MAGIC:
3544 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3545 break;
3546 case SLTG_DISPATCH_FUNCTION_MAGIC:
3547 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3548 break;
3549 case SLTG_STATIC_FUNCTION_MAGIC:
3550 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3551 break;
3552 default:
3553 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3554 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
3555 *ppFuncDesc = NULL;
3556 return;
3558 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3560 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3561 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3562 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3563 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3564 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3565 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3567 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3568 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3570 if(pFunc->retnextopt & 0x80)
3571 pType = &pFunc->rettype;
3572 else
3573 pType = (WORD*)(pBlk + pFunc->rettype);
3575 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3577 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3578 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3579 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3580 (*ppFuncDesc)->pParamDesc =
3581 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3582 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3584 pArg = (WORD*)(pBlk + pFunc->arg_off);
3586 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3587 char *paramName = pNameTable + *pArg;
3588 BOOL HaveOffs;
3589 /* If arg type follows then paramName points to the 2nd
3590 letter of the name, else the next WORD is an offset to
3591 the arg type and paramName points to the first letter.
3592 So let's take one char off paramName and see if we're
3593 pointing at an alpha-numeric char. However if *pArg is
3594 0xffff or 0xfffe then the param has no name, the former
3595 meaning that the next WORD is the type, the latter
3596 meaning that the next WORD is an offset to the type. */
3598 HaveOffs = FALSE;
3599 if(*pArg == 0xffff)
3600 paramName = NULL;
3601 else if(*pArg == 0xfffe) {
3602 paramName = NULL;
3603 HaveOffs = TRUE;
3605 else if(paramName[-1] && !isalnum(paramName[-1]))
3606 HaveOffs = TRUE;
3608 pArg++;
3610 if(HaveOffs) { /* the next word is an offset to type */
3611 pType = (WORD*)(pBlk + *pArg);
3612 SLTG_DoElem(pType, pBlk,
3613 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3614 pArg++;
3615 } else {
3616 if(paramName)
3617 paramName--;
3618 pArg = SLTG_DoElem(pArg, pBlk,
3619 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3622 /* Are we an optional param ? */
3623 if((*ppFuncDesc)->funcdesc.cParams - param <=
3624 (*ppFuncDesc)->funcdesc.cParamsOpt)
3625 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3627 if(paramName) {
3628 (*ppFuncDesc)->pParamDesc[param].Name =
3629 TLB_MultiByteToBSTR(paramName);
3630 } else {
3631 (*ppFuncDesc)->pParamDesc[param].Name =
3632 SysAllocString((*ppFuncDesc)->Name);
3636 ppFuncDesc = &((*ppFuncDesc)->next);
3637 if(pFunc->next == 0xffff) break;
3639 pTI->TypeAttr.cFuncs = cFuncs;
3642 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3643 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3644 SLTG_TypeInfoTail *pTITail)
3646 char *pFirstItem;
3647 sltg_ref_lookup_t *ref_lookup = NULL;
3649 if(pTIHeader->href_table != 0xffffffff) {
3650 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3651 pNameTable);
3654 pFirstItem = pBlk;
3656 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3657 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3659 HeapFree(GetProcessHeap(), 0, ref_lookup);
3663 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3664 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3665 const SLTG_TypeInfoTail *pTITail)
3667 char *pFirstItem;
3668 sltg_ref_lookup_t *ref_lookup = NULL;
3670 if(pTIHeader->href_table != 0xffffffff) {
3671 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3672 pNameTable);
3675 pFirstItem = pBlk;
3677 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3678 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3681 if (pTITail->funcs_off != 0xffff)
3682 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3684 HeapFree(GetProcessHeap(), 0, ref_lookup);
3686 if (TRACE_ON(typelib))
3687 dump_TLBFuncDesc(pTI->funclist);
3690 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3691 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3692 const SLTG_TypeInfoTail *pTITail)
3694 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3697 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3698 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3699 const SLTG_TypeInfoTail *pTITail)
3701 WORD *pType;
3702 sltg_ref_lookup_t *ref_lookup = NULL;
3704 if (pTITail->simple_alias) {
3705 /* if simple alias, no more processing required */
3706 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3707 return;
3710 if(pTIHeader->href_table != 0xffffffff) {
3711 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3712 pNameTable);
3715 /* otherwise it is an offset to a type */
3716 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3718 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3720 HeapFree(GetProcessHeap(), 0, ref_lookup);
3723 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3724 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3725 const SLTG_TypeInfoTail *pTITail)
3727 sltg_ref_lookup_t *ref_lookup = NULL;
3728 if (pTIHeader->href_table != 0xffffffff)
3729 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3730 pNameTable);
3732 if (pTITail->vars_off != 0xffff)
3733 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3735 if (pTITail->funcs_off != 0xffff)
3736 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3738 if (pTITail->impls_off != 0xffff)
3739 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
3741 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3742 * of dispinterface functions including the IDispatch ones, so
3743 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3744 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3746 HeapFree(GetProcessHeap(), 0, ref_lookup);
3747 if (TRACE_ON(typelib))
3748 dump_TLBFuncDesc(pTI->funclist);
3751 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3752 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3753 const SLTG_TypeInfoTail *pTITail)
3755 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3758 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3759 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3760 const SLTG_TypeInfoTail *pTITail)
3762 sltg_ref_lookup_t *ref_lookup = NULL;
3763 if (pTIHeader->href_table != 0xffffffff)
3764 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3765 pNameTable);
3767 if (pTITail->vars_off != 0xffff)
3768 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3770 if (pTITail->funcs_off != 0xffff)
3771 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3772 HeapFree(GetProcessHeap(), 0, ref_lookup);
3773 if (TRACE_ON(typelib))
3774 dump_TypeInfo(pTI);
3777 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3778 managable copy of it into this */
3779 typedef struct {
3780 WORD small_no;
3781 char *index_name;
3782 char *other_name;
3783 WORD res1a;
3784 WORD name_offs;
3785 WORD more_bytes;
3786 char *extra;
3787 WORD res20;
3788 DWORD helpcontext;
3789 WORD res26;
3790 GUID uuid;
3791 } SLTG_InternalOtherTypeInfo;
3793 /****************************************************************************
3794 * ITypeLib2_Constructor_SLTG
3796 * loading a SLTG typelib from an in-memory image
3798 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3800 ITypeLibImpl *pTypeLibImpl;
3801 SLTG_Header *pHeader;
3802 SLTG_BlkEntry *pBlkEntry;
3803 SLTG_Magic *pMagic;
3804 SLTG_Index *pIndex;
3805 SLTG_Pad9 *pPad9;
3806 LPVOID pBlk, pFirstBlk;
3807 SLTG_LibBlk *pLibBlk;
3808 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3809 char *pAfterOTIBlks = NULL;
3810 char *pNameTable, *ptr;
3811 int i;
3812 DWORD len, order;
3813 ITypeInfoImpl **ppTypeInfoImpl;
3815 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3818 pTypeLibImpl = TypeLibImpl_Constructor();
3819 if (!pTypeLibImpl) return NULL;
3821 pHeader = pLib;
3823 TRACE_(typelib)("header:\n");
3824 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3825 pHeader->nrOfFileBlks );
3826 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3827 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3828 pHeader->SLTG_magic);
3829 return NULL;
3832 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3833 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3835 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3836 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3838 /* Next we have a magic block */
3839 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3841 /* Let's see if we're still in sync */
3842 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3843 sizeof(SLTG_COMPOBJ_MAGIC))) {
3844 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3845 return NULL;
3847 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3848 sizeof(SLTG_DIR_MAGIC))) {
3849 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
3850 return NULL;
3853 pIndex = (SLTG_Index*)(pMagic+1);
3855 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3857 pFirstBlk = pPad9 + 1;
3859 /* We'll set up a ptr to the main library block, which is the last one. */
3861 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3862 pBlkEntry[order].next != 0;
3863 order = pBlkEntry[order].next - 1, i++) {
3864 pBlk = (char*)pBlk + pBlkEntry[order].len;
3866 pLibBlk = pBlk;
3868 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3870 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3871 interspersed */
3873 len += 0x40;
3875 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3877 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3878 sizeof(*pOtherTypeInfoBlks) *
3879 pTypeLibImpl->TypeInfoCount);
3882 ptr = (char*)pLibBlk + len;
3884 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3885 WORD w, extra;
3886 len = 0;
3888 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3890 w = *(WORD*)(ptr + 2);
3891 if(w != 0xffff) {
3892 len += w;
3893 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3894 w+1);
3895 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3896 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3898 w = *(WORD*)(ptr + 4 + len);
3899 if(w != 0xffff) {
3900 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3901 len += w;
3902 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3903 w+1);
3904 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3905 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3907 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3908 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3909 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3910 if(extra) {
3911 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3912 extra);
3913 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3914 len += extra;
3916 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3917 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3918 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3919 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3920 len += sizeof(SLTG_OtherTypeInfo);
3921 ptr += len;
3924 pAfterOTIBlks = ptr;
3926 /* Skip this WORD and get the next DWORD */
3927 len = *(DWORD*)(pAfterOTIBlks + 2);
3929 /* Now add this to pLibBLk look at what we're pointing at and
3930 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3931 dust and we should be pointing at the beginning of the name
3932 table */
3934 pNameTable = (char*)pLibBlk + len;
3936 switch(*(WORD*)pNameTable) {
3937 case 0xffff:
3938 break;
3939 case 0x0200:
3940 pNameTable += 0x20;
3941 break;
3942 default:
3943 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
3944 break;
3947 pNameTable += 0x216;
3949 pNameTable += 2;
3951 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
3953 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3956 /* Hopefully we now have enough ptrs set up to actually read in
3957 some TypeInfos. It's not clear which order to do them in, so
3958 I'll just follow the links along the BlkEntry chain and read
3959 them in the order in which they are in the file */
3961 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3963 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3964 pBlkEntry[order].next != 0;
3965 order = pBlkEntry[order].next - 1, i++) {
3967 SLTG_TypeInfoHeader *pTIHeader;
3968 SLTG_TypeInfoTail *pTITail;
3969 SLTG_MemberHeader *pMemHeader;
3971 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3972 pOtherTypeInfoBlks[i].index_name)) {
3973 FIXME_(typelib)("Index strings don't match\n");
3974 return NULL;
3977 pTIHeader = pBlk;
3978 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3979 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3980 return NULL;
3982 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
3983 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3984 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3986 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3987 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3988 (*ppTypeInfoImpl)->index = i;
3989 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3990 pOtherTypeInfoBlks[i].name_offs +
3991 pNameTable);
3992 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3993 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
3994 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3995 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3996 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3997 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3998 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4000 if((*ppTypeInfoImpl)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
4001 (*ppTypeInfoImpl)->TypeAttr.typekind = TKIND_DISPATCH;
4003 if((pTIHeader->typeflags1 & 7) != 2)
4004 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4005 if(pTIHeader->typeflags3 != 2)
4006 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4008 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4009 debugstr_w((*ppTypeInfoImpl)->Name),
4010 typekind_desc[pTIHeader->typekind],
4011 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
4012 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
4014 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4016 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4018 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
4019 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
4020 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
4022 switch(pTIHeader->typekind) {
4023 case TKIND_ENUM:
4024 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4025 pTIHeader, pTITail);
4026 break;
4028 case TKIND_RECORD:
4029 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4030 pTIHeader, pTITail);
4031 break;
4033 case TKIND_INTERFACE:
4034 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4035 pTIHeader, pTITail);
4036 break;
4038 case TKIND_COCLASS:
4039 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4040 pTIHeader, pTITail);
4041 break;
4043 case TKIND_ALIAS:
4044 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4045 pTIHeader, pTITail);
4046 break;
4048 case TKIND_DISPATCH:
4049 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4050 pTIHeader, pTITail);
4051 break;
4053 case TKIND_MODULE:
4054 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4055 pTIHeader, pTITail);
4056 break;
4058 default:
4059 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4060 break;
4064 /* could get cFuncs, cVars and cImplTypes from here
4065 but we've already set those */
4066 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4067 X(06);
4068 X(16);
4069 X(18);
4070 X(1a);
4071 X(1e);
4072 X(24);
4073 X(26);
4074 X(2a);
4075 X(2c);
4076 X(2e);
4077 X(30);
4078 X(32);
4079 X(34);
4080 #undef X
4081 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
4082 pBlk = (char*)pBlk + pBlkEntry[order].len;
4085 if(i != pTypeLibImpl->TypeInfoCount) {
4086 FIXME("Somehow processed %d TypeInfos\n", i);
4087 return NULL;
4090 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
4091 return (ITypeLib2*)pTypeLibImpl;
4094 /* ITypeLib::QueryInterface
4096 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
4097 ITypeLib2 * iface,
4098 REFIID riid,
4099 VOID **ppvObject)
4101 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4103 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4105 *ppvObject=NULL;
4106 if(IsEqualIID(riid, &IID_IUnknown) ||
4107 IsEqualIID(riid,&IID_ITypeLib)||
4108 IsEqualIID(riid,&IID_ITypeLib2))
4110 *ppvObject = This;
4113 if(*ppvObject)
4115 ITypeLib2_AddRef(iface);
4116 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4117 return S_OK;
4119 TRACE("-- Interface: E_NOINTERFACE\n");
4120 return E_NOINTERFACE;
4123 /* ITypeLib::AddRef
4125 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4127 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4128 ULONG ref = InterlockedIncrement(&This->ref);
4130 TRACE("(%p)->ref was %u\n",This, ref - 1);
4132 return ref;
4135 /* ITypeLib::Release
4137 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4139 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4140 ULONG ref = InterlockedDecrement(&This->ref);
4142 TRACE("(%p)->(%u)\n",This, ref);
4144 if (!ref)
4146 TLBImpLib *pImpLib, *pImpLibNext;
4147 TLBCustData *pCustData, *pCustDataNext;
4148 TLBRefType *ref_type;
4149 void *cursor2;
4150 int i;
4151 ITypeInfoImpl *pTI, *pTINext;
4153 /* remove cache entry */
4154 if(This->path)
4156 TRACE("removing from cache list\n");
4157 EnterCriticalSection(&cache_section);
4158 if (This->next) This->next->prev = This->prev;
4159 if (This->prev) This->prev->next = This->next;
4160 else tlb_cache_first = This->next;
4161 LeaveCriticalSection(&cache_section);
4162 HeapFree(GetProcessHeap(), 0, This->path);
4164 TRACE(" destroying ITypeLib(%p)\n",This);
4166 SysFreeString(This->Name);
4167 This->Name = NULL;
4169 SysFreeString(This->DocString);
4170 This->DocString = NULL;
4172 SysFreeString(This->HelpFile);
4173 This->HelpFile = NULL;
4175 SysFreeString(This->HelpStringDll);
4176 This->HelpStringDll = NULL;
4178 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
4180 VariantClear(&pCustData->data);
4182 pCustDataNext = pCustData->next;
4183 TLB_Free(pCustData);
4186 for (i = 0; i < This->ctTypeDesc; i++)
4187 if (This->pTypeDesc[i].vt == VT_CARRAY)
4188 TLB_Free(This->pTypeDesc[i].u.lpadesc);
4190 TLB_Free(This->pTypeDesc);
4192 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
4194 if (pImpLib->pImpTypeLib)
4195 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
4196 SysFreeString(pImpLib->name);
4198 pImpLibNext = pImpLib->next;
4199 TLB_Free(pImpLib);
4202 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4204 list_remove(&ref_type->entry);
4205 TLB_Free(ref_type);
4208 for (pTI = This->pTypeInfo; pTI; pTI = pTINext)
4210 pTINext = pTI->next;
4211 ITypeInfo_fnDestroy(pTI);
4213 HeapFree(GetProcessHeap(),0,This);
4214 return 0;
4217 return ref;
4220 /* ITypeLib::GetTypeInfoCount
4222 * Returns the number of type descriptions in the type library
4224 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4226 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4227 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4228 return This->TypeInfoCount;
4231 /* ITypeLib::GetTypeInfo
4233 * retrieves the specified type description in the library.
4235 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4236 ITypeLib2 *iface,
4237 UINT index,
4238 ITypeInfo **ppTInfo)
4240 UINT i;
4242 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4243 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
4245 TRACE("(%p)->(index=%d)\n", This, index);
4247 if (!ppTInfo) return E_INVALIDARG;
4249 /* search element n in list */
4250 for(i=0; i < index; i++)
4252 pTypeInfo = pTypeInfo->next;
4253 if (!pTypeInfo)
4255 TRACE("-- element not found\n");
4256 return TYPE_E_ELEMENTNOTFOUND;
4260 *ppTInfo = (ITypeInfo *) pTypeInfo;
4262 ITypeInfo_AddRef(*ppTInfo);
4263 TRACE("-- found (%p)\n",*ppTInfo);
4264 return S_OK;
4268 /* ITypeLibs::GetTypeInfoType
4270 * Retrieves the type of a type description.
4272 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4273 ITypeLib2 *iface,
4274 UINT index,
4275 TYPEKIND *pTKind)
4277 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4278 UINT i;
4279 ITypeInfoImpl *pTInfo = This->pTypeInfo;
4281 if (ITypeLib2_fnGetTypeInfoCount(iface) < index + 1)
4282 return TYPE_E_ELEMENTNOTFOUND;
4284 TRACE("(%p) index %d\n", This, index);
4286 if(!pTKind) return E_INVALIDARG;
4288 /* search element n in list */
4289 for(i=0; i < index; i++)
4291 if(!pTInfo)
4293 TRACE("-- element not found\n");
4294 return TYPE_E_ELEMENTNOTFOUND;
4296 pTInfo = pTInfo->next;
4299 *pTKind = pTInfo->TypeAttr.typekind;
4300 TRACE("-- found Type (%d)\n", *pTKind);
4301 return S_OK;
4304 /* ITypeLib::GetTypeInfoOfGuid
4306 * Retrieves the type description that corresponds to the specified GUID.
4309 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4310 ITypeLib2 *iface,
4311 REFGUID guid,
4312 ITypeInfo **ppTInfo)
4314 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4315 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
4317 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
4319 if (!pTypeInfo)
4321 WARN("-- element not found\n");
4322 return TYPE_E_ELEMENTNOTFOUND;
4325 /* search linked list for guid */
4326 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
4328 pTypeInfo = pTypeInfo->next;
4330 if (!pTypeInfo)
4332 /* end of list reached */
4333 WARN("-- element not found\n");
4334 return TYPE_E_ELEMENTNOTFOUND;
4338 TRACE("-- found (%p, %s)\n",
4339 pTypeInfo,
4340 debugstr_w(pTypeInfo->Name));
4342 *ppTInfo = (ITypeInfo*)pTypeInfo;
4343 ITypeInfo_AddRef(*ppTInfo);
4344 return S_OK;
4347 /* ITypeLib::GetLibAttr
4349 * Retrieves the structure that contains the library's attributes.
4352 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4353 ITypeLib2 *iface,
4354 LPTLIBATTR *ppTLibAttr)
4356 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4357 TRACE("(%p)\n",This);
4358 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
4359 **ppTLibAttr = This->LibAttr;
4360 return S_OK;
4363 /* ITypeLib::GetTypeComp
4365 * Enables a client compiler to bind to a library's types, variables,
4366 * constants, and global functions.
4369 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4370 ITypeLib2 *iface,
4371 ITypeComp **ppTComp)
4373 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4375 TRACE("(%p)->(%p)\n",This,ppTComp);
4376 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4377 ITypeComp_AddRef(*ppTComp);
4379 return S_OK;
4382 /* ITypeLib::GetDocumentation
4384 * Retrieves the library's documentation string, the complete Help file name
4385 * and path, and the context identifier for the library Help topic in the Help
4386 * file.
4388 * On a successful return all non-null BSTR pointers will have been set,
4389 * possibly to NULL.
4391 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4392 ITypeLib2 *iface,
4393 INT index,
4394 BSTR *pBstrName,
4395 BSTR *pBstrDocString,
4396 DWORD *pdwHelpContext,
4397 BSTR *pBstrHelpFile)
4399 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4401 HRESULT result = E_INVALIDARG;
4403 ITypeInfo *pTInfo;
4406 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4407 This, index,
4408 pBstrName, pBstrDocString,
4409 pdwHelpContext, pBstrHelpFile);
4411 if(index<0)
4413 /* documentation for the typelib */
4414 if(pBstrName)
4416 if (This->Name)
4418 if(!(*pBstrName = SysAllocString(This->Name)))
4419 goto memerr1;
4421 else
4422 *pBstrName = NULL;
4424 if(pBstrDocString)
4426 if (This->DocString)
4428 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4429 goto memerr2;
4431 else if (This->Name)
4433 if(!(*pBstrDocString = SysAllocString(This->Name)))
4434 goto memerr2;
4436 else
4437 *pBstrDocString = NULL;
4439 if(pdwHelpContext)
4441 *pdwHelpContext = This->dwHelpContext;
4443 if(pBstrHelpFile)
4445 if (This->HelpFile)
4447 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4448 goto memerr3;
4450 else
4451 *pBstrHelpFile = NULL;
4454 result = S_OK;
4456 else
4458 /* for a typeinfo */
4459 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4461 if(SUCCEEDED(result))
4463 result = ITypeInfo_GetDocumentation(pTInfo,
4464 MEMBERID_NIL,
4465 pBstrName,
4466 pBstrDocString,
4467 pdwHelpContext, pBstrHelpFile);
4469 ITypeInfo_Release(pTInfo);
4472 return result;
4473 memerr3:
4474 if (pBstrDocString) SysFreeString (*pBstrDocString);
4475 memerr2:
4476 if (pBstrName) SysFreeString (*pBstrName);
4477 memerr1:
4478 return STG_E_INSUFFICIENTMEMORY;
4481 /* ITypeLib::IsName
4483 * Indicates whether a passed-in string contains the name of a type or member
4484 * described in the library.
4487 static HRESULT WINAPI ITypeLib2_fnIsName(
4488 ITypeLib2 *iface,
4489 LPOLESTR szNameBuf,
4490 ULONG lHashVal,
4491 BOOL *pfName)
4493 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4494 ITypeInfoImpl *pTInfo;
4495 TLBFuncDesc *pFInfo;
4496 TLBVarDesc *pVInfo;
4497 int i;
4498 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4500 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4501 pfName);
4503 *pfName=TRUE;
4504 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
4505 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4506 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4507 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4508 for(i=0;i<pFInfo->funcdesc.cParams;i++)
4509 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
4510 goto ITypeLib2_fnIsName_exit;
4512 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4513 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4516 *pfName=FALSE;
4518 ITypeLib2_fnIsName_exit:
4519 TRACE("(%p)slow! search for %s: %s found!\n", This,
4520 debugstr_w(szNameBuf), *pfName?"NOT":"");
4522 return S_OK;
4525 /* ITypeLib::FindName
4527 * Finds occurrences of a type description in a type library. This may be used
4528 * to quickly verify that a name exists in a type library.
4531 static HRESULT WINAPI ITypeLib2_fnFindName(
4532 ITypeLib2 *iface,
4533 LPOLESTR szNameBuf,
4534 ULONG lHashVal,
4535 ITypeInfo **ppTInfo,
4536 MEMBERID *rgMemId,
4537 UINT16 *pcFound)
4539 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4540 ITypeInfoImpl *pTInfo;
4541 TLBFuncDesc *pFInfo;
4542 TLBVarDesc *pVInfo;
4543 int i,j = 0;
4544 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4546 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
4547 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4548 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4549 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4550 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
4551 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
4552 goto ITypeLib2_fnFindName_exit;
4555 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4556 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4557 continue;
4558 ITypeLib2_fnFindName_exit:
4559 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4560 ppTInfo[j]=(LPTYPEINFO)pTInfo;
4561 j++;
4563 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4564 This, *pcFound, debugstr_w(szNameBuf), j);
4566 *pcFound=j;
4568 return S_OK;
4571 /* ITypeLib::ReleaseTLibAttr
4573 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4576 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4577 ITypeLib2 *iface,
4578 TLIBATTR *pTLibAttr)
4580 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4581 TRACE("freeing (%p)\n",This);
4582 HeapFree(GetProcessHeap(),0,pTLibAttr);
4586 /* ITypeLib2::GetCustData
4588 * gets the custom data
4590 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4591 ITypeLib2 * iface,
4592 REFGUID guid,
4593 VARIANT *pVarVal)
4595 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4596 TLBCustData *pCData;
4598 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4600 if( IsEqualIID(guid, &pCData->guid)) break;
4603 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4605 if(pCData)
4607 VariantInit( pVarVal);
4608 VariantCopy( pVarVal, &pCData->data);
4609 return S_OK;
4611 return E_INVALIDARG; /* FIXME: correct? */
4614 /* ITypeLib2::GetLibStatistics
4616 * Returns statistics about a type library that are required for efficient
4617 * sizing of hash tables.
4620 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4621 ITypeLib2 * iface,
4622 ULONG *pcUniqueNames,
4623 ULONG *pcchUniqueNames)
4625 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4627 FIXME("(%p): stub!\n", This);
4629 if(pcUniqueNames) *pcUniqueNames=1;
4630 if(pcchUniqueNames) *pcchUniqueNames=1;
4631 return S_OK;
4634 /* ITypeLib2::GetDocumentation2
4636 * Retrieves the library's documentation string, the complete Help file name
4637 * and path, the localization context to use, and the context ID for the
4638 * library Help topic in the Help file.
4641 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4642 ITypeLib2 * iface,
4643 INT index,
4644 LCID lcid,
4645 BSTR *pbstrHelpString,
4646 DWORD *pdwHelpStringContext,
4647 BSTR *pbstrHelpStringDll)
4649 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4650 HRESULT result;
4651 ITypeInfo *pTInfo;
4653 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4655 /* the help string should be obtained from the helpstringdll,
4656 * using the _DLLGetDocumentation function, based on the supplied
4657 * lcid. Nice to do sometime...
4659 if(index<0)
4661 /* documentation for the typelib */
4662 if(pbstrHelpString)
4663 *pbstrHelpString=SysAllocString(This->DocString);
4664 if(pdwHelpStringContext)
4665 *pdwHelpStringContext=This->dwHelpContext;
4666 if(pbstrHelpStringDll)
4667 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4669 result = S_OK;
4671 else
4673 /* for a typeinfo */
4674 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4676 if(SUCCEEDED(result))
4678 ITypeInfo2 * pTInfo2;
4679 result = ITypeInfo_QueryInterface(pTInfo,
4680 &IID_ITypeInfo2,
4681 (LPVOID*) &pTInfo2);
4683 if(SUCCEEDED(result))
4685 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4686 MEMBERID_NIL,
4687 lcid,
4688 pbstrHelpString,
4689 pdwHelpStringContext,
4690 pbstrHelpStringDll);
4692 ITypeInfo2_Release(pTInfo2);
4695 ITypeInfo_Release(pTInfo);
4698 return result;
4701 /* ITypeLib2::GetAllCustData
4703 * Gets all custom data items for the library.
4706 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4707 ITypeLib2 * iface,
4708 CUSTDATA *pCustData)
4710 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4711 TLBCustData *pCData;
4712 int i;
4713 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4714 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4715 if(pCustData->prgCustData ){
4716 pCustData->cCustData=This->ctCustData;
4717 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4718 pCustData->prgCustData[i].guid=pCData->guid;
4719 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4721 }else{
4722 ERR(" OUT OF MEMORY!\n");
4723 return E_OUTOFMEMORY;
4725 return S_OK;
4728 static const ITypeLib2Vtbl tlbvt = {
4729 ITypeLib2_fnQueryInterface,
4730 ITypeLib2_fnAddRef,
4731 ITypeLib2_fnRelease,
4732 ITypeLib2_fnGetTypeInfoCount,
4733 ITypeLib2_fnGetTypeInfo,
4734 ITypeLib2_fnGetTypeInfoType,
4735 ITypeLib2_fnGetTypeInfoOfGuid,
4736 ITypeLib2_fnGetLibAttr,
4737 ITypeLib2_fnGetTypeComp,
4738 ITypeLib2_fnGetDocumentation,
4739 ITypeLib2_fnIsName,
4740 ITypeLib2_fnFindName,
4741 ITypeLib2_fnReleaseTLibAttr,
4743 ITypeLib2_fnGetCustData,
4744 ITypeLib2_fnGetLibStatistics,
4745 ITypeLib2_fnGetDocumentation2,
4746 ITypeLib2_fnGetAllCustData
4750 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4752 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4754 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4757 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4759 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4761 return ITypeLib2_AddRef((ITypeLib2 *)This);
4764 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4766 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4768 return ITypeLib2_Release((ITypeLib2 *)This);
4771 static HRESULT WINAPI ITypeLibComp_fnBind(
4772 ITypeComp * iface,
4773 OLECHAR * szName,
4774 ULONG lHash,
4775 WORD wFlags,
4776 ITypeInfo ** ppTInfo,
4777 DESCKIND * pDescKind,
4778 BINDPTR * pBindPtr)
4780 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4781 ITypeInfoImpl *pTypeInfo;
4782 int typemismatch=0;
4784 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4786 *pDescKind = DESCKIND_NONE;
4787 pBindPtr->lptcomp = NULL;
4788 *ppTInfo = NULL;
4790 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4792 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4794 /* FIXME: check wFlags here? */
4795 /* FIXME: we should use a hash table to look this info up using lHash
4796 * instead of an O(n) search */
4797 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4798 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4800 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4802 *pDescKind = DESCKIND_TYPECOMP;
4803 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4804 ITypeComp_AddRef(pBindPtr->lptcomp);
4805 TRACE("module or enum: %s\n", debugstr_w(szName));
4806 return S_OK;
4810 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4811 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4813 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4814 HRESULT hr;
4816 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4817 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4819 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4820 return S_OK;
4822 else if (hr == TYPE_E_TYPEMISMATCH)
4823 typemismatch = 1;
4826 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4827 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4829 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4830 HRESULT hr;
4831 ITypeInfo *subtypeinfo;
4832 BINDPTR subbindptr;
4833 DESCKIND subdesckind;
4835 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4836 &subtypeinfo, &subdesckind, &subbindptr);
4837 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4839 TYPEDESC tdesc_appobject;
4840 const VARDESC vardesc_appobject =
4842 -2, /* memid */
4843 NULL, /* lpstrSchema */
4845 0 /* oInst */
4848 /* ELEMDESC */
4850 /* TYPEDESC */
4852 &tdesc_appobject
4854 VT_PTR
4857 0, /* wVarFlags */
4858 VAR_STATIC /* varkind */
4861 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
4862 tdesc_appobject.vt = VT_USERDEFINED;
4864 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4866 /* cleanup things filled in by Bind call so we can put our
4867 * application object data in there instead */
4868 switch (subdesckind)
4870 case DESCKIND_FUNCDESC:
4871 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4872 break;
4873 case DESCKIND_VARDESC:
4874 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4875 break;
4876 default:
4877 break;
4879 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4881 if (pTypeInfo->hreftype == -1)
4882 FIXME("no hreftype for interface %p\n", pTypeInfo);
4884 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4885 if (FAILED(hr))
4886 return hr;
4888 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4889 *ppTInfo = (ITypeInfo *)pTypeInfo;
4890 ITypeInfo_AddRef(*ppTInfo);
4891 return S_OK;
4893 else if (hr == TYPE_E_TYPEMISMATCH)
4894 typemismatch = 1;
4898 if (typemismatch)
4900 TRACE("type mismatch %s\n", debugstr_w(szName));
4901 return TYPE_E_TYPEMISMATCH;
4903 else
4905 TRACE("name not found %s\n", debugstr_w(szName));
4906 return S_OK;
4910 static HRESULT WINAPI ITypeLibComp_fnBindType(
4911 ITypeComp * iface,
4912 OLECHAR * szName,
4913 ULONG lHash,
4914 ITypeInfo ** ppTInfo,
4915 ITypeComp ** ppTComp)
4917 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4918 ITypeInfoImpl *pTypeInfo;
4920 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4922 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4924 /* FIXME: should use lHash to do the search */
4925 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4927 TRACE("returning %p\n", pTypeInfo);
4928 *ppTInfo = (ITypeInfo *)&pTypeInfo->lpVtbl;
4929 ITypeInfo_AddRef(*ppTInfo);
4930 *ppTComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4931 ITypeComp_AddRef(*ppTComp);
4932 return S_OK;
4936 TRACE("not found\n");
4937 *ppTInfo = NULL;
4938 *ppTComp = NULL;
4939 return S_OK;
4942 static const ITypeCompVtbl tlbtcvt =
4945 ITypeLibComp_fnQueryInterface,
4946 ITypeLibComp_fnAddRef,
4947 ITypeLibComp_fnRelease,
4949 ITypeLibComp_fnBind,
4950 ITypeLibComp_fnBindType
4953 /*================== ITypeInfo(2) Methods ===================================*/
4954 static ITypeInfo2 * ITypeInfo_Constructor(void)
4956 ITypeInfoImpl * pTypeInfoImpl;
4958 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4959 if (pTypeInfoImpl)
4961 pTypeInfoImpl->lpVtbl = &tinfvt;
4962 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4963 pTypeInfoImpl->ref = 0;
4964 pTypeInfoImpl->hreftype = -1;
4965 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4966 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4968 TRACE("(%p)\n", pTypeInfoImpl);
4969 return (ITypeInfo2*) pTypeInfoImpl;
4972 /* ITypeInfo::QueryInterface
4974 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4975 ITypeInfo2 *iface,
4976 REFIID riid,
4977 VOID **ppvObject)
4979 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4981 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4983 *ppvObject=NULL;
4984 if(IsEqualIID(riid, &IID_IUnknown) ||
4985 IsEqualIID(riid,&IID_ITypeInfo)||
4986 IsEqualIID(riid,&IID_ITypeInfo2))
4987 *ppvObject = This;
4989 if(*ppvObject){
4990 ITypeInfo_AddRef(iface);
4991 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4992 return S_OK;
4994 TRACE("-- Interface: E_NOINTERFACE\n");
4995 return E_NOINTERFACE;
4998 /* ITypeInfo::AddRef
5000 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5002 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5003 ULONG ref = InterlockedIncrement(&This->ref);
5005 TRACE("(%p)->ref is %u\n",This, ref);
5007 if (ref == 1 /* incremented from 0 */)
5008 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
5010 return ref;
5013 static void ITypeInfo_fnDestroy(ITypeInfoImpl *This)
5015 TLBFuncDesc *pFInfo, *pFInfoNext;
5016 TLBVarDesc *pVInfo, *pVInfoNext;
5017 TLBImplType *pImpl, *pImplNext;
5019 TRACE("destroying ITypeInfo(%p)\n",This);
5021 SysFreeString(This->Name);
5022 This->Name = NULL;
5024 SysFreeString(This->DocString);
5025 This->DocString = NULL;
5027 SysFreeString(This->DllName);
5028 This->DllName = NULL;
5030 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
5032 INT i;
5033 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
5035 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
5036 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5038 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5039 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
5041 SysFreeString(pFInfo->pParamDesc[i].Name);
5043 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
5044 TLB_Free(pFInfo->pParamDesc);
5045 TLB_FreeCustData(pFInfo->pCustData);
5046 if (!IS_INTRESOURCE(pFInfo->Entry) && pFInfo->Entry != (BSTR)-1)
5047 SysFreeString(pFInfo->Entry);
5048 SysFreeString(pFInfo->HelpString);
5049 SysFreeString(pFInfo->Name);
5051 pFInfoNext = pFInfo->next;
5052 TLB_Free(pFInfo);
5054 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
5056 if (pVInfo->vardesc.varkind == VAR_CONST)
5058 VariantClear(pVInfo->vardesc.u.lpvarValue);
5059 TLB_Free(pVInfo->vardesc.u.lpvarValue);
5061 TLB_FreeCustData(pVInfo->pCustData);
5062 SysFreeString(pVInfo->Name);
5063 pVInfoNext = pVInfo->next;
5064 TLB_Free(pVInfo);
5066 for (pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
5068 TLB_FreeCustData(pImpl->pCustData);
5069 pImplNext = pImpl->next;
5070 TLB_Free(pImpl);
5072 TLB_FreeCustData(This->pCustData);
5074 HeapFree(GetProcessHeap(), 0, This);
5077 /* ITypeInfo::Release
5079 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5081 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5082 ULONG ref = InterlockedDecrement(&This->ref);
5084 TRACE("(%p)->(%u)\n",This, ref);
5086 if (!ref)
5088 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5089 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
5090 if (not_attached_to_typelib)
5091 HeapFree(GetProcessHeap(), 0, This);
5092 /* otherwise This will be freed when typelib is freed */
5095 return ref;
5098 /* ITypeInfo::GetTypeAttr
5100 * Retrieves a TYPEATTR structure that contains the attributes of the type
5101 * description.
5104 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5105 LPTYPEATTR *ppTypeAttr)
5107 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5108 SIZE_T size;
5110 TRACE("(%p)\n",This);
5112 size = sizeof(**ppTypeAttr);
5113 if (This->TypeAttr.typekind == TKIND_ALIAS)
5114 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
5116 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
5117 if (!*ppTypeAttr)
5118 return E_OUTOFMEMORY;
5120 **ppTypeAttr = This->TypeAttr;
5122 if (This->TypeAttr.typekind == TKIND_ALIAS)
5123 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5124 &This->TypeAttr.tdescAlias, *ppTypeAttr + 1);
5126 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5127 /* This should include all the inherited funcs */
5128 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
5129 (*ppTypeAttr)->cbSizeVft = 7 * sizeof(void *); /* This is always the size of IDispatch's vtbl */
5130 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5132 return S_OK;
5135 /* ITypeInfo::GetTypeComp
5137 * Retrieves the ITypeComp interface for the type description, which enables a
5138 * client compiler to bind to the type description's members.
5141 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5142 ITypeComp * *ppTComp)
5144 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5146 TRACE("(%p)->(%p)\n", This, ppTComp);
5148 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
5149 ITypeComp_AddRef(*ppTComp);
5150 return S_OK;
5153 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5155 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5156 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5157 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5158 return size;
5161 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5163 *dest = *src;
5164 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5165 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5167 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5168 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5169 *buffer += sizeof(PARAMDESCEX);
5170 *pparamdescex_dest = *pparamdescex_src;
5171 VariantInit(&pparamdescex_dest->varDefaultValue);
5172 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5173 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5175 else
5176 dest->u.paramdesc.pparamdescex = NULL;
5177 return S_OK;
5180 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5182 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5183 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5186 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5188 FUNCDESC *dest;
5189 char *buffer;
5190 SIZE_T size = sizeof(*src);
5191 SHORT i;
5192 HRESULT hr;
5194 size += sizeof(*src->lprgscode) * src->cScodes;
5195 size += TLB_SizeElemDesc(&src->elemdescFunc);
5196 for (i = 0; i < src->cParams; i++)
5198 size += sizeof(ELEMDESC);
5199 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5202 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5203 if (!dest) return E_OUTOFMEMORY;
5205 *dest = *src;
5206 if (dispinterface) /* overwrite funckind */
5207 dest->funckind = FUNC_DISPATCH;
5208 buffer = (char *)(dest + 1);
5210 dest->lprgscode = (SCODE *)buffer;
5211 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5212 buffer += sizeof(*src->lprgscode) * src->cScodes;
5214 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5215 if (FAILED(hr))
5217 SysFreeString((BSTR)dest);
5218 return hr;
5221 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5222 buffer += sizeof(ELEMDESC) * src->cParams;
5223 for (i = 0; i < src->cParams; i++)
5225 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5226 if (FAILED(hr))
5227 break;
5229 if (FAILED(hr))
5231 /* undo the above actions */
5232 for (i = i - 1; i >= 0; i--)
5233 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5234 TLB_FreeElemDesc(&dest->elemdescFunc);
5235 SysFreeString((BSTR)dest);
5236 return hr;
5239 /* special treatment for dispinterfaces: this makes functions appear
5240 * to return their [retval] value when it is really returning an
5241 * HRESULT */
5242 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5244 if (dest->cParams &&
5245 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5247 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5248 if (elemdesc->tdesc.vt != VT_PTR)
5250 ERR("elemdesc should have started with VT_PTR instead of:\n");
5251 if (ERR_ON(ole))
5252 dump_ELEMDESC(elemdesc);
5253 return E_UNEXPECTED;
5256 /* copy last parameter to the return value. we are using a flat
5257 * buffer so there is no danger of leaking memory in
5258 * elemdescFunc */
5259 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5261 /* remove the last parameter */
5262 dest->cParams--;
5264 else
5265 /* otherwise this function is made to appear to have no return
5266 * value */
5267 dest->elemdescFunc.tdesc.vt = VT_VOID;
5271 *dest_ptr = dest;
5272 return S_OK;
5275 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5277 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5278 const TLBFuncDesc *pFDesc;
5279 UINT i;
5281 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
5284 if (pFDesc)
5286 *ppFuncDesc = &pFDesc->funcdesc;
5287 return S_OK;
5290 return TYPE_E_ELEMENTNOTFOUND;
5293 /* internal function to make the inherited interfaces' methods appear
5294 * part of the interface */
5295 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5296 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5298 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5299 HRESULT hr;
5300 UINT implemented_funcs = 0;
5302 if (funcs)
5303 *funcs = 0;
5304 else
5305 *hrefoffset = DISPATCH_HREF_OFFSET;
5307 if(This->impltypelist)
5309 ITypeInfo *pSubTypeInfo;
5310 UINT sub_funcs;
5312 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
5313 if (FAILED(hr))
5314 return hr;
5316 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5317 index,
5318 ppFuncDesc,
5319 &sub_funcs, hrefoffset);
5320 implemented_funcs += sub_funcs;
5321 ITypeInfo_Release(pSubTypeInfo);
5322 if (SUCCEEDED(hr))
5323 return hr;
5324 *hrefoffset += DISPATCH_HREF_OFFSET;
5327 if (funcs)
5328 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
5329 else
5330 *hrefoffset = 0;
5332 if (index < implemented_funcs)
5333 return E_INVALIDARG;
5334 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5335 ppFuncDesc);
5338 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5340 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5341 while (TRUE)
5343 switch (pTypeDesc->vt)
5345 case VT_USERDEFINED:
5346 pTypeDesc->u.hreftype += hrefoffset;
5347 return;
5348 case VT_PTR:
5349 case VT_SAFEARRAY:
5350 pTypeDesc = pTypeDesc->u.lptdesc;
5351 break;
5352 case VT_CARRAY:
5353 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5354 break;
5355 default:
5356 return;
5361 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5363 SHORT i;
5364 for (i = 0; i < pFuncDesc->cParams; i++)
5365 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5366 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5369 /* ITypeInfo::GetFuncDesc
5371 * Retrieves the FUNCDESC structure that contains information about a
5372 * specified function.
5375 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5376 LPFUNCDESC *ppFuncDesc)
5378 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5379 const FUNCDESC *internal_funcdesc;
5380 HRESULT hr;
5381 UINT hrefoffset = 0;
5383 TRACE("(%p) index %d\n", This, index);
5385 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5386 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5387 &internal_funcdesc, NULL,
5388 &hrefoffset);
5389 else
5390 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5391 &internal_funcdesc);
5392 if (FAILED(hr))
5394 WARN("description for function %d not found\n", index);
5395 return hr;
5398 hr = TLB_AllocAndInitFuncDesc(
5399 internal_funcdesc,
5400 ppFuncDesc,
5401 This->TypeAttr.typekind == TKIND_DISPATCH);
5403 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5404 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5406 TRACE("-- 0x%08x\n", hr);
5407 return hr;
5410 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5412 VARDESC *dest;
5413 char *buffer;
5414 SIZE_T size = sizeof(*src);
5415 HRESULT hr;
5417 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5418 if (src->varkind == VAR_CONST)
5419 size += sizeof(VARIANT);
5420 size += TLB_SizeElemDesc(&src->elemdescVar);
5422 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5423 if (!dest) return E_OUTOFMEMORY;
5425 *dest = *src;
5426 buffer = (char *)(dest + 1);
5427 if (src->lpstrSchema)
5429 int len;
5430 dest->lpstrSchema = (LPOLESTR)buffer;
5431 len = strlenW(src->lpstrSchema);
5432 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5433 buffer += (len + 1) * sizeof(WCHAR);
5436 if (src->varkind == VAR_CONST)
5438 HRESULT hr;
5440 dest->u.lpvarValue = (VARIANT *)buffer;
5441 *dest->u.lpvarValue = *src->u.lpvarValue;
5442 buffer += sizeof(VARIANT);
5443 VariantInit(dest->u.lpvarValue);
5444 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5445 if (FAILED(hr))
5447 SysFreeString((BSTR)dest);
5448 return hr;
5451 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5452 if (FAILED(hr))
5454 if (src->varkind == VAR_CONST)
5455 VariantClear(dest->u.lpvarValue);
5456 SysFreeString((BSTR)dest);
5457 return hr;
5459 *dest_ptr = dest;
5460 return S_OK;
5463 /* ITypeInfo::GetVarDesc
5465 * Retrieves a VARDESC structure that describes the specified variable.
5468 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5469 LPVARDESC *ppVarDesc)
5471 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5472 UINT i;
5473 const TLBVarDesc *pVDesc;
5475 TRACE("(%p) index %d\n", This, index);
5477 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
5480 if (pVDesc)
5481 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5483 return E_INVALIDARG;
5486 /* ITypeInfo_GetNames
5488 * Retrieves the variable with the specified member ID (or the name of the
5489 * property or method and its parameters) that correspond to the specified
5490 * function ID.
5492 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5493 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5495 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5496 const TLBFuncDesc *pFDesc;
5497 const TLBVarDesc *pVDesc;
5498 int i;
5499 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5500 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
5501 if(pFDesc)
5503 /* function found, now return function and parameter names */
5504 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5506 if(!i)
5507 *rgBstrNames=SysAllocString(pFDesc->Name);
5508 else
5509 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5511 *pcNames=i;
5513 else
5515 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
5516 if(pVDesc)
5518 *rgBstrNames=SysAllocString(pVDesc->Name);
5519 *pcNames=1;
5521 else
5523 if(This->impltypelist &&
5524 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5525 /* recursive search */
5526 ITypeInfo *pTInfo;
5527 HRESULT result;
5528 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5529 &pTInfo);
5530 if(SUCCEEDED(result))
5532 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5533 ITypeInfo_Release(pTInfo);
5534 return result;
5536 WARN("Could not search inherited interface!\n");
5538 else
5540 WARN("no names found\n");
5542 *pcNames=0;
5543 return TYPE_E_ELEMENTNOTFOUND;
5546 return S_OK;
5550 /* ITypeInfo::GetRefTypeOfImplType
5552 * If a type description describes a COM class, it retrieves the type
5553 * description of the implemented interface types. For an interface,
5554 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5555 * if any exist.
5558 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5559 ITypeInfo2 *iface,
5560 UINT index,
5561 HREFTYPE *pRefType)
5563 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5564 UINT i;
5565 HRESULT hr = S_OK;
5566 const TLBImplType *pImpl = This->impltypelist;
5568 TRACE("(%p) index %d\n", This, index);
5569 if (TRACE_ON(ole)) dump_TypeInfo(This);
5571 if(index==(UINT)-1)
5573 /* only valid on dual interfaces;
5574 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5576 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5578 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
5580 *pRefType = -1;
5582 else
5584 hr = TYPE_E_ELEMENTNOTFOUND;
5587 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5589 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5590 *pRefType = This->pTypeLib->dispatch_href;
5592 else
5594 /* get element n from linked list */
5595 for(i=0; pImpl && i<index; i++)
5597 pImpl = pImpl->next;
5600 if (pImpl)
5601 *pRefType = pImpl->hRef;
5602 else
5603 hr = TYPE_E_ELEMENTNOTFOUND;
5606 if(TRACE_ON(ole))
5608 if(SUCCEEDED(hr))
5609 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5610 else
5611 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5614 return hr;
5617 /* ITypeInfo::GetImplTypeFlags
5619 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5620 * or base interface in a type description.
5622 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5623 UINT index, INT *pImplTypeFlags)
5625 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5626 UINT i;
5627 TLBImplType *pImpl;
5629 TRACE("(%p) index %d\n", This, index);
5630 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5631 i++, pImpl=pImpl->next)
5633 if(i==index && pImpl){
5634 *pImplTypeFlags=pImpl->implflags;
5635 return S_OK;
5637 *pImplTypeFlags=0;
5639 if(This->TypeAttr.typekind==TKIND_DISPATCH && !index)
5640 return S_OK;
5642 WARN("ImplType %d not found\n", index);
5643 return TYPE_E_ELEMENTNOTFOUND;
5646 /* GetIDsOfNames
5647 * Maps between member names and member IDs, and parameter names and
5648 * parameter IDs.
5650 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5651 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5653 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5654 const TLBFuncDesc *pFDesc;
5655 const TLBVarDesc *pVDesc;
5656 HRESULT ret=S_OK;
5657 UINT i;
5659 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5660 cNames);
5662 /* init out parameters in case of failure */
5663 for (i = 0; i < cNames; i++)
5664 pMemId[i] = MEMBERID_NIL;
5666 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5667 int j;
5668 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5669 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5670 for(i=1; i < cNames; i++){
5671 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5672 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5673 break;
5674 if( j<pFDesc->funcdesc.cParams)
5675 pMemId[i]=j;
5676 else
5677 ret=DISP_E_UNKNOWNNAME;
5679 TRACE("-- 0x%08x\n", ret);
5680 return ret;
5683 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5684 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5685 if(cNames) *pMemId=pVDesc->vardesc.memid;
5686 return ret;
5689 /* not found, see if it can be found in an inherited interface */
5690 if(This->impltypelist) {
5691 /* recursive search */
5692 ITypeInfo *pTInfo;
5693 ret=ITypeInfo_GetRefTypeInfo(iface,
5694 This->impltypelist->hRef, &pTInfo);
5695 if(SUCCEEDED(ret)){
5696 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5697 ITypeInfo_Release(pTInfo);
5698 return ret;
5700 WARN("Could not search inherited interface!\n");
5701 } else
5702 WARN("no names found\n");
5703 return DISP_E_UNKNOWNNAME;
5707 #ifdef __i386__
5709 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
5710 __ASM_GLOBAL_FUNC( call_method,
5711 "pushl %ebp\n\t"
5712 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
5713 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
5714 "movl %esp,%ebp\n\t"
5715 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
5716 "pushl %esi\n\t"
5717 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
5718 "pushl %edi\n\t"
5719 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
5720 "movl 12(%ebp),%edx\n\t"
5721 "movl %esp,%edi\n\t"
5722 "shll $2,%edx\n\t"
5723 "jz 1f\n\t"
5724 "subl %edx,%edi\n\t"
5725 "andl $~15,%edi\n\t"
5726 "movl %edi,%esp\n\t"
5727 "movl 12(%ebp),%ecx\n\t"
5728 "movl 16(%ebp),%esi\n\t"
5729 "cld\n\t"
5730 "rep; movsl\n"
5731 "1:\tcall *8(%ebp)\n\t"
5732 "subl %esp,%edi\n\t"
5733 "movl 20(%ebp),%ecx\n\t"
5734 "movl %edi,(%ecx)\n\t"
5735 "leal -8(%ebp),%esp\n\t"
5736 "popl %edi\n\t"
5737 __ASM_CFI(".cfi_same_value %edi\n\t")
5738 "popl %esi\n\t"
5739 __ASM_CFI(".cfi_same_value %esi\n\t")
5740 "popl %ebp\n\t"
5741 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
5742 __ASM_CFI(".cfi_same_value %ebp\n\t")
5743 "ret" )
5745 /* same function but returning floating point */
5746 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
5748 /* ITypeInfo::Invoke
5750 * Invokes a method, or accesses a property of an object, that implements the
5751 * interface described by the type description.
5753 DWORD
5754 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5755 DWORD res;
5756 int stack_offset;
5758 if (TRACE_ON(ole)) {
5759 int i;
5760 TRACE("Calling %p(",func);
5761 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
5762 if (nrargs > 30) TRACE("...");
5763 TRACE(")\n");
5766 switch (callconv) {
5767 case CC_STDCALL:
5768 case CC_CDECL:
5769 res = call_method( func, nrargs, args, &stack_offset );
5770 break;
5771 default:
5772 FIXME("unsupported calling convention %d\n",callconv);
5773 res = -1;
5774 break;
5776 TRACE("returns %08x\n",res);
5777 return res;
5780 #elif defined(__x86_64__)
5782 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
5783 __ASM_GLOBAL_FUNC( call_method,
5784 "pushq %rbp\n\t"
5785 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
5786 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
5787 "movq %rsp,%rbp\n\t"
5788 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
5789 "pushq %rsi\n\t"
5790 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
5791 "pushq %rdi\n\t"
5792 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
5793 "movq %rcx,%rax\n\t"
5794 "movq $4,%rcx\n\t"
5795 "cmp %rcx,%rdx\n\t"
5796 "cmovgq %rdx,%rcx\n\t"
5797 "leaq 0(,%rcx,8),%rdx\n\t"
5798 "subq %rdx,%rsp\n\t"
5799 "andq $~15,%rsp\n\t"
5800 "movq %rsp,%rdi\n\t"
5801 "movq %r8,%rsi\n\t"
5802 "rep; movsq\n\t"
5803 "movq 0(%rsp),%rcx\n\t"
5804 "movq 8(%rsp),%rdx\n\t"
5805 "movq 16(%rsp),%r8\n\t"
5806 "movq 24(%rsp),%r9\n\t"
5807 "movq %rcx,%xmm0\n\t"
5808 "movq %rdx,%xmm1\n\t"
5809 "movq %r8,%xmm2\n\t"
5810 "movq %r9,%xmm3\n\t"
5811 "callq *%rax\n\t"
5812 "leaq -16(%rbp),%rsp\n\t"
5813 "popq %rdi\n\t"
5814 __ASM_CFI(".cfi_same_value %rdi\n\t")
5815 "popq %rsi\n\t"
5816 __ASM_CFI(".cfi_same_value %rsi\n\t")
5817 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
5818 "popq %rbp\n\t"
5819 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
5820 __ASM_CFI(".cfi_same_value %rbp\n\t")
5821 "ret")
5823 /* same function but returning floating point */
5824 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
5826 #endif /* __x86_64__ */
5828 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5830 HRESULT hr = S_OK;
5831 ITypeInfo *tinfo2 = NULL;
5832 TYPEATTR *tattr = NULL;
5834 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5835 if (hr)
5837 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5838 "hr = 0x%08x\n",
5839 tdesc->u.hreftype, hr);
5840 return hr;
5842 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5843 if (hr)
5845 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5846 ITypeInfo_Release(tinfo2);
5847 return hr;
5850 switch (tattr->typekind)
5852 case TKIND_ENUM:
5853 *vt |= VT_I4;
5854 break;
5856 case TKIND_ALIAS:
5857 tdesc = &tattr->tdescAlias;
5858 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5859 break;
5861 case TKIND_INTERFACE:
5862 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5863 *vt |= VT_DISPATCH;
5864 else
5865 *vt |= VT_UNKNOWN;
5866 break;
5868 case TKIND_DISPATCH:
5869 *vt |= VT_DISPATCH;
5870 break;
5872 case TKIND_COCLASS:
5873 *vt |= VT_DISPATCH;
5874 break;
5876 case TKIND_RECORD:
5877 FIXME("TKIND_RECORD unhandled.\n");
5878 hr = E_NOTIMPL;
5879 break;
5881 case TKIND_UNION:
5882 FIXME("TKIND_UNION unhandled.\n");
5883 hr = E_NOTIMPL;
5884 break;
5886 default:
5887 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5888 hr = E_NOTIMPL;
5889 break;
5891 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5892 ITypeInfo_Release(tinfo2);
5893 return hr;
5896 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5898 HRESULT hr = S_OK;
5900 /* enforce only one level of pointer indirection */
5901 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5903 tdesc = tdesc->u.lptdesc;
5905 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5906 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5907 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5908 if ((tdesc->vt == VT_USERDEFINED) ||
5909 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5911 VARTYPE vt_userdefined = 0;
5912 const TYPEDESC *tdesc_userdefined = tdesc;
5913 if (tdesc->vt == VT_PTR)
5915 vt_userdefined = VT_BYREF;
5916 tdesc_userdefined = tdesc->u.lptdesc;
5918 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5919 if ((hr == S_OK) &&
5920 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5921 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5923 *vt |= vt_userdefined;
5924 return S_OK;
5927 *vt = VT_BYREF;
5930 switch (tdesc->vt)
5932 case VT_HRESULT:
5933 *vt |= VT_ERROR;
5934 break;
5935 case VT_USERDEFINED:
5936 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5937 break;
5938 case VT_VOID:
5939 case VT_CARRAY:
5940 case VT_PTR:
5941 case VT_LPSTR:
5942 case VT_LPWSTR:
5943 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5944 hr = DISP_E_BADVARTYPE;
5945 break;
5946 case VT_SAFEARRAY:
5947 *vt |= VT_ARRAY;
5948 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5949 break;
5950 case VT_INT:
5951 *vt |= VT_I4;
5952 break;
5953 case VT_UINT:
5954 *vt |= VT_UI4;
5955 break;
5956 default:
5957 *vt |= tdesc->vt;
5958 break;
5960 return hr;
5963 /***********************************************************************
5964 * DispCallFunc (OLEAUT32.@)
5966 * Invokes a function of the specified calling convention, passing the
5967 * specified arguments and returns the result.
5969 * PARAMS
5970 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5971 * oVft [I] The offset in the vtable. See notes.
5972 * cc [I] Calling convention of the function to call.
5973 * vtReturn [I] The return type of the function.
5974 * cActuals [I] Number of parameters.
5975 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5976 * prgpvarg [I] The arguments to pass.
5977 * pvargResult [O] The return value of the function. Can be NULL.
5979 * RETURNS
5980 * Success: S_OK.
5981 * Failure: HRESULT code.
5983 * NOTES
5984 * The HRESULT return value of this function is not affected by the return
5985 * value of the user supplied function, which is returned in pvargResult.
5987 * If pvInstance is NULL then a non-object function is to be called and oVft
5988 * is the address of the function to call.
5990 * The cc parameter can be one of the following values:
5991 *|CC_FASTCALL
5992 *|CC_CDECL
5993 *|CC_PASCAL
5994 *|CC_STDCALL
5995 *|CC_FPFASTCALL
5996 *|CC_SYSCALL
5997 *|CC_MPWCDECL
5998 *|CC_MPWPASCAL
6001 HRESULT WINAPI
6002 DispCallFunc(
6003 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
6004 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
6006 #ifdef __i386__
6007 int argspos, stack_offset;
6008 void *func;
6009 UINT i;
6010 DWORD *args;
6012 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6013 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6014 pvargResult, V_VT(pvargResult));
6016 if (cc != CC_STDCALL && cc != CC_CDECL)
6018 FIXME("unsupported calling convention %d\n",cc);
6019 return E_INVALIDARG;
6022 /* maximum size for an argument is sizeof(VARIANT) */
6023 args = HeapAlloc( GetProcessHeap(), 0, sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6025 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6026 argspos = 1;
6027 if (pvInstance)
6029 const FARPROC *vtable = *(FARPROC **)pvInstance;
6030 func = vtable[oVft/sizeof(void *)];
6031 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6033 else func = (void *)oVft;
6035 for (i = 0; i < cActuals; i++)
6037 VARIANT *arg = prgpvarg[i];
6039 switch (prgvt[i])
6041 case VT_EMPTY:
6042 break;
6043 case VT_I8:
6044 case VT_UI8:
6045 case VT_R8:
6046 case VT_DATE:
6047 case VT_CY:
6048 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6049 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6050 break;
6051 case VT_DECIMAL:
6052 case VT_VARIANT:
6053 memcpy( &args[argspos], arg, sizeof(*arg) );
6054 argspos += sizeof(*arg) / sizeof(DWORD);
6055 break;
6056 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6057 args[argspos++] = V_BOOL(arg);
6058 break;
6059 default:
6060 args[argspos++] = V_UI4(arg);
6061 break;
6063 TRACE("arg %u: type %d\n",i,prgvt[i]);
6064 dump_Variant(arg);
6067 switch (vtReturn)
6069 case VT_EMPTY:
6070 call_method( func, argspos - 1, args + 1, &stack_offset );
6071 break;
6072 case VT_R4:
6073 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6074 break;
6075 case VT_R8:
6076 case VT_DATE:
6077 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6078 break;
6079 case VT_DECIMAL:
6080 case VT_VARIANT:
6081 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6082 call_method( func, argspos, args, &stack_offset );
6083 break;
6084 case VT_I8:
6085 case VT_UI8:
6086 case VT_CY:
6087 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6088 break;
6089 default:
6090 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6091 break;
6093 HeapFree( GetProcessHeap(), 0, args );
6094 if (stack_offset && cc == CC_STDCALL)
6096 WARN( "stack pointer off by %d\n", stack_offset );
6097 return DISP_E_BADCALLEE;
6099 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6100 TRACE("retval: "); dump_Variant(pvargResult);
6101 return S_OK;
6103 #elif defined(__x86_64__)
6104 int argspos;
6105 UINT i;
6106 DWORD_PTR *args;
6107 void *func;
6109 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6110 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6111 pvargResult, V_VT(pvargResult));
6113 if (cc != CC_STDCALL && cc != CC_CDECL)
6115 FIXME("unsupported calling convention %d\n",cc);
6116 return E_INVALIDARG;
6119 /* maximum size for an argument is sizeof(DWORD_PTR) */
6120 args = HeapAlloc( GetProcessHeap(), 0, sizeof(DWORD_PTR) * (cActuals + 2) );
6122 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6123 argspos = 1;
6124 if (pvInstance)
6126 const FARPROC *vtable = *(FARPROC **)pvInstance;
6127 func = vtable[oVft/sizeof(void *)];
6128 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6130 else func = (void *)oVft;
6132 for (i = 0; i < cActuals; i++)
6134 VARIANT *arg = prgpvarg[i];
6136 switch (prgvt[i])
6138 case VT_DECIMAL:
6139 case VT_VARIANT:
6140 args[argspos++] = (ULONG_PTR)arg;
6141 break;
6142 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6143 args[argspos++] = V_BOOL(arg);
6144 break;
6145 default:
6146 args[argspos++] = V_UI8(arg);
6147 break;
6149 TRACE("arg %u: type %d\n",i,prgvt[i]);
6150 dump_Variant(arg);
6153 switch (vtReturn)
6155 case VT_R4:
6156 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6157 break;
6158 case VT_R8:
6159 case VT_DATE:
6160 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6161 break;
6162 case VT_DECIMAL:
6163 case VT_VARIANT:
6164 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6165 call_method( func, argspos, args );
6166 break;
6167 default:
6168 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6169 break;
6171 HeapFree( GetProcessHeap(), 0, args );
6172 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6173 TRACE("retval: "); dump_Variant(pvargResult);
6174 return S_OK;
6176 #else
6177 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6178 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6179 return E_NOTIMPL;
6180 #endif
6183 #define INVBUF_ELEMENT_SIZE \
6184 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6185 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6186 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6187 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6188 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6189 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6190 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6191 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6193 static HRESULT WINAPI ITypeInfo_fnInvoke(
6194 ITypeInfo2 *iface,
6195 VOID *pIUnk,
6196 MEMBERID memid,
6197 UINT16 wFlags,
6198 DISPPARAMS *pDispParams,
6199 VARIANT *pVarResult,
6200 EXCEPINFO *pExcepInfo,
6201 UINT *pArgErr)
6203 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6204 int i;
6205 unsigned int var_index;
6206 TYPEKIND type_kind;
6207 HRESULT hres;
6208 const TLBFuncDesc *pFuncInfo;
6210 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6211 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6214 if( This->TypeAttr.wTypeFlags & TYPEFLAG_FRESTRICTED )
6215 return DISP_E_MEMBERNOTFOUND;
6217 if (!pDispParams)
6219 ERR("NULL pDispParams not allowed\n");
6220 return E_INVALIDARG;
6223 dump_DispParms(pDispParams);
6225 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6227 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6228 pDispParams->cNamedArgs, pDispParams->cArgs);
6229 return E_INVALIDARG;
6232 /* we do this instead of using GetFuncDesc since it will return a fake
6233 * FUNCDESC for dispinterfaces and we want the real function description */
6234 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
6235 if ((memid == pFuncInfo->funcdesc.memid) &&
6236 (wFlags & pFuncInfo->funcdesc.invkind) &&
6237 (pFuncInfo->funcdesc.wFuncFlags & FUNCFLAG_FRESTRICTED) == 0)
6238 break;
6240 if (pFuncInfo) {
6241 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6243 if (TRACE_ON(ole))
6245 TRACE("invoking:\n");
6246 dump_TLBFuncDescOne(pFuncInfo);
6249 switch (func_desc->funckind) {
6250 case FUNC_PUREVIRTUAL:
6251 case FUNC_VIRTUAL: {
6252 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
6253 VARIANT varresult;
6254 VARIANT retval; /* pointer for storing byref retvals in */
6255 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6256 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6257 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6258 UINT cNamedArgs = pDispParams->cNamedArgs;
6259 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6260 UINT vargs_converted=0;
6262 hres = S_OK;
6264 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6266 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6268 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6269 hres = DISP_E_PARAMNOTFOUND;
6270 goto func_fail;
6274 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6276 ERR("functions with the vararg attribute do not support named arguments\n");
6277 hres = DISP_E_NONAMEDARGS;
6278 goto func_fail;
6281 for (i = 0; i < func_desc->cParams; i++)
6283 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6284 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6285 if (FAILED(hres))
6286 goto func_fail;
6289 TRACE("changing args\n");
6290 for (i = 0; i < func_desc->cParams; i++)
6292 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6293 VARIANTARG *src_arg;
6295 if (wParamFlags & PARAMFLAG_FLCID)
6297 VARIANTARG *arg;
6298 arg = prgpvarg[i] = &rgvarg[i];
6299 V_VT(arg) = VT_I4;
6300 V_I4(arg) = This->pTypeLib->lcid;
6301 continue;
6304 src_arg = NULL;
6306 if (cNamedArgs)
6308 USHORT j;
6309 for (j = 0; j < cNamedArgs; j++)
6310 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
6312 src_arg = &pDispParams->rgvarg[j];
6313 break;
6317 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
6319 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6320 vargs_converted++;
6323 if (wParamFlags & PARAMFLAG_FRETVAL)
6325 /* under most conditions the caller is not allowed to
6326 * pass in a dispparam arg in the index of what would be
6327 * the retval parameter. however, there is an exception
6328 * where the extra parameter is used in an extra
6329 * IDispatch::Invoke below */
6330 if ((i < pDispParams->cArgs) &&
6331 ((func_desc->cParams != 1) || !pVarResult ||
6332 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6334 hres = DISP_E_BADPARAMCOUNT;
6335 break;
6338 /* note: this check is placed so that if the caller passes
6339 * in a VARIANTARG for the retval we just ignore it, like
6340 * native does */
6341 if (i == func_desc->cParams - 1)
6343 VARIANTARG *arg;
6344 arg = prgpvarg[i] = &rgvarg[i];
6345 memset(arg, 0, sizeof(*arg));
6346 V_VT(arg) = rgvt[i];
6347 memset(&retval, 0, sizeof(retval));
6348 V_BYREF(arg) = &retval;
6350 else
6352 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6353 hres = E_UNEXPECTED;
6354 break;
6357 else if (src_arg)
6359 dump_Variant(src_arg);
6361 if (rgvt[i] == VT_VARIANT)
6362 hres = VariantCopy(&rgvarg[i], src_arg);
6363 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6365 if (rgvt[i] == V_VT(src_arg))
6366 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6367 else
6369 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6370 if (wParamFlags & PARAMFLAG_FIN)
6371 hres = VariantCopy(&missing_arg[i], src_arg);
6372 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6374 V_VT(&rgvarg[i]) = rgvt[i];
6376 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6378 SAFEARRAY *a;
6379 SAFEARRAYBOUND bound;
6380 VARIANT *v;
6381 LONG j;
6382 bound.lLbound = 0;
6383 bound.cElements = pDispParams->cArgs-i;
6384 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6386 ERR("SafeArrayCreate failed\n");
6387 break;
6389 hres = SafeArrayAccessData(a, (LPVOID)&v);
6390 if (hres != S_OK)
6392 ERR("SafeArrayAccessData failed with %x\n", hres);
6393 break;
6395 for (j = 0; j < bound.cElements; j++)
6396 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6397 hres = SafeArrayUnaccessData(a);
6398 if (hres != S_OK)
6400 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6401 break;
6403 V_ARRAY(&rgvarg[i]) = a;
6404 V_VT(&rgvarg[i]) = rgvt[i];
6406 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6408 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6409 if (wParamFlags & PARAMFLAG_FIN)
6410 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6411 else
6412 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
6413 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6414 V_VT(&rgvarg[i]) = rgvt[i];
6416 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6418 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6419 V_VT(&rgvarg[i]) = rgvt[i];
6421 else
6423 /* FIXME: this doesn't work for VT_BYREF arguments if
6424 * they are not the same type as in the paramdesc */
6425 V_VT(&rgvarg[i]) = V_VT(src_arg);
6426 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6427 V_VT(&rgvarg[i]) = rgvt[i];
6430 if (FAILED(hres))
6432 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6433 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6434 debugstr_VT(src_arg), debugstr_VF(src_arg));
6435 break;
6437 prgpvarg[i] = &rgvarg[i];
6439 else if (wParamFlags & PARAMFLAG_FOPT)
6441 VARIANTARG *arg;
6442 arg = prgpvarg[i] = &rgvarg[i];
6443 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6445 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6446 if (FAILED(hres))
6447 break;
6449 else
6451 VARIANTARG *missing_arg;
6452 /* if the function wants a pointer to a variant then
6453 * set that up, otherwise just pass the VT_ERROR in
6454 * the argument by value */
6455 if (rgvt[i] & VT_BYREF)
6457 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6458 V_VT(arg) = VT_VARIANT | VT_BYREF;
6459 V_VARIANTREF(arg) = missing_arg;
6461 else
6462 missing_arg = arg;
6463 V_VT(missing_arg) = VT_ERROR;
6464 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6467 else
6469 hres = DISP_E_BADPARAMCOUNT;
6470 break;
6473 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6475 /* VT_VOID is a special case for return types, so it is not
6476 * handled in the general function */
6477 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6478 V_VT(&varresult) = VT_EMPTY;
6479 else
6481 V_VT(&varresult) = 0;
6482 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6483 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6486 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6487 V_VT(&varresult), func_desc->cParams, rgvt,
6488 prgpvarg, &varresult);
6490 vargs_converted = 0;
6492 for (i = 0; i < func_desc->cParams; i++)
6494 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6495 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6497 if (wParamFlags & PARAMFLAG_FLCID)
6498 continue;
6499 else if (wParamFlags & PARAMFLAG_FRETVAL)
6501 if (TRACE_ON(ole))
6503 TRACE("[retval] value: ");
6504 dump_Variant(prgpvarg[i]);
6507 if (pVarResult)
6509 VariantInit(pVarResult);
6510 /* deref return value */
6511 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6514 VARIANT_ClearInd(prgpvarg[i]);
6516 else if (vargs_converted < pDispParams->cArgs)
6518 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6519 if (wParamFlags & PARAMFLAG_FOUT)
6521 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
6523 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6525 if (FAILED(hres))
6527 ERR("failed to convert param %d to vt %d\n", i,
6528 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
6529 break;
6533 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6534 func_desc->cParamsOpt < 0 &&
6535 i == func_desc->cParams-1)
6537 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6538 LONG j, ubound;
6539 VARIANT *v;
6540 hres = SafeArrayGetUBound(a, 1, &ubound);
6541 if (hres != S_OK)
6543 ERR("SafeArrayGetUBound failed with %x\n", hres);
6544 break;
6546 hres = SafeArrayAccessData(a, (LPVOID)&v);
6547 if (hres != S_OK)
6549 ERR("SafeArrayAccessData failed with %x\n", hres);
6550 break;
6552 for (j = 0; j <= ubound; j++)
6553 VariantClear(&v[j]);
6554 hres = SafeArrayUnaccessData(a);
6555 if (hres != S_OK)
6557 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6558 break;
6561 VariantClear(&rgvarg[i]);
6562 vargs_converted++;
6564 else if (wParamFlags & PARAMFLAG_FOPT)
6566 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6567 VariantClear(&rgvarg[i]);
6570 VariantClear(&missing_arg[i]);
6573 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6575 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6576 hres = DISP_E_EXCEPTION;
6577 if (pExcepInfo)
6579 IErrorInfo *pErrorInfo;
6580 pExcepInfo->scode = V_ERROR(&varresult);
6581 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6583 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6584 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6585 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6586 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6588 IErrorInfo_Release(pErrorInfo);
6592 if (V_VT(&varresult) != VT_ERROR)
6594 TRACE("varresult value: ");
6595 dump_Variant(&varresult);
6597 if (pVarResult)
6599 VariantClear(pVarResult);
6600 *pVarResult = varresult;
6602 else
6603 VariantClear(&varresult);
6606 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6607 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6608 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6609 (pDispParams->cArgs != 0))
6611 if (V_VT(pVarResult) == VT_DISPATCH)
6613 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6614 /* Note: not VariantClear; we still need the dispatch
6615 * pointer to be valid */
6616 VariantInit(pVarResult);
6617 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6618 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6619 pDispParams, pVarResult, pExcepInfo, pArgErr);
6620 IDispatch_Release(pDispatch);
6622 else
6624 VariantClear(pVarResult);
6625 hres = DISP_E_NOTACOLLECTION;
6629 func_fail:
6630 HeapFree(GetProcessHeap(), 0, buffer);
6631 break;
6633 case FUNC_DISPATCH: {
6634 IDispatch *disp;
6636 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6637 if (SUCCEEDED(hres)) {
6638 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6639 hres = IDispatch_Invoke(
6640 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6641 pVarResult,pExcepInfo,pArgErr
6643 if (FAILED(hres))
6644 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6645 IDispatch_Release(disp);
6646 } else
6647 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6648 break;
6650 default:
6651 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6652 hres = E_FAIL;
6653 break;
6656 TRACE("-- 0x%08x\n", hres);
6657 return hres;
6659 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6660 VARDESC *var_desc;
6662 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6663 if(FAILED(hres)) return hres;
6665 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6666 dump_VARDESC(var_desc);
6667 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6668 return E_NOTIMPL;
6671 /* not found, look for it in inherited interfaces */
6672 ITypeInfo2_GetTypeKind(iface, &type_kind);
6673 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6674 if(This->impltypelist) {
6675 /* recursive search */
6676 ITypeInfo *pTInfo;
6677 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6678 if(SUCCEEDED(hres)){
6679 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6680 ITypeInfo_Release(pTInfo);
6681 return hres;
6683 WARN("Could not search inherited interface!\n");
6686 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6687 return DISP_E_MEMBERNOTFOUND;
6690 /* ITypeInfo::GetDocumentation
6692 * Retrieves the documentation string, the complete Help file name and path,
6693 * and the context ID for the Help topic for a specified type description.
6695 * (Can be tested by the Visual Basic Editor in Word for instance.)
6697 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6698 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6699 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6701 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6702 const TLBFuncDesc *pFDesc;
6703 const TLBVarDesc *pVDesc;
6704 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6705 " HelpContext(%p) HelpFile(%p)\n",
6706 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6707 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6708 if(pBstrName)
6709 *pBstrName=SysAllocString(This->Name);
6710 if(pBstrDocString)
6711 *pBstrDocString=SysAllocString(This->DocString);
6712 if(pdwHelpContext)
6713 *pdwHelpContext=This->dwHelpContext;
6714 if(pBstrHelpFile)
6715 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6716 return S_OK;
6717 }else {/* for a member */
6718 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6719 if(pFDesc->funcdesc.memid==memid){
6720 if(pBstrName)
6721 *pBstrName = SysAllocString(pFDesc->Name);
6722 if(pBstrDocString)
6723 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6724 if(pdwHelpContext)
6725 *pdwHelpContext=pFDesc->helpcontext;
6726 return S_OK;
6728 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6729 if(pVDesc->vardesc.memid==memid){
6730 if(pBstrName)
6731 *pBstrName = SysAllocString(pVDesc->Name);
6732 if(pBstrDocString)
6733 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6734 if(pdwHelpContext)
6735 *pdwHelpContext=pVDesc->HelpContext;
6736 return S_OK;
6740 if(This->impltypelist &&
6741 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6742 /* recursive search */
6743 ITypeInfo *pTInfo;
6744 HRESULT result;
6745 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6746 &pTInfo);
6747 if(SUCCEEDED(result)) {
6748 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6749 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6750 ITypeInfo_Release(pTInfo);
6751 return result;
6753 WARN("Could not search inherited interface!\n");
6756 WARN("member %d not found\n", memid);
6757 return TYPE_E_ELEMENTNOTFOUND;
6760 /* ITypeInfo::GetDllEntry
6762 * Retrieves a description or specification of an entry point for a function
6763 * in a DLL.
6765 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6766 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6767 WORD *pwOrdinal)
6769 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6770 const TLBFuncDesc *pFDesc;
6772 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6774 if (pBstrDllName) *pBstrDllName = NULL;
6775 if (pBstrName) *pBstrName = NULL;
6776 if (pwOrdinal) *pwOrdinal = 0;
6778 if (This->TypeAttr.typekind != TKIND_MODULE)
6779 return TYPE_E_BADMODULEKIND;
6781 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6782 if(pFDesc->funcdesc.memid==memid){
6783 dump_TypeInfo(This);
6784 if (TRACE_ON(ole))
6785 dump_TLBFuncDescOne(pFDesc);
6787 if (pBstrDllName)
6788 *pBstrDllName = SysAllocString(This->DllName);
6790 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6791 if (pBstrName)
6792 *pBstrName = SysAllocString(pFDesc->Entry);
6793 if (pwOrdinal)
6794 *pwOrdinal = -1;
6795 return S_OK;
6797 if (pBstrName)
6798 *pBstrName = NULL;
6799 if (pwOrdinal)
6800 *pwOrdinal = LOWORD(pFDesc->Entry);
6801 return S_OK;
6803 return TYPE_E_ELEMENTNOTFOUND;
6806 /* internal function to make the inherited interfaces' methods appear
6807 * part of the interface */
6808 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6809 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6811 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6812 HRESULT hr;
6814 TRACE("%p, 0x%x\n", iface, *hRefType);
6816 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK))
6818 ITypeInfo *pSubTypeInfo;
6820 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
6821 if (FAILED(hr))
6822 return hr;
6824 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6825 hRefType, ppTInfo);
6826 ITypeInfo_Release(pSubTypeInfo);
6827 if (SUCCEEDED(hr))
6828 return hr;
6830 *hRefType -= DISPATCH_HREF_OFFSET;
6832 if (!(*hRefType & DISPATCH_HREF_MASK))
6833 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6834 else
6835 return E_FAIL;
6838 /* ITypeInfo::GetRefTypeInfo
6840 * If a type description references other type descriptions, it retrieves
6841 * the referenced type descriptions.
6843 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6844 ITypeInfo2 *iface,
6845 HREFTYPE hRefType,
6846 ITypeInfo **ppTInfo)
6848 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6849 HRESULT result = E_FAIL;
6851 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6853 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6854 ITypeInfo_AddRef(*ppTInfo);
6855 result = S_OK;
6857 else if (hRefType == -1 &&
6858 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6859 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6861 /* when we meet a DUAL dispinterface, we must create the interface
6862 * version of it.
6864 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
6867 /* the interface version contains the same information as the dispinterface
6868 * copy the contents of the structs.
6870 *pTypeInfoImpl = *This;
6871 pTypeInfoImpl->ref = 0;
6873 /* change the type to interface */
6874 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6876 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6878 /* the AddRef implicitly adds a reference to the parent typelib, which
6879 * stops the copied data from being destroyed until the new typeinfo's
6880 * refcount goes to zero, but we need to signal to the new instance to
6881 * not free its data structures when it is destroyed */
6882 pTypeInfoImpl->not_attached_to_typelib = TRUE;
6884 ITypeInfo_AddRef(*ppTInfo);
6886 result = S_OK;
6888 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6889 (This->TypeAttr.typekind == TKIND_DISPATCH))
6891 HREFTYPE href_dispatch = hRefType;
6892 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6893 } else {
6894 TLBRefType *ref_type;
6895 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6897 if(ref_type->reference == hRefType)
6898 break;
6900 if(&ref_type->entry == &This->pTypeLib->ref_list)
6902 FIXME("Can't find pRefType for ref %x\n", hRefType);
6903 goto end;
6905 if(hRefType != -1) {
6906 ITypeLib *pTLib = NULL;
6908 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6909 UINT Index;
6910 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6911 } else {
6912 if(ref_type->pImpTLInfo->pImpTypeLib) {
6913 TRACE("typeinfo in imported typelib that is already loaded\n");
6914 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6915 ITypeLib2_AddRef(pTLib);
6916 result = S_OK;
6917 } else {
6918 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6919 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6920 ref_type->pImpTLInfo->wVersionMajor,
6921 ref_type->pImpTLInfo->wVersionMinor,
6922 ref_type->pImpTLInfo->lcid,
6923 &pTLib);
6925 if(FAILED(result)) {
6926 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6927 result=LoadTypeLib(libnam, &pTLib);
6928 SysFreeString(libnam);
6930 if(SUCCEEDED(result)) {
6931 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6932 ITypeLib2_AddRef(pTLib);
6936 if(SUCCEEDED(result)) {
6937 if(ref_type->index == TLB_REF_USE_GUID)
6938 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6939 &ref_type->guid,
6940 ppTInfo);
6941 else
6942 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6943 ppTInfo);
6945 if (pTLib != NULL)
6946 ITypeLib2_Release(pTLib);
6950 end:
6951 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6952 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6953 return result;
6956 /* ITypeInfo::AddressOfMember
6958 * Retrieves the addresses of static functions or variables, such as those
6959 * defined in a DLL.
6961 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6962 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6964 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6965 HRESULT hr;
6966 BSTR dll, entry;
6967 WORD ordinal;
6968 HMODULE module;
6970 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6972 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6973 if (FAILED(hr))
6974 return hr;
6976 module = LoadLibraryW(dll);
6977 if (!module)
6979 ERR("couldn't load %s\n", debugstr_w(dll));
6980 SysFreeString(dll);
6981 SysFreeString(entry);
6982 return STG_E_FILENOTFOUND;
6984 /* FIXME: store library somewhere where we can free it */
6986 if (entry)
6988 LPSTR entryA;
6989 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6990 entryA = HeapAlloc(GetProcessHeap(), 0, len);
6991 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6993 *ppv = GetProcAddress(module, entryA);
6994 if (!*ppv)
6995 ERR("function not found %s\n", debugstr_a(entryA));
6997 HeapFree(GetProcessHeap(), 0, entryA);
6999 else
7001 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7002 if (!*ppv)
7003 ERR("function not found %d\n", ordinal);
7006 SysFreeString(dll);
7007 SysFreeString(entry);
7009 if (!*ppv)
7010 return TYPE_E_DLLFUNCTIONNOTFOUND;
7012 return S_OK;
7015 /* ITypeInfo::CreateInstance
7017 * Creates a new instance of a type that describes a component object class
7018 * (coclass).
7020 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7021 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7023 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7024 HRESULT hr;
7025 TYPEATTR *pTA;
7027 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7029 *ppvObj = NULL;
7031 if(pOuterUnk)
7033 WARN("Not able to aggregate\n");
7034 return CLASS_E_NOAGGREGATION;
7037 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
7038 if(FAILED(hr)) return hr;
7040 if(pTA->typekind != TKIND_COCLASS)
7042 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7043 hr = E_INVALIDARG;
7044 goto end;
7047 hr = S_FALSE;
7048 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7050 IUnknown *pUnk;
7051 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7052 TRACE("GetActiveObject rets %08x\n", hr);
7053 if(hr == S_OK)
7055 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7056 IUnknown_Release(pUnk);
7060 if(hr != S_OK)
7061 hr = CoCreateInstance(&pTA->guid, NULL,
7062 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7063 riid, ppvObj);
7065 end:
7066 ITypeInfo_ReleaseTypeAttr(iface, pTA);
7067 return hr;
7070 /* ITypeInfo::GetMops
7072 * Retrieves marshalling information.
7074 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7075 BSTR *pBstrMops)
7077 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7078 FIXME("(%p %d) stub!\n", This, memid);
7079 *pBstrMops = NULL;
7080 return S_OK;
7083 /* ITypeInfo::GetContainingTypeLib
7085 * Retrieves the containing type library and the index of the type description
7086 * within that type library.
7088 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7089 ITypeLib * *ppTLib, UINT *pIndex)
7091 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7093 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7094 if (pIndex) {
7095 *pIndex=This->index;
7096 TRACE("returning pIndex=%d\n", *pIndex);
7099 if (ppTLib) {
7100 *ppTLib=(LPTYPELIB )(This->pTypeLib);
7101 ITypeLib2_AddRef(*ppTLib);
7102 TRACE("returning ppTLib=%p\n", *ppTLib);
7105 return S_OK;
7108 /* ITypeInfo::ReleaseTypeAttr
7110 * Releases a TYPEATTR previously returned by GetTypeAttr.
7113 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7114 TYPEATTR* pTypeAttr)
7116 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7117 TRACE("(%p)->(%p)\n", This, pTypeAttr);
7118 HeapFree(GetProcessHeap(), 0, pTypeAttr);
7121 /* ITypeInfo::ReleaseFuncDesc
7123 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7125 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7126 ITypeInfo2 *iface,
7127 FUNCDESC *pFuncDesc)
7129 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7130 SHORT i;
7132 TRACE("(%p)->(%p)\n", This, pFuncDesc);
7134 for (i = 0; i < pFuncDesc->cParams; i++)
7135 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7136 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7138 SysFreeString((BSTR)pFuncDesc);
7141 /* ITypeInfo::ReleaseVarDesc
7143 * Releases a VARDESC previously returned by GetVarDesc.
7145 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7146 VARDESC *pVarDesc)
7148 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7149 TRACE("(%p)->(%p)\n", This, pVarDesc);
7151 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
7152 if (pVarDesc->varkind == VAR_CONST)
7153 VariantClear(pVarDesc->u.lpvarValue);
7154 SysFreeString((BSTR)pVarDesc);
7157 /* ITypeInfo2::GetTypeKind
7159 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7162 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7163 TYPEKIND *pTypeKind)
7165 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7166 *pTypeKind=This->TypeAttr.typekind;
7167 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7168 return S_OK;
7171 /* ITypeInfo2::GetTypeFlags
7173 * Returns the type flags without any allocations. This returns a DWORD type
7174 * flag, which expands the type flags without growing the TYPEATTR (type
7175 * attribute).
7178 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7180 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7181 *pTypeFlags=This->TypeAttr.wTypeFlags;
7182 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7183 return S_OK;
7186 /* ITypeInfo2::GetFuncIndexOfMemId
7187 * Binds to a specific member based on a known DISPID, where the member name
7188 * is not known (for example, when binding to a default member).
7191 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7192 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7194 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7195 const TLBFuncDesc *pFuncInfo;
7196 int i;
7197 HRESULT result;
7199 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
7200 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7201 break;
7202 if(pFuncInfo) {
7203 *pFuncIndex = i;
7204 result = S_OK;
7205 } else
7206 result = TYPE_E_ELEMENTNOTFOUND;
7208 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7209 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7210 return result;
7213 /* TypeInfo2::GetVarIndexOfMemId
7215 * Binds to a specific member based on a known DISPID, where the member name
7216 * is not known (for example, when binding to a default member).
7219 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7220 MEMBERID memid, UINT *pVarIndex)
7222 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7223 TLBVarDesc *pVarInfo;
7224 int i;
7225 HRESULT result;
7226 for(i=0, pVarInfo=This->varlist; pVarInfo &&
7227 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
7229 if(pVarInfo) {
7230 *pVarIndex = i;
7231 result = S_OK;
7232 } else
7233 result = TYPE_E_ELEMENTNOTFOUND;
7235 TRACE("(%p) memid 0x%08x -> %s\n", This,
7236 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7237 return result;
7240 /* ITypeInfo2::GetCustData
7242 * Gets the custom data
7244 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7245 ITypeInfo2 * iface,
7246 REFGUID guid,
7247 VARIANT *pVarVal)
7249 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7250 TLBCustData *pCData;
7252 for(pCData=This->pCustData; pCData; pCData = pCData->next)
7253 if( IsEqualIID(guid, &pCData->guid)) break;
7255 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7257 VariantInit( pVarVal);
7258 if (pCData)
7259 VariantCopy( pVarVal, &pCData->data);
7260 else
7261 VariantClear( pVarVal );
7262 return S_OK;
7265 /* ITypeInfo2::GetFuncCustData
7267 * Gets the custom data
7269 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7270 ITypeInfo2 * iface,
7271 UINT index,
7272 REFGUID guid,
7273 VARIANT *pVarVal)
7275 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7276 TLBCustData *pCData=NULL;
7277 TLBFuncDesc * pFDesc;
7278 UINT i;
7279 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7280 pFDesc=pFDesc->next);
7282 if(pFDesc)
7283 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
7284 if( IsEqualIID(guid, &pCData->guid)) break;
7286 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7288 if(pCData){
7289 VariantInit( pVarVal);
7290 VariantCopy( pVarVal, &pCData->data);
7291 return S_OK;
7293 return E_INVALIDARG; /* FIXME: correct? */
7296 /* ITypeInfo2::GetParamCustData
7298 * Gets the custom data
7300 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7301 ITypeInfo2 * iface,
7302 UINT indexFunc,
7303 UINT indexParam,
7304 REFGUID guid,
7305 VARIANT *pVarVal)
7307 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7308 TLBCustData *pCData=NULL;
7309 TLBFuncDesc * pFDesc;
7310 UINT i;
7312 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
7314 if(pFDesc && indexParam<pFDesc->funcdesc.cParams)
7315 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
7316 pCData = pCData->next)
7317 if( IsEqualIID(guid, &pCData->guid)) break;
7319 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7321 if(pCData)
7323 VariantInit( pVarVal);
7324 VariantCopy( pVarVal, &pCData->data);
7325 return S_OK;
7327 return E_INVALIDARG; /* FIXME: correct? */
7330 /* ITypeInfo2::GetVarCustData
7332 * Gets the custom data
7334 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7335 ITypeInfo2 * iface,
7336 UINT index,
7337 REFGUID guid,
7338 VARIANT *pVarVal)
7340 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7341 TLBCustData *pCData=NULL;
7342 TLBVarDesc * pVDesc;
7343 UINT i;
7345 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
7347 if(pVDesc)
7349 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
7351 if( IsEqualIID(guid, &pCData->guid)) break;
7355 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7357 if(pCData)
7359 VariantInit( pVarVal);
7360 VariantCopy( pVarVal, &pCData->data);
7361 return S_OK;
7363 return E_INVALIDARG; /* FIXME: correct? */
7366 /* ITypeInfo2::GetImplCustData
7368 * Gets the custom data
7370 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7371 ITypeInfo2 * iface,
7372 UINT index,
7373 REFGUID guid,
7374 VARIANT *pVarVal)
7376 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7377 TLBCustData *pCData=NULL;
7378 TLBImplType * pRDesc;
7379 UINT i;
7381 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
7383 if(pRDesc)
7385 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
7387 if( IsEqualIID(guid, &pCData->guid)) break;
7391 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7393 if(pCData)
7395 VariantInit( pVarVal);
7396 VariantCopy( pVarVal, &pCData->data);
7397 return S_OK;
7399 return E_INVALIDARG; /* FIXME: correct? */
7402 /* ITypeInfo2::GetDocumentation2
7404 * Retrieves the documentation string, the complete Help file name and path,
7405 * the localization context to use, and the context ID for the library Help
7406 * topic in the Help file.
7409 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7410 ITypeInfo2 * iface,
7411 MEMBERID memid,
7412 LCID lcid,
7413 BSTR *pbstrHelpString,
7414 DWORD *pdwHelpStringContext,
7415 BSTR *pbstrHelpStringDll)
7417 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7418 const TLBFuncDesc *pFDesc;
7419 const TLBVarDesc *pVDesc;
7420 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7421 "HelpStringContext(%p) HelpStringDll(%p)\n",
7422 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7423 pbstrHelpStringDll );
7424 /* the help string should be obtained from the helpstringdll,
7425 * using the _DLLGetDocumentation function, based on the supplied
7426 * lcid. Nice to do sometime...
7428 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7429 if(pbstrHelpString)
7430 *pbstrHelpString=SysAllocString(This->Name);
7431 if(pdwHelpStringContext)
7432 *pdwHelpStringContext=This->dwHelpStringContext;
7433 if(pbstrHelpStringDll)
7434 *pbstrHelpStringDll=
7435 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7436 return S_OK;
7437 }else {/* for a member */
7438 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
7439 if(pFDesc->funcdesc.memid==memid){
7440 if(pbstrHelpString)
7441 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
7442 if(pdwHelpStringContext)
7443 *pdwHelpStringContext=pFDesc->HelpStringContext;
7444 if(pbstrHelpStringDll)
7445 *pbstrHelpStringDll=
7446 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7447 return S_OK;
7449 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
7450 if(pVDesc->vardesc.memid==memid){
7451 if(pbstrHelpString)
7452 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
7453 if(pdwHelpStringContext)
7454 *pdwHelpStringContext=pVDesc->HelpStringContext;
7455 if(pbstrHelpStringDll)
7456 *pbstrHelpStringDll=
7457 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7458 return S_OK;
7461 return TYPE_E_ELEMENTNOTFOUND;
7464 /* ITypeInfo2::GetAllCustData
7466 * Gets all custom data items for the Type info.
7469 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7470 ITypeInfo2 * iface,
7471 CUSTDATA *pCustData)
7473 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7474 TLBCustData *pCData;
7475 int i;
7477 TRACE("(%p) returning %d items\n", This, This->ctCustData);
7479 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
7480 if(pCustData->prgCustData ){
7481 pCustData->cCustData=This->ctCustData;
7482 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
7483 pCustData->prgCustData[i].guid=pCData->guid;
7484 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
7486 }else{
7487 ERR(" OUT OF MEMORY!\n");
7488 return E_OUTOFMEMORY;
7490 return S_OK;
7493 /* ITypeInfo2::GetAllFuncCustData
7495 * Gets all custom data items for the specified Function
7498 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7499 ITypeInfo2 * iface,
7500 UINT index,
7501 CUSTDATA *pCustData)
7503 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7504 TLBCustData *pCData;
7505 TLBFuncDesc * pFDesc;
7506 UINT i;
7507 TRACE("(%p) index %d\n", This, index);
7508 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7509 pFDesc=pFDesc->next)
7511 if(pFDesc){
7512 pCustData->prgCustData =
7513 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
7514 if(pCustData->prgCustData ){
7515 pCustData->cCustData=pFDesc->ctCustData;
7516 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
7517 pCData = pCData->next){
7518 pCustData->prgCustData[i].guid=pCData->guid;
7519 VariantCopy(& pCustData->prgCustData[i].varValue,
7520 & pCData->data);
7522 }else{
7523 ERR(" OUT OF MEMORY!\n");
7524 return E_OUTOFMEMORY;
7526 return S_OK;
7528 return TYPE_E_ELEMENTNOTFOUND;
7531 /* ITypeInfo2::GetAllParamCustData
7533 * Gets all custom data items for the Functions
7536 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7537 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7539 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7540 TLBCustData *pCData=NULL;
7541 TLBFuncDesc * pFDesc;
7542 UINT i;
7543 TRACE("(%p) index %d\n", This, indexFunc);
7544 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
7545 pFDesc=pFDesc->next)
7547 if(pFDesc && indexParam<pFDesc->funcdesc.cParams){
7548 pCustData->prgCustData =
7549 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
7550 sizeof(CUSTDATAITEM));
7551 if(pCustData->prgCustData ){
7552 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
7553 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
7554 pCData; i++, pCData = pCData->next){
7555 pCustData->prgCustData[i].guid=pCData->guid;
7556 VariantCopy(& pCustData->prgCustData[i].varValue,
7557 & pCData->data);
7559 }else{
7560 ERR(" OUT OF MEMORY!\n");
7561 return E_OUTOFMEMORY;
7563 return S_OK;
7565 return TYPE_E_ELEMENTNOTFOUND;
7568 /* ITypeInfo2::GetAllVarCustData
7570 * Gets all custom data items for the specified Variable
7573 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7574 UINT index, CUSTDATA *pCustData)
7576 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7577 TLBCustData *pCData;
7578 TLBVarDesc * pVDesc;
7579 UINT i;
7580 TRACE("(%p) index %d\n", This, index);
7581 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
7582 pVDesc=pVDesc->next)
7584 if(pVDesc){
7585 pCustData->prgCustData =
7586 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
7587 if(pCustData->prgCustData ){
7588 pCustData->cCustData=pVDesc->ctCustData;
7589 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
7590 pCData = pCData->next){
7591 pCustData->prgCustData[i].guid=pCData->guid;
7592 VariantCopy(& pCustData->prgCustData[i].varValue,
7593 & pCData->data);
7595 }else{
7596 ERR(" OUT OF MEMORY!\n");
7597 return E_OUTOFMEMORY;
7599 return S_OK;
7601 return TYPE_E_ELEMENTNOTFOUND;
7604 /* ITypeInfo2::GetAllImplCustData
7606 * Gets all custom data items for the specified implementation type
7609 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7610 ITypeInfo2 * iface,
7611 UINT index,
7612 CUSTDATA *pCustData)
7614 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7615 TLBCustData *pCData;
7616 TLBImplType * pRDesc;
7617 UINT i;
7618 TRACE("(%p) index %d\n", This, index);
7619 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
7620 pRDesc=pRDesc->next)
7622 if(pRDesc){
7623 pCustData->prgCustData =
7624 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
7625 if(pCustData->prgCustData ){
7626 pCustData->cCustData=pRDesc->ctCustData;
7627 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
7628 pCData = pCData->next){
7629 pCustData->prgCustData[i].guid=pCData->guid;
7630 VariantCopy(& pCustData->prgCustData[i].varValue,
7631 & pCData->data);
7633 }else{
7634 ERR(" OUT OF MEMORY!\n");
7635 return E_OUTOFMEMORY;
7637 return S_OK;
7639 return TYPE_E_ELEMENTNOTFOUND;
7642 static const ITypeInfo2Vtbl tinfvt =
7645 ITypeInfo_fnQueryInterface,
7646 ITypeInfo_fnAddRef,
7647 ITypeInfo_fnRelease,
7649 ITypeInfo_fnGetTypeAttr,
7650 ITypeInfo_fnGetTypeComp,
7651 ITypeInfo_fnGetFuncDesc,
7652 ITypeInfo_fnGetVarDesc,
7653 ITypeInfo_fnGetNames,
7654 ITypeInfo_fnGetRefTypeOfImplType,
7655 ITypeInfo_fnGetImplTypeFlags,
7656 ITypeInfo_fnGetIDsOfNames,
7657 ITypeInfo_fnInvoke,
7658 ITypeInfo_fnGetDocumentation,
7659 ITypeInfo_fnGetDllEntry,
7660 ITypeInfo_fnGetRefTypeInfo,
7661 ITypeInfo_fnAddressOfMember,
7662 ITypeInfo_fnCreateInstance,
7663 ITypeInfo_fnGetMops,
7664 ITypeInfo_fnGetContainingTypeLib,
7665 ITypeInfo_fnReleaseTypeAttr,
7666 ITypeInfo_fnReleaseFuncDesc,
7667 ITypeInfo_fnReleaseVarDesc,
7669 ITypeInfo2_fnGetTypeKind,
7670 ITypeInfo2_fnGetTypeFlags,
7671 ITypeInfo2_fnGetFuncIndexOfMemId,
7672 ITypeInfo2_fnGetVarIndexOfMemId,
7673 ITypeInfo2_fnGetCustData,
7674 ITypeInfo2_fnGetFuncCustData,
7675 ITypeInfo2_fnGetParamCustData,
7676 ITypeInfo2_fnGetVarCustData,
7677 ITypeInfo2_fnGetImplTypeCustData,
7678 ITypeInfo2_fnGetDocumentation2,
7679 ITypeInfo2_fnGetAllCustData,
7680 ITypeInfo2_fnGetAllFuncCustData,
7681 ITypeInfo2_fnGetAllParamCustData,
7682 ITypeInfo2_fnGetAllVarCustData,
7683 ITypeInfo2_fnGetAllImplTypeCustData,
7686 /******************************************************************************
7687 * CreateDispTypeInfo [OLEAUT32.31]
7689 * Build type information for an object so it can be called through an
7690 * IDispatch interface.
7692 * RETURNS
7693 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7694 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7696 * NOTES
7697 * This call allows an objects methods to be accessed through IDispatch, by
7698 * building an ITypeInfo object that IDispatch can use to call through.
7700 HRESULT WINAPI CreateDispTypeInfo(
7701 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7702 LCID lcid, /* [I] Locale Id */
7703 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7705 ITypeInfoImpl *pTIClass, *pTIIface;
7706 ITypeLibImpl *pTypeLibImpl;
7707 unsigned int param, func;
7708 TLBFuncDesc **ppFuncDesc;
7709 TLBRefType *ref;
7711 TRACE("\n");
7712 pTypeLibImpl = TypeLibImpl_Constructor();
7713 if (!pTypeLibImpl) return E_FAIL;
7715 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
7716 pTIIface->pTypeLib = pTypeLibImpl;
7717 pTIIface->index = 0;
7718 pTIIface->Name = NULL;
7719 pTIIface->dwHelpContext = -1;
7720 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7721 pTIIface->TypeAttr.lcid = lcid;
7722 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7723 pTIIface->TypeAttr.wMajorVerNum = 0;
7724 pTIIface->TypeAttr.wMinorVerNum = 0;
7725 pTIIface->TypeAttr.cbAlignment = 2;
7726 pTIIface->TypeAttr.cbSizeInstance = -1;
7727 pTIIface->TypeAttr.cbSizeVft = -1;
7728 pTIIface->TypeAttr.cFuncs = 0;
7729 pTIIface->TypeAttr.cImplTypes = 0;
7730 pTIIface->TypeAttr.cVars = 0;
7731 pTIIface->TypeAttr.wTypeFlags = 0;
7733 ppFuncDesc = &pTIIface->funclist;
7734 for(func = 0; func < pidata->cMembers; func++) {
7735 METHODDATA *md = pidata->pmethdata + func;
7736 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
7737 (*ppFuncDesc)->Name = SysAllocString(md->szName);
7738 (*ppFuncDesc)->funcdesc.memid = md->dispid;
7739 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
7740 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
7741 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
7742 (*ppFuncDesc)->funcdesc.callconv = md->cc;
7743 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
7744 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
7745 (*ppFuncDesc)->funcdesc.oVft = md->iMeth * sizeof(void *);
7746 (*ppFuncDesc)->funcdesc.cScodes = 0;
7747 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
7748 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7749 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7750 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7751 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7752 md->cArgs * sizeof(ELEMDESC));
7753 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7754 md->cArgs * sizeof(TLBParDesc));
7755 for(param = 0; param < md->cArgs; param++) {
7756 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7757 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7759 (*ppFuncDesc)->helpcontext = 0;
7760 (*ppFuncDesc)->HelpStringContext = 0;
7761 (*ppFuncDesc)->HelpString = NULL;
7762 (*ppFuncDesc)->Entry = NULL;
7763 (*ppFuncDesc)->ctCustData = 0;
7764 (*ppFuncDesc)->pCustData = NULL;
7765 (*ppFuncDesc)->next = NULL;
7766 pTIIface->TypeAttr.cFuncs++;
7767 ppFuncDesc = &(*ppFuncDesc)->next;
7770 dump_TypeInfo(pTIIface);
7772 pTypeLibImpl->pTypeInfo = pTIIface;
7773 pTypeLibImpl->TypeInfoCount++;
7775 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
7776 pTIClass->pTypeLib = pTypeLibImpl;
7777 pTIClass->index = 1;
7778 pTIClass->Name = NULL;
7779 pTIClass->dwHelpContext = -1;
7780 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7781 pTIClass->TypeAttr.lcid = lcid;
7782 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7783 pTIClass->TypeAttr.wMajorVerNum = 0;
7784 pTIClass->TypeAttr.wMinorVerNum = 0;
7785 pTIClass->TypeAttr.cbAlignment = 2;
7786 pTIClass->TypeAttr.cbSizeInstance = -1;
7787 pTIClass->TypeAttr.cbSizeVft = -1;
7788 pTIClass->TypeAttr.cFuncs = 0;
7789 pTIClass->TypeAttr.cImplTypes = 1;
7790 pTIClass->TypeAttr.cVars = 0;
7791 pTIClass->TypeAttr.wTypeFlags = 0;
7793 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
7794 pTIClass->impltypelist->hRef = 0;
7796 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
7797 ref->index = 0;
7798 ref->reference = 0;
7799 ref->pImpTLInfo = TLB_REF_INTERNAL;
7800 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7802 dump_TypeInfo(pTIClass);
7804 pTIIface->next = pTIClass;
7805 pTypeLibImpl->TypeInfoCount++;
7807 *pptinfo = (ITypeInfo*)pTIClass;
7809 ITypeInfo_AddRef(*pptinfo);
7810 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7812 return S_OK;
7816 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7818 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7820 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7823 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7825 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7827 return ITypeInfo_AddRef((ITypeInfo *)This);
7830 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7832 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7834 return ITypeInfo_Release((ITypeInfo *)This);
7837 static HRESULT WINAPI ITypeComp_fnBind(
7838 ITypeComp * iface,
7839 OLECHAR * szName,
7840 ULONG lHash,
7841 WORD wFlags,
7842 ITypeInfo ** ppTInfo,
7843 DESCKIND * pDescKind,
7844 BINDPTR * pBindPtr)
7846 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7847 const TLBFuncDesc *pFDesc;
7848 const TLBVarDesc *pVDesc;
7849 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7851 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7853 *pDescKind = DESCKIND_NONE;
7854 pBindPtr->lpfuncdesc = NULL;
7855 *ppTInfo = NULL;
7857 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
7858 if (!strcmpiW(pFDesc->Name, szName)) {
7859 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7860 break;
7861 else
7862 /* name found, but wrong flags */
7863 hr = TYPE_E_TYPEMISMATCH;
7866 if (pFDesc)
7868 HRESULT hr = TLB_AllocAndInitFuncDesc(
7869 &pFDesc->funcdesc,
7870 &pBindPtr->lpfuncdesc,
7871 This->TypeAttr.typekind == TKIND_DISPATCH);
7872 if (FAILED(hr))
7873 return hr;
7874 *pDescKind = DESCKIND_FUNCDESC;
7875 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7876 ITypeInfo_AddRef(*ppTInfo);
7877 return S_OK;
7878 } else {
7879 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7880 if (!strcmpiW(pVDesc->Name, szName)) {
7881 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7882 if (FAILED(hr))
7883 return hr;
7884 *pDescKind = DESCKIND_VARDESC;
7885 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7886 ITypeInfo_AddRef(*ppTInfo);
7887 return S_OK;
7891 /* FIXME: search each inherited interface, not just the first */
7892 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7893 /* recursive search */
7894 ITypeInfo *pTInfo;
7895 ITypeComp *pTComp;
7896 HRESULT hr;
7897 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7898 if (SUCCEEDED(hr))
7900 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7901 ITypeInfo_Release(pTInfo);
7903 if (SUCCEEDED(hr))
7905 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7906 ITypeComp_Release(pTComp);
7907 return hr;
7909 WARN("Could not search inherited interface!\n");
7911 if (hr == DISP_E_MEMBERNOTFOUND)
7912 hr = S_OK;
7913 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
7914 return hr;
7917 static HRESULT WINAPI ITypeComp_fnBindType(
7918 ITypeComp * iface,
7919 OLECHAR * szName,
7920 ULONG lHash,
7921 ITypeInfo ** ppTInfo,
7922 ITypeComp ** ppTComp)
7924 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7926 /* strange behaviour (does nothing) but like the
7927 * original */
7929 if (!ppTInfo || !ppTComp)
7930 return E_POINTER;
7932 *ppTInfo = NULL;
7933 *ppTComp = NULL;
7935 return S_OK;
7938 static const ITypeCompVtbl tcompvt =
7941 ITypeComp_fnQueryInterface,
7942 ITypeComp_fnAddRef,
7943 ITypeComp_fnRelease,
7945 ITypeComp_fnBind,
7946 ITypeComp_fnBindType