oleaut32: Convert TLBImpLib to use standard linked list.
[wine/multimedia.git] / dlls / oleaut32 / typelib.c
blob7d5b85a3d4e46fa4ecac701cc63db1da8cb72c8f
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) != S_OK) {
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 list entry;
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 list entry;
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 **typeinfos;
1002 struct list custdata_list;
1003 struct list implib_list;
1004 int ctTypeDesc; /* number of items in type desc array */
1005 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1006 library. Only used while reading MSFT
1007 typelibs */
1008 struct list ref_list; /* list of ref types in this typelib */
1009 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1012 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1013 struct tagITypeLibImpl *next, *prev;
1014 WCHAR *path;
1015 INT index;
1016 } ITypeLibImpl;
1018 static const ITypeLib2Vtbl tlbvt;
1019 static const ITypeCompVtbl tlbtcvt;
1021 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1023 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
1026 /* ITypeLib methods */
1027 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1028 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1030 /*======================= ITypeInfo implementation =======================*/
1032 /* data for referenced types */
1033 typedef struct tagTLBRefType
1035 INT index; /* Type index for internal ref or for external ref
1036 it the format is SLTG. -2 indicates to
1037 use guid */
1039 GUID guid; /* guid of the referenced type */
1040 /* if index == TLB_REF_USE_GUID */
1042 HREFTYPE reference; /* The href of this ref */
1043 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1044 TLB_REF_INTERNAL for internal refs
1045 TLB_REF_NOT_FOUND for broken refs */
1047 struct list entry;
1048 } TLBRefType;
1050 #define TLB_REF_USE_GUID -2
1052 #define TLB_REF_INTERNAL (void*)-2
1053 #define TLB_REF_NOT_FOUND (void*)-1
1055 /* internal Parameter data */
1056 typedef struct tagTLBParDesc
1058 BSTR Name;
1059 struct list custdata_list;
1060 } TLBParDesc;
1062 /* internal Function data */
1063 typedef struct tagTLBFuncDesc
1065 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1066 BSTR Name; /* the name of this function */
1067 TLBParDesc *pParamDesc; /* array with param names and custom data */
1068 int helpcontext;
1069 int HelpStringContext;
1070 BSTR HelpString;
1071 BSTR Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1072 struct list custdata_list;
1073 } TLBFuncDesc;
1075 /* internal Variable data */
1076 typedef struct tagTLBVarDesc
1078 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1079 BSTR Name; /* the name of this variable */
1080 int HelpContext;
1081 int HelpStringContext;
1082 BSTR HelpString;
1083 struct list custdata_list;
1084 } TLBVarDesc;
1086 /* internal implemented interface data */
1087 typedef struct tagTLBImplType
1089 HREFTYPE hRef; /* hRef of interface */
1090 int implflags; /* IMPLFLAG_*s */
1091 struct list custdata_list;
1092 } TLBImplType;
1094 /* internal TypeInfo data */
1095 typedef struct tagITypeInfoImpl
1097 const ITypeInfo2Vtbl *lpVtbl;
1098 const ITypeCompVtbl *lpVtblTypeComp;
1099 LONG ref;
1100 BOOL not_attached_to_typelib;
1101 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1102 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1103 int index; /* index in this typelib; */
1104 HREFTYPE hreftype; /* hreftype for app object binding */
1105 /* type libs seem to store the doc strings in ascii
1106 * so why should we do it in unicode?
1108 BSTR Name;
1109 BSTR DocString;
1110 BSTR DllName;
1111 DWORD dwHelpContext;
1112 DWORD dwHelpStringContext;
1114 /* functions */
1115 TLBFuncDesc *funcdescs;
1117 /* variables */
1118 TLBVarDesc *vardescs;
1120 /* Implemented Interfaces */
1121 TLBImplType *impltypes;
1123 struct list custdata_list;
1124 } ITypeInfoImpl;
1126 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1128 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1131 static const ITypeInfo2Vtbl tinfvt;
1132 static const ITypeCompVtbl tcompvt;
1134 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1135 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1137 typedef struct tagTLBContext
1139 unsigned int oStart; /* start of TLB in file */
1140 unsigned int pos; /* current pos */
1141 unsigned int length; /* total length */
1142 void *mapping; /* memory mapping */
1143 MSFT_SegDir * pTblDir;
1144 ITypeLibImpl* pLibInfo;
1145 } TLBContext;
1148 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1151 debug
1153 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1154 if (pTD->vt & VT_RESERVED)
1155 szVarType += strlen(strcpy(szVarType, "reserved | "));
1156 if (pTD->vt & VT_BYREF)
1157 szVarType += strlen(strcpy(szVarType, "ref to "));
1158 if (pTD->vt & VT_ARRAY)
1159 szVarType += strlen(strcpy(szVarType, "array of "));
1160 if (pTD->vt & VT_VECTOR)
1161 szVarType += strlen(strcpy(szVarType, "vector of "));
1162 switch(pTD->vt & VT_TYPEMASK) {
1163 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1164 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1165 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1166 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1167 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1168 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1169 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1170 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1171 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1172 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1173 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1174 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1175 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1176 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1177 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1178 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1179 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1180 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1181 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1182 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1183 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1184 pTD->u.hreftype); break;
1185 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1186 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1187 case VT_PTR: sprintf(szVarType, "ptr to ");
1188 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1189 break;
1190 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1191 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1192 break;
1193 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1194 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1195 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1196 break;
1198 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1202 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1203 char buf[200];
1204 USHORT flags = edesc->u.paramdesc.wParamFlags;
1205 dump_TypeDesc(&edesc->tdesc,buf);
1206 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1207 MESSAGE("\t\tu.paramdesc.wParamFlags");
1208 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1209 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1210 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1211 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1212 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1213 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1214 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1215 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1216 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1218 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1219 int i;
1220 MESSAGE("memid is %08x\n",funcdesc->memid);
1221 for (i=0;i<funcdesc->cParams;i++) {
1222 MESSAGE("Param %d:\n",i);
1223 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1225 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1226 switch (funcdesc->funckind) {
1227 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1228 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1229 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1230 case FUNC_STATIC: MESSAGE("static");break;
1231 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1232 default: MESSAGE("unknown");break;
1234 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1235 switch (funcdesc->invkind) {
1236 case INVOKE_FUNC: MESSAGE("func");break;
1237 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1238 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1239 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1241 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1242 switch (funcdesc->callconv) {
1243 case CC_CDECL: MESSAGE("cdecl");break;
1244 case CC_PASCAL: MESSAGE("pascal");break;
1245 case CC_STDCALL: MESSAGE("stdcall");break;
1246 case CC_SYSCALL: MESSAGE("syscall");break;
1247 default:break;
1249 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1250 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1251 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1253 MESSAGE("\telemdescFunc (return value type):\n");
1254 dump_ELEMDESC(&funcdesc->elemdescFunc);
1257 static const char * const typekind_desc[] =
1259 "TKIND_ENUM",
1260 "TKIND_RECORD",
1261 "TKIND_MODULE",
1262 "TKIND_INTERFACE",
1263 "TKIND_DISPATCH",
1264 "TKIND_COCLASS",
1265 "TKIND_ALIAS",
1266 "TKIND_UNION",
1267 "TKIND_MAX"
1270 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1272 int i;
1273 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1274 for (i=0;i<pfd->funcdesc.cParams;i++)
1275 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1278 dump_FUNCDESC(&(pfd->funcdesc));
1280 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1281 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1283 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1285 while (n)
1287 dump_TLBFuncDescOne(pfd);
1288 ++pfd;
1289 --n;
1292 static void dump_TLBVarDesc(const TLBVarDesc * pvd, UINT n)
1294 while (n)
1296 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1297 ++pvd;
1298 --n;
1302 static void dump_TLBImpLib(const TLBImpLib *import)
1304 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1305 debugstr_w(import->name));
1306 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1307 import->wVersionMinor, import->lcid, import->offset);
1310 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1312 TLBRefType *ref;
1314 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1316 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1317 if(ref->index == -1)
1318 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1319 else
1320 TRACE_(typelib)("type no: %d\n", ref->index);
1322 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1324 TRACE_(typelib)("in lib\n");
1325 dump_TLBImpLib(ref->pImpTLInfo);
1330 static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1332 if(!impl)
1333 return;
1334 while (n) {
1335 TRACE_(typelib)("implementing/inheriting interface hRef = %x implflags %x\n",
1336 impl->hRef, impl->implflags);
1337 ++impl;
1338 --n;
1342 static void dump_Variant(const VARIANT * pvar)
1344 SYSTEMTIME st;
1346 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1348 if (pvar)
1350 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1351 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1353 TRACE(",%p", V_BYREF(pvar));
1355 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1357 TRACE(",%p", V_ARRAY(pvar));
1359 else switch (V_TYPE(pvar))
1361 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1362 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1363 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1364 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1365 case VT_INT:
1366 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1367 case VT_UINT:
1368 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1369 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1370 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1371 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1372 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1373 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1374 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1375 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1376 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1377 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1378 V_CY(pvar).s.Lo); break;
1379 case VT_DATE:
1380 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1381 TRACE(",<invalid>");
1382 else
1383 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1384 st.wHour, st.wMinute, st.wSecond);
1385 break;
1386 case VT_ERROR:
1387 case VT_VOID:
1388 case VT_USERDEFINED:
1389 case VT_EMPTY:
1390 case VT_NULL: break;
1391 default: TRACE(",?"); break;
1394 TRACE("}\n");
1397 static void dump_DispParms(const DISPPARAMS * pdp)
1399 unsigned int index;
1401 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1403 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1405 TRACE("named args:\n");
1406 for (index = 0; index < pdp->cNamedArgs; index++)
1407 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1410 if (pdp->cArgs && pdp->rgvarg)
1412 TRACE("args:\n");
1413 for (index = 0; index < pdp->cArgs; index++)
1414 dump_Variant( &pdp->rgvarg[index] );
1418 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1420 TRACE("%p ref=%u\n", pty, pty->ref);
1421 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1422 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1423 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1424 TRACE("fct:%u var:%u impl:%u\n",
1425 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1426 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1427 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1428 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1429 if (TRACE_ON(ole))
1430 dump_TLBFuncDesc(pty->funcdescs, pty->TypeAttr.cFuncs);
1431 dump_TLBVarDesc(pty->vardescs, pty->TypeAttr.cVars);
1432 dump_TLBImplType(pty->impltypes, pty->TypeAttr.cImplTypes);
1435 static void dump_VARDESC(const VARDESC *v)
1437 MESSAGE("memid %d\n",v->memid);
1438 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1439 MESSAGE("oInst %d\n",v->u.oInst);
1440 dump_ELEMDESC(&(v->elemdescVar));
1441 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1442 MESSAGE("varkind %d\n",v->varkind);
1445 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1447 /* VT_LPWSTR is largest type that, may appear in type description */
1448 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1449 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1450 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1451 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1452 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1453 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1454 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1455 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1458 static void TLB_abort(void)
1460 DebugBreak();
1463 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size)
1465 void *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
1466 if (!ret) ERR("cannot allocate memory\n");
1467 return ret;
1470 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size)
1472 void *ret = HeapAlloc(GetProcessHeap(), 0, size);
1473 if (!ret) ERR("cannot allocate memory\n");
1474 return ret;
1477 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr, unsigned size)
1479 return HeapReAlloc(GetProcessHeap(), 0, ptr, size);
1482 void heap_free(void *ptr)
1484 HeapFree(GetProcessHeap(), 0, ptr);
1487 /* returns the size required for a deep copy of a typedesc into a
1488 * flat buffer */
1489 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1491 SIZE_T size = 0;
1493 if (alloc_initial_space)
1494 size += sizeof(TYPEDESC);
1496 switch (tdesc->vt)
1498 case VT_PTR:
1499 case VT_SAFEARRAY:
1500 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1501 break;
1502 case VT_CARRAY:
1503 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1504 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1505 break;
1507 return size;
1510 /* deep copy a typedesc into a flat buffer */
1511 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1513 if (!dest)
1515 dest = buffer;
1516 buffer = (char *)buffer + sizeof(TYPEDESC);
1519 *dest = *src;
1521 switch (src->vt)
1523 case VT_PTR:
1524 case VT_SAFEARRAY:
1525 dest->u.lptdesc = buffer;
1526 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1527 break;
1528 case VT_CARRAY:
1529 dest->u.lpadesc = buffer;
1530 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1531 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1532 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1533 break;
1535 return buffer;
1538 /* free custom data allocated by MSFT_CustData */
1539 static inline void TLB_FreeCustData(struct list *custdata_list)
1541 TLBCustData *cd, *cdn;
1542 LIST_FOR_EACH_ENTRY_SAFE(cd, cdn, custdata_list, TLBCustData, entry)
1544 list_remove(&cd->entry);
1545 VariantClear(&cd->data);
1546 heap_free(cd);
1550 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1552 DWORD len;
1553 BSTR ret;
1555 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1556 ret = SysAllocStringLen(NULL, len - 1);
1557 if (!ret) return ret;
1558 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1559 return ret;
1562 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(TLBFuncDesc *funcdescs,
1563 UINT n, MEMBERID memid)
1565 while(n){
1566 if(funcdescs->funcdesc.memid == memid)
1567 return funcdescs;
1568 ++funcdescs;
1569 --n;
1571 return NULL;
1574 static inline TLBFuncDesc *TLB_get_funcdesc_by_name(TLBFuncDesc *funcdescs,
1575 UINT n, const OLECHAR *name)
1577 while(n){
1578 if(!lstrcmpiW(funcdescs->Name, name))
1579 return funcdescs;
1580 ++funcdescs;
1581 --n;
1583 return NULL;
1586 static inline TLBVarDesc *TLB_get_vardesc_by_memberid(TLBVarDesc *vardescs,
1587 UINT n, MEMBERID memid)
1589 while(n){
1590 if(vardescs->vardesc.memid == memid)
1591 return vardescs;
1592 ++vardescs;
1593 --n;
1595 return NULL;
1598 static inline TLBVarDesc *TLB_get_vardesc_by_name(TLBVarDesc *vardescs,
1599 UINT n, const OLECHAR *name)
1601 while(n){
1602 if(!lstrcmpiW(vardescs->Name, name))
1603 return vardescs;
1604 ++vardescs;
1605 --n;
1607 return NULL;
1610 static inline TLBCustData *TLB_get_custdata_by_guid(struct list *custdata_list, REFGUID guid)
1612 TLBCustData *cust_data;
1613 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1614 if(IsEqualIID(&cust_data->guid, guid))
1615 return cust_data;
1616 return NULL;
1619 static TLBVarDesc *TLBVarDesc_Constructor(UINT n)
1621 TLBVarDesc *ret;
1623 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1624 if(!ret)
1625 return NULL;
1627 while(n){
1628 list_init(&ret[n-1].custdata_list);
1629 --n;
1632 return ret;
1635 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1637 TLBParDesc *ret;
1639 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1640 if(!ret)
1641 return NULL;
1643 while(n){
1644 list_init(&ret[n-1].custdata_list);
1645 --n;
1648 return ret;
1651 static TLBFuncDesc *TLBFuncDesc_Constructor(UINT n)
1653 TLBFuncDesc *ret;
1655 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1656 if(!ret)
1657 return NULL;
1659 while(n){
1660 list_init(&ret[n-1].custdata_list);
1661 --n;
1664 return ret;
1667 static TLBImplType *TLBImplType_Constructor(UINT n)
1669 TLBImplType *ret;
1671 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1672 if(!ret)
1673 return NULL;
1675 while(n){
1676 list_init(&ret[n-1].custdata_list);
1677 --n;
1680 return ret;
1683 /**********************************************************************
1685 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1687 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1689 return pcx->pos;
1692 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
1694 if (where != DO_NOT_SEEK)
1696 where += pcx->oStart;
1697 if (where > pcx->length)
1699 /* FIXME */
1700 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
1701 TLB_abort();
1703 pcx->pos = where;
1707 /* read function */
1708 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
1710 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
1711 pcx->pos, count, pcx->oStart, pcx->length, where);
1713 MSFT_Seek(pcx, where);
1714 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1715 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1716 pcx->pos += count;
1717 return count;
1720 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1721 LONG where )
1723 DWORD ret;
1725 ret = MSFT_Read(buffer, count, pcx, where);
1726 FromLEDWords(buffer, ret);
1728 return ret;
1731 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1732 LONG where )
1734 DWORD ret;
1736 ret = MSFT_Read(buffer, count, pcx, where);
1737 FromLEWords(buffer, ret);
1739 return ret;
1742 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1744 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1745 memset(pGuid,0, sizeof(GUID));
1746 return;
1748 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1749 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1750 pGuid->Data2 = FromLEWord(pGuid->Data2);
1751 pGuid->Data3 = FromLEWord(pGuid->Data3);
1752 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1755 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1757 MSFT_NameIntro niName;
1759 if (offset < 0)
1761 ERR_(typelib)("bad offset %d\n", offset);
1762 return -1;
1765 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1766 pcx->pTblDir->pNametab.offset+offset);
1768 return niName.hreftype;
1771 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1773 char * name;
1774 MSFT_NameIntro niName;
1775 int lengthInChars;
1776 BSTR bstrName = NULL;
1778 if (offset < 0)
1780 ERR_(typelib)("bad offset %d\n", offset);
1781 return NULL;
1783 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1784 pcx->pTblDir->pNametab.offset+offset);
1785 niName.namelen &= 0xFF; /* FIXME: correct ? */
1786 name = heap_alloc_zero((niName.namelen & 0xff) +1);
1787 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1788 name[niName.namelen & 0xff]='\0';
1790 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1791 name, -1, NULL, 0);
1793 /* no invalid characters in string */
1794 if (lengthInChars)
1796 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1798 /* don't check for invalid character since this has been done previously */
1799 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1801 heap_free(name);
1803 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1804 return bstrName;
1807 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1809 char * string;
1810 INT16 length;
1811 int lengthInChars;
1812 BSTR bstr = NULL;
1814 if(offset<0) return NULL;
1815 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1816 if(length <= 0) return 0;
1817 string = heap_alloc_zero(length +1);
1818 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1819 string[length]='\0';
1821 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1822 string, -1, NULL, 0);
1824 /* no invalid characters in string */
1825 if (lengthInChars)
1827 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1829 /* don't check for invalid character since this has been done previously */
1830 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1832 heap_free(string);
1834 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1835 return bstr;
1838 * read a value and fill a VARIANT structure
1840 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1842 int size;
1844 TRACE_(typelib)("\n");
1846 if(offset <0) { /* data are packed in here */
1847 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1848 V_I4(pVar) = offset & 0x3ffffff;
1849 return;
1851 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1852 pcx->pTblDir->pCustData.offset + offset );
1853 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1854 switch (V_VT(pVar)){
1855 case VT_EMPTY: /* FIXME: is this right? */
1856 case VT_NULL: /* FIXME: is this right? */
1857 case VT_I2 : /* this should not happen */
1858 case VT_I4 :
1859 case VT_R4 :
1860 case VT_ERROR :
1861 case VT_BOOL :
1862 case VT_I1 :
1863 case VT_UI1 :
1864 case VT_UI2 :
1865 case VT_UI4 :
1866 case VT_INT :
1867 case VT_UINT :
1868 case VT_VOID : /* FIXME: is this right? */
1869 case VT_HRESULT :
1870 size=4; break;
1871 case VT_R8 :
1872 case VT_CY :
1873 case VT_DATE :
1874 case VT_I8 :
1875 case VT_UI8 :
1876 case VT_DECIMAL : /* FIXME: is this right? */
1877 case VT_FILETIME :
1878 size=8;break;
1879 /* pointer types with known behaviour */
1880 case VT_BSTR :{
1881 char * ptr;
1882 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1883 if(size < 0) {
1884 char next;
1885 DWORD origPos = MSFT_Tell(pcx), nullPos;
1887 do {
1888 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1889 } while (next);
1890 nullPos = MSFT_Tell(pcx);
1891 size = nullPos - origPos;
1892 MSFT_Seek(pcx, origPos);
1894 ptr = heap_alloc_zero(size);/* allocate temp buffer */
1895 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1896 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1897 /* FIXME: do we need a AtoW conversion here? */
1898 V_UNION(pVar, bstrVal[size])='\0';
1899 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1900 heap_free(ptr);
1902 size=-4; break;
1903 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1904 case VT_DISPATCH :
1905 case VT_VARIANT :
1906 case VT_UNKNOWN :
1907 case VT_PTR :
1908 case VT_SAFEARRAY :
1909 case VT_CARRAY :
1910 case VT_USERDEFINED :
1911 case VT_LPSTR :
1912 case VT_LPWSTR :
1913 case VT_BLOB :
1914 case VT_STREAM :
1915 case VT_STORAGE :
1916 case VT_STREAMED_OBJECT :
1917 case VT_STORED_OBJECT :
1918 case VT_BLOB_OBJECT :
1919 case VT_CF :
1920 case VT_CLSID :
1921 default:
1922 size=0;
1923 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1924 V_VT(pVar));
1927 if(size>0) /* (big|small) endian correct? */
1928 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1929 return;
1932 * create a linked list with custom data
1934 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
1936 MSFT_CDGuid entry;
1937 TLBCustData* pNew;
1938 int count=0;
1940 TRACE_(typelib)("\n");
1942 while(offset >=0){
1943 count++;
1944 pNew=heap_alloc_zero(sizeof(TLBCustData));
1945 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1946 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1947 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1948 list_add_head(custdata_list, &pNew->entry);
1949 offset = entry.next;
1951 return count;
1954 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1955 ITypeInfoImpl *pTI)
1957 if(type <0)
1958 pTd->vt=type & VT_TYPEMASK;
1959 else
1960 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1962 if(pTd->vt == VT_USERDEFINED)
1963 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1965 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1968 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1970 /* resolve referenced type if any */
1971 while (lpTypeDesc)
1973 switch (lpTypeDesc->vt)
1975 case VT_PTR:
1976 lpTypeDesc = lpTypeDesc->u.lptdesc;
1977 break;
1979 case VT_CARRAY:
1980 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1981 break;
1983 case VT_USERDEFINED:
1984 MSFT_DoRefType(pcx, pTI->pTypeLib,
1985 lpTypeDesc->u.hreftype);
1987 lpTypeDesc = NULL;
1988 break;
1990 default:
1991 lpTypeDesc = NULL;
1996 static void
1997 MSFT_DoFuncs(TLBContext* pcx,
1998 ITypeInfoImpl* pTI,
1999 int cFuncs,
2000 int cVars,
2001 int offset,
2002 TLBFuncDesc** pptfd)
2005 * member information is stored in a data structure at offset
2006 * indicated by the memoffset field of the typeinfo structure
2007 * There are several distinctive parts.
2008 * The first part starts with a field that holds the total length
2009 * of this (first) part excluding this field. Then follow the records,
2010 * for each member there is one record.
2012 * The first entry is always the length of the record (including this
2013 * length word).
2014 * The rest of the record depends on the type of the member. If there is
2015 * a field indicating the member type (function, variable, interface, etc)
2016 * I have not found it yet. At this time we depend on the information
2017 * in the type info and the usual order how things are stored.
2019 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2020 * for each member;
2022 * Third is an equal sized array with file offsets to the name entry
2023 * of each member.
2025 * The fourth and last (?) part is an array with offsets to the records
2026 * in the first part of this file segment.
2029 int infolen, nameoffset, reclength, i;
2030 int recoffset = offset + sizeof(INT);
2032 char *recbuf = heap_alloc(0xffff);
2033 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2034 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2036 TRACE_(typelib)("\n");
2038 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2040 *pptfd = TLBFuncDesc_Constructor(cFuncs);
2041 ptfd = *pptfd;
2042 for ( i = 0; i < cFuncs ; i++ )
2044 int optional;
2046 /* name, eventually add to a hash table */
2047 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2048 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2050 /* nameoffset is sometimes -1 on the second half of a propget/propput
2051 * pair of functions */
2052 if ((nameoffset == -1) && (i > 0))
2053 ptfd->Name = SysAllocString(ptfd_prev->Name);
2054 else
2055 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2057 /* read the function information record */
2058 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2060 reclength &= 0xffff;
2062 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2064 /* size without argument data */
2065 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2067 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2068 ptfd->helpcontext = pFuncRec->HelpContext;
2070 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2071 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2073 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2075 if (pFuncRec->FKCCIC & 0x2000 )
2077 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2078 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2079 ptfd->Entry = (BSTR)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2081 else
2082 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2084 else
2085 ptfd->Entry = (BSTR)-1;
2087 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2088 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2090 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2091 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2093 /* fill the FuncDesc Structure */
2094 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2095 offset + infolen + ( i + 1) * sizeof(INT));
2097 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2098 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2099 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2100 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2101 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2102 ptfd->funcdesc.oVft = pFuncRec->VtableOffset & ~1;
2103 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2105 MSFT_GetTdesc(pcx,
2106 pFuncRec->DataType,
2107 &ptfd->funcdesc.elemdescFunc.tdesc,
2108 pTI);
2109 MSFT_ResolveReferencedTypes(pcx, pTI, &ptfd->funcdesc.elemdescFunc.tdesc);
2111 /* do the parameters/arguments */
2112 if(pFuncRec->nrargs)
2114 int j = 0;
2115 MSFT_ParameterInfo paraminfo;
2117 ptfd->funcdesc.lprgelemdescParam =
2118 heap_alloc_zero(pFuncRec->nrargs * sizeof(ELEMDESC));
2120 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2122 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2123 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2125 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2127 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2129 MSFT_GetTdesc(pcx,
2130 paraminfo.DataType,
2131 &elemdesc->tdesc,
2132 pTI);
2134 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2136 /* name */
2137 if (paraminfo.oName == -1)
2138 /* this occurs for [propput] or [propget] methods, so
2139 * we should just set the name of the parameter to the
2140 * name of the method. */
2141 ptfd->pParamDesc[j].Name = SysAllocString(ptfd->Name);
2142 else
2143 ptfd->pParamDesc[j].Name =
2144 MSFT_ReadName( pcx, paraminfo.oName );
2145 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(ptfd->pParamDesc[j].Name));
2147 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
2149 /* default value */
2150 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2151 (pFuncRec->FKCCIC & 0x1000) )
2153 INT* pInt = (INT *)((char *)pFuncRec +
2154 reclength -
2155 (pFuncRec->nrargs * 4) * sizeof(INT) );
2157 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2159 pParamDesc->pparamdescex = heap_alloc_zero(sizeof(PARAMDESCEX));
2160 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2162 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2163 pInt[j], pcx);
2165 else
2166 elemdesc->u.paramdesc.pparamdescex = NULL;
2168 /* custom info */
2169 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2170 j*sizeof(pFuncRec->oArgCustData[0])) &&
2171 pFuncRec->FKCCIC & 0x80 )
2173 MSFT_CustData(pcx,
2174 pFuncRec->oArgCustData[j],
2175 &ptfd->pParamDesc[j].custdata_list);
2178 /* SEEK value = jump to offset,
2179 * from there jump to the end of record,
2180 * go back by (j-1) arguments
2182 MSFT_ReadLEDWords( &paraminfo ,
2183 sizeof(MSFT_ParameterInfo), pcx,
2184 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2185 * sizeof(MSFT_ParameterInfo)));
2189 /* scode is not used: archaic win16 stuff FIXME: right? */
2190 ptfd->funcdesc.cScodes = 0 ;
2191 ptfd->funcdesc.lprgscode = NULL ;
2193 ptfd_prev = ptfd;
2194 ++ptfd;
2195 recoffset += reclength;
2197 heap_free(recbuf);
2200 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2201 int cVars, int offset, TLBVarDesc ** pptvd)
2203 int infolen, nameoffset, reclength;
2204 char recbuf[256];
2205 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2206 TLBVarDesc *ptvd;
2207 int i;
2208 int recoffset;
2210 TRACE_(typelib)("\n");
2212 ptvd = *pptvd = TLBVarDesc_Constructor(cVars);
2213 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2214 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2215 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2216 recoffset += offset+sizeof(INT);
2217 for(i=0;i<cVars;i++, ++ptvd){
2218 /* name, eventually add to a hash table */
2219 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2220 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2221 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2222 /* read the variable information record */
2223 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2224 reclength &= 0xff;
2225 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2227 /* optional data */
2228 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2229 ptvd->HelpContext = pVarRec->HelpContext;
2231 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2232 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2234 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2235 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2237 /* fill the VarDesc Structure */
2238 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2239 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2240 ptvd->vardesc.varkind = pVarRec->VarKind;
2241 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2242 MSFT_GetTdesc(pcx, pVarRec->DataType,
2243 &ptvd->vardesc.elemdescVar.tdesc, pTI);
2244 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2245 if(pVarRec->VarKind == VAR_CONST ){
2246 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2247 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2248 pVarRec->OffsValue, pcx);
2249 } else
2250 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2251 MSFT_ResolveReferencedTypes(pcx, pTI, &ptvd->vardesc.elemdescVar.tdesc);
2252 recoffset += reclength;
2256 /* fill in data for a hreftype (offset). When the referenced type is contained
2257 * in the typelib, it's just an (file) offset in the type info base dir.
2258 * If comes from import, it's an offset+1 in the ImpInfo table
2259 * */
2260 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2261 int offset)
2263 TLBRefType *ref;
2265 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2267 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2269 if(ref->reference == offset) return;
2272 ref = heap_alloc_zero(sizeof(TLBRefType));
2273 list_add_tail(&pTL->ref_list, &ref->entry);
2275 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2276 /* external typelib */
2277 MSFT_ImpInfo impinfo;
2278 TLBImpLib *pImpLib;
2280 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2282 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2283 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2285 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2286 if(pImpLib->offset==impinfo.oImpFile)
2287 break;
2289 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2290 ref->reference = offset;
2291 ref->pImpTLInfo = pImpLib;
2292 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2293 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2294 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2295 ref->index = TLB_REF_USE_GUID;
2296 } else
2297 ref->index = impinfo.oGuid;
2298 }else{
2299 ERR("Cannot find a reference\n");
2300 ref->reference = -1;
2301 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2303 }else{
2304 /* in this typelib */
2305 ref->index = MSFT_HREFTYPE_INDEX(offset);
2306 ref->reference = offset;
2307 ref->pImpTLInfo = TLB_REF_INTERNAL;
2311 /* process Implemented Interfaces of a com class */
2312 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2313 int offset)
2315 int i;
2316 MSFT_RefRecord refrec;
2317 TLBImplType *pImpl;
2319 TRACE_(typelib)("\n");
2321 pTI->impltypes = TLBImplType_Constructor(count);
2322 pImpl = pTI->impltypes;
2323 for(i=0;i<count;i++){
2324 if(offset<0) break; /* paranoia */
2325 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2326 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2327 pImpl->hRef = refrec.reftype;
2328 pImpl->implflags=refrec.flags;
2329 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2330 offset=refrec.onext;
2331 ++pImpl;
2335 * process a typeinfo record
2337 static ITypeInfoImpl * MSFT_DoTypeInfo(
2338 TLBContext *pcx,
2339 int count,
2340 ITypeLibImpl * pLibInfo)
2342 MSFT_TypeInfoBase tiBase;
2343 ITypeInfoImpl *ptiRet;
2345 TRACE_(typelib)("count=%u\n", count);
2347 ptiRet = ITypeInfoImpl_Constructor();
2348 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2349 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2351 /* this is where we are coming from */
2352 ptiRet->pTypeLib = pLibInfo;
2353 ptiRet->index=count;
2354 /* fill in the typeattr fields */
2356 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2357 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2358 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2359 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2360 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2361 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2362 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2363 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2364 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2365 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2366 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2367 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2368 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2369 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2370 MSFT_GetTdesc(pcx, tiBase.datatype1,
2371 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2373 /* FIXME: */
2374 /* IDLDESC idldescType; *//* never saw this one != zero */
2376 /* name, eventually add to a hash table */
2377 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2378 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2379 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2380 /* help info */
2381 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2382 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2383 ptiRet->dwHelpContext=tiBase.helpcontext;
2385 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2386 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2388 /* note: InfoType's Help file and HelpStringDll come from the containing
2389 * library. Further HelpString and Docstring appear to be the same thing :(
2391 /* functions */
2392 if(ptiRet->TypeAttr.cFuncs >0 )
2393 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2394 ptiRet->TypeAttr.cVars,
2395 tiBase.memoffset, &ptiRet->funcdescs);
2396 /* variables */
2397 if(ptiRet->TypeAttr.cVars >0 )
2398 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2399 ptiRet->TypeAttr.cVars,
2400 tiBase.memoffset, &ptiRet->vardescs);
2401 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2402 switch(ptiRet->TypeAttr.typekind)
2404 case TKIND_COCLASS:
2405 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2406 tiBase.datatype1);
2407 break;
2408 case TKIND_DISPATCH:
2409 /* This is not -1 when the interface is a non-base dual interface or
2410 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2411 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2412 not this interface.
2415 if (tiBase.datatype1 != -1)
2417 ptiRet->impltypes = TLBImplType_Constructor(1);
2418 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2419 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2421 break;
2422 default:
2423 ptiRet->impltypes = TLBImplType_Constructor(1);
2424 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2425 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2426 break;
2429 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->custdata_list);
2431 TRACE_(typelib)("%s guid: %s kind:%s\n",
2432 debugstr_w(ptiRet->Name),
2433 debugstr_guid(&ptiRet->TypeAttr.guid),
2434 typekind_desc[ptiRet->TypeAttr.typekind]);
2435 if (TRACE_ON(typelib))
2436 dump_TypeInfo(ptiRet);
2438 return ptiRet;
2441 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2442 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2443 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2444 * tradeoff here.
2446 static ITypeLibImpl *tlb_cache_first;
2447 static CRITICAL_SECTION cache_section;
2448 static CRITICAL_SECTION_DEBUG cache_section_debug =
2450 0, 0, &cache_section,
2451 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2452 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2454 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2457 typedef struct TLB_PEFile
2459 const IUnknownVtbl *lpvtbl;
2460 LONG refs;
2461 HMODULE dll;
2462 HRSRC typelib_resource;
2463 HGLOBAL typelib_global;
2464 LPVOID typelib_base;
2465 } TLB_PEFile;
2467 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2469 if (IsEqualIID(riid, &IID_IUnknown))
2471 *ppv = iface;
2472 IUnknown_AddRef(iface);
2473 return S_OK;
2475 *ppv = NULL;
2476 return E_NOINTERFACE;
2479 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2481 TLB_PEFile *This = (TLB_PEFile *)iface;
2482 return InterlockedIncrement(&This->refs);
2485 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2487 TLB_PEFile *This = (TLB_PEFile *)iface;
2488 ULONG refs = InterlockedDecrement(&This->refs);
2489 if (!refs)
2491 if (This->typelib_global)
2492 FreeResource(This->typelib_global);
2493 if (This->dll)
2494 FreeLibrary(This->dll);
2495 heap_free(This);
2497 return refs;
2500 static const IUnknownVtbl TLB_PEFile_Vtable =
2502 TLB_PEFile_QueryInterface,
2503 TLB_PEFile_AddRef,
2504 TLB_PEFile_Release
2507 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2509 TLB_PEFile *This;
2511 This = heap_alloc(sizeof(TLB_PEFile));
2512 if (!This)
2513 return E_OUTOFMEMORY;
2515 This->lpvtbl = &TLB_PEFile_Vtable;
2516 This->refs = 1;
2517 This->dll = NULL;
2518 This->typelib_resource = NULL;
2519 This->typelib_global = NULL;
2520 This->typelib_base = NULL;
2522 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2523 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2525 if (This->dll)
2527 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2528 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2529 if (This->typelib_resource)
2531 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2532 if (This->typelib_global)
2534 This->typelib_base = LockResource(This->typelib_global);
2536 if (This->typelib_base)
2538 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2539 *ppBase = This->typelib_base;
2540 *ppFile = (IUnknown *)&This->lpvtbl;
2541 return S_OK;
2547 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2548 return TYPE_E_CANTLOADLIBRARY;
2551 typedef struct TLB_NEFile
2553 const IUnknownVtbl *lpvtbl;
2554 LONG refs;
2555 LPVOID typelib_base;
2556 } TLB_NEFile;
2558 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2560 if (IsEqualIID(riid, &IID_IUnknown))
2562 *ppv = iface;
2563 IUnknown_AddRef(iface);
2564 return S_OK;
2566 *ppv = NULL;
2567 return E_NOINTERFACE;
2570 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2572 TLB_NEFile *This = (TLB_NEFile *)iface;
2573 return InterlockedIncrement(&This->refs);
2576 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2578 TLB_NEFile *This = (TLB_NEFile *)iface;
2579 ULONG refs = InterlockedDecrement(&This->refs);
2580 if (!refs)
2582 heap_free(This->typelib_base);
2583 heap_free(This);
2585 return refs;
2588 static const IUnknownVtbl TLB_NEFile_Vtable =
2590 TLB_NEFile_QueryInterface,
2591 TLB_NEFile_AddRef,
2592 TLB_NEFile_Release
2595 /***********************************************************************
2596 * read_xx_header [internal]
2598 static int read_xx_header( HFILE lzfd )
2600 IMAGE_DOS_HEADER mzh;
2601 char magic[3];
2603 LZSeek( lzfd, 0, SEEK_SET );
2604 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2605 return 0;
2606 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2607 return 0;
2609 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2610 if ( 2 != LZRead( lzfd, magic, 2 ) )
2611 return 0;
2613 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2615 if ( magic[0] == 'N' && magic[1] == 'E' )
2616 return IMAGE_OS2_SIGNATURE;
2617 if ( magic[0] == 'P' && magic[1] == 'E' )
2618 return IMAGE_NT_SIGNATURE;
2620 magic[2] = '\0';
2621 WARN("Can't handle %s files.\n", magic );
2622 return 0;
2626 /***********************************************************************
2627 * find_ne_resource [internal]
2629 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2630 DWORD *resLen, DWORD *resOff )
2632 IMAGE_OS2_HEADER nehd;
2633 NE_TYPEINFO *typeInfo;
2634 NE_NAMEINFO *nameInfo;
2635 DWORD nehdoffset;
2636 LPBYTE resTab;
2637 DWORD resTabSize;
2638 int count;
2640 /* Read in NE header */
2641 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2642 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2644 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2645 if ( !resTabSize )
2647 TRACE("No resources in NE dll\n" );
2648 return FALSE;
2651 /* Read in resource table */
2652 resTab = heap_alloc( resTabSize );
2653 if ( !resTab ) return FALSE;
2655 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2656 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2658 heap_free( resTab );
2659 return FALSE;
2662 /* Find resource */
2663 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2665 if (!IS_INTRESOURCE(typeid)) /* named type */
2667 BYTE len = strlen( typeid );
2668 while (typeInfo->type_id)
2670 if (!(typeInfo->type_id & 0x8000))
2672 BYTE *p = resTab + typeInfo->type_id;
2673 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2675 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2676 typeInfo->count * sizeof(NE_NAMEINFO));
2679 else /* numeric type id */
2681 WORD id = LOWORD(typeid) | 0x8000;
2682 while (typeInfo->type_id)
2684 if (typeInfo->type_id == id) goto found_type;
2685 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2686 typeInfo->count * sizeof(NE_NAMEINFO));
2689 TRACE("No typeid entry found for %p\n", typeid );
2690 heap_free( resTab );
2691 return FALSE;
2693 found_type:
2694 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2696 if (!IS_INTRESOURCE(resid)) /* named resource */
2698 BYTE len = strlen( resid );
2699 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2701 BYTE *p = resTab + nameInfo->id;
2702 if (nameInfo->id & 0x8000) continue;
2703 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2706 else /* numeric resource id */
2708 WORD id = LOWORD(resid) | 0x8000;
2709 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2710 if (nameInfo->id == id) goto found_name;
2712 TRACE("No resid entry found for %p\n", typeid );
2713 heap_free( resTab );
2714 return FALSE;
2716 found_name:
2717 /* Return resource data */
2718 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2719 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2721 heap_free( resTab );
2722 return TRUE;
2725 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
2727 HFILE lzfd = -1;
2728 OFSTRUCT ofs;
2729 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2730 TLB_NEFile *This;
2732 This = heap_alloc(sizeof(TLB_NEFile));
2733 if (!This) return E_OUTOFMEMORY;
2735 This->lpvtbl = &TLB_NEFile_Vtable;
2736 This->refs = 1;
2737 This->typelib_base = NULL;
2739 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
2740 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
2742 DWORD reslen, offset;
2743 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
2745 This->typelib_base = heap_alloc(reslen);
2746 if( !This->typelib_base )
2747 hr = E_OUTOFMEMORY;
2748 else
2750 LZSeek( lzfd, offset, SEEK_SET );
2751 reslen = LZRead( lzfd, This->typelib_base, reslen );
2752 LZClose( lzfd );
2753 *ppBase = This->typelib_base;
2754 *pdwTLBLength = reslen;
2755 *ppFile = (IUnknown *)&This->lpvtbl;
2756 return S_OK;
2761 if( lzfd >= 0) LZClose( lzfd );
2762 TLB_NEFile_Release((IUnknown *)&This->lpvtbl);
2763 return hr;
2766 typedef struct TLB_Mapping
2768 const IUnknownVtbl *lpvtbl;
2769 LONG refs;
2770 HANDLE file;
2771 HANDLE mapping;
2772 LPVOID typelib_base;
2773 } TLB_Mapping;
2775 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2777 if (IsEqualIID(riid, &IID_IUnknown))
2779 *ppv = iface;
2780 IUnknown_AddRef(iface);
2781 return S_OK;
2783 *ppv = NULL;
2784 return E_NOINTERFACE;
2787 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2789 TLB_Mapping *This = (TLB_Mapping *)iface;
2790 return InterlockedIncrement(&This->refs);
2793 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2795 TLB_Mapping *This = (TLB_Mapping *)iface;
2796 ULONG refs = InterlockedDecrement(&This->refs);
2797 if (!refs)
2799 if (This->typelib_base)
2800 UnmapViewOfFile(This->typelib_base);
2801 if (This->mapping)
2802 CloseHandle(This->mapping);
2803 if (This->file != INVALID_HANDLE_VALUE)
2804 CloseHandle(This->file);
2805 heap_free(This);
2807 return refs;
2810 static const IUnknownVtbl TLB_Mapping_Vtable =
2812 TLB_Mapping_QueryInterface,
2813 TLB_Mapping_AddRef,
2814 TLB_Mapping_Release
2817 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2819 TLB_Mapping *This;
2821 This = heap_alloc(sizeof(TLB_Mapping));
2822 if (!This)
2823 return E_OUTOFMEMORY;
2825 This->lpvtbl = &TLB_Mapping_Vtable;
2826 This->refs = 1;
2827 This->file = INVALID_HANDLE_VALUE;
2828 This->mapping = NULL;
2829 This->typelib_base = NULL;
2831 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2832 if (INVALID_HANDLE_VALUE != This->file)
2834 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2835 if (This->mapping)
2837 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2838 if(This->typelib_base)
2840 /* retrieve file size */
2841 *pdwTLBLength = GetFileSize(This->file, NULL);
2842 *ppBase = This->typelib_base;
2843 *ppFile = (IUnknown *)&This->lpvtbl;
2844 return S_OK;
2849 IUnknown_Release((IUnknown *)&This->lpvtbl);
2850 return TYPE_E_CANTLOADLIBRARY;
2853 /****************************************************************************
2854 * TLB_ReadTypeLib
2856 * find the type of the typelib file and map the typelib resource into
2857 * the memory
2860 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2861 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2863 ITypeLibImpl *entry;
2864 HRESULT ret;
2865 INT index = 1;
2866 LPWSTR index_str, file = (LPWSTR)pszFileName;
2867 LPVOID pBase = NULL;
2868 DWORD dwTLBLength = 0;
2869 IUnknown *pFile = NULL;
2871 *ppTypeLib = NULL;
2873 index_str = strrchrW(pszFileName, '\\');
2874 if(index_str && *++index_str != '\0')
2876 LPWSTR end_ptr;
2877 LONG idx = strtolW(index_str, &end_ptr, 10);
2878 if(*end_ptr == '\0')
2880 int str_len = index_str - pszFileName - 1;
2881 index = idx;
2882 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
2883 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2884 file[str_len] = 0;
2888 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2890 if(strchrW(file, '\\'))
2892 lstrcpyW(pszPath, file);
2894 else
2896 int len = GetSystemDirectoryW(pszPath, cchPath);
2897 pszPath[len] = '\\';
2898 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2902 if(file != pszFileName) heap_free(file);
2904 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2906 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2907 EnterCriticalSection(&cache_section);
2908 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2910 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2912 TRACE("cache hit\n");
2913 *ppTypeLib = (ITypeLib2*)entry;
2914 ITypeLib_AddRef(*ppTypeLib);
2915 LeaveCriticalSection(&cache_section);
2916 return S_OK;
2919 LeaveCriticalSection(&cache_section);
2921 /* now actually load and parse the typelib */
2923 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2924 if (ret == TYPE_E_CANTLOADLIBRARY)
2925 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2926 if (ret == TYPE_E_CANTLOADLIBRARY)
2927 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2928 if (SUCCEEDED(ret))
2930 if (dwTLBLength >= 4)
2932 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2933 if (dwSignature == MSFT_SIGNATURE)
2934 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2935 else if (dwSignature == SLTG_SIGNATURE)
2936 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2937 else
2939 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2940 ret = TYPE_E_CANTLOADLIBRARY;
2943 else
2944 ret = TYPE_E_CANTLOADLIBRARY;
2945 IUnknown_Release(pFile);
2948 if(*ppTypeLib) {
2949 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2951 TRACE("adding to cache\n");
2952 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
2953 lstrcpyW(impl->path, pszPath);
2954 /* We should really canonicalise the path here. */
2955 impl->index = index;
2957 /* FIXME: check if it has added already in the meantime */
2958 EnterCriticalSection(&cache_section);
2959 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2960 impl->prev = NULL;
2961 tlb_cache_first = impl;
2962 LeaveCriticalSection(&cache_section);
2963 ret = S_OK;
2964 } else
2965 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2967 return ret;
2970 /*================== ITypeLib(2) Methods ===================================*/
2972 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2974 ITypeLibImpl* pTypeLibImpl;
2976 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
2977 if (!pTypeLibImpl) return NULL;
2979 pTypeLibImpl->lpVtbl = &tlbvt;
2980 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2981 pTypeLibImpl->ref = 1;
2983 list_init(&pTypeLibImpl->implib_list);
2984 list_init(&pTypeLibImpl->custdata_list);
2985 list_init(&pTypeLibImpl->ref_list);
2986 pTypeLibImpl->dispatch_href = -1;
2988 return pTypeLibImpl;
2991 /****************************************************************************
2992 * ITypeLib2_Constructor_MSFT
2994 * loading an MSFT typelib from an in-memory image
2996 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2998 TLBContext cx;
2999 LONG lPSegDir;
3000 MSFT_Header tlbHeader;
3001 MSFT_SegDir tlbSegDir;
3002 ITypeLibImpl * pTypeLibImpl;
3004 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3006 pTypeLibImpl = TypeLibImpl_Constructor();
3007 if (!pTypeLibImpl) return NULL;
3009 /* get pointer to beginning of typelib data */
3010 cx.pos = 0;
3011 cx.oStart=0;
3012 cx.mapping = pLib;
3013 cx.pLibInfo = pTypeLibImpl;
3014 cx.length = dwTLBLength;
3016 /* read header */
3017 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
3018 TRACE_(typelib)("header:\n");
3019 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3020 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3021 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3022 return NULL;
3024 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3026 /* there is a small amount of information here until the next important
3027 * part:
3028 * the segment directory . Try to calculate the amount of data */
3029 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3031 /* now read the segment directory */
3032 TRACE("read segment directory (at %d)\n",lPSegDir);
3033 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3034 cx.pTblDir = &tlbSegDir;
3036 /* just check two entries */
3037 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3039 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3040 heap_free(pTypeLibImpl);
3041 return NULL;
3044 /* now fill our internal data */
3045 /* TLIBATTR fields */
3046 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
3048 pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid2;
3049 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3050 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
3051 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
3052 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
3054 pTypeLibImpl->lcid = tlbHeader.lcid;
3056 /* name, eventually add to a hash table */
3057 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3059 /* help info */
3060 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3061 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3063 if( tlbHeader.varflags & HELPDLLFLAG)
3065 int offset;
3066 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3067 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3070 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3072 /* custom data */
3073 if(tlbHeader.CustomDataOffset >= 0)
3075 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3078 /* fill in type descriptions */
3079 if(tlbSegDir.pTypdescTab.length > 0)
3081 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3082 INT16 td[4];
3083 pTypeLibImpl->ctTypeDesc = cTD;
3084 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3085 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3086 for(i=0; i<cTD; )
3088 /* FIXME: add several sanity checks here */
3089 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3090 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3092 /* FIXME: check safearray */
3093 if(td[3] < 0)
3094 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3095 else
3096 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3098 else if(td[0] == VT_CARRAY)
3100 /* array descr table here */
3101 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3103 else if(td[0] == VT_USERDEFINED)
3105 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3107 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3110 /* second time around to fill the array subscript info */
3111 for(i=0;i<cTD;i++)
3113 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3114 if(tlbSegDir.pArrayDescriptions.offset>0)
3116 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3117 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3119 if(td[1]<0)
3120 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3121 else
3122 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3124 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3126 for(j = 0; j<td[2]; j++)
3128 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3129 sizeof(INT), &cx, DO_NOT_SEEK);
3130 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3131 sizeof(INT), &cx, DO_NOT_SEEK);
3134 else
3136 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3137 ERR("didn't find array description data\n");
3142 /* imported type libs */
3143 if(tlbSegDir.pImpFiles.offset>0)
3145 TLBImpLib *pImpLib;
3146 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3147 UINT16 size;
3149 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3151 char *name;
3153 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3154 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3155 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3157 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3158 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3159 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3160 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3162 size >>= 2;
3163 name = heap_alloc_zero(size+1);
3164 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3165 pImpLib->name = TLB_MultiByteToBSTR(name);
3166 heap_free(name);
3168 MSFT_ReadGuid(&pImpLib->guid, oGuid, &cx);
3169 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3171 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3175 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3176 if(pTypeLibImpl->dispatch_href != -1)
3177 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
3179 /* type infos */
3180 if(tlbHeader.nrtypeinfos >= 0 )
3182 ITypeInfoImpl **ppTI;
3183 int i;
3185 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3187 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3189 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3191 ++ppTI;
3192 (pTypeLibImpl->TypeInfoCount)++;
3196 TRACE("(%p)\n", pTypeLibImpl);
3197 return (ITypeLib2*) pTypeLibImpl;
3201 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3203 char b[3];
3204 int i;
3205 short s;
3207 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3208 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3209 return FALSE;
3212 guid->Data4[0] = s >> 8;
3213 guid->Data4[1] = s & 0xff;
3215 b[2] = '\0';
3216 for(i = 0; i < 6; i++) {
3217 memcpy(b, str + 24 + 2 * i, 2);
3218 guid->Data4[i + 2] = strtol(b, NULL, 16);
3220 return TRUE;
3223 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
3225 WORD bytelen;
3226 DWORD len;
3228 *pBstr = NULL;
3229 bytelen = *(const WORD*)ptr;
3230 if(bytelen == 0xffff) return 2;
3231 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3232 *pBstr = SysAllocStringLen(NULL, len);
3233 if (*pBstr)
3234 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
3235 return bytelen + 2;
3238 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3240 WORD bytelen;
3242 *str = NULL;
3243 bytelen = *(const WORD*)ptr;
3244 if(bytelen == 0xffff) return 2;
3245 *str = heap_alloc(bytelen + 1);
3246 memcpy(*str, ptr + 2, bytelen);
3247 (*str)[bytelen] = '\0';
3248 return bytelen + 2;
3251 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3253 char *ptr = pLibBlk;
3254 WORD w;
3256 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3257 FIXME("libblk magic = %04x\n", w);
3258 return 0;
3261 ptr += 6;
3262 if((w = *(WORD*)ptr) != 0xffff) {
3263 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3264 ptr += w;
3266 ptr += 2;
3268 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
3270 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
3272 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3273 ptr += 4;
3275 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
3276 ptr += 2;
3278 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3279 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3280 else
3281 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = 0;
3282 ptr += 2;
3284 ptr += 4; /* skip res12 */
3286 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
3287 ptr += 2;
3289 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
3290 ptr += 2;
3292 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
3293 ptr += 2;
3295 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
3296 ptr += sizeof(GUID);
3298 return ptr - (char*)pLibBlk;
3301 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3302 typedef struct
3304 unsigned int num;
3305 HREFTYPE refs[1];
3306 } sltg_ref_lookup_t;
3308 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3309 HREFTYPE *typelib_ref)
3311 if(table && typeinfo_ref < table->num)
3313 *typelib_ref = table->refs[typeinfo_ref];
3314 return S_OK;
3317 ERR_(typelib)("Unable to find reference\n");
3318 *typelib_ref = -1;
3319 return E_FAIL;
3322 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3324 BOOL done = FALSE;
3326 while(!done) {
3327 if((*pType & 0xe00) == 0xe00) {
3328 pTD->vt = VT_PTR;
3329 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3330 pTD = pTD->u.lptdesc;
3332 switch(*pType & 0x3f) {
3333 case VT_PTR:
3334 pTD->vt = VT_PTR;
3335 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3336 pTD = pTD->u.lptdesc;
3337 break;
3339 case VT_USERDEFINED:
3340 pTD->vt = VT_USERDEFINED;
3341 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3342 done = TRUE;
3343 break;
3345 case VT_CARRAY:
3347 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3348 array */
3350 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3352 pTD->vt = VT_CARRAY;
3353 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3354 pTD->u.lpadesc->cDims = pSA->cDims;
3355 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3356 pSA->cDims * sizeof(SAFEARRAYBOUND));
3358 pTD = &pTD->u.lpadesc->tdescElem;
3359 break;
3362 case VT_SAFEARRAY:
3364 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3365 useful? */
3367 pType++;
3368 pTD->vt = VT_SAFEARRAY;
3369 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3370 pTD = pTD->u.lptdesc;
3371 break;
3373 default:
3374 pTD->vt = *pType & 0x3f;
3375 done = TRUE;
3376 break;
3378 pType++;
3380 return pType;
3383 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3384 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3386 /* Handle [in/out] first */
3387 if((*pType & 0xc000) == 0xc000)
3388 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3389 else if(*pType & 0x8000)
3390 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3391 else if(*pType & 0x4000)
3392 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3393 else
3394 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3396 if(*pType & 0x2000)
3397 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3399 if(*pType & 0x80)
3400 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3402 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3406 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3407 char *pNameTable)
3409 unsigned int ref;
3410 char *name;
3411 TLBRefType *ref_type;
3412 sltg_ref_lookup_t *table;
3413 HREFTYPE typelib_ref;
3415 if(pRef->magic != SLTG_REF_MAGIC) {
3416 FIXME("Ref magic = %x\n", pRef->magic);
3417 return NULL;
3419 name = ( (char*)pRef->names + pRef->number);
3421 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3422 table->num = pRef->number >> 3;
3424 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3426 /* We don't want the first href to be 0 */
3427 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3429 for(ref = 0; ref < pRef->number >> 3; ref++) {
3430 char *refname;
3431 unsigned int lib_offs, type_num;
3433 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3435 name += SLTG_ReadStringA(name, &refname);
3436 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3437 FIXME_(typelib)("Can't sscanf ref\n");
3438 if(lib_offs != 0xffff) {
3439 TLBImpLib *import;
3441 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
3442 if(import->offset == lib_offs)
3443 break;
3445 if(&import->entry == &pTL->implib_list) {
3446 char fname[MAX_PATH+1];
3447 int len;
3449 import = heap_alloc_zero(sizeof(*import));
3450 import->offset = lib_offs;
3451 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3452 &import->guid);
3453 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3454 &import->wVersionMajor,
3455 &import->wVersionMinor,
3456 &import->lcid, fname) != 4) {
3457 FIXME_(typelib)("can't sscanf ref %s\n",
3458 pNameTable + lib_offs + 40);
3460 len = strlen(fname);
3461 if(fname[len-1] != '#')
3462 FIXME("fname = %s\n", fname);
3463 fname[len-1] = '\0';
3464 import->name = TLB_MultiByteToBSTR(fname);
3465 list_add_tail(&pTL->implib_list, &import->entry);
3467 ref_type->pImpTLInfo = import;
3469 /* Store a reference to IDispatch */
3470 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid, &IID_StdOle) && type_num == 4)
3471 pTL->dispatch_href = typelib_ref;
3473 } else { /* internal ref */
3474 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3476 ref_type->reference = typelib_ref;
3477 ref_type->index = type_num;
3479 heap_free(refname);
3480 list_add_tail(&pTL->ref_list, &ref_type->entry);
3482 table->refs[ref] = typelib_ref;
3483 typelib_ref += 4;
3485 if((BYTE)*name != SLTG_REF_MAGIC)
3486 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3487 dump_TLBRefType(pTL);
3488 return table;
3491 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3492 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3494 SLTG_ImplInfo *info;
3495 TLBImplType *pImplType;
3496 /* I don't really get this structure, usually it's 0x16 bytes
3497 long, but iuser.tlb contains some that are 0x18 bytes long.
3498 That's ok because we can use the next ptr to jump to the next
3499 one. But how do we know the length of the last one? The WORD
3500 at offs 0x8 might be the clue. For now I'm just assuming that
3501 the last one is the regular 0x16 bytes. */
3503 info = (SLTG_ImplInfo*)pBlk;
3504 while(1){
3505 pTI->TypeAttr.cImplTypes++;
3506 if(info->next == 0xffff)
3507 break;
3508 info = (SLTG_ImplInfo*)(pBlk + info->next);
3511 info = (SLTG_ImplInfo*)pBlk;
3512 pTI->impltypes = TLBImplType_Constructor(pTI->TypeAttr.cImplTypes);
3513 pImplType = pTI->impltypes;
3514 while(1) {
3515 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
3516 pImplType->implflags = info->impltypeflags;
3517 ++pImplType;
3519 if(info->next == 0xffff)
3520 break;
3521 if(OneOnly)
3522 FIXME_(typelib)("Interface inheriting more than one interface\n");
3523 info = (SLTG_ImplInfo*)(pBlk + info->next);
3525 info++; /* see comment at top of function */
3526 return (char*)info;
3529 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3530 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3532 TLBVarDesc *pVarDesc;
3533 BSTR bstrPrevName = NULL;
3534 SLTG_Variable *pItem;
3535 unsigned short i;
3536 WORD *pType;
3538 pVarDesc = pTI->vardescs = TLBVarDesc_Constructor(cVars);
3540 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3541 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
3543 pVarDesc->vardesc.memid = pItem->memid;
3545 if (pItem->magic != SLTG_VAR_MAGIC &&
3546 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3547 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3548 return;
3551 if (pItem->name == 0xfffe)
3552 pVarDesc->Name = SysAllocString(bstrPrevName);
3553 else
3554 pVarDesc->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3556 TRACE_(typelib)("name: %s\n", debugstr_w(pVarDesc->Name));
3557 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3558 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3560 if(pItem->flags & 0x02)
3561 pType = &pItem->type;
3562 else
3563 pType = (WORD*)(pBlk + pItem->type);
3565 if (pItem->flags & ~0xda)
3566 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3568 SLTG_DoElem(pType, pBlk,
3569 &pVarDesc->vardesc.elemdescVar, ref_lookup);
3571 if (TRACE_ON(typelib)) {
3572 char buf[300];
3573 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
3574 TRACE_(typelib)("elemdescVar: %s\n", buf);
3577 if (pItem->flags & 0x40) {
3578 TRACE_(typelib)("VAR_DISPATCH\n");
3579 pVarDesc->vardesc.varkind = VAR_DISPATCH;
3581 else if (pItem->flags & 0x10) {
3582 TRACE_(typelib)("VAR_CONST\n");
3583 pVarDesc->vardesc.varkind = VAR_CONST;
3584 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
3585 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
3586 if (pItem->flags & 0x08)
3587 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
3588 else {
3589 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
3591 case VT_LPSTR:
3592 case VT_LPWSTR:
3593 case VT_BSTR:
3595 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3596 BSTR str;
3597 TRACE_(typelib)("len = %u\n", len);
3598 if (len == 0xffff) {
3599 str = NULL;
3600 } else {
3601 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3602 str = SysAllocStringLen(NULL, alloc_len);
3603 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3605 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
3606 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
3607 break;
3609 case VT_I2:
3610 case VT_UI2:
3611 case VT_I4:
3612 case VT_UI4:
3613 case VT_INT:
3614 case VT_UINT:
3615 V_INT(pVarDesc->vardesc.u.lpvarValue) =
3616 *(INT*)(pBlk + pItem->byte_offs);
3617 break;
3618 default:
3619 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
3623 else {
3624 TRACE_(typelib)("VAR_PERINSTANCE\n");
3625 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
3626 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
3629 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3630 pVarDesc->vardesc.wVarFlags = pItem->varflags;
3632 if (pItem->flags & 0x80)
3633 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3635 bstrPrevName = pVarDesc->Name;
3637 pTI->TypeAttr.cVars = cVars;
3640 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3641 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3643 SLTG_Function *pFunc;
3644 unsigned short i;
3645 TLBFuncDesc *pFuncDesc;
3647 pTI->funcdescs = TLBFuncDesc_Constructor(cFuncs);
3649 pFuncDesc = pTI->funcdescs;
3650 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
3651 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
3653 int param;
3654 WORD *pType, *pArg;
3656 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3657 case SLTG_FUNCTION_MAGIC:
3658 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
3659 break;
3660 case SLTG_DISPATCH_FUNCTION_MAGIC:
3661 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
3662 break;
3663 case SLTG_STATIC_FUNCTION_MAGIC:
3664 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
3665 break;
3666 default:
3667 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3668 continue;
3670 pFuncDesc->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3672 pFuncDesc->funcdesc.memid = pFunc->dispid;
3673 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
3674 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
3675 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
3676 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3677 pFuncDesc->funcdesc.oVft = pFunc->vtblpos & ~1;
3679 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3680 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
3682 if(pFunc->retnextopt & 0x80)
3683 pType = &pFunc->rettype;
3684 else
3685 pType = (WORD*)(pBlk + pFunc->rettype);
3687 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
3689 pFuncDesc->funcdesc.lprgelemdescParam =
3690 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
3691 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
3693 pArg = (WORD*)(pBlk + pFunc->arg_off);
3695 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
3696 char *paramName = pNameTable + *pArg;
3697 BOOL HaveOffs;
3698 /* If arg type follows then paramName points to the 2nd
3699 letter of the name, else the next WORD is an offset to
3700 the arg type and paramName points to the first letter.
3701 So let's take one char off paramName and see if we're
3702 pointing at an alpha-numeric char. However if *pArg is
3703 0xffff or 0xfffe then the param has no name, the former
3704 meaning that the next WORD is the type, the latter
3705 meaning that the next WORD is an offset to the type. */
3707 HaveOffs = FALSE;
3708 if(*pArg == 0xffff)
3709 paramName = NULL;
3710 else if(*pArg == 0xfffe) {
3711 paramName = NULL;
3712 HaveOffs = TRUE;
3714 else if(paramName[-1] && !isalnum(paramName[-1]))
3715 HaveOffs = TRUE;
3717 pArg++;
3719 if(HaveOffs) { /* the next word is an offset to type */
3720 pType = (WORD*)(pBlk + *pArg);
3721 SLTG_DoElem(pType, pBlk,
3722 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
3723 pArg++;
3724 } else {
3725 if(paramName)
3726 paramName--;
3727 pArg = SLTG_DoElem(pArg, pBlk,
3728 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
3731 /* Are we an optional param ? */
3732 if(pFuncDesc->funcdesc.cParams - param <=
3733 pFuncDesc->funcdesc.cParamsOpt)
3734 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3736 if(paramName) {
3737 pFuncDesc->pParamDesc[param].Name =
3738 TLB_MultiByteToBSTR(paramName);
3739 } else {
3740 pFuncDesc->pParamDesc[param].Name =
3741 SysAllocString(pFuncDesc->Name);
3745 pTI->TypeAttr.cFuncs = cFuncs;
3748 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3749 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3750 SLTG_TypeInfoTail *pTITail)
3752 char *pFirstItem;
3753 sltg_ref_lookup_t *ref_lookup = NULL;
3755 if(pTIHeader->href_table != 0xffffffff) {
3756 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3757 pNameTable);
3760 pFirstItem = pBlk;
3762 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3763 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3765 heap_free(ref_lookup);
3769 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3770 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3771 const SLTG_TypeInfoTail *pTITail)
3773 char *pFirstItem;
3774 sltg_ref_lookup_t *ref_lookup = NULL;
3776 if(pTIHeader->href_table != 0xffffffff) {
3777 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3778 pNameTable);
3781 pFirstItem = pBlk;
3783 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3784 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3787 if (pTITail->funcs_off != 0xffff)
3788 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3790 heap_free(ref_lookup);
3792 if (TRACE_ON(typelib))
3793 dump_TLBFuncDesc(pTI->funcdescs, pTI->TypeAttr.cFuncs);
3796 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3797 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3798 const SLTG_TypeInfoTail *pTITail)
3800 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3803 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3804 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3805 const SLTG_TypeInfoTail *pTITail)
3807 WORD *pType;
3808 sltg_ref_lookup_t *ref_lookup = NULL;
3810 if (pTITail->simple_alias) {
3811 /* if simple alias, no more processing required */
3812 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3813 return;
3816 if(pTIHeader->href_table != 0xffffffff) {
3817 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3818 pNameTable);
3821 /* otherwise it is an offset to a type */
3822 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3824 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3826 heap_free(ref_lookup);
3829 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3830 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3831 const SLTG_TypeInfoTail *pTITail)
3833 sltg_ref_lookup_t *ref_lookup = NULL;
3834 if (pTIHeader->href_table != 0xffffffff)
3835 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3836 pNameTable);
3838 if (pTITail->vars_off != 0xffff)
3839 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3841 if (pTITail->funcs_off != 0xffff)
3842 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3844 if (pTITail->impls_off != 0xffff)
3845 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
3847 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3848 * of dispinterface functions including the IDispatch ones, so
3849 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3850 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3852 heap_free(ref_lookup);
3853 if (TRACE_ON(typelib))
3854 dump_TLBFuncDesc(pTI->funcdescs, pTI->TypeAttr.cFuncs);
3857 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3858 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3859 const SLTG_TypeInfoTail *pTITail)
3861 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3864 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3865 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3866 const SLTG_TypeInfoTail *pTITail)
3868 sltg_ref_lookup_t *ref_lookup = NULL;
3869 if (pTIHeader->href_table != 0xffffffff)
3870 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3871 pNameTable);
3873 if (pTITail->vars_off != 0xffff)
3874 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3876 if (pTITail->funcs_off != 0xffff)
3877 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3878 heap_free(ref_lookup);
3879 if (TRACE_ON(typelib))
3880 dump_TypeInfo(pTI);
3883 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3884 managable copy of it into this */
3885 typedef struct {
3886 WORD small_no;
3887 char *index_name;
3888 char *other_name;
3889 WORD res1a;
3890 WORD name_offs;
3891 WORD more_bytes;
3892 char *extra;
3893 WORD res20;
3894 DWORD helpcontext;
3895 WORD res26;
3896 GUID uuid;
3897 } SLTG_InternalOtherTypeInfo;
3899 /****************************************************************************
3900 * ITypeLib2_Constructor_SLTG
3902 * loading a SLTG typelib from an in-memory image
3904 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3906 ITypeLibImpl *pTypeLibImpl;
3907 SLTG_Header *pHeader;
3908 SLTG_BlkEntry *pBlkEntry;
3909 SLTG_Magic *pMagic;
3910 SLTG_Index *pIndex;
3911 SLTG_Pad9 *pPad9;
3912 LPVOID pBlk, pFirstBlk;
3913 SLTG_LibBlk *pLibBlk;
3914 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3915 char *pAfterOTIBlks = NULL;
3916 char *pNameTable, *ptr;
3917 int i;
3918 DWORD len, order;
3919 ITypeInfoImpl **ppTypeInfoImpl;
3921 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3924 pTypeLibImpl = TypeLibImpl_Constructor();
3925 if (!pTypeLibImpl) return NULL;
3927 pHeader = pLib;
3929 TRACE_(typelib)("header:\n");
3930 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3931 pHeader->nrOfFileBlks );
3932 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3933 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3934 pHeader->SLTG_magic);
3935 return NULL;
3938 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3939 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3941 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3942 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3944 /* Next we have a magic block */
3945 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3947 /* Let's see if we're still in sync */
3948 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3949 sizeof(SLTG_COMPOBJ_MAGIC))) {
3950 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3951 return NULL;
3953 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3954 sizeof(SLTG_DIR_MAGIC))) {
3955 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
3956 return NULL;
3959 pIndex = (SLTG_Index*)(pMagic+1);
3961 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3963 pFirstBlk = pPad9 + 1;
3965 /* We'll set up a ptr to the main library block, which is the last one. */
3967 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3968 pBlkEntry[order].next != 0;
3969 order = pBlkEntry[order].next - 1, i++) {
3970 pBlk = (char*)pBlk + pBlkEntry[order].len;
3972 pLibBlk = pBlk;
3974 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3976 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3977 interspersed */
3979 len += 0x40;
3981 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3983 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
3986 ptr = (char*)pLibBlk + len;
3988 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3989 WORD w, extra;
3990 len = 0;
3992 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3994 w = *(WORD*)(ptr + 2);
3995 if(w != 0xffff) {
3996 len += w;
3997 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
3998 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3999 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4001 w = *(WORD*)(ptr + 4 + len);
4002 if(w != 0xffff) {
4003 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4004 len += w;
4005 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4006 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4007 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4009 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4010 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4011 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4012 if(extra) {
4013 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4014 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4015 len += extra;
4017 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4018 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4019 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4020 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4021 len += sizeof(SLTG_OtherTypeInfo);
4022 ptr += len;
4025 pAfterOTIBlks = ptr;
4027 /* Skip this WORD and get the next DWORD */
4028 len = *(DWORD*)(pAfterOTIBlks + 2);
4030 /* Now add this to pLibBLk look at what we're pointing at and
4031 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4032 dust and we should be pointing at the beginning of the name
4033 table */
4035 pNameTable = (char*)pLibBlk + len;
4037 switch(*(WORD*)pNameTable) {
4038 case 0xffff:
4039 break;
4040 case 0x0200:
4041 pNameTable += 0x20;
4042 break;
4043 default:
4044 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4045 break;
4048 pNameTable += 0x216;
4050 pNameTable += 2;
4052 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4054 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
4057 /* Hopefully we now have enough ptrs set up to actually read in
4058 some TypeInfos. It's not clear which order to do them in, so
4059 I'll just follow the links along the BlkEntry chain and read
4060 them in the order in which they are in the file */
4062 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4063 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4065 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4066 pBlkEntry[order].next != 0;
4067 order = pBlkEntry[order].next - 1, i++) {
4069 SLTG_TypeInfoHeader *pTIHeader;
4070 SLTG_TypeInfoTail *pTITail;
4071 SLTG_MemberHeader *pMemHeader;
4073 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
4074 pOtherTypeInfoBlks[i].index_name)) {
4075 FIXME_(typelib)("Index strings don't match\n");
4076 return NULL;
4079 pTIHeader = pBlk;
4080 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4081 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4082 return NULL;
4084 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4085 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4086 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4088 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4089 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4090 (*ppTypeInfoImpl)->index = i;
4091 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
4092 pOtherTypeInfoBlks[i].name_offs +
4093 pNameTable);
4094 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4095 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
4096 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
4097 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
4098 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
4099 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
4100 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4102 if((*ppTypeInfoImpl)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
4103 (*ppTypeInfoImpl)->TypeAttr.typekind = TKIND_DISPATCH;
4105 if((pTIHeader->typeflags1 & 7) != 2)
4106 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4107 if(pTIHeader->typeflags3 != 2)
4108 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4110 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4111 debugstr_w((*ppTypeInfoImpl)->Name),
4112 typekind_desc[pTIHeader->typekind],
4113 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
4114 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
4116 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4118 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4120 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
4121 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
4122 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
4124 switch(pTIHeader->typekind) {
4125 case TKIND_ENUM:
4126 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4127 pTIHeader, pTITail);
4128 break;
4130 case TKIND_RECORD:
4131 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4132 pTIHeader, pTITail);
4133 break;
4135 case TKIND_INTERFACE:
4136 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4137 pTIHeader, pTITail);
4138 break;
4140 case TKIND_COCLASS:
4141 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4142 pTIHeader, pTITail);
4143 break;
4145 case TKIND_ALIAS:
4146 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4147 pTIHeader, pTITail);
4148 break;
4150 case TKIND_DISPATCH:
4151 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4152 pTIHeader, pTITail);
4153 break;
4155 case TKIND_MODULE:
4156 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4157 pTIHeader, pTITail);
4158 break;
4160 default:
4161 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4162 break;
4166 /* could get cFuncs, cVars and cImplTypes from here
4167 but we've already set those */
4168 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4169 X(06);
4170 X(16);
4171 X(18);
4172 X(1a);
4173 X(1e);
4174 X(24);
4175 X(26);
4176 X(2a);
4177 X(2c);
4178 X(2e);
4179 X(30);
4180 X(32);
4181 X(34);
4182 #undef X
4183 ++ppTypeInfoImpl;
4184 pBlk = (char*)pBlk + pBlkEntry[order].len;
4187 if(i != pTypeLibImpl->TypeInfoCount) {
4188 FIXME("Somehow processed %d TypeInfos\n", i);
4189 return NULL;
4192 heap_free(pOtherTypeInfoBlks);
4193 return (ITypeLib2*)pTypeLibImpl;
4196 /* ITypeLib::QueryInterface
4198 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
4199 ITypeLib2 * iface,
4200 REFIID riid,
4201 VOID **ppvObject)
4203 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4205 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4207 *ppvObject=NULL;
4208 if(IsEqualIID(riid, &IID_IUnknown) ||
4209 IsEqualIID(riid,&IID_ITypeLib)||
4210 IsEqualIID(riid,&IID_ITypeLib2))
4212 *ppvObject = This;
4215 if(*ppvObject)
4217 ITypeLib2_AddRef(iface);
4218 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4219 return S_OK;
4221 TRACE("-- Interface: E_NOINTERFACE\n");
4222 return E_NOINTERFACE;
4225 /* ITypeLib::AddRef
4227 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4229 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4230 ULONG ref = InterlockedIncrement(&This->ref);
4232 TRACE("(%p)->ref was %u\n",This, ref - 1);
4234 return ref;
4237 /* ITypeLib::Release
4239 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4241 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4242 ULONG ref = InterlockedDecrement(&This->ref);
4244 TRACE("(%p)->(%u)\n",This, ref);
4246 if (!ref)
4248 TLBImpLib *pImpLib, *pImpLibNext;
4249 TLBRefType *ref_type;
4250 void *cursor2;
4251 int i;
4253 /* remove cache entry */
4254 if(This->path)
4256 TRACE("removing from cache list\n");
4257 EnterCriticalSection(&cache_section);
4258 if (This->next) This->next->prev = This->prev;
4259 if (This->prev) This->prev->next = This->next;
4260 else tlb_cache_first = This->next;
4261 LeaveCriticalSection(&cache_section);
4262 heap_free(This->path);
4264 TRACE(" destroying ITypeLib(%p)\n",This);
4266 SysFreeString(This->Name);
4267 This->Name = NULL;
4269 SysFreeString(This->DocString);
4270 This->DocString = NULL;
4272 SysFreeString(This->HelpFile);
4273 This->HelpFile = NULL;
4275 SysFreeString(This->HelpStringDll);
4276 This->HelpStringDll = NULL;
4278 TLB_FreeCustData(&This->custdata_list);
4280 for (i = 0; i < This->ctTypeDesc; i++)
4281 if (This->pTypeDesc[i].vt == VT_CARRAY)
4282 heap_free(This->pTypeDesc[i].u.lpadesc);
4284 heap_free(This->pTypeDesc);
4286 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4288 if (pImpLib->pImpTypeLib)
4289 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
4290 SysFreeString(pImpLib->name);
4292 list_remove(&pImpLib->entry);
4293 heap_free(pImpLib);
4296 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4298 list_remove(&ref_type->entry);
4299 heap_free(ref_type);
4302 for (i = 0; i < This->TypeInfoCount; ++i)
4303 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4304 heap_free(This->typeinfos);
4305 heap_free(This);
4306 return 0;
4309 return ref;
4312 /* ITypeLib::GetTypeInfoCount
4314 * Returns the number of type descriptions in the type library
4316 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4318 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4319 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4320 return This->TypeInfoCount;
4323 /* ITypeLib::GetTypeInfo
4325 * retrieves the specified type description in the library.
4327 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4328 ITypeLib2 *iface,
4329 UINT index,
4330 ITypeInfo **ppTInfo)
4332 ITypeLibImpl *This = (ITypeLibImpl*)iface;
4334 TRACE("%p %u %p\n", This, index, ppTInfo);
4336 if(!ppTInfo)
4337 return E_INVALIDARG;
4339 if(index >= This->TypeInfoCount)
4340 return TYPE_E_ELEMENTNOTFOUND;
4342 *ppTInfo = (ITypeInfo*)This->typeinfos[index];
4343 ITypeInfo_AddRef(*ppTInfo);
4345 return S_OK;
4349 /* ITypeLibs::GetTypeInfoType
4351 * Retrieves the type of a type description.
4353 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4354 ITypeLib2 *iface,
4355 UINT index,
4356 TYPEKIND *pTKind)
4358 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4360 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4362 if(!pTKind)
4363 return E_INVALIDARG;
4365 if(index >= This->TypeInfoCount)
4366 return TYPE_E_ELEMENTNOTFOUND;
4368 *pTKind = This->typeinfos[index]->TypeAttr.typekind;
4370 return S_OK;
4373 /* ITypeLib::GetTypeInfoOfGuid
4375 * Retrieves the type description that corresponds to the specified GUID.
4378 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4379 ITypeLib2 *iface,
4380 REFGUID guid,
4381 ITypeInfo **ppTInfo)
4383 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4384 UINT i;
4386 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4388 for(i = 0; i < This->TypeInfoCount; ++i){
4389 if(IsEqualIID(&This->typeinfos[i]->TypeAttr.guid, guid)){
4390 *ppTInfo = (ITypeInfo*)This->typeinfos[i];
4391 ITypeInfo_AddRef(*ppTInfo);
4392 return S_OK;
4396 return TYPE_E_ELEMENTNOTFOUND;
4399 /* ITypeLib::GetLibAttr
4401 * Retrieves the structure that contains the library's attributes.
4404 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4405 ITypeLib2 *iface,
4406 LPTLIBATTR *attr)
4408 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4410 TRACE("(%p, %p)\n", This, attr);
4412 if (!attr) return E_INVALIDARG;
4414 *attr = heap_alloc(sizeof(**attr));
4415 if (!*attr) return E_OUTOFMEMORY;
4417 **attr = This->LibAttr;
4418 return S_OK;
4421 /* ITypeLib::GetTypeComp
4423 * Enables a client compiler to bind to a library's types, variables,
4424 * constants, and global functions.
4427 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4428 ITypeLib2 *iface,
4429 ITypeComp **ppTComp)
4431 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4433 TRACE("(%p)->(%p)\n",This,ppTComp);
4434 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4435 ITypeComp_AddRef(*ppTComp);
4437 return S_OK;
4440 /* ITypeLib::GetDocumentation
4442 * Retrieves the library's documentation string, the complete Help file name
4443 * and path, and the context identifier for the library Help topic in the Help
4444 * file.
4446 * On a successful return all non-null BSTR pointers will have been set,
4447 * possibly to NULL.
4449 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4450 ITypeLib2 *iface,
4451 INT index,
4452 BSTR *pBstrName,
4453 BSTR *pBstrDocString,
4454 DWORD *pdwHelpContext,
4455 BSTR *pBstrHelpFile)
4457 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4459 HRESULT result = E_INVALIDARG;
4461 ITypeInfo *pTInfo;
4464 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4465 This, index,
4466 pBstrName, pBstrDocString,
4467 pdwHelpContext, pBstrHelpFile);
4469 if(index<0)
4471 /* documentation for the typelib */
4472 if(pBstrName)
4474 if (This->Name)
4476 if(!(*pBstrName = SysAllocString(This->Name)))
4477 goto memerr1;
4479 else
4480 *pBstrName = NULL;
4482 if(pBstrDocString)
4484 if (This->DocString)
4486 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4487 goto memerr2;
4489 else if (This->Name)
4491 if(!(*pBstrDocString = SysAllocString(This->Name)))
4492 goto memerr2;
4494 else
4495 *pBstrDocString = NULL;
4497 if(pdwHelpContext)
4499 *pdwHelpContext = This->dwHelpContext;
4501 if(pBstrHelpFile)
4503 if (This->HelpFile)
4505 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4506 goto memerr3;
4508 else
4509 *pBstrHelpFile = NULL;
4512 result = S_OK;
4514 else
4516 /* for a typeinfo */
4517 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4519 if(SUCCEEDED(result))
4521 result = ITypeInfo_GetDocumentation(pTInfo,
4522 MEMBERID_NIL,
4523 pBstrName,
4524 pBstrDocString,
4525 pdwHelpContext, pBstrHelpFile);
4527 ITypeInfo_Release(pTInfo);
4530 return result;
4531 memerr3:
4532 if (pBstrDocString) SysFreeString (*pBstrDocString);
4533 memerr2:
4534 if (pBstrName) SysFreeString (*pBstrName);
4535 memerr1:
4536 return STG_E_INSUFFICIENTMEMORY;
4539 /* ITypeLib::IsName
4541 * Indicates whether a passed-in string contains the name of a type or member
4542 * described in the library.
4545 static HRESULT WINAPI ITypeLib2_fnIsName(
4546 ITypeLib2 *iface,
4547 LPOLESTR szNameBuf,
4548 ULONG lHashVal,
4549 BOOL *pfName)
4551 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4552 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), tic, fdc, vrc, pc;
4554 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4555 pfName);
4557 *pfName=TRUE;
4558 for(tic = 0; tic < This->TypeInfoCount; ++tic){
4559 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
4560 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4561 for(fdc = 0; fdc < pTInfo->TypeAttr.cFuncs; ++fdc) {
4562 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
4563 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4564 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++)
4565 if(!memcmp(szNameBuf,pFInfo->pParamDesc[pc].Name, nNameBufLen))
4566 goto ITypeLib2_fnIsName_exit;
4568 for(vrc = 0; vrc < pTInfo->TypeAttr.cVars; ++vrc){
4569 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
4570 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4574 *pfName=FALSE;
4576 ITypeLib2_fnIsName_exit:
4577 TRACE("(%p)slow! search for %s: %s found!\n", This,
4578 debugstr_w(szNameBuf), *pfName?"NOT":"");
4580 return S_OK;
4583 /* ITypeLib::FindName
4585 * Finds occurrences of a type description in a type library. This may be used
4586 * to quickly verify that a name exists in a type library.
4589 static HRESULT WINAPI ITypeLib2_fnFindName(
4590 ITypeLib2 *iface,
4591 LPOLESTR szNameBuf,
4592 ULONG lHashVal,
4593 ITypeInfo **ppTInfo,
4594 MEMBERID *rgMemId,
4595 UINT16 *pcFound)
4597 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4598 TLBVarDesc *pVInfo;
4599 UINT tic, fdc, pc, count = 0;
4600 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4602 for(tic = 0; tic < This->TypeInfoCount; ++tic){
4603 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
4604 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4605 for(fdc = 0; fdc < pTInfo->TypeAttr.cFuncs; ++fdc) {
4606 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
4607 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4608 for(pc = 0;pc < pFInfo->funcdesc.cParams; pc++) {
4609 if(!memcmp(szNameBuf,pFInfo->pParamDesc[pc].Name,nNameBufLen))
4610 goto ITypeLib2_fnFindName_exit;
4614 pVInfo = TLB_get_vardesc_by_name(pTInfo->vardescs, pTInfo->TypeAttr.cVars, szNameBuf);
4615 if(pVInfo)
4616 goto ITypeLib2_fnFindName_exit;
4618 continue;
4619 ITypeLib2_fnFindName_exit:
4620 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4621 ppTInfo[count]=(LPTYPEINFO)pTInfo;
4622 count++;
4624 TRACE("(%p)slow! search for %d with %s: found %d TypeInfos!\n",
4625 This, *pcFound, debugstr_w(szNameBuf), count);
4627 *pcFound = count;
4629 return S_OK;
4632 /* ITypeLib::ReleaseTLibAttr
4634 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4637 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4638 ITypeLib2 *iface,
4639 TLIBATTR *pTLibAttr)
4641 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4642 TRACE("freeing (%p)\n",This);
4643 heap_free(pTLibAttr);
4647 /* ITypeLib2::GetCustData
4649 * gets the custom data
4651 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4652 ITypeLib2 * iface,
4653 REFGUID guid,
4654 VARIANT *pVarVal)
4656 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4657 TLBCustData *pCData;
4659 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
4661 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
4662 if(!pCData)
4663 return TYPE_E_ELEMENTNOTFOUND;
4665 VariantInit(pVarVal);
4666 VariantCopy(pVarVal, &pCData->data);
4668 return S_OK;
4671 /* ITypeLib2::GetLibStatistics
4673 * Returns statistics about a type library that are required for efficient
4674 * sizing of hash tables.
4677 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4678 ITypeLib2 * iface,
4679 ULONG *pcUniqueNames,
4680 ULONG *pcchUniqueNames)
4682 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4684 FIXME("(%p): stub!\n", This);
4686 if(pcUniqueNames) *pcUniqueNames=1;
4687 if(pcchUniqueNames) *pcchUniqueNames=1;
4688 return S_OK;
4691 /* ITypeLib2::GetDocumentation2
4693 * Retrieves the library's documentation string, the complete Help file name
4694 * and path, the localization context to use, and the context ID for the
4695 * library Help topic in the Help file.
4698 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4699 ITypeLib2 * iface,
4700 INT index,
4701 LCID lcid,
4702 BSTR *pbstrHelpString,
4703 DWORD *pdwHelpStringContext,
4704 BSTR *pbstrHelpStringDll)
4706 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4707 HRESULT result;
4708 ITypeInfo *pTInfo;
4710 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4712 /* the help string should be obtained from the helpstringdll,
4713 * using the _DLLGetDocumentation function, based on the supplied
4714 * lcid. Nice to do sometime...
4716 if(index<0)
4718 /* documentation for the typelib */
4719 if(pbstrHelpString)
4720 *pbstrHelpString=SysAllocString(This->DocString);
4721 if(pdwHelpStringContext)
4722 *pdwHelpStringContext=This->dwHelpContext;
4723 if(pbstrHelpStringDll)
4724 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4726 result = S_OK;
4728 else
4730 /* for a typeinfo */
4731 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4733 if(SUCCEEDED(result))
4735 ITypeInfo2 * pTInfo2;
4736 result = ITypeInfo_QueryInterface(pTInfo,
4737 &IID_ITypeInfo2,
4738 (LPVOID*) &pTInfo2);
4740 if(SUCCEEDED(result))
4742 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4743 MEMBERID_NIL,
4744 lcid,
4745 pbstrHelpString,
4746 pdwHelpStringContext,
4747 pbstrHelpStringDll);
4749 ITypeInfo2_Release(pTInfo2);
4752 ITypeInfo_Release(pTInfo);
4755 return result;
4758 static HRESULT TLB_copy_all_custdata(struct list *custdata_list, CUSTDATA *pCustData)
4760 TLBCustData *pCData;
4761 unsigned int ct;
4762 CUSTDATAITEM *cdi;
4764 ct = list_count(custdata_list);
4766 pCustData->prgCustData = heap_alloc_zero(ct * sizeof(CUSTDATAITEM));
4767 if(!pCustData->prgCustData)
4768 return E_OUTOFMEMORY;
4770 pCustData->cCustData = ct;
4772 cdi = pCustData->prgCustData;
4773 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
4774 cdi->guid = pCData->guid;
4775 VariantCopy(&cdi->varValue, &pCData->data);
4776 ++cdi;
4779 return S_OK;
4783 /* ITypeLib2::GetAllCustData
4785 * Gets all custom data items for the library.
4788 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4789 ITypeLib2 * iface,
4790 CUSTDATA *pCustData)
4792 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4793 TRACE("%p %p\n", iface, pCustData);
4794 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
4797 static const ITypeLib2Vtbl tlbvt = {
4798 ITypeLib2_fnQueryInterface,
4799 ITypeLib2_fnAddRef,
4800 ITypeLib2_fnRelease,
4801 ITypeLib2_fnGetTypeInfoCount,
4802 ITypeLib2_fnGetTypeInfo,
4803 ITypeLib2_fnGetTypeInfoType,
4804 ITypeLib2_fnGetTypeInfoOfGuid,
4805 ITypeLib2_fnGetLibAttr,
4806 ITypeLib2_fnGetTypeComp,
4807 ITypeLib2_fnGetDocumentation,
4808 ITypeLib2_fnIsName,
4809 ITypeLib2_fnFindName,
4810 ITypeLib2_fnReleaseTLibAttr,
4812 ITypeLib2_fnGetCustData,
4813 ITypeLib2_fnGetLibStatistics,
4814 ITypeLib2_fnGetDocumentation2,
4815 ITypeLib2_fnGetAllCustData
4819 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4821 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4823 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4826 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4828 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4830 return ITypeLib2_AddRef((ITypeLib2 *)This);
4833 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4835 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4837 return ITypeLib2_Release((ITypeLib2 *)This);
4840 static HRESULT WINAPI ITypeLibComp_fnBind(
4841 ITypeComp * iface,
4842 OLECHAR * szName,
4843 ULONG lHash,
4844 WORD wFlags,
4845 ITypeInfo ** ppTInfo,
4846 DESCKIND * pDescKind,
4847 BINDPTR * pBindPtr)
4849 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4850 int typemismatch=0, i;
4852 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4854 *pDescKind = DESCKIND_NONE;
4855 pBindPtr->lptcomp = NULL;
4856 *ppTInfo = NULL;
4858 for(i = 0; i < This->TypeInfoCount; ++i){
4859 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
4860 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4862 /* FIXME: check wFlags here? */
4863 /* FIXME: we should use a hash table to look this info up using lHash
4864 * instead of an O(n) search */
4865 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4866 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4868 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4870 *pDescKind = DESCKIND_TYPECOMP;
4871 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4872 ITypeComp_AddRef(pBindPtr->lptcomp);
4873 TRACE("module or enum: %s\n", debugstr_w(szName));
4874 return S_OK;
4878 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4879 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4881 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4882 HRESULT hr;
4884 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4885 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4887 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4888 return S_OK;
4890 else if (hr == TYPE_E_TYPEMISMATCH)
4891 typemismatch = 1;
4894 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4895 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4897 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4898 HRESULT hr;
4899 ITypeInfo *subtypeinfo;
4900 BINDPTR subbindptr;
4901 DESCKIND subdesckind;
4903 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4904 &subtypeinfo, &subdesckind, &subbindptr);
4905 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4907 TYPEDESC tdesc_appobject;
4908 const VARDESC vardesc_appobject =
4910 -2, /* memid */
4911 NULL, /* lpstrSchema */
4913 0 /* oInst */
4916 /* ELEMDESC */
4918 /* TYPEDESC */
4920 &tdesc_appobject
4922 VT_PTR
4925 0, /* wVarFlags */
4926 VAR_STATIC /* varkind */
4929 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
4930 tdesc_appobject.vt = VT_USERDEFINED;
4932 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4934 /* cleanup things filled in by Bind call so we can put our
4935 * application object data in there instead */
4936 switch (subdesckind)
4938 case DESCKIND_FUNCDESC:
4939 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4940 break;
4941 case DESCKIND_VARDESC:
4942 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4943 break;
4944 default:
4945 break;
4947 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4949 if (pTypeInfo->hreftype == -1)
4950 FIXME("no hreftype for interface %p\n", pTypeInfo);
4952 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4953 if (FAILED(hr))
4954 return hr;
4956 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4957 *ppTInfo = (ITypeInfo *)pTypeInfo;
4958 ITypeInfo_AddRef(*ppTInfo);
4959 return S_OK;
4961 else if (hr == TYPE_E_TYPEMISMATCH)
4962 typemismatch = 1;
4966 if (typemismatch)
4968 TRACE("type mismatch %s\n", debugstr_w(szName));
4969 return TYPE_E_TYPEMISMATCH;
4971 else
4973 TRACE("name not found %s\n", debugstr_w(szName));
4974 return S_OK;
4978 static HRESULT WINAPI ITypeLibComp_fnBindType(
4979 ITypeComp * iface,
4980 OLECHAR * szName,
4981 ULONG lHash,
4982 ITypeInfo ** ppTInfo,
4983 ITypeComp ** ppTComp)
4985 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4986 UINT i;
4988 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4990 if(!szName || !ppTInfo || !ppTComp)
4991 return E_INVALIDARG;
4993 for(i = 0; i < This->TypeInfoCount; ++i)
4995 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
4996 /* FIXME: should use lHash to do the search */
4997 if (pTypeInfo->Name && !strcmpiW(pTypeInfo->Name, szName))
4999 TRACE("returning %p\n", pTypeInfo);
5000 *ppTInfo = (ITypeInfo *)&pTypeInfo->lpVtbl;
5001 ITypeInfo_AddRef(*ppTInfo);
5002 *ppTComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
5003 ITypeComp_AddRef(*ppTComp);
5004 return S_OK;
5008 TRACE("not found\n");
5009 *ppTInfo = NULL;
5010 *ppTComp = NULL;
5011 return S_OK;
5014 static const ITypeCompVtbl tlbtcvt =
5017 ITypeLibComp_fnQueryInterface,
5018 ITypeLibComp_fnAddRef,
5019 ITypeLibComp_fnRelease,
5021 ITypeLibComp_fnBind,
5022 ITypeLibComp_fnBindType
5025 /*================== ITypeInfo(2) Methods ===================================*/
5026 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5028 ITypeInfoImpl *pTypeInfoImpl;
5030 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5031 if (pTypeInfoImpl)
5033 pTypeInfoImpl->lpVtbl = &tinfvt;
5034 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
5035 pTypeInfoImpl->ref = 0;
5036 pTypeInfoImpl->hreftype = -1;
5037 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
5038 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
5039 list_init(&pTypeInfoImpl->custdata_list);
5041 TRACE("(%p)\n", pTypeInfoImpl);
5042 return pTypeInfoImpl;
5045 /* ITypeInfo::QueryInterface
5047 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5048 ITypeInfo2 *iface,
5049 REFIID riid,
5050 VOID **ppvObject)
5052 ITypeLibImpl *This = (ITypeLibImpl *)iface;
5054 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5056 *ppvObject=NULL;
5057 if(IsEqualIID(riid, &IID_IUnknown) ||
5058 IsEqualIID(riid,&IID_ITypeInfo)||
5059 IsEqualIID(riid,&IID_ITypeInfo2))
5060 *ppvObject = This;
5062 if(*ppvObject){
5063 ITypeInfo_AddRef(iface);
5064 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5065 return S_OK;
5067 TRACE("-- Interface: E_NOINTERFACE\n");
5068 return E_NOINTERFACE;
5071 /* ITypeInfo::AddRef
5073 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5075 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5076 ULONG ref = InterlockedIncrement(&This->ref);
5078 TRACE("(%p)->ref is %u\n",This, ref);
5080 if (ref == 1 /* incremented from 0 */)
5081 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
5083 return ref;
5086 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5088 UINT i, j;
5090 TRACE("destroying ITypeInfo(%p)\n",This);
5092 SysFreeString(This->Name);
5093 This->Name = NULL;
5095 SysFreeString(This->DocString);
5096 This->DocString = NULL;
5098 SysFreeString(This->DllName);
5099 This->DllName = NULL;
5101 for (i = 0; i < This->TypeAttr.cFuncs; ++i)
5103 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5104 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5106 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5107 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5109 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5110 heap_free(elemdesc->u.paramdesc.pparamdescex);
5112 TLB_FreeCustData(&pFInfo->pParamDesc[j].custdata_list);
5113 SysFreeString(pFInfo->pParamDesc[j].Name);
5115 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5116 heap_free(pFInfo->pParamDesc);
5117 TLB_FreeCustData(&pFInfo->custdata_list);
5118 if (!IS_INTRESOURCE(pFInfo->Entry) && pFInfo->Entry != (BSTR)-1)
5119 SysFreeString(pFInfo->Entry);
5120 SysFreeString(pFInfo->HelpString);
5121 SysFreeString(pFInfo->Name);
5123 heap_free(This->funcdescs);
5125 for(i = 0; i < This->TypeAttr.cVars; ++i)
5127 TLBVarDesc *pVInfo = &This->vardescs[i];
5128 if (pVInfo->vardesc.varkind == VAR_CONST)
5130 VariantClear(pVInfo->vardesc.u.lpvarValue);
5131 heap_free(pVInfo->vardesc.u.lpvarValue);
5133 TLB_FreeCustData(&pVInfo->custdata_list);
5134 SysFreeString(pVInfo->Name);
5135 SysFreeString(pVInfo->HelpString);
5137 heap_free(This->vardescs);
5139 if(This->impltypes){
5140 for (i = 0; i < This->TypeAttr.cImplTypes; ++i){
5141 TLBImplType *pImpl = &This->impltypes[i];
5142 TLB_FreeCustData(&pImpl->custdata_list);
5144 heap_free(This->impltypes);
5147 TLB_FreeCustData(&This->custdata_list);
5149 heap_free(This);
5152 /* ITypeInfo::Release
5154 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5156 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5157 ULONG ref = InterlockedDecrement(&This->ref);
5159 TRACE("(%p)->(%u)\n",This, ref);
5161 if (!ref)
5163 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5164 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
5165 if (not_attached_to_typelib)
5166 heap_free(This);
5167 /* otherwise This will be freed when typelib is freed */
5170 return ref;
5173 /* ITypeInfo::GetTypeAttr
5175 * Retrieves a TYPEATTR structure that contains the attributes of the type
5176 * description.
5179 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5180 LPTYPEATTR *ppTypeAttr)
5182 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5183 SIZE_T size;
5185 TRACE("(%p)\n",This);
5187 size = sizeof(**ppTypeAttr);
5188 if (This->TypeAttr.typekind == TKIND_ALIAS)
5189 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
5191 *ppTypeAttr = heap_alloc(size);
5192 if (!*ppTypeAttr)
5193 return E_OUTOFMEMORY;
5195 **ppTypeAttr = This->TypeAttr;
5197 if (This->TypeAttr.typekind == TKIND_ALIAS)
5198 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5199 &This->TypeAttr.tdescAlias, *ppTypeAttr + 1);
5201 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5202 /* This should include all the inherited funcs */
5203 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
5204 /* This is always the size of IDispatch's vtbl */
5205 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5206 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5208 return S_OK;
5211 /* ITypeInfo::GetTypeComp
5213 * Retrieves the ITypeComp interface for the type description, which enables a
5214 * client compiler to bind to the type description's members.
5217 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5218 ITypeComp * *ppTComp)
5220 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5222 TRACE("(%p)->(%p)\n", This, ppTComp);
5224 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
5225 ITypeComp_AddRef(*ppTComp);
5226 return S_OK;
5229 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5231 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5232 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5233 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5234 return size;
5237 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5239 *dest = *src;
5240 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5241 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5243 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5244 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5245 *buffer += sizeof(PARAMDESCEX);
5246 *pparamdescex_dest = *pparamdescex_src;
5247 VariantInit(&pparamdescex_dest->varDefaultValue);
5248 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5249 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5251 else
5252 dest->u.paramdesc.pparamdescex = NULL;
5253 return S_OK;
5256 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5258 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5259 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5262 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5264 FUNCDESC *dest;
5265 char *buffer;
5266 SIZE_T size = sizeof(*src);
5267 SHORT i;
5268 HRESULT hr;
5270 size += sizeof(*src->lprgscode) * src->cScodes;
5271 size += TLB_SizeElemDesc(&src->elemdescFunc);
5272 for (i = 0; i < src->cParams; i++)
5274 size += sizeof(ELEMDESC);
5275 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5278 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5279 if (!dest) return E_OUTOFMEMORY;
5281 *dest = *src;
5282 if (dispinterface) /* overwrite funckind */
5283 dest->funckind = FUNC_DISPATCH;
5284 buffer = (char *)(dest + 1);
5286 dest->lprgscode = (SCODE *)buffer;
5287 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5288 buffer += sizeof(*src->lprgscode) * src->cScodes;
5290 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5291 if (FAILED(hr))
5293 SysFreeString((BSTR)dest);
5294 return hr;
5297 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5298 buffer += sizeof(ELEMDESC) * src->cParams;
5299 for (i = 0; i < src->cParams; i++)
5301 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5302 if (FAILED(hr))
5303 break;
5305 if (FAILED(hr))
5307 /* undo the above actions */
5308 for (i = i - 1; i >= 0; i--)
5309 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5310 TLB_FreeElemDesc(&dest->elemdescFunc);
5311 SysFreeString((BSTR)dest);
5312 return hr;
5315 /* special treatment for dispinterfaces: this makes functions appear
5316 * to return their [retval] value when it is really returning an
5317 * HRESULT */
5318 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5320 if (dest->cParams &&
5321 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5323 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5324 if (elemdesc->tdesc.vt != VT_PTR)
5326 ERR("elemdesc should have started with VT_PTR instead of:\n");
5327 if (ERR_ON(ole))
5328 dump_ELEMDESC(elemdesc);
5329 return E_UNEXPECTED;
5332 /* copy last parameter to the return value. we are using a flat
5333 * buffer so there is no danger of leaking memory in
5334 * elemdescFunc */
5335 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5337 /* remove the last parameter */
5338 dest->cParams--;
5340 else
5341 /* otherwise this function is made to appear to have no return
5342 * value */
5343 dest->elemdescFunc.tdesc.vt = VT_VOID;
5347 *dest_ptr = dest;
5348 return S_OK;
5351 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5353 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5355 if (index >= This->TypeAttr.cFuncs)
5356 return TYPE_E_ELEMENTNOTFOUND;
5358 *ppFuncDesc = &This->funcdescs[index].funcdesc;
5359 return S_OK;
5362 /* internal function to make the inherited interfaces' methods appear
5363 * part of the interface */
5364 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5365 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5367 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5368 HRESULT hr;
5369 UINT implemented_funcs = 0;
5371 if (funcs)
5372 *funcs = 0;
5373 else
5374 *hrefoffset = DISPATCH_HREF_OFFSET;
5376 if(This->impltypes)
5378 ITypeInfo *pSubTypeInfo;
5379 UINT sub_funcs;
5381 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5382 if (FAILED(hr))
5383 return hr;
5385 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5386 index,
5387 ppFuncDesc,
5388 &sub_funcs, hrefoffset);
5389 implemented_funcs += sub_funcs;
5390 ITypeInfo_Release(pSubTypeInfo);
5391 if (SUCCEEDED(hr))
5392 return hr;
5393 *hrefoffset += DISPATCH_HREF_OFFSET;
5396 if (funcs)
5397 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
5398 else
5399 *hrefoffset = 0;
5401 if (index < implemented_funcs)
5402 return E_INVALIDARG;
5403 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5404 ppFuncDesc);
5407 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5409 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5410 while (TRUE)
5412 switch (pTypeDesc->vt)
5414 case VT_USERDEFINED:
5415 pTypeDesc->u.hreftype += hrefoffset;
5416 return;
5417 case VT_PTR:
5418 case VT_SAFEARRAY:
5419 pTypeDesc = pTypeDesc->u.lptdesc;
5420 break;
5421 case VT_CARRAY:
5422 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5423 break;
5424 default:
5425 return;
5430 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5432 SHORT i;
5433 for (i = 0; i < pFuncDesc->cParams; i++)
5434 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5435 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5438 /* ITypeInfo::GetFuncDesc
5440 * Retrieves the FUNCDESC structure that contains information about a
5441 * specified function.
5444 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5445 LPFUNCDESC *ppFuncDesc)
5447 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5448 const FUNCDESC *internal_funcdesc;
5449 HRESULT hr;
5450 UINT hrefoffset = 0;
5452 TRACE("(%p) index %d\n", This, index);
5454 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5455 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5456 &internal_funcdesc, NULL,
5457 &hrefoffset);
5458 else
5459 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5460 &internal_funcdesc);
5461 if (FAILED(hr))
5463 WARN("description for function %d not found\n", index);
5464 return hr;
5467 hr = TLB_AllocAndInitFuncDesc(
5468 internal_funcdesc,
5469 ppFuncDesc,
5470 This->TypeAttr.typekind == TKIND_DISPATCH);
5472 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5473 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5475 TRACE("-- 0x%08x\n", hr);
5476 return hr;
5479 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5481 VARDESC *dest;
5482 char *buffer;
5483 SIZE_T size = sizeof(*src);
5484 HRESULT hr;
5486 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5487 if (src->varkind == VAR_CONST)
5488 size += sizeof(VARIANT);
5489 size += TLB_SizeElemDesc(&src->elemdescVar);
5491 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5492 if (!dest) return E_OUTOFMEMORY;
5494 *dest = *src;
5495 buffer = (char *)(dest + 1);
5496 if (src->lpstrSchema)
5498 int len;
5499 dest->lpstrSchema = (LPOLESTR)buffer;
5500 len = strlenW(src->lpstrSchema);
5501 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5502 buffer += (len + 1) * sizeof(WCHAR);
5505 if (src->varkind == VAR_CONST)
5507 HRESULT hr;
5509 dest->u.lpvarValue = (VARIANT *)buffer;
5510 *dest->u.lpvarValue = *src->u.lpvarValue;
5511 buffer += sizeof(VARIANT);
5512 VariantInit(dest->u.lpvarValue);
5513 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5514 if (FAILED(hr))
5516 SysFreeString((BSTR)dest);
5517 return hr;
5520 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5521 if (FAILED(hr))
5523 if (src->varkind == VAR_CONST)
5524 VariantClear(dest->u.lpvarValue);
5525 SysFreeString((BSTR)dest);
5526 return hr;
5528 *dest_ptr = dest;
5529 return S_OK;
5532 /* ITypeInfo::GetVarDesc
5534 * Retrieves a VARDESC structure that describes the specified variable.
5537 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5538 LPVARDESC *ppVarDesc)
5540 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5541 const TLBVarDesc *pVDesc = &This->vardescs[index];
5543 TRACE("(%p) index %d\n", This, index);
5545 if(index >= This->TypeAttr.cVars)
5546 return TYPE_E_ELEMENTNOTFOUND;
5548 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5551 /* ITypeInfo_GetNames
5553 * Retrieves the variable with the specified member ID (or the name of the
5554 * property or method and its parameters) that correspond to the specified
5555 * function ID.
5557 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5558 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5560 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5561 const TLBFuncDesc *pFDesc;
5562 const TLBVarDesc *pVDesc;
5563 int i;
5564 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5565 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
5566 if(pFDesc)
5568 /* function found, now return function and parameter names */
5569 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5571 if(!i)
5572 *rgBstrNames=SysAllocString(pFDesc->Name);
5573 else
5574 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5576 *pcNames=i;
5578 else
5580 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
5581 if(pVDesc)
5583 *rgBstrNames=SysAllocString(pVDesc->Name);
5584 *pcNames=1;
5586 else
5588 if(This->impltypes &&
5589 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5590 /* recursive search */
5591 ITypeInfo *pTInfo;
5592 HRESULT result;
5593 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef,
5594 &pTInfo);
5595 if(SUCCEEDED(result))
5597 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5598 ITypeInfo_Release(pTInfo);
5599 return result;
5601 WARN("Could not search inherited interface!\n");
5603 else
5605 WARN("no names found\n");
5607 *pcNames=0;
5608 return TYPE_E_ELEMENTNOTFOUND;
5611 return S_OK;
5615 /* ITypeInfo::GetRefTypeOfImplType
5617 * If a type description describes a COM class, it retrieves the type
5618 * description of the implemented interface types. For an interface,
5619 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5620 * if any exist.
5623 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5624 ITypeInfo2 *iface,
5625 UINT index,
5626 HREFTYPE *pRefType)
5628 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5629 HRESULT hr = S_OK;
5631 TRACE("(%p) index %d\n", This, index);
5632 if (TRACE_ON(ole)) dump_TypeInfo(This);
5634 if(index==(UINT)-1)
5636 /* only valid on dual interfaces;
5637 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5639 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5641 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
5643 *pRefType = -1;
5645 else
5647 hr = TYPE_E_ELEMENTNOTFOUND;
5650 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5652 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5653 *pRefType = This->pTypeLib->dispatch_href;
5655 else
5657 if(index >= This->TypeAttr.cImplTypes)
5658 hr = TYPE_E_ELEMENTNOTFOUND;
5659 else
5660 *pRefType = This->impltypes[index].hRef;
5663 if(TRACE_ON(ole))
5665 if(SUCCEEDED(hr))
5666 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5667 else
5668 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5671 return hr;
5674 /* ITypeInfo::GetImplTypeFlags
5676 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5677 * or base interface in a type description.
5679 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5680 UINT index, INT *pImplTypeFlags)
5682 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5684 TRACE("(%p) index %d\n", This, index);
5686 if(This->TypeAttr.typekind == TKIND_DISPATCH && index == 0){
5687 *pImplTypeFlags = 0;
5688 return S_OK;
5691 if(index >= This->TypeAttr.cImplTypes)
5692 return TYPE_E_ELEMENTNOTFOUND;
5694 *pImplTypeFlags = This->impltypes[index].implflags;
5696 return S_OK;
5699 /* GetIDsOfNames
5700 * Maps between member names and member IDs, and parameter names and
5701 * parameter IDs.
5703 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5704 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5706 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5707 const TLBVarDesc *pVDesc;
5708 HRESULT ret=S_OK;
5709 UINT i, fdc;
5711 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5712 cNames);
5714 /* init out parameters in case of failure */
5715 for (i = 0; i < cNames; i++)
5716 pMemId[i] = MEMBERID_NIL;
5718 for (fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc) {
5719 int j;
5720 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
5721 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5722 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5723 for(i=1; i < cNames; i++){
5724 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5725 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5726 break;
5727 if( j<pFDesc->funcdesc.cParams)
5728 pMemId[i]=j;
5729 else
5730 ret=DISP_E_UNKNOWNNAME;
5732 TRACE("-- 0x%08x\n", ret);
5733 return ret;
5736 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->TypeAttr.cVars, *rgszNames);
5737 if(pVDesc){
5738 if(cNames)
5739 *pMemId = pVDesc->vardesc.memid;
5740 return ret;
5742 /* not found, see if it can be found in an inherited interface */
5743 if(This->impltypes) {
5744 /* recursive search */
5745 ITypeInfo *pTInfo;
5746 ret=ITypeInfo_GetRefTypeInfo(iface,
5747 This->impltypes[0].hRef, &pTInfo);
5748 if(SUCCEEDED(ret)){
5749 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5750 ITypeInfo_Release(pTInfo);
5751 return ret;
5753 WARN("Could not search inherited interface!\n");
5754 } else
5755 WARN("no names found\n");
5756 return DISP_E_UNKNOWNNAME;
5760 #ifdef __i386__
5762 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
5763 __ASM_GLOBAL_FUNC( call_method,
5764 "pushl %ebp\n\t"
5765 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
5766 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
5767 "movl %esp,%ebp\n\t"
5768 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
5769 "pushl %esi\n\t"
5770 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
5771 "pushl %edi\n\t"
5772 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
5773 "movl 12(%ebp),%edx\n\t"
5774 "movl %esp,%edi\n\t"
5775 "shll $2,%edx\n\t"
5776 "jz 1f\n\t"
5777 "subl %edx,%edi\n\t"
5778 "andl $~15,%edi\n\t"
5779 "movl %edi,%esp\n\t"
5780 "movl 12(%ebp),%ecx\n\t"
5781 "movl 16(%ebp),%esi\n\t"
5782 "cld\n\t"
5783 "rep; movsl\n"
5784 "1:\tcall *8(%ebp)\n\t"
5785 "subl %esp,%edi\n\t"
5786 "movl 20(%ebp),%ecx\n\t"
5787 "movl %edi,(%ecx)\n\t"
5788 "leal -8(%ebp),%esp\n\t"
5789 "popl %edi\n\t"
5790 __ASM_CFI(".cfi_same_value %edi\n\t")
5791 "popl %esi\n\t"
5792 __ASM_CFI(".cfi_same_value %esi\n\t")
5793 "popl %ebp\n\t"
5794 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
5795 __ASM_CFI(".cfi_same_value %ebp\n\t")
5796 "ret" )
5798 /* same function but returning floating point */
5799 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
5801 /* ITypeInfo::Invoke
5803 * Invokes a method, or accesses a property of an object, that implements the
5804 * interface described by the type description.
5806 DWORD
5807 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5808 DWORD res;
5809 int stack_offset;
5811 if (TRACE_ON(ole)) {
5812 int i;
5813 TRACE("Calling %p(",func);
5814 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
5815 if (nrargs > 30) TRACE("...");
5816 TRACE(")\n");
5819 switch (callconv) {
5820 case CC_STDCALL:
5821 case CC_CDECL:
5822 res = call_method( func, nrargs, args, &stack_offset );
5823 break;
5824 default:
5825 FIXME("unsupported calling convention %d\n",callconv);
5826 res = -1;
5827 break;
5829 TRACE("returns %08x\n",res);
5830 return res;
5833 #elif defined(__x86_64__)
5835 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
5836 __ASM_GLOBAL_FUNC( call_method,
5837 "pushq %rbp\n\t"
5838 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
5839 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
5840 "movq %rsp,%rbp\n\t"
5841 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
5842 "pushq %rsi\n\t"
5843 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
5844 "pushq %rdi\n\t"
5845 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
5846 "movq %rcx,%rax\n\t"
5847 "movq $4,%rcx\n\t"
5848 "cmp %rcx,%rdx\n\t"
5849 "cmovgq %rdx,%rcx\n\t"
5850 "leaq 0(,%rcx,8),%rdx\n\t"
5851 "subq %rdx,%rsp\n\t"
5852 "andq $~15,%rsp\n\t"
5853 "movq %rsp,%rdi\n\t"
5854 "movq %r8,%rsi\n\t"
5855 "rep; movsq\n\t"
5856 "movq 0(%rsp),%rcx\n\t"
5857 "movq 8(%rsp),%rdx\n\t"
5858 "movq 16(%rsp),%r8\n\t"
5859 "movq 24(%rsp),%r9\n\t"
5860 "movq %rcx,%xmm0\n\t"
5861 "movq %rdx,%xmm1\n\t"
5862 "movq %r8,%xmm2\n\t"
5863 "movq %r9,%xmm3\n\t"
5864 "callq *%rax\n\t"
5865 "leaq -16(%rbp),%rsp\n\t"
5866 "popq %rdi\n\t"
5867 __ASM_CFI(".cfi_same_value %rdi\n\t")
5868 "popq %rsi\n\t"
5869 __ASM_CFI(".cfi_same_value %rsi\n\t")
5870 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
5871 "popq %rbp\n\t"
5872 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
5873 __ASM_CFI(".cfi_same_value %rbp\n\t")
5874 "ret")
5876 /* same function but returning floating point */
5877 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
5879 #endif /* __x86_64__ */
5881 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5883 HRESULT hr = S_OK;
5884 ITypeInfo *tinfo2 = NULL;
5885 TYPEATTR *tattr = NULL;
5887 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5888 if (hr)
5890 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5891 "hr = 0x%08x\n",
5892 tdesc->u.hreftype, hr);
5893 return hr;
5895 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5896 if (hr)
5898 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5899 ITypeInfo_Release(tinfo2);
5900 return hr;
5903 switch (tattr->typekind)
5905 case TKIND_ENUM:
5906 *vt |= VT_I4;
5907 break;
5909 case TKIND_ALIAS:
5910 tdesc = &tattr->tdescAlias;
5911 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5912 break;
5914 case TKIND_INTERFACE:
5915 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5916 *vt |= VT_DISPATCH;
5917 else
5918 *vt |= VT_UNKNOWN;
5919 break;
5921 case TKIND_DISPATCH:
5922 *vt |= VT_DISPATCH;
5923 break;
5925 case TKIND_COCLASS:
5926 *vt |= VT_DISPATCH;
5927 break;
5929 case TKIND_RECORD:
5930 FIXME("TKIND_RECORD unhandled.\n");
5931 hr = E_NOTIMPL;
5932 break;
5934 case TKIND_UNION:
5935 FIXME("TKIND_UNION unhandled.\n");
5936 hr = E_NOTIMPL;
5937 break;
5939 default:
5940 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5941 hr = E_NOTIMPL;
5942 break;
5944 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5945 ITypeInfo_Release(tinfo2);
5946 return hr;
5949 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5951 HRESULT hr = S_OK;
5953 /* enforce only one level of pointer indirection */
5954 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5956 tdesc = tdesc->u.lptdesc;
5958 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5959 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5960 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5961 if ((tdesc->vt == VT_USERDEFINED) ||
5962 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5964 VARTYPE vt_userdefined = 0;
5965 const TYPEDESC *tdesc_userdefined = tdesc;
5966 if (tdesc->vt == VT_PTR)
5968 vt_userdefined = VT_BYREF;
5969 tdesc_userdefined = tdesc->u.lptdesc;
5971 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5972 if ((hr == S_OK) &&
5973 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5974 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5976 *vt |= vt_userdefined;
5977 return S_OK;
5980 *vt = VT_BYREF;
5983 switch (tdesc->vt)
5985 case VT_HRESULT:
5986 *vt |= VT_ERROR;
5987 break;
5988 case VT_USERDEFINED:
5989 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5990 break;
5991 case VT_VOID:
5992 case VT_CARRAY:
5993 case VT_PTR:
5994 case VT_LPSTR:
5995 case VT_LPWSTR:
5996 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5997 hr = DISP_E_BADVARTYPE;
5998 break;
5999 case VT_SAFEARRAY:
6000 *vt |= VT_ARRAY;
6001 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
6002 break;
6003 case VT_INT:
6004 *vt |= VT_I4;
6005 break;
6006 case VT_UINT:
6007 *vt |= VT_UI4;
6008 break;
6009 default:
6010 *vt |= tdesc->vt;
6011 break;
6013 return hr;
6016 /***********************************************************************
6017 * DispCallFunc (OLEAUT32.@)
6019 * Invokes a function of the specified calling convention, passing the
6020 * specified arguments and returns the result.
6022 * PARAMS
6023 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6024 * oVft [I] The offset in the vtable. See notes.
6025 * cc [I] Calling convention of the function to call.
6026 * vtReturn [I] The return type of the function.
6027 * cActuals [I] Number of parameters.
6028 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6029 * prgpvarg [I] The arguments to pass.
6030 * pvargResult [O] The return value of the function. Can be NULL.
6032 * RETURNS
6033 * Success: S_OK.
6034 * Failure: HRESULT code.
6036 * NOTES
6037 * The HRESULT return value of this function is not affected by the return
6038 * value of the user supplied function, which is returned in pvargResult.
6040 * If pvInstance is NULL then a non-object function is to be called and oVft
6041 * is the address of the function to call.
6043 * The cc parameter can be one of the following values:
6044 *|CC_FASTCALL
6045 *|CC_CDECL
6046 *|CC_PASCAL
6047 *|CC_STDCALL
6048 *|CC_FPFASTCALL
6049 *|CC_SYSCALL
6050 *|CC_MPWCDECL
6051 *|CC_MPWPASCAL
6054 HRESULT WINAPI
6055 DispCallFunc(
6056 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
6057 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
6059 #ifdef __i386__
6060 int argspos, stack_offset;
6061 void *func;
6062 UINT i;
6063 DWORD *args;
6065 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6066 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6067 pvargResult, V_VT(pvargResult));
6069 if (cc != CC_STDCALL && cc != CC_CDECL)
6071 FIXME("unsupported calling convention %d\n",cc);
6072 return E_INVALIDARG;
6075 /* maximum size for an argument is sizeof(VARIANT) */
6076 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6078 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6079 argspos = 1;
6080 if (pvInstance)
6082 const FARPROC *vtable = *(FARPROC **)pvInstance;
6083 func = vtable[oVft/sizeof(void *)];
6084 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6086 else func = (void *)oVft;
6088 for (i = 0; i < cActuals; i++)
6090 VARIANT *arg = prgpvarg[i];
6092 switch (prgvt[i])
6094 case VT_EMPTY:
6095 break;
6096 case VT_I8:
6097 case VT_UI8:
6098 case VT_R8:
6099 case VT_DATE:
6100 case VT_CY:
6101 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6102 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6103 break;
6104 case VT_DECIMAL:
6105 case VT_VARIANT:
6106 memcpy( &args[argspos], arg, sizeof(*arg) );
6107 argspos += sizeof(*arg) / sizeof(DWORD);
6108 break;
6109 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6110 args[argspos++] = V_BOOL(arg);
6111 break;
6112 default:
6113 args[argspos++] = V_UI4(arg);
6114 break;
6116 TRACE("arg %u: type %d\n",i,prgvt[i]);
6117 dump_Variant(arg);
6120 switch (vtReturn)
6122 case VT_EMPTY:
6123 call_method( func, argspos - 1, args + 1, &stack_offset );
6124 break;
6125 case VT_R4:
6126 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6127 break;
6128 case VT_R8:
6129 case VT_DATE:
6130 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6131 break;
6132 case VT_DECIMAL:
6133 case VT_VARIANT:
6134 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6135 call_method( func, argspos, args, &stack_offset );
6136 break;
6137 case VT_I8:
6138 case VT_UI8:
6139 case VT_CY:
6140 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6141 break;
6142 default:
6143 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6144 break;
6146 heap_free( args );
6147 if (stack_offset && cc == CC_STDCALL)
6149 WARN( "stack pointer off by %d\n", stack_offset );
6150 return DISP_E_BADCALLEE;
6152 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6153 TRACE("retval: "); dump_Variant(pvargResult);
6154 return S_OK;
6156 #elif defined(__x86_64__)
6157 int argspos;
6158 UINT i;
6159 DWORD_PTR *args;
6160 void *func;
6162 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6163 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6164 pvargResult, V_VT(pvargResult));
6166 if (cc != CC_STDCALL && cc != CC_CDECL)
6168 FIXME("unsupported calling convention %d\n",cc);
6169 return E_INVALIDARG;
6172 /* maximum size for an argument is sizeof(DWORD_PTR) */
6173 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6175 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6176 argspos = 1;
6177 if (pvInstance)
6179 const FARPROC *vtable = *(FARPROC **)pvInstance;
6180 func = vtable[oVft/sizeof(void *)];
6181 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6183 else func = (void *)oVft;
6185 for (i = 0; i < cActuals; i++)
6187 VARIANT *arg = prgpvarg[i];
6189 switch (prgvt[i])
6191 case VT_DECIMAL:
6192 case VT_VARIANT:
6193 args[argspos++] = (ULONG_PTR)arg;
6194 break;
6195 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6196 args[argspos++] = V_BOOL(arg);
6197 break;
6198 default:
6199 args[argspos++] = V_UI8(arg);
6200 break;
6202 TRACE("arg %u: type %d\n",i,prgvt[i]);
6203 dump_Variant(arg);
6206 switch (vtReturn)
6208 case VT_R4:
6209 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6210 break;
6211 case VT_R8:
6212 case VT_DATE:
6213 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6214 break;
6215 case VT_DECIMAL:
6216 case VT_VARIANT:
6217 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6218 call_method( func, argspos, args );
6219 break;
6220 default:
6221 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6222 break;
6224 heap_free( args );
6225 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6226 TRACE("retval: "); dump_Variant(pvargResult);
6227 return S_OK;
6229 #else
6230 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6231 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6232 return E_NOTIMPL;
6233 #endif
6236 #define INVBUF_ELEMENT_SIZE \
6237 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6238 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6239 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6240 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6241 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6242 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6243 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6244 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6246 static HRESULT WINAPI ITypeInfo_fnInvoke(
6247 ITypeInfo2 *iface,
6248 VOID *pIUnk,
6249 MEMBERID memid,
6250 UINT16 wFlags,
6251 DISPPARAMS *pDispParams,
6252 VARIANT *pVarResult,
6253 EXCEPINFO *pExcepInfo,
6254 UINT *pArgErr)
6256 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6257 int i;
6258 unsigned int var_index;
6259 TYPEKIND type_kind;
6260 HRESULT hres;
6261 const TLBFuncDesc *pFuncInfo;
6262 UINT fdc;
6264 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6265 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6268 if( This->TypeAttr.wTypeFlags & TYPEFLAG_FRESTRICTED )
6269 return DISP_E_MEMBERNOTFOUND;
6271 if (!pDispParams)
6273 ERR("NULL pDispParams not allowed\n");
6274 return E_INVALIDARG;
6277 dump_DispParms(pDispParams);
6279 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6281 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6282 pDispParams->cNamedArgs, pDispParams->cArgs);
6283 return E_INVALIDARG;
6286 /* we do this instead of using GetFuncDesc since it will return a fake
6287 * FUNCDESC for dispinterfaces and we want the real function description */
6288 for (fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc){
6289 pFuncInfo = &This->funcdescs[fdc];
6290 if ((memid == pFuncInfo->funcdesc.memid) &&
6291 (wFlags & pFuncInfo->funcdesc.invkind) &&
6292 (pFuncInfo->funcdesc.wFuncFlags & FUNCFLAG_FRESTRICTED) == 0)
6293 break;
6296 if (fdc < This->TypeAttr.cFuncs) {
6297 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6299 if (TRACE_ON(ole))
6301 TRACE("invoking:\n");
6302 dump_TLBFuncDescOne(pFuncInfo);
6305 switch (func_desc->funckind) {
6306 case FUNC_PUREVIRTUAL:
6307 case FUNC_VIRTUAL: {
6308 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
6309 VARIANT varresult;
6310 VARIANT retval; /* pointer for storing byref retvals in */
6311 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6312 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6313 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6314 UINT cNamedArgs = pDispParams->cNamedArgs;
6315 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6316 UINT vargs_converted=0;
6318 hres = S_OK;
6320 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6322 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6324 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6325 hres = DISP_E_PARAMNOTFOUND;
6326 goto func_fail;
6330 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6332 ERR("functions with the vararg attribute do not support named arguments\n");
6333 hres = DISP_E_NONAMEDARGS;
6334 goto func_fail;
6337 for (i = 0; i < func_desc->cParams; i++)
6339 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6340 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6341 if (FAILED(hres))
6342 goto func_fail;
6345 TRACE("changing args\n");
6346 for (i = 0; i < func_desc->cParams; i++)
6348 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6349 VARIANTARG *src_arg;
6351 if (wParamFlags & PARAMFLAG_FLCID)
6353 VARIANTARG *arg;
6354 arg = prgpvarg[i] = &rgvarg[i];
6355 V_VT(arg) = VT_I4;
6356 V_I4(arg) = This->pTypeLib->lcid;
6357 continue;
6360 src_arg = NULL;
6362 if (cNamedArgs)
6364 USHORT j;
6365 for (j = 0; j < cNamedArgs; j++)
6366 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
6368 src_arg = &pDispParams->rgvarg[j];
6369 break;
6373 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
6375 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6376 vargs_converted++;
6379 if (wParamFlags & PARAMFLAG_FRETVAL)
6381 /* under most conditions the caller is not allowed to
6382 * pass in a dispparam arg in the index of what would be
6383 * the retval parameter. however, there is an exception
6384 * where the extra parameter is used in an extra
6385 * IDispatch::Invoke below */
6386 if ((i < pDispParams->cArgs) &&
6387 ((func_desc->cParams != 1) || !pVarResult ||
6388 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6390 hres = DISP_E_BADPARAMCOUNT;
6391 break;
6394 /* note: this check is placed so that if the caller passes
6395 * in a VARIANTARG for the retval we just ignore it, like
6396 * native does */
6397 if (i == func_desc->cParams - 1)
6399 VARIANTARG *arg;
6400 arg = prgpvarg[i] = &rgvarg[i];
6401 memset(arg, 0, sizeof(*arg));
6402 V_VT(arg) = rgvt[i];
6403 memset(&retval, 0, sizeof(retval));
6404 V_BYREF(arg) = &retval;
6406 else
6408 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6409 hres = E_UNEXPECTED;
6410 break;
6413 else if (src_arg)
6415 dump_Variant(src_arg);
6417 if (rgvt[i] == VT_VARIANT)
6418 hres = VariantCopy(&rgvarg[i], src_arg);
6419 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6421 if (rgvt[i] == V_VT(src_arg))
6422 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6423 else
6425 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6426 if (wParamFlags & PARAMFLAG_FIN)
6427 hres = VariantCopy(&missing_arg[i], src_arg);
6428 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6430 V_VT(&rgvarg[i]) = rgvt[i];
6432 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6434 SAFEARRAY *a;
6435 SAFEARRAYBOUND bound;
6436 VARIANT *v;
6437 LONG j;
6438 bound.lLbound = 0;
6439 bound.cElements = pDispParams->cArgs-i;
6440 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6442 ERR("SafeArrayCreate failed\n");
6443 break;
6445 hres = SafeArrayAccessData(a, (LPVOID)&v);
6446 if (hres != S_OK)
6448 ERR("SafeArrayAccessData failed with %x\n", hres);
6449 break;
6451 for (j = 0; j < bound.cElements; j++)
6452 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6453 hres = SafeArrayUnaccessData(a);
6454 if (hres != S_OK)
6456 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6457 break;
6459 V_ARRAY(&rgvarg[i]) = a;
6460 V_VT(&rgvarg[i]) = rgvt[i];
6462 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6464 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6465 if (wParamFlags & PARAMFLAG_FIN)
6466 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6467 else
6468 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
6469 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6470 V_VT(&rgvarg[i]) = rgvt[i];
6472 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6474 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6475 V_VT(&rgvarg[i]) = rgvt[i];
6477 else
6479 /* FIXME: this doesn't work for VT_BYREF arguments if
6480 * they are not the same type as in the paramdesc */
6481 V_VT(&rgvarg[i]) = V_VT(src_arg);
6482 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6483 V_VT(&rgvarg[i]) = rgvt[i];
6486 if (FAILED(hres))
6488 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6489 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6490 debugstr_VT(src_arg), debugstr_VF(src_arg));
6491 break;
6493 prgpvarg[i] = &rgvarg[i];
6495 else if (wParamFlags & PARAMFLAG_FOPT)
6497 VARIANTARG *arg;
6498 arg = prgpvarg[i] = &rgvarg[i];
6499 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6501 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6502 if (FAILED(hres))
6503 break;
6505 else
6507 VARIANTARG *missing_arg;
6508 /* if the function wants a pointer to a variant then
6509 * set that up, otherwise just pass the VT_ERROR in
6510 * the argument by value */
6511 if (rgvt[i] & VT_BYREF)
6513 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6514 V_VT(arg) = VT_VARIANT | VT_BYREF;
6515 V_VARIANTREF(arg) = missing_arg;
6517 else
6518 missing_arg = arg;
6519 V_VT(missing_arg) = VT_ERROR;
6520 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6523 else
6525 hres = DISP_E_BADPARAMCOUNT;
6526 break;
6529 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6531 /* VT_VOID is a special case for return types, so it is not
6532 * handled in the general function */
6533 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6534 V_VT(&varresult) = VT_EMPTY;
6535 else
6537 V_VT(&varresult) = 0;
6538 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6539 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6542 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6543 V_VT(&varresult), func_desc->cParams, rgvt,
6544 prgpvarg, &varresult);
6546 vargs_converted = 0;
6548 for (i = 0; i < func_desc->cParams; i++)
6550 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6551 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6553 if (wParamFlags & PARAMFLAG_FLCID)
6554 continue;
6555 else if (wParamFlags & PARAMFLAG_FRETVAL)
6557 if (TRACE_ON(ole))
6559 TRACE("[retval] value: ");
6560 dump_Variant(prgpvarg[i]);
6563 if (pVarResult)
6565 VariantInit(pVarResult);
6566 /* deref return value */
6567 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6570 VARIANT_ClearInd(prgpvarg[i]);
6572 else if (vargs_converted < pDispParams->cArgs)
6574 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6575 if (wParamFlags & PARAMFLAG_FOUT)
6577 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
6579 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6581 if (FAILED(hres))
6583 ERR("failed to convert param %d to vt %d\n", i,
6584 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
6585 break;
6589 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6590 func_desc->cParamsOpt < 0 &&
6591 i == func_desc->cParams-1)
6593 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6594 LONG j, ubound;
6595 VARIANT *v;
6596 hres = SafeArrayGetUBound(a, 1, &ubound);
6597 if (hres != S_OK)
6599 ERR("SafeArrayGetUBound failed with %x\n", hres);
6600 break;
6602 hres = SafeArrayAccessData(a, (LPVOID)&v);
6603 if (hres != S_OK)
6605 ERR("SafeArrayAccessData failed with %x\n", hres);
6606 break;
6608 for (j = 0; j <= ubound; j++)
6609 VariantClear(&v[j]);
6610 hres = SafeArrayUnaccessData(a);
6611 if (hres != S_OK)
6613 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6614 break;
6617 VariantClear(&rgvarg[i]);
6618 vargs_converted++;
6620 else if (wParamFlags & PARAMFLAG_FOPT)
6622 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6623 VariantClear(&rgvarg[i]);
6626 VariantClear(&missing_arg[i]);
6629 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6631 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6632 hres = DISP_E_EXCEPTION;
6633 if (pExcepInfo)
6635 IErrorInfo *pErrorInfo;
6636 pExcepInfo->scode = V_ERROR(&varresult);
6637 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6639 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6640 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6641 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6642 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6644 IErrorInfo_Release(pErrorInfo);
6648 if (V_VT(&varresult) != VT_ERROR)
6650 TRACE("varresult value: ");
6651 dump_Variant(&varresult);
6653 if (pVarResult)
6655 VariantClear(pVarResult);
6656 *pVarResult = varresult;
6658 else
6659 VariantClear(&varresult);
6662 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6663 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6664 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6665 (pDispParams->cArgs != 0))
6667 if (V_VT(pVarResult) == VT_DISPATCH)
6669 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6670 /* Note: not VariantClear; we still need the dispatch
6671 * pointer to be valid */
6672 VariantInit(pVarResult);
6673 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6674 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6675 pDispParams, pVarResult, pExcepInfo, pArgErr);
6676 IDispatch_Release(pDispatch);
6678 else
6680 VariantClear(pVarResult);
6681 hres = DISP_E_NOTACOLLECTION;
6685 func_fail:
6686 heap_free(buffer);
6687 break;
6689 case FUNC_DISPATCH: {
6690 IDispatch *disp;
6692 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6693 if (SUCCEEDED(hres)) {
6694 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6695 hres = IDispatch_Invoke(
6696 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6697 pVarResult,pExcepInfo,pArgErr
6699 if (FAILED(hres))
6700 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6701 IDispatch_Release(disp);
6702 } else
6703 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6704 break;
6706 default:
6707 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6708 hres = E_FAIL;
6709 break;
6712 TRACE("-- 0x%08x\n", hres);
6713 return hres;
6715 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6716 VARDESC *var_desc;
6718 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6719 if(FAILED(hres)) return hres;
6721 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6722 dump_VARDESC(var_desc);
6723 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6724 return E_NOTIMPL;
6727 /* not found, look for it in inherited interfaces */
6728 ITypeInfo2_GetTypeKind(iface, &type_kind);
6729 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6730 if(This->impltypes) {
6731 /* recursive search */
6732 ITypeInfo *pTInfo;
6733 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6734 if(SUCCEEDED(hres)){
6735 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6736 ITypeInfo_Release(pTInfo);
6737 return hres;
6739 WARN("Could not search inherited interface!\n");
6742 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6743 return DISP_E_MEMBERNOTFOUND;
6746 /* ITypeInfo::GetDocumentation
6748 * Retrieves the documentation string, the complete Help file name and path,
6749 * and the context ID for the Help topic for a specified type description.
6751 * (Can be tested by the Visual Basic Editor in Word for instance.)
6753 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6754 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6755 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6757 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6758 const TLBFuncDesc *pFDesc;
6759 const TLBVarDesc *pVDesc;
6760 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6761 " HelpContext(%p) HelpFile(%p)\n",
6762 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6763 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6764 if(pBstrName)
6765 *pBstrName=SysAllocString(This->Name);
6766 if(pBstrDocString)
6767 *pBstrDocString=SysAllocString(This->DocString);
6768 if(pdwHelpContext)
6769 *pdwHelpContext=This->dwHelpContext;
6770 if(pBstrHelpFile)
6771 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6772 return S_OK;
6773 }else {/* for a member */
6774 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
6775 if(pFDesc){
6776 if(pBstrName)
6777 *pBstrName = SysAllocString(pFDesc->Name);
6778 if(pBstrDocString)
6779 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6780 if(pdwHelpContext)
6781 *pdwHelpContext=pFDesc->helpcontext;
6782 return S_OK;
6784 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
6785 if(pVDesc){
6786 if(pBstrName)
6787 *pBstrName = SysAllocString(pVDesc->Name);
6788 if(pBstrDocString)
6789 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6790 if(pdwHelpContext)
6791 *pdwHelpContext=pVDesc->HelpContext;
6792 return S_OK;
6796 if(This->impltypes &&
6797 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6798 /* recursive search */
6799 ITypeInfo *pTInfo;
6800 HRESULT result;
6801 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef,
6802 &pTInfo);
6803 if(SUCCEEDED(result)) {
6804 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6805 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6806 ITypeInfo_Release(pTInfo);
6807 return result;
6809 WARN("Could not search inherited interface!\n");
6812 WARN("member %d not found\n", memid);
6813 return TYPE_E_ELEMENTNOTFOUND;
6816 /* ITypeInfo::GetDllEntry
6818 * Retrieves a description or specification of an entry point for a function
6819 * in a DLL.
6821 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6822 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6823 WORD *pwOrdinal)
6825 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6826 const TLBFuncDesc *pFDesc;
6828 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6830 if (pBstrDllName) *pBstrDllName = NULL;
6831 if (pBstrName) *pBstrName = NULL;
6832 if (pwOrdinal) *pwOrdinal = 0;
6834 if (This->TypeAttr.typekind != TKIND_MODULE)
6835 return TYPE_E_BADMODULEKIND;
6837 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
6838 if(pFDesc){
6839 dump_TypeInfo(This);
6840 if (TRACE_ON(ole))
6841 dump_TLBFuncDescOne(pFDesc);
6843 if (pBstrDllName)
6844 *pBstrDllName = SysAllocString(This->DllName);
6846 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6847 if (pBstrName)
6848 *pBstrName = SysAllocString(pFDesc->Entry);
6849 if (pwOrdinal)
6850 *pwOrdinal = -1;
6851 return S_OK;
6853 if (pBstrName)
6854 *pBstrName = NULL;
6855 if (pwOrdinal)
6856 *pwOrdinal = LOWORD(pFDesc->Entry);
6857 return S_OK;
6859 return TYPE_E_ELEMENTNOTFOUND;
6862 /* internal function to make the inherited interfaces' methods appear
6863 * part of the interface */
6864 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6865 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6867 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6868 HRESULT hr;
6870 TRACE("%p, 0x%x\n", iface, *hRefType);
6872 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
6874 ITypeInfo *pSubTypeInfo;
6876 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
6877 if (FAILED(hr))
6878 return hr;
6880 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6881 hRefType, ppTInfo);
6882 ITypeInfo_Release(pSubTypeInfo);
6883 if (SUCCEEDED(hr))
6884 return hr;
6886 *hRefType -= DISPATCH_HREF_OFFSET;
6888 if (!(*hRefType & DISPATCH_HREF_MASK))
6889 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6890 else
6891 return E_FAIL;
6894 /* ITypeInfo::GetRefTypeInfo
6896 * If a type description references other type descriptions, it retrieves
6897 * the referenced type descriptions.
6899 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6900 ITypeInfo2 *iface,
6901 HREFTYPE hRefType,
6902 ITypeInfo **ppTInfo)
6904 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6905 HRESULT result = E_FAIL;
6907 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6909 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6910 ITypeInfo_AddRef(*ppTInfo);
6911 result = S_OK;
6913 else if (hRefType == -1 &&
6914 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6915 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6917 /* when we meet a DUAL dispinterface, we must create the interface
6918 * version of it.
6920 ITypeInfoImpl *pTypeInfoImpl = ITypeInfoImpl_Constructor();
6923 /* the interface version contains the same information as the dispinterface
6924 * copy the contents of the structs.
6926 *pTypeInfoImpl = *This;
6927 pTypeInfoImpl->ref = 0;
6929 /* change the type to interface */
6930 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6932 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6934 /* the AddRef implicitly adds a reference to the parent typelib, which
6935 * stops the copied data from being destroyed until the new typeinfo's
6936 * refcount goes to zero, but we need to signal to the new instance to
6937 * not free its data structures when it is destroyed */
6938 pTypeInfoImpl->not_attached_to_typelib = TRUE;
6940 ITypeInfo_AddRef(*ppTInfo);
6942 result = S_OK;
6944 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6945 (This->TypeAttr.typekind == TKIND_DISPATCH))
6947 HREFTYPE href_dispatch = hRefType;
6948 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6949 } else {
6950 TLBRefType *ref_type;
6951 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6953 if(ref_type->reference == hRefType)
6954 break;
6956 if(&ref_type->entry == &This->pTypeLib->ref_list)
6958 FIXME("Can't find pRefType for ref %x\n", hRefType);
6959 goto end;
6961 if(hRefType != -1) {
6962 ITypeLib *pTLib = NULL;
6964 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6965 UINT Index;
6966 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6967 } else {
6968 if(ref_type->pImpTLInfo->pImpTypeLib) {
6969 TRACE("typeinfo in imported typelib that is already loaded\n");
6970 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6971 ITypeLib2_AddRef(pTLib);
6972 result = S_OK;
6973 } else {
6974 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6975 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6976 ref_type->pImpTLInfo->wVersionMajor,
6977 ref_type->pImpTLInfo->wVersionMinor,
6978 ref_type->pImpTLInfo->lcid,
6979 &pTLib);
6981 if(FAILED(result)) {
6982 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6983 result=LoadTypeLib(libnam, &pTLib);
6984 SysFreeString(libnam);
6986 if(SUCCEEDED(result)) {
6987 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6988 ITypeLib2_AddRef(pTLib);
6992 if(SUCCEEDED(result)) {
6993 if(ref_type->index == TLB_REF_USE_GUID)
6994 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6995 &ref_type->guid,
6996 ppTInfo);
6997 else
6998 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6999 ppTInfo);
7001 if (pTLib != NULL)
7002 ITypeLib2_Release(pTLib);
7006 end:
7007 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
7008 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
7009 return result;
7012 /* ITypeInfo::AddressOfMember
7014 * Retrieves the addresses of static functions or variables, such as those
7015 * defined in a DLL.
7017 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
7018 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
7020 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7021 HRESULT hr;
7022 BSTR dll, entry;
7023 WORD ordinal;
7024 HMODULE module;
7026 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
7028 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
7029 if (FAILED(hr))
7030 return hr;
7032 module = LoadLibraryW(dll);
7033 if (!module)
7035 ERR("couldn't load %s\n", debugstr_w(dll));
7036 SysFreeString(dll);
7037 SysFreeString(entry);
7038 return STG_E_FILENOTFOUND;
7040 /* FIXME: store library somewhere where we can free it */
7042 if (entry)
7044 LPSTR entryA;
7045 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
7046 entryA = heap_alloc(len);
7047 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
7049 *ppv = GetProcAddress(module, entryA);
7050 if (!*ppv)
7051 ERR("function not found %s\n", debugstr_a(entryA));
7053 heap_free(entryA);
7055 else
7057 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7058 if (!*ppv)
7059 ERR("function not found %d\n", ordinal);
7062 SysFreeString(dll);
7063 SysFreeString(entry);
7065 if (!*ppv)
7066 return TYPE_E_DLLFUNCTIONNOTFOUND;
7068 return S_OK;
7071 /* ITypeInfo::CreateInstance
7073 * Creates a new instance of a type that describes a component object class
7074 * (coclass).
7076 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7077 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7079 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7080 HRESULT hr;
7081 TYPEATTR *pTA;
7083 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7085 *ppvObj = NULL;
7087 if(pOuterUnk)
7089 WARN("Not able to aggregate\n");
7090 return CLASS_E_NOAGGREGATION;
7093 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
7094 if(FAILED(hr)) return hr;
7096 if(pTA->typekind != TKIND_COCLASS)
7098 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7099 hr = E_INVALIDARG;
7100 goto end;
7103 hr = S_FALSE;
7104 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7106 IUnknown *pUnk;
7107 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7108 TRACE("GetActiveObject rets %08x\n", hr);
7109 if(hr == S_OK)
7111 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7112 IUnknown_Release(pUnk);
7116 if(hr != S_OK)
7117 hr = CoCreateInstance(&pTA->guid, NULL,
7118 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7119 riid, ppvObj);
7121 end:
7122 ITypeInfo_ReleaseTypeAttr(iface, pTA);
7123 return hr;
7126 /* ITypeInfo::GetMops
7128 * Retrieves marshalling information.
7130 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7131 BSTR *pBstrMops)
7133 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7134 FIXME("(%p %d) stub!\n", This, memid);
7135 *pBstrMops = NULL;
7136 return S_OK;
7139 /* ITypeInfo::GetContainingTypeLib
7141 * Retrieves the containing type library and the index of the type description
7142 * within that type library.
7144 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7145 ITypeLib * *ppTLib, UINT *pIndex)
7147 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7149 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7150 if (pIndex) {
7151 *pIndex=This->index;
7152 TRACE("returning pIndex=%d\n", *pIndex);
7155 if (ppTLib) {
7156 *ppTLib=(LPTYPELIB )(This->pTypeLib);
7157 ITypeLib2_AddRef(*ppTLib);
7158 TRACE("returning ppTLib=%p\n", *ppTLib);
7161 return S_OK;
7164 /* ITypeInfo::ReleaseTypeAttr
7166 * Releases a TYPEATTR previously returned by GetTypeAttr.
7169 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7170 TYPEATTR* pTypeAttr)
7172 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7173 TRACE("(%p)->(%p)\n", This, pTypeAttr);
7174 heap_free(pTypeAttr);
7177 /* ITypeInfo::ReleaseFuncDesc
7179 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7181 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7182 ITypeInfo2 *iface,
7183 FUNCDESC *pFuncDesc)
7185 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7186 SHORT i;
7188 TRACE("(%p)->(%p)\n", This, pFuncDesc);
7190 for (i = 0; i < pFuncDesc->cParams; i++)
7191 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7192 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7194 SysFreeString((BSTR)pFuncDesc);
7197 /* ITypeInfo::ReleaseVarDesc
7199 * Releases a VARDESC previously returned by GetVarDesc.
7201 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7202 VARDESC *pVarDesc)
7204 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7205 TRACE("(%p)->(%p)\n", This, pVarDesc);
7207 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
7208 if (pVarDesc->varkind == VAR_CONST)
7209 VariantClear(pVarDesc->u.lpvarValue);
7210 SysFreeString((BSTR)pVarDesc);
7213 /* ITypeInfo2::GetTypeKind
7215 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7218 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7219 TYPEKIND *pTypeKind)
7221 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7222 *pTypeKind=This->TypeAttr.typekind;
7223 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7224 return S_OK;
7227 /* ITypeInfo2::GetTypeFlags
7229 * Returns the type flags without any allocations. This returns a DWORD type
7230 * flag, which expands the type flags without growing the TYPEATTR (type
7231 * attribute).
7234 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7236 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7237 *pTypeFlags=This->TypeAttr.wTypeFlags;
7238 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7239 return S_OK;
7242 /* ITypeInfo2::GetFuncIndexOfMemId
7243 * Binds to a specific member based on a known DISPID, where the member name
7244 * is not known (for example, when binding to a default member).
7247 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7248 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7250 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7251 UINT fdc;
7252 HRESULT result;
7254 for (fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc){
7255 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
7256 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7257 break;
7259 if(fdc < This->TypeAttr.cFuncs) {
7260 *pFuncIndex = fdc;
7261 result = S_OK;
7262 } else
7263 result = TYPE_E_ELEMENTNOTFOUND;
7265 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7266 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7267 return result;
7270 /* TypeInfo2::GetVarIndexOfMemId
7272 * Binds to a specific member based on a known DISPID, where the member name
7273 * is not known (for example, when binding to a default member).
7276 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7277 MEMBERID memid, UINT *pVarIndex)
7279 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7280 TLBVarDesc *pVarInfo;
7282 TRACE("%p %d %p\n", iface, memid, pVarIndex);
7284 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
7285 if(!pVarInfo)
7286 return TYPE_E_ELEMENTNOTFOUND;
7288 *pVarIndex = (pVarInfo - This->vardescs);
7290 return S_OK;
7293 /* ITypeInfo2::GetCustData
7295 * Gets the custom data
7297 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7298 ITypeInfo2 * iface,
7299 REFGUID guid,
7300 VARIANT *pVarVal)
7302 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7303 TLBCustData *pCData;
7305 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7307 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
7309 VariantInit( pVarVal);
7310 if (pCData)
7311 VariantCopy( pVarVal, &pCData->data);
7312 else
7313 VariantClear( pVarVal );
7314 return S_OK;
7317 /* ITypeInfo2::GetFuncCustData
7319 * Gets the custom data
7321 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7322 ITypeInfo2 * iface,
7323 UINT index,
7324 REFGUID guid,
7325 VARIANT *pVarVal)
7327 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7328 TLBCustData *pCData;
7329 TLBFuncDesc *pFDesc = &This->funcdescs[index];
7331 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
7333 if(index >= This->TypeAttr.cFuncs)
7334 return TYPE_E_ELEMENTNOTFOUND;
7336 pCData = TLB_get_custdata_by_guid(&pFDesc->custdata_list, guid);
7337 if(!pCData)
7338 return TYPE_E_ELEMENTNOTFOUND;
7340 VariantInit(pVarVal);
7341 VariantCopy(pVarVal, &pCData->data);
7343 return S_OK;
7346 /* ITypeInfo2::GetParamCustData
7348 * Gets the custom data
7350 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7351 ITypeInfo2 * iface,
7352 UINT indexFunc,
7353 UINT indexParam,
7354 REFGUID guid,
7355 VARIANT *pVarVal)
7357 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7358 TLBCustData *pCData;
7359 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
7361 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
7362 debugstr_guid(guid), pVarVal);
7364 if(indexFunc >= This->TypeAttr.cFuncs)
7365 return TYPE_E_ELEMENTNOTFOUND;
7367 if(indexParam >= pFDesc->funcdesc.cParams)
7368 return TYPE_E_ELEMENTNOTFOUND;
7370 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
7371 if(!pCData)
7372 return TYPE_E_ELEMENTNOTFOUND;
7374 VariantInit(pVarVal);
7375 VariantCopy(pVarVal, &pCData->data);
7377 return S_OK;
7380 /* ITypeInfo2::GetVarCustData
7382 * Gets the custom data
7384 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7385 ITypeInfo2 * iface,
7386 UINT index,
7387 REFGUID guid,
7388 VARIANT *pVarVal)
7390 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7391 TLBCustData *pCData;
7392 TLBVarDesc *pVDesc = &This->vardescs[index];
7394 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7396 if(index >= This->TypeAttr.cVars)
7397 return TYPE_E_ELEMENTNOTFOUND;
7399 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
7400 if(!pCData)
7401 return TYPE_E_ELEMENTNOTFOUND;
7403 VariantInit(pVarVal);
7404 VariantCopy(pVarVal, &pCData->data);
7406 return S_OK;
7409 /* ITypeInfo2::GetImplCustData
7411 * Gets the custom data
7413 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7414 ITypeInfo2 * iface,
7415 UINT index,
7416 REFGUID guid,
7417 VARIANT *pVarVal)
7419 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7420 TLBCustData *pCData;
7421 TLBImplType *pRDesc = &This->impltypes[index];
7423 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
7425 if(index >= This->TypeAttr.cImplTypes)
7426 return TYPE_E_ELEMENTNOTFOUND;
7428 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
7429 if(!pCData)
7430 return TYPE_E_ELEMENTNOTFOUND;
7432 VariantInit(pVarVal);
7433 VariantCopy(pVarVal, &pCData->data);
7435 return S_OK;
7438 /* ITypeInfo2::GetDocumentation2
7440 * Retrieves the documentation string, the complete Help file name and path,
7441 * the localization context to use, and the context ID for the library Help
7442 * topic in the Help file.
7445 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7446 ITypeInfo2 * iface,
7447 MEMBERID memid,
7448 LCID lcid,
7449 BSTR *pbstrHelpString,
7450 DWORD *pdwHelpStringContext,
7451 BSTR *pbstrHelpStringDll)
7453 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7454 const TLBFuncDesc *pFDesc;
7455 const TLBVarDesc *pVDesc;
7456 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7457 "HelpStringContext(%p) HelpStringDll(%p)\n",
7458 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7459 pbstrHelpStringDll );
7460 /* the help string should be obtained from the helpstringdll,
7461 * using the _DLLGetDocumentation function, based on the supplied
7462 * lcid. Nice to do sometime...
7464 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7465 if(pbstrHelpString)
7466 *pbstrHelpString=SysAllocString(This->Name);
7467 if(pdwHelpStringContext)
7468 *pdwHelpStringContext=This->dwHelpStringContext;
7469 if(pbstrHelpStringDll)
7470 *pbstrHelpStringDll=
7471 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7472 return S_OK;
7473 }else {/* for a member */
7474 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
7475 if(pFDesc){
7476 if(pbstrHelpString)
7477 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
7478 if(pdwHelpStringContext)
7479 *pdwHelpStringContext=pFDesc->HelpStringContext;
7480 if(pbstrHelpStringDll)
7481 *pbstrHelpStringDll=
7482 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7483 return S_OK;
7485 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
7486 if(pVDesc){
7487 if(pbstrHelpString)
7488 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
7489 if(pdwHelpStringContext)
7490 *pdwHelpStringContext=pVDesc->HelpStringContext;
7491 if(pbstrHelpStringDll)
7492 *pbstrHelpStringDll=
7493 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7494 return S_OK;
7497 return TYPE_E_ELEMENTNOTFOUND;
7500 /* ITypeInfo2::GetAllCustData
7502 * Gets all custom data items for the Type info.
7505 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7506 ITypeInfo2 * iface,
7507 CUSTDATA *pCustData)
7509 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7511 TRACE("%p %p\n", This, pCustData);
7513 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
7516 /* ITypeInfo2::GetAllFuncCustData
7518 * Gets all custom data items for the specified Function
7521 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7522 ITypeInfo2 * iface,
7523 UINT index,
7524 CUSTDATA *pCustData)
7526 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7527 TLBFuncDesc *pFDesc = &This->funcdescs[index];
7529 TRACE("%p %u %p\n", This, index, pCustData);
7531 if(index >= This->TypeAttr.cFuncs)
7532 return TYPE_E_ELEMENTNOTFOUND;
7534 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
7537 /* ITypeInfo2::GetAllParamCustData
7539 * Gets all custom data items for the Functions
7542 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7543 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7545 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7546 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
7548 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
7550 if(indexFunc >= This->TypeAttr.cFuncs)
7551 return TYPE_E_ELEMENTNOTFOUND;
7553 if(indexParam >= pFDesc->funcdesc.cParams)
7554 return TYPE_E_ELEMENTNOTFOUND;
7556 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
7559 /* ITypeInfo2::GetAllVarCustData
7561 * Gets all custom data items for the specified Variable
7564 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7565 UINT index, CUSTDATA *pCustData)
7567 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7568 TLBVarDesc * pVDesc = &This->vardescs[index];
7570 TRACE("%p %u %p\n", This, index, pCustData);
7572 if(index >= This->TypeAttr.cVars)
7573 return TYPE_E_ELEMENTNOTFOUND;
7575 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
7578 /* ITypeInfo2::GetAllImplCustData
7580 * Gets all custom data items for the specified implementation type
7583 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7584 ITypeInfo2 * iface,
7585 UINT index,
7586 CUSTDATA *pCustData)
7588 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7589 TLBImplType *pRDesc = &This->impltypes[index];
7591 TRACE("%p %u %p\n", This, index, pCustData);
7593 if(index >= This->TypeAttr.cImplTypes)
7594 return TYPE_E_ELEMENTNOTFOUND;
7596 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
7599 static const ITypeInfo2Vtbl tinfvt =
7602 ITypeInfo_fnQueryInterface,
7603 ITypeInfo_fnAddRef,
7604 ITypeInfo_fnRelease,
7606 ITypeInfo_fnGetTypeAttr,
7607 ITypeInfo_fnGetTypeComp,
7608 ITypeInfo_fnGetFuncDesc,
7609 ITypeInfo_fnGetVarDesc,
7610 ITypeInfo_fnGetNames,
7611 ITypeInfo_fnGetRefTypeOfImplType,
7612 ITypeInfo_fnGetImplTypeFlags,
7613 ITypeInfo_fnGetIDsOfNames,
7614 ITypeInfo_fnInvoke,
7615 ITypeInfo_fnGetDocumentation,
7616 ITypeInfo_fnGetDllEntry,
7617 ITypeInfo_fnGetRefTypeInfo,
7618 ITypeInfo_fnAddressOfMember,
7619 ITypeInfo_fnCreateInstance,
7620 ITypeInfo_fnGetMops,
7621 ITypeInfo_fnGetContainingTypeLib,
7622 ITypeInfo_fnReleaseTypeAttr,
7623 ITypeInfo_fnReleaseFuncDesc,
7624 ITypeInfo_fnReleaseVarDesc,
7626 ITypeInfo2_fnGetTypeKind,
7627 ITypeInfo2_fnGetTypeFlags,
7628 ITypeInfo2_fnGetFuncIndexOfMemId,
7629 ITypeInfo2_fnGetVarIndexOfMemId,
7630 ITypeInfo2_fnGetCustData,
7631 ITypeInfo2_fnGetFuncCustData,
7632 ITypeInfo2_fnGetParamCustData,
7633 ITypeInfo2_fnGetVarCustData,
7634 ITypeInfo2_fnGetImplTypeCustData,
7635 ITypeInfo2_fnGetDocumentation2,
7636 ITypeInfo2_fnGetAllCustData,
7637 ITypeInfo2_fnGetAllFuncCustData,
7638 ITypeInfo2_fnGetAllParamCustData,
7639 ITypeInfo2_fnGetAllVarCustData,
7640 ITypeInfo2_fnGetAllImplTypeCustData,
7643 /******************************************************************************
7644 * CreateDispTypeInfo [OLEAUT32.31]
7646 * Build type information for an object so it can be called through an
7647 * IDispatch interface.
7649 * RETURNS
7650 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7651 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7653 * NOTES
7654 * This call allows an objects methods to be accessed through IDispatch, by
7655 * building an ITypeInfo object that IDispatch can use to call through.
7657 HRESULT WINAPI CreateDispTypeInfo(
7658 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7659 LCID lcid, /* [I] Locale Id */
7660 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7662 ITypeInfoImpl *pTIClass, *pTIIface;
7663 ITypeLibImpl *pTypeLibImpl;
7664 unsigned int param, func;
7665 TLBFuncDesc *pFuncDesc;
7666 TLBRefType *ref;
7668 TRACE("\n");
7669 pTypeLibImpl = TypeLibImpl_Constructor();
7670 if (!pTypeLibImpl) return E_FAIL;
7672 pTypeLibImpl->TypeInfoCount = 2;
7673 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
7675 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
7676 pTIIface->pTypeLib = pTypeLibImpl;
7677 pTIIface->index = 0;
7678 pTIIface->Name = NULL;
7679 pTIIface->dwHelpContext = -1;
7680 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7681 pTIIface->TypeAttr.lcid = lcid;
7682 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7683 pTIIface->TypeAttr.wMajorVerNum = 0;
7684 pTIIface->TypeAttr.wMinorVerNum = 0;
7685 pTIIface->TypeAttr.cbAlignment = 2;
7686 pTIIface->TypeAttr.cbSizeInstance = -1;
7687 pTIIface->TypeAttr.cbSizeVft = -1;
7688 pTIIface->TypeAttr.cFuncs = 0;
7689 pTIIface->TypeAttr.cImplTypes = 0;
7690 pTIIface->TypeAttr.cVars = 0;
7691 pTIIface->TypeAttr.wTypeFlags = 0;
7693 pTIIface->funcdescs = TLBFuncDesc_Constructor(pidata->cMembers);
7694 pFuncDesc = pTIIface->funcdescs;
7695 for(func = 0; func < pidata->cMembers; func++) {
7696 METHODDATA *md = pidata->pmethdata + func;
7697 pFuncDesc->Name = SysAllocString(md->szName);
7698 pFuncDesc->funcdesc.memid = md->dispid;
7699 pFuncDesc->funcdesc.lprgscode = NULL;
7700 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
7701 pFuncDesc->funcdesc.invkind = md->wFlags;
7702 pFuncDesc->funcdesc.callconv = md->cc;
7703 pFuncDesc->funcdesc.cParams = md->cArgs;
7704 pFuncDesc->funcdesc.cParamsOpt = 0;
7705 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
7706 pFuncDesc->funcdesc.cScodes = 0;
7707 pFuncDesc->funcdesc.wFuncFlags = 0;
7708 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7709 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7710 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7711 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7712 md->cArgs * sizeof(ELEMDESC));
7713 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
7714 for(param = 0; param < md->cArgs; param++) {
7715 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7716 pFuncDesc->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7718 pFuncDesc->helpcontext = 0;
7719 pFuncDesc->HelpStringContext = 0;
7720 pFuncDesc->HelpString = NULL;
7721 pFuncDesc->Entry = NULL;
7722 list_init(&pFuncDesc->custdata_list);
7723 pTIIface->TypeAttr.cFuncs++;
7724 ++pFuncDesc;
7727 dump_TypeInfo(pTIIface);
7729 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
7730 pTIClass->pTypeLib = pTypeLibImpl;
7731 pTIClass->index = 1;
7732 pTIClass->Name = NULL;
7733 pTIClass->dwHelpContext = -1;
7734 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7735 pTIClass->TypeAttr.lcid = lcid;
7736 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7737 pTIClass->TypeAttr.wMajorVerNum = 0;
7738 pTIClass->TypeAttr.wMinorVerNum = 0;
7739 pTIClass->TypeAttr.cbAlignment = 2;
7740 pTIClass->TypeAttr.cbSizeInstance = -1;
7741 pTIClass->TypeAttr.cbSizeVft = -1;
7742 pTIClass->TypeAttr.cFuncs = 0;
7743 pTIClass->TypeAttr.cImplTypes = 1;
7744 pTIClass->TypeAttr.cVars = 0;
7745 pTIClass->TypeAttr.wTypeFlags = 0;
7747 pTIClass->impltypes = TLBImplType_Constructor(1);
7749 ref = heap_alloc_zero(sizeof(*ref));
7750 ref->pImpTLInfo = TLB_REF_INTERNAL;
7751 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7753 dump_TypeInfo(pTIClass);
7755 *pptinfo = (ITypeInfo*)pTIClass;
7757 ITypeInfo_AddRef(*pptinfo);
7758 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7760 return S_OK;
7764 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7766 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7768 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7771 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7773 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7775 return ITypeInfo_AddRef((ITypeInfo *)This);
7778 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7780 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7782 return ITypeInfo_Release((ITypeInfo *)This);
7785 static HRESULT WINAPI ITypeComp_fnBind(
7786 ITypeComp * iface,
7787 OLECHAR * szName,
7788 ULONG lHash,
7789 WORD wFlags,
7790 ITypeInfo ** ppTInfo,
7791 DESCKIND * pDescKind,
7792 BINDPTR * pBindPtr)
7794 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7795 const TLBFuncDesc *pFDesc;
7796 const TLBVarDesc *pVDesc;
7797 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7798 UINT fdc;
7800 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7802 *pDescKind = DESCKIND_NONE;
7803 pBindPtr->lpfuncdesc = NULL;
7804 *ppTInfo = NULL;
7806 for(fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc){
7807 pFDesc = &This->funcdescs[fdc];
7808 if (!strcmpiW(pFDesc->Name, szName)) {
7809 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7810 break;
7811 else
7812 /* name found, but wrong flags */
7813 hr = TYPE_E_TYPEMISMATCH;
7817 if (fdc < This->TypeAttr.cFuncs)
7819 HRESULT hr = TLB_AllocAndInitFuncDesc(
7820 &pFDesc->funcdesc,
7821 &pBindPtr->lpfuncdesc,
7822 This->TypeAttr.typekind == TKIND_DISPATCH);
7823 if (FAILED(hr))
7824 return hr;
7825 *pDescKind = DESCKIND_FUNCDESC;
7826 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7827 ITypeInfo_AddRef(*ppTInfo);
7828 return S_OK;
7829 } else {
7830 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->TypeAttr.cVars, szName);
7831 if(pVDesc){
7832 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7833 if (FAILED(hr))
7834 return hr;
7835 *pDescKind = DESCKIND_VARDESC;
7836 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7837 ITypeInfo_AddRef(*ppTInfo);
7838 return S_OK;
7841 /* FIXME: search each inherited interface, not just the first */
7842 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
7843 /* recursive search */
7844 ITypeInfo *pTInfo;
7845 ITypeComp *pTComp;
7846 HRESULT hr;
7847 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypes[0].hRef, &pTInfo);
7848 if (SUCCEEDED(hr))
7850 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7851 ITypeInfo_Release(pTInfo);
7853 if (SUCCEEDED(hr))
7855 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7856 ITypeComp_Release(pTComp);
7857 return hr;
7859 WARN("Could not search inherited interface!\n");
7861 if (hr == DISP_E_MEMBERNOTFOUND)
7862 hr = S_OK;
7863 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
7864 return hr;
7867 static HRESULT WINAPI ITypeComp_fnBindType(
7868 ITypeComp * iface,
7869 OLECHAR * szName,
7870 ULONG lHash,
7871 ITypeInfo ** ppTInfo,
7872 ITypeComp ** ppTComp)
7874 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7876 /* strange behaviour (does nothing) but like the
7877 * original */
7879 if (!ppTInfo || !ppTComp)
7880 return E_POINTER;
7882 *ppTInfo = NULL;
7883 *ppTComp = NULL;
7885 return S_OK;
7888 static const ITypeCompVtbl tcompvt =
7891 ITypeComp_fnQueryInterface,
7892 ITypeComp_fnAddRef,
7893 ITypeComp_fnRelease,
7895 ITypeComp_fnBind,
7896 ITypeComp_fnBindType