oleaut32: Use implementation pointer to avoid casts.
[wine/wine-gecko.git] / dlls / oleaut32 / typelib.c
blobd9fa638138564c780a750b52be832335bbe95610
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 tagTLBCustData* next;
961 } TLBCustData;
963 /* data structure for import typelibs */
964 typedef struct tagTLBImpLib
966 int offset; /* offset in the file (MSFT)
967 offset in nametable (SLTG)
968 just used to identify library while reading
969 data from file */
970 GUID guid; /* libid */
971 BSTR name; /* name */
973 LCID lcid; /* lcid of imported typelib */
975 WORD wVersionMajor; /* major version number */
976 WORD wVersionMinor; /* minor version number */
978 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
979 NULL if not yet loaded */
980 struct tagTLBImpLib * next;
981 } TLBImpLib;
983 /* internal ITypeLib data */
984 typedef struct tagITypeLibImpl
986 const ITypeLib2Vtbl *lpVtbl;
987 const ITypeCompVtbl *lpVtblTypeComp;
988 LONG ref;
989 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
990 LCID lcid;
992 /* strings can be stored in tlb as multibyte strings BUT they are *always*
993 * exported to the application as a UNICODE string.
995 BSTR Name;
996 BSTR DocString;
997 BSTR HelpFile;
998 BSTR HelpStringDll;
999 DWORD dwHelpContext;
1000 int TypeInfoCount; /* nr of typeinfo's in librarry */
1001 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
1002 int ctCustData; /* number of items in cust data list */
1003 TLBCustData * pCustData; /* linked list to cust data */
1004 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
1005 int ctTypeDesc; /* number of items in type desc array */
1006 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1007 library. Only used while reading MSFT
1008 typelibs */
1009 struct list ref_list; /* list of ref types in this typelib */
1010 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1013 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1014 struct tagITypeLibImpl *next, *prev;
1015 WCHAR *path;
1016 INT index;
1017 } ITypeLibImpl;
1019 static const ITypeLib2Vtbl tlbvt;
1020 static const ITypeCompVtbl tlbtcvt;
1022 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1024 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
1027 /* ITypeLib methods */
1028 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1029 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1031 /*======================= ITypeInfo implementation =======================*/
1033 /* data for referenced types */
1034 typedef struct tagTLBRefType
1036 INT index; /* Type index for internal ref or for external ref
1037 it the format is SLTG. -2 indicates to
1038 use guid */
1040 GUID guid; /* guid of the referenced type */
1041 /* if index == TLB_REF_USE_GUID */
1043 HREFTYPE reference; /* The href of this ref */
1044 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1045 TLB_REF_INTERNAL for internal refs
1046 TLB_REF_NOT_FOUND for broken refs */
1048 struct list entry;
1049 } TLBRefType;
1051 #define TLB_REF_USE_GUID -2
1053 #define TLB_REF_INTERNAL (void*)-2
1054 #define TLB_REF_NOT_FOUND (void*)-1
1056 /* internal Parameter data */
1057 typedef struct tagTLBParDesc
1059 BSTR Name;
1060 int ctCustData;
1061 TLBCustData * pCustData; /* linked list to cust data */
1062 } TLBParDesc;
1064 /* internal Function data */
1065 typedef struct tagTLBFuncDesc
1067 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1068 BSTR Name; /* the name of this function */
1069 TLBParDesc *pParamDesc; /* array with param names and custom data */
1070 int helpcontext;
1071 int HelpStringContext;
1072 BSTR HelpString;
1073 BSTR Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1074 int ctCustData;
1075 TLBCustData * pCustData; /* linked list to cust data; */
1076 struct tagTLBFuncDesc * next;
1077 } TLBFuncDesc;
1079 /* internal Variable data */
1080 typedef struct tagTLBVarDesc
1082 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1083 BSTR Name; /* the name of this variable */
1084 int HelpContext;
1085 int HelpStringContext; /* FIXME: where? */
1086 BSTR HelpString;
1087 int ctCustData;
1088 TLBCustData * pCustData;/* linked list to cust data; */
1089 struct tagTLBVarDesc * next;
1090 } TLBVarDesc;
1092 /* internal implemented interface data */
1093 typedef struct tagTLBImplType
1095 HREFTYPE hRef; /* hRef of interface */
1096 int implflags; /* IMPLFLAG_*s */
1097 int ctCustData;
1098 TLBCustData * pCustData;/* linked list to custom data; */
1099 struct tagTLBImplType *next;
1100 } TLBImplType;
1102 /* internal TypeInfo data */
1103 typedef struct tagITypeInfoImpl
1105 const ITypeInfo2Vtbl *lpVtbl;
1106 const ITypeCompVtbl *lpVtblTypeComp;
1107 LONG ref;
1108 BOOL not_attached_to_typelib;
1109 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1110 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1111 int index; /* index in this typelib; */
1112 HREFTYPE hreftype; /* hreftype for app object binding */
1113 /* type libs seem to store the doc strings in ascii
1114 * so why should we do it in unicode?
1116 BSTR Name;
1117 BSTR DocString;
1118 BSTR DllName;
1119 DWORD dwHelpContext;
1120 DWORD dwHelpStringContext;
1122 /* functions */
1123 TLBFuncDesc * funclist; /* linked list with function descriptions */
1125 /* variables */
1126 TLBVarDesc * varlist; /* linked list with variable descriptions */
1128 /* Implemented Interfaces */
1129 TLBImplType * impltypelist;
1131 int ctCustData;
1132 TLBCustData * pCustData; /* linked list to cust data; */
1133 struct tagITypeInfoImpl * next;
1134 } ITypeInfoImpl;
1136 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1138 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1141 static const ITypeInfo2Vtbl tinfvt;
1142 static const ITypeCompVtbl tcompvt;
1144 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1145 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1147 typedef struct tagTLBContext
1149 unsigned int oStart; /* start of TLB in file */
1150 unsigned int pos; /* current pos */
1151 unsigned int length; /* total length */
1152 void *mapping; /* memory mapping */
1153 MSFT_SegDir * pTblDir;
1154 ITypeLibImpl* pLibInfo;
1155 } TLBContext;
1158 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1161 debug
1163 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1164 if (pTD->vt & VT_RESERVED)
1165 szVarType += strlen(strcpy(szVarType, "reserved | "));
1166 if (pTD->vt & VT_BYREF)
1167 szVarType += strlen(strcpy(szVarType, "ref to "));
1168 if (pTD->vt & VT_ARRAY)
1169 szVarType += strlen(strcpy(szVarType, "array of "));
1170 if (pTD->vt & VT_VECTOR)
1171 szVarType += strlen(strcpy(szVarType, "vector of "));
1172 switch(pTD->vt & VT_TYPEMASK) {
1173 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1174 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1175 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1176 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1177 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1178 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1179 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1180 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1181 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1182 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1183 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1184 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1185 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1186 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1187 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1188 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1189 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1190 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1191 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1192 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1193 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1194 pTD->u.hreftype); break;
1195 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1196 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1197 case VT_PTR: sprintf(szVarType, "ptr to ");
1198 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1199 break;
1200 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1201 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1202 break;
1203 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1204 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1205 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1206 break;
1208 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1212 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1213 char buf[200];
1214 USHORT flags = edesc->u.paramdesc.wParamFlags;
1215 dump_TypeDesc(&edesc->tdesc,buf);
1216 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1217 MESSAGE("\t\tu.paramdesc.wParamFlags");
1218 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1219 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1220 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1221 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1222 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1223 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1224 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1225 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1226 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1228 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1229 int i;
1230 MESSAGE("memid is %08x\n",funcdesc->memid);
1231 for (i=0;i<funcdesc->cParams;i++) {
1232 MESSAGE("Param %d:\n",i);
1233 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1235 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1236 switch (funcdesc->funckind) {
1237 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1238 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1239 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1240 case FUNC_STATIC: MESSAGE("static");break;
1241 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1242 default: MESSAGE("unknown");break;
1244 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1245 switch (funcdesc->invkind) {
1246 case INVOKE_FUNC: MESSAGE("func");break;
1247 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1248 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1249 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1251 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1252 switch (funcdesc->callconv) {
1253 case CC_CDECL: MESSAGE("cdecl");break;
1254 case CC_PASCAL: MESSAGE("pascal");break;
1255 case CC_STDCALL: MESSAGE("stdcall");break;
1256 case CC_SYSCALL: MESSAGE("syscall");break;
1257 default:break;
1259 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1260 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1261 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1263 MESSAGE("\telemdescFunc (return value type):\n");
1264 dump_ELEMDESC(&funcdesc->elemdescFunc);
1267 static const char * const typekind_desc[] =
1269 "TKIND_ENUM",
1270 "TKIND_RECORD",
1271 "TKIND_MODULE",
1272 "TKIND_INTERFACE",
1273 "TKIND_DISPATCH",
1274 "TKIND_COCLASS",
1275 "TKIND_ALIAS",
1276 "TKIND_UNION",
1277 "TKIND_MAX"
1280 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1282 int i;
1283 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1284 for (i=0;i<pfd->funcdesc.cParams;i++)
1285 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1288 dump_FUNCDESC(&(pfd->funcdesc));
1290 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1291 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1293 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1295 while (pfd)
1297 dump_TLBFuncDescOne(pfd);
1298 pfd = pfd->next;
1301 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1303 while (pvd)
1305 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1306 pvd = pvd->next;
1310 static void dump_TLBImpLib(const TLBImpLib *import)
1312 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1313 debugstr_w(import->name));
1314 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1315 import->wVersionMinor, import->lcid, import->offset);
1318 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1320 TLBRefType *ref;
1322 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1324 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1325 if(ref->index == -1)
1326 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1327 else
1328 TRACE_(typelib)("type no: %d\n", ref->index);
1330 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1332 TRACE_(typelib)("in lib\n");
1333 dump_TLBImpLib(ref->pImpTLInfo);
1338 static void dump_TLBImplType(const TLBImplType * impl)
1340 while (impl) {
1341 TRACE_(typelib)(
1342 "implementing/inheriting interface hRef = %x implflags %x\n",
1343 impl->hRef, impl->implflags);
1344 impl = impl->next;
1348 static void dump_Variant(const VARIANT * pvar)
1350 SYSTEMTIME st;
1352 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1354 if (pvar)
1356 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1357 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1359 TRACE(",%p", V_BYREF(pvar));
1361 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1363 TRACE(",%p", V_ARRAY(pvar));
1365 else switch (V_TYPE(pvar))
1367 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1368 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1369 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1370 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1371 case VT_INT:
1372 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1373 case VT_UINT:
1374 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1375 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1376 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1377 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1378 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1379 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1380 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1381 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1382 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1383 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1384 V_CY(pvar).s.Lo); break;
1385 case VT_DATE:
1386 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1387 TRACE(",<invalid>");
1388 else
1389 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1390 st.wHour, st.wMinute, st.wSecond);
1391 break;
1392 case VT_ERROR:
1393 case VT_VOID:
1394 case VT_USERDEFINED:
1395 case VT_EMPTY:
1396 case VT_NULL: break;
1397 default: TRACE(",?"); break;
1400 TRACE("}\n");
1403 static void dump_DispParms(const DISPPARAMS * pdp)
1405 unsigned int index;
1407 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1409 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1411 TRACE("named args:\n");
1412 for (index = 0; index < pdp->cNamedArgs; index++)
1413 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1416 if (pdp->cArgs && pdp->rgvarg)
1418 TRACE("args:\n");
1419 for (index = 0; index < pdp->cArgs; index++)
1420 dump_Variant( &pdp->rgvarg[index] );
1424 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1426 TRACE("%p ref=%u\n", pty, pty->ref);
1427 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1428 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1429 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1430 TRACE("fct:%u var:%u impl:%u\n",
1431 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1432 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1433 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1434 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1435 if (TRACE_ON(ole))
1436 dump_TLBFuncDesc(pty->funclist);
1437 dump_TLBVarDesc(pty->varlist);
1438 dump_TLBImplType(pty->impltypelist);
1441 static void dump_VARDESC(const VARDESC *v)
1443 MESSAGE("memid %d\n",v->memid);
1444 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1445 MESSAGE("oInst %d\n",v->u.oInst);
1446 dump_ELEMDESC(&(v->elemdescVar));
1447 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1448 MESSAGE("varkind %d\n",v->varkind);
1451 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1453 /* VT_LPWSTR is largest type that */
1454 /* may appear in type description*/
1455 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1456 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1457 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1458 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1459 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1460 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1461 {{0},30},{{0},31}
1464 static void TLB_abort(void)
1466 DebugBreak();
1469 static inline void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size)
1471 void *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
1472 if (!ret) ERR("cannot allocate memory\n");
1473 return ret;
1476 static inline void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size)
1478 void *ret = HeapAlloc(GetProcessHeap(), 0, size);
1479 if (!ret) ERR("cannot allocate memory\n");
1480 return ret;
1483 static inline void heap_free(void *ptr)
1485 HeapFree(GetProcessHeap(), 0, ptr);
1488 /* returns the size required for a deep copy of a typedesc into a
1489 * flat buffer */
1490 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1492 SIZE_T size = 0;
1494 if (alloc_initial_space)
1495 size += sizeof(TYPEDESC);
1497 switch (tdesc->vt)
1499 case VT_PTR:
1500 case VT_SAFEARRAY:
1501 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1502 break;
1503 case VT_CARRAY:
1504 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1505 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1506 break;
1508 return size;
1511 /* deep copy a typedesc into a flat buffer */
1512 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1514 if (!dest)
1516 dest = buffer;
1517 buffer = (char *)buffer + sizeof(TYPEDESC);
1520 *dest = *src;
1522 switch (src->vt)
1524 case VT_PTR:
1525 case VT_SAFEARRAY:
1526 dest->u.lptdesc = buffer;
1527 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1528 break;
1529 case VT_CARRAY:
1530 dest->u.lpadesc = buffer;
1531 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1532 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1533 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1534 break;
1536 return buffer;
1539 /* free custom data allocated by MSFT_CustData */
1540 static inline void TLB_FreeCustData(TLBCustData *pCustData)
1542 TLBCustData *pCustDataNext;
1543 for (; pCustData; pCustData = pCustDataNext)
1545 VariantClear(&pCustData->data);
1547 pCustDataNext = pCustData->next;
1548 heap_free(pCustData);
1552 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1554 DWORD len;
1555 BSTR ret;
1557 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1558 ret = SysAllocStringLen(NULL, len - 1);
1559 if (!ret) return ret;
1560 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1561 return ret;
1564 /**********************************************************************
1566 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1568 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1570 return pcx->pos;
1573 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
1575 if (where != DO_NOT_SEEK)
1577 where += pcx->oStart;
1578 if (where > pcx->length)
1580 /* FIXME */
1581 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
1582 TLB_abort();
1584 pcx->pos = where;
1588 /* read function */
1589 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
1591 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
1592 pcx->pos, count, pcx->oStart, pcx->length, where);
1594 MSFT_Seek(pcx, where);
1595 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1596 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1597 pcx->pos += count;
1598 return count;
1601 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1602 LONG where )
1604 DWORD ret;
1606 ret = MSFT_Read(buffer, count, pcx, where);
1607 FromLEDWords(buffer, ret);
1609 return ret;
1612 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1613 LONG where )
1615 DWORD ret;
1617 ret = MSFT_Read(buffer, count, pcx, where);
1618 FromLEWords(buffer, ret);
1620 return ret;
1623 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1625 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1626 memset(pGuid,0, sizeof(GUID));
1627 return;
1629 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1630 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1631 pGuid->Data2 = FromLEWord(pGuid->Data2);
1632 pGuid->Data3 = FromLEWord(pGuid->Data3);
1633 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1636 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1638 MSFT_NameIntro niName;
1640 if (offset < 0)
1642 ERR_(typelib)("bad offset %d\n", offset);
1643 return -1;
1646 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1647 pcx->pTblDir->pNametab.offset+offset);
1649 return niName.hreftype;
1652 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1654 char * name;
1655 MSFT_NameIntro niName;
1656 int lengthInChars;
1657 BSTR bstrName = NULL;
1659 if (offset < 0)
1661 ERR_(typelib)("bad offset %d\n", offset);
1662 return NULL;
1664 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1665 pcx->pTblDir->pNametab.offset+offset);
1666 niName.namelen &= 0xFF; /* FIXME: correct ? */
1667 name = heap_alloc_zero((niName.namelen & 0xff) +1);
1668 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1669 name[niName.namelen & 0xff]='\0';
1671 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1672 name, -1, NULL, 0);
1674 /* no invalid characters in string */
1675 if (lengthInChars)
1677 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1679 /* don't check for invalid character since this has been done previously */
1680 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1682 heap_free(name);
1684 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1685 return bstrName;
1688 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1690 char * string;
1691 INT16 length;
1692 int lengthInChars;
1693 BSTR bstr = NULL;
1695 if(offset<0) return NULL;
1696 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1697 if(length <= 0) return 0;
1698 string = heap_alloc_zero(length +1);
1699 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1700 string[length]='\0';
1702 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1703 string, -1, NULL, 0);
1705 /* no invalid characters in string */
1706 if (lengthInChars)
1708 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1710 /* don't check for invalid character since this has been done previously */
1711 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1713 heap_free(string);
1715 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1716 return bstr;
1719 * read a value and fill a VARIANT structure
1721 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1723 int size;
1725 TRACE_(typelib)("\n");
1727 if(offset <0) { /* data are packed in here */
1728 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1729 V_I4(pVar) = offset & 0x3ffffff;
1730 return;
1732 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1733 pcx->pTblDir->pCustData.offset + offset );
1734 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1735 switch (V_VT(pVar)){
1736 case VT_EMPTY: /* FIXME: is this right? */
1737 case VT_NULL: /* FIXME: is this right? */
1738 case VT_I2 : /* this should not happen */
1739 case VT_I4 :
1740 case VT_R4 :
1741 case VT_ERROR :
1742 case VT_BOOL :
1743 case VT_I1 :
1744 case VT_UI1 :
1745 case VT_UI2 :
1746 case VT_UI4 :
1747 case VT_INT :
1748 case VT_UINT :
1749 case VT_VOID : /* FIXME: is this right? */
1750 case VT_HRESULT :
1751 size=4; break;
1752 case VT_R8 :
1753 case VT_CY :
1754 case VT_DATE :
1755 case VT_I8 :
1756 case VT_UI8 :
1757 case VT_DECIMAL : /* FIXME: is this right? */
1758 case VT_FILETIME :
1759 size=8;break;
1760 /* pointer types with known behaviour */
1761 case VT_BSTR :{
1762 char * ptr;
1763 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1764 if(size < 0) {
1765 char next;
1766 DWORD origPos = MSFT_Tell(pcx), nullPos;
1768 do {
1769 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1770 } while (next);
1771 nullPos = MSFT_Tell(pcx);
1772 size = nullPos - origPos;
1773 MSFT_Seek(pcx, origPos);
1775 ptr = heap_alloc_zero(size);/* allocate temp buffer */
1776 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1777 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1778 /* FIXME: do we need a AtoW conversion here? */
1779 V_UNION(pVar, bstrVal[size])='\0';
1780 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1781 heap_free(ptr);
1783 size=-4; break;
1784 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1785 case VT_DISPATCH :
1786 case VT_VARIANT :
1787 case VT_UNKNOWN :
1788 case VT_PTR :
1789 case VT_SAFEARRAY :
1790 case VT_CARRAY :
1791 case VT_USERDEFINED :
1792 case VT_LPSTR :
1793 case VT_LPWSTR :
1794 case VT_BLOB :
1795 case VT_STREAM :
1796 case VT_STORAGE :
1797 case VT_STREAMED_OBJECT :
1798 case VT_STORED_OBJECT :
1799 case VT_BLOB_OBJECT :
1800 case VT_CF :
1801 case VT_CLSID :
1802 default:
1803 size=0;
1804 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1805 V_VT(pVar));
1808 if(size>0) /* (big|small) endian correct? */
1809 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1810 return;
1813 * create a linked list with custom data
1815 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1817 MSFT_CDGuid entry;
1818 TLBCustData* pNew;
1819 int count=0;
1821 TRACE_(typelib)("\n");
1823 while(offset >=0){
1824 count++;
1825 pNew=heap_alloc_zero(sizeof(TLBCustData));
1826 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1827 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1828 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1829 /* add new custom data at head of the list */
1830 pNew->next=*ppCustData;
1831 *ppCustData=pNew;
1832 offset = entry.next;
1834 return count;
1837 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1838 ITypeInfoImpl *pTI)
1840 if(type <0)
1841 pTd->vt=type & VT_TYPEMASK;
1842 else
1843 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1845 if(pTd->vt == VT_USERDEFINED)
1846 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1848 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1851 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1853 /* resolve referenced type if any */
1854 while (lpTypeDesc)
1856 switch (lpTypeDesc->vt)
1858 case VT_PTR:
1859 lpTypeDesc = lpTypeDesc->u.lptdesc;
1860 break;
1862 case VT_CARRAY:
1863 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1864 break;
1866 case VT_USERDEFINED:
1867 MSFT_DoRefType(pcx, pTI->pTypeLib,
1868 lpTypeDesc->u.hreftype);
1870 lpTypeDesc = NULL;
1871 break;
1873 default:
1874 lpTypeDesc = NULL;
1879 static void
1880 MSFT_DoFuncs(TLBContext* pcx,
1881 ITypeInfoImpl* pTI,
1882 int cFuncs,
1883 int cVars,
1884 int offset,
1885 TLBFuncDesc** pptfd)
1888 * member information is stored in a data structure at offset
1889 * indicated by the memoffset field of the typeinfo structure
1890 * There are several distinctive parts.
1891 * The first part starts with a field that holds the total length
1892 * of this (first) part excluding this field. Then follow the records,
1893 * for each member there is one record.
1895 * The first entry is always the length of the record (including this
1896 * length word).
1897 * The rest of the record depends on the type of the member. If there is
1898 * a field indicating the member type (function, variable, interface, etc)
1899 * I have not found it yet. At this time we depend on the information
1900 * in the type info and the usual order how things are stored.
1902 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1903 * for each member;
1905 * Third is an equal sized array with file offsets to the name entry
1906 * of each member.
1908 * The fourth and last (?) part is an array with offsets to the records
1909 * in the first part of this file segment.
1912 int infolen, nameoffset, reclength, i;
1913 int recoffset = offset + sizeof(INT);
1915 char *recbuf = heap_alloc(0xffff);
1916 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
1917 TLBFuncDesc *ptfd_prev = NULL;
1919 TRACE_(typelib)("\n");
1921 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1923 for ( i = 0; i < cFuncs ; i++ )
1925 int optional;
1927 *pptfd = heap_alloc_zero(sizeof(TLBFuncDesc));
1929 /* name, eventually add to a hash table */
1930 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1931 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1933 /* nameoffset is sometimes -1 on the second half of a propget/propput
1934 * pair of functions */
1935 if ((nameoffset == -1) && (i > 0))
1936 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1937 else
1938 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1940 /* read the function information record */
1941 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
1943 reclength &= 0xffff;
1945 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
1947 /* size without argument data */
1948 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
1950 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
1951 (*pptfd)->helpcontext = pFuncRec->HelpContext;
1953 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
1954 (*pptfd)->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
1956 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
1958 if (pFuncRec->FKCCIC & 0x2000 )
1960 if (!IS_INTRESOURCE(pFuncRec->oEntry))
1961 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
1962 (*pptfd)->Entry = (BSTR)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
1964 else
1965 (*pptfd)->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
1967 else
1968 (*pptfd)->Entry = (BSTR)-1;
1970 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
1971 (*pptfd)->HelpStringContext = pFuncRec->HelpStringContext;
1973 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
1974 MSFT_CustData(pcx, pFuncRec->oCustData, &(*pptfd)->pCustData);
1976 /* fill the FuncDesc Structure */
1977 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1978 offset + infolen + ( i + 1) * sizeof(INT));
1980 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1981 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1982 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1983 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1984 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1985 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset;
1986 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1988 MSFT_GetTdesc(pcx,
1989 pFuncRec->DataType,
1990 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1991 pTI);
1992 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1994 /* do the parameters/arguments */
1995 if(pFuncRec->nrargs)
1997 int j = 0;
1998 MSFT_ParameterInfo paraminfo;
2000 (*pptfd)->funcdesc.lprgelemdescParam =
2001 heap_alloc_zero(pFuncRec->nrargs * sizeof(ELEMDESC));
2003 (*pptfd)->pParamDesc =
2004 heap_alloc_zero(pFuncRec->nrargs * sizeof(TLBParDesc));
2006 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2007 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2009 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2011 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
2013 MSFT_GetTdesc(pcx,
2014 paraminfo.DataType,
2015 &elemdesc->tdesc,
2016 pTI);
2018 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2020 /* name */
2021 if (paraminfo.oName == -1)
2022 /* this occurs for [propput] or [propget] methods, so
2023 * we should just set the name of the parameter to the
2024 * name of the method. */
2025 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
2026 else
2027 (*pptfd)->pParamDesc[j].Name =
2028 MSFT_ReadName( pcx, paraminfo.oName );
2029 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
2031 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
2033 /* default value */
2034 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2035 (pFuncRec->FKCCIC & 0x1000) )
2037 INT* pInt = (INT *)((char *)pFuncRec +
2038 reclength -
2039 (pFuncRec->nrargs * 4) * sizeof(INT) );
2041 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2043 pParamDesc->pparamdescex = heap_alloc_zero(sizeof(PARAMDESCEX));
2044 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2046 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2047 pInt[j], pcx);
2049 else
2050 elemdesc->u.paramdesc.pparamdescex = NULL;
2052 /* custom info */
2053 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2054 j*sizeof(pFuncRec->oArgCustData[0])) &&
2055 pFuncRec->FKCCIC & 0x80 )
2057 MSFT_CustData(pcx,
2058 pFuncRec->oArgCustData[j],
2059 &(*pptfd)->pParamDesc[j].pCustData);
2062 /* SEEK value = jump to offset,
2063 * from there jump to the end of record,
2064 * go back by (j-1) arguments
2066 MSFT_ReadLEDWords( &paraminfo ,
2067 sizeof(MSFT_ParameterInfo), pcx,
2068 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2069 * sizeof(MSFT_ParameterInfo)));
2073 /* scode is not used: archaic win16 stuff FIXME: right? */
2074 (*pptfd)->funcdesc.cScodes = 0 ;
2075 (*pptfd)->funcdesc.lprgscode = NULL ;
2077 ptfd_prev = *pptfd;
2078 pptfd = & ((*pptfd)->next);
2079 recoffset += reclength;
2081 heap_free(recbuf);
2084 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2085 int cVars, int offset, TLBVarDesc ** pptvd)
2087 int infolen, nameoffset, reclength;
2088 char recbuf[256];
2089 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2090 int i;
2091 int recoffset;
2093 TRACE_(typelib)("\n");
2095 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2096 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2097 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2098 recoffset += offset+sizeof(INT);
2099 for(i=0;i<cVars;i++){
2100 *pptvd = heap_alloc_zero(sizeof(TLBVarDesc));
2101 /* name, eventually add to a hash table */
2102 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2103 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2104 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
2105 /* read the variable information record */
2106 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2107 reclength &= 0xff;
2108 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2110 /* optional data */
2111 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2112 (*pptvd)->HelpContext = pVarRec->HelpContext;
2114 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2115 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2117 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2118 (*pptvd)->HelpStringContext = pVarRec->HelpStringContext;
2120 /* fill the VarDesc Structure */
2121 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
2122 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2123 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
2124 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
2125 MSFT_GetTdesc(pcx, pVarRec->DataType,
2126 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
2127 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2128 if(pVarRec->VarKind == VAR_CONST ){
2129 (*pptvd)->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2130 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
2131 pVarRec->OffsValue, pcx);
2132 } else
2133 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
2134 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
2135 pptvd=&((*pptvd)->next);
2136 recoffset += reclength;
2139 /* fill in data for a hreftype (offset). When the referenced type is contained
2140 * in the typelib, it's just an (file) offset in the type info base dir.
2141 * If comes from import, it's an offset+1 in the ImpInfo table
2142 * */
2143 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2144 int offset)
2146 TLBRefType *ref;
2148 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2150 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2152 if(ref->reference == offset) return;
2155 ref = heap_alloc_zero(sizeof(TLBRefType));
2156 list_add_tail(&pTL->ref_list, &ref->entry);
2158 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2159 /* external typelib */
2160 MSFT_ImpInfo impinfo;
2161 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2163 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2165 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2166 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2167 while (pImpLib){ /* search the known offsets of all import libraries */
2168 if(pImpLib->offset==impinfo.oImpFile) break;
2169 pImpLib=pImpLib->next;
2171 if(pImpLib){
2172 ref->reference = offset;
2173 ref->pImpTLInfo = pImpLib;
2174 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2175 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2176 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2177 ref->index = TLB_REF_USE_GUID;
2178 } else
2179 ref->index = impinfo.oGuid;
2180 }else{
2181 ERR("Cannot find a reference\n");
2182 ref->reference = -1;
2183 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2185 }else{
2186 /* in this typelib */
2187 ref->index = MSFT_HREFTYPE_INDEX(offset);
2188 ref->reference = offset;
2189 ref->pImpTLInfo = TLB_REF_INTERNAL;
2193 /* process Implemented Interfaces of a com class */
2194 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2195 int offset)
2197 int i;
2198 MSFT_RefRecord refrec;
2199 TLBImplType **ppImpl = &pTI->impltypelist;
2201 TRACE_(typelib)("\n");
2203 for(i=0;i<count;i++){
2204 if(offset<0) break; /* paranoia */
2205 *ppImpl = heap_alloc_zero(sizeof(**ppImpl));
2206 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2207 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2208 (*ppImpl)->hRef = refrec.reftype;
2209 (*ppImpl)->implflags=refrec.flags;
2210 (*ppImpl)->ctCustData=
2211 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2212 offset=refrec.onext;
2213 ppImpl=&((*ppImpl)->next);
2217 * process a typeinfo record
2219 static ITypeInfoImpl * MSFT_DoTypeInfo(
2220 TLBContext *pcx,
2221 int count,
2222 ITypeLibImpl * pLibInfo)
2224 MSFT_TypeInfoBase tiBase;
2225 ITypeInfoImpl *ptiRet;
2227 TRACE_(typelib)("count=%u\n", count);
2229 ptiRet = ITypeInfoImpl_Constructor();
2230 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2231 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2233 /* this is where we are coming from */
2234 ptiRet->pTypeLib = pLibInfo;
2235 ptiRet->index=count;
2236 /* fill in the typeattr fields */
2238 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2239 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2240 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2241 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2242 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2243 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2244 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2245 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2246 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2247 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2248 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2249 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2250 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2251 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2252 MSFT_GetTdesc(pcx, tiBase.datatype1,
2253 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2255 /* FIXME: */
2256 /* IDLDESC idldescType; *//* never saw this one != zero */
2258 /* name, eventually add to a hash table */
2259 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2260 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2261 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2262 /* help info */
2263 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2264 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2265 ptiRet->dwHelpContext=tiBase.helpcontext;
2267 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2268 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2270 /* note: InfoType's Help file and HelpStringDll come from the containing
2271 * library. Further HelpString and Docstring appear to be the same thing :(
2273 /* functions */
2274 if(ptiRet->TypeAttr.cFuncs >0 )
2275 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2276 ptiRet->TypeAttr.cVars,
2277 tiBase.memoffset, & ptiRet->funclist);
2278 /* variables */
2279 if(ptiRet->TypeAttr.cVars >0 )
2280 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2281 ptiRet->TypeAttr.cVars,
2282 tiBase.memoffset, & ptiRet->varlist);
2283 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2284 switch(ptiRet->TypeAttr.typekind)
2286 case TKIND_COCLASS:
2287 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2288 tiBase.datatype1);
2289 break;
2290 case TKIND_DISPATCH:
2291 /* This is not -1 when the interface is a non-base dual interface or
2292 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2293 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2294 not this interface.
2297 if (tiBase.datatype1 != -1)
2299 ptiRet->impltypelist = heap_alloc_zero(sizeof(TLBImplType));
2300 ptiRet->impltypelist->hRef = tiBase.datatype1;
2301 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2303 break;
2304 default:
2305 ptiRet->impltypelist = heap_alloc_zero(sizeof(TLBImplType));
2306 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2307 ptiRet->impltypelist->hRef = tiBase.datatype1;
2308 break;
2311 ptiRet->ctCustData=
2312 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2314 TRACE_(typelib)("%s guid: %s kind:%s\n",
2315 debugstr_w(ptiRet->Name),
2316 debugstr_guid(&ptiRet->TypeAttr.guid),
2317 typekind_desc[ptiRet->TypeAttr.typekind]);
2318 if (TRACE_ON(typelib))
2319 dump_TypeInfo(ptiRet);
2321 return ptiRet;
2324 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2325 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2326 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2327 * tradeoff here.
2329 static ITypeLibImpl *tlb_cache_first;
2330 static CRITICAL_SECTION cache_section;
2331 static CRITICAL_SECTION_DEBUG cache_section_debug =
2333 0, 0, &cache_section,
2334 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2335 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2337 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2340 typedef struct TLB_PEFile
2342 const IUnknownVtbl *lpvtbl;
2343 LONG refs;
2344 HMODULE dll;
2345 HRSRC typelib_resource;
2346 HGLOBAL typelib_global;
2347 LPVOID typelib_base;
2348 } TLB_PEFile;
2350 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2352 if (IsEqualIID(riid, &IID_IUnknown))
2354 *ppv = iface;
2355 IUnknown_AddRef(iface);
2356 return S_OK;
2358 *ppv = NULL;
2359 return E_NOINTERFACE;
2362 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2364 TLB_PEFile *This = (TLB_PEFile *)iface;
2365 return InterlockedIncrement(&This->refs);
2368 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2370 TLB_PEFile *This = (TLB_PEFile *)iface;
2371 ULONG refs = InterlockedDecrement(&This->refs);
2372 if (!refs)
2374 if (This->typelib_global)
2375 FreeResource(This->typelib_global);
2376 if (This->dll)
2377 FreeLibrary(This->dll);
2378 heap_free(This);
2380 return refs;
2383 static const IUnknownVtbl TLB_PEFile_Vtable =
2385 TLB_PEFile_QueryInterface,
2386 TLB_PEFile_AddRef,
2387 TLB_PEFile_Release
2390 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2392 TLB_PEFile *This;
2394 This = heap_alloc(sizeof(TLB_PEFile));
2395 if (!This)
2396 return E_OUTOFMEMORY;
2398 This->lpvtbl = &TLB_PEFile_Vtable;
2399 This->refs = 1;
2400 This->dll = NULL;
2401 This->typelib_resource = NULL;
2402 This->typelib_global = NULL;
2403 This->typelib_base = NULL;
2405 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2406 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2408 if (This->dll)
2410 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2411 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2412 if (This->typelib_resource)
2414 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2415 if (This->typelib_global)
2417 This->typelib_base = LockResource(This->typelib_global);
2419 if (This->typelib_base)
2421 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2422 *ppBase = This->typelib_base;
2423 *ppFile = (IUnknown *)&This->lpvtbl;
2424 return S_OK;
2430 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2431 return TYPE_E_CANTLOADLIBRARY;
2434 typedef struct TLB_NEFile
2436 const IUnknownVtbl *lpvtbl;
2437 LONG refs;
2438 LPVOID typelib_base;
2439 } TLB_NEFile;
2441 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2443 if (IsEqualIID(riid, &IID_IUnknown))
2445 *ppv = iface;
2446 IUnknown_AddRef(iface);
2447 return S_OK;
2449 *ppv = NULL;
2450 return E_NOINTERFACE;
2453 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2455 TLB_NEFile *This = (TLB_NEFile *)iface;
2456 return InterlockedIncrement(&This->refs);
2459 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2461 TLB_NEFile *This = (TLB_NEFile *)iface;
2462 ULONG refs = InterlockedDecrement(&This->refs);
2463 if (!refs)
2465 heap_free(This->typelib_base);
2466 heap_free(This);
2468 return refs;
2471 static const IUnknownVtbl TLB_NEFile_Vtable =
2473 TLB_NEFile_QueryInterface,
2474 TLB_NEFile_AddRef,
2475 TLB_NEFile_Release
2478 /***********************************************************************
2479 * read_xx_header [internal]
2481 static int read_xx_header( HFILE lzfd )
2483 IMAGE_DOS_HEADER mzh;
2484 char magic[3];
2486 LZSeek( lzfd, 0, SEEK_SET );
2487 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2488 return 0;
2489 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2490 return 0;
2492 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2493 if ( 2 != LZRead( lzfd, magic, 2 ) )
2494 return 0;
2496 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2498 if ( magic[0] == 'N' && magic[1] == 'E' )
2499 return IMAGE_OS2_SIGNATURE;
2500 if ( magic[0] == 'P' && magic[1] == 'E' )
2501 return IMAGE_NT_SIGNATURE;
2503 magic[2] = '\0';
2504 WARN("Can't handle %s files.\n", magic );
2505 return 0;
2509 /***********************************************************************
2510 * find_ne_resource [internal]
2512 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2513 DWORD *resLen, DWORD *resOff )
2515 IMAGE_OS2_HEADER nehd;
2516 NE_TYPEINFO *typeInfo;
2517 NE_NAMEINFO *nameInfo;
2518 DWORD nehdoffset;
2519 LPBYTE resTab;
2520 DWORD resTabSize;
2521 int count;
2523 /* Read in NE header */
2524 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2525 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2527 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2528 if ( !resTabSize )
2530 TRACE("No resources in NE dll\n" );
2531 return FALSE;
2534 /* Read in resource table */
2535 resTab = heap_alloc( resTabSize );
2536 if ( !resTab ) return FALSE;
2538 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2539 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2541 heap_free( resTab );
2542 return FALSE;
2545 /* Find resource */
2546 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2548 if (!IS_INTRESOURCE(typeid)) /* named type */
2550 BYTE len = strlen( typeid );
2551 while (typeInfo->type_id)
2553 if (!(typeInfo->type_id & 0x8000))
2555 BYTE *p = resTab + typeInfo->type_id;
2556 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2558 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2559 typeInfo->count * sizeof(NE_NAMEINFO));
2562 else /* numeric type id */
2564 WORD id = LOWORD(typeid) | 0x8000;
2565 while (typeInfo->type_id)
2567 if (typeInfo->type_id == id) goto found_type;
2568 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2569 typeInfo->count * sizeof(NE_NAMEINFO));
2572 TRACE("No typeid entry found for %p\n", typeid );
2573 heap_free( resTab );
2574 return FALSE;
2576 found_type:
2577 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2579 if (!IS_INTRESOURCE(resid)) /* named resource */
2581 BYTE len = strlen( resid );
2582 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2584 BYTE *p = resTab + nameInfo->id;
2585 if (nameInfo->id & 0x8000) continue;
2586 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2589 else /* numeric resource id */
2591 WORD id = LOWORD(resid) | 0x8000;
2592 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2593 if (nameInfo->id == id) goto found_name;
2595 TRACE("No resid entry found for %p\n", typeid );
2596 heap_free( resTab );
2597 return FALSE;
2599 found_name:
2600 /* Return resource data */
2601 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2602 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2604 heap_free( resTab );
2605 return TRUE;
2608 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
2610 HFILE lzfd = -1;
2611 OFSTRUCT ofs;
2612 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2613 TLB_NEFile *This;
2615 This = heap_alloc(sizeof(TLB_NEFile));
2616 if (!This) return E_OUTOFMEMORY;
2618 This->lpvtbl = &TLB_NEFile_Vtable;
2619 This->refs = 1;
2620 This->typelib_base = NULL;
2622 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
2623 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
2625 DWORD reslen, offset;
2626 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
2628 This->typelib_base = heap_alloc(reslen);
2629 if( !This->typelib_base )
2630 hr = E_OUTOFMEMORY;
2631 else
2633 LZSeek( lzfd, offset, SEEK_SET );
2634 reslen = LZRead( lzfd, This->typelib_base, reslen );
2635 LZClose( lzfd );
2636 *ppBase = This->typelib_base;
2637 *pdwTLBLength = reslen;
2638 *ppFile = (IUnknown *)&This->lpvtbl;
2639 return S_OK;
2644 if( lzfd >= 0) LZClose( lzfd );
2645 TLB_NEFile_Release((IUnknown *)&This->lpvtbl);
2646 return hr;
2649 typedef struct TLB_Mapping
2651 const IUnknownVtbl *lpvtbl;
2652 LONG refs;
2653 HANDLE file;
2654 HANDLE mapping;
2655 LPVOID typelib_base;
2656 } TLB_Mapping;
2658 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2660 if (IsEqualIID(riid, &IID_IUnknown))
2662 *ppv = iface;
2663 IUnknown_AddRef(iface);
2664 return S_OK;
2666 *ppv = NULL;
2667 return E_NOINTERFACE;
2670 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2672 TLB_Mapping *This = (TLB_Mapping *)iface;
2673 return InterlockedIncrement(&This->refs);
2676 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2678 TLB_Mapping *This = (TLB_Mapping *)iface;
2679 ULONG refs = InterlockedDecrement(&This->refs);
2680 if (!refs)
2682 if (This->typelib_base)
2683 UnmapViewOfFile(This->typelib_base);
2684 if (This->mapping)
2685 CloseHandle(This->mapping);
2686 if (This->file != INVALID_HANDLE_VALUE)
2687 CloseHandle(This->file);
2688 heap_free(This);
2690 return refs;
2693 static const IUnknownVtbl TLB_Mapping_Vtable =
2695 TLB_Mapping_QueryInterface,
2696 TLB_Mapping_AddRef,
2697 TLB_Mapping_Release
2700 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2702 TLB_Mapping *This;
2704 This = heap_alloc(sizeof(TLB_Mapping));
2705 if (!This)
2706 return E_OUTOFMEMORY;
2708 This->lpvtbl = &TLB_Mapping_Vtable;
2709 This->refs = 1;
2710 This->file = INVALID_HANDLE_VALUE;
2711 This->mapping = NULL;
2712 This->typelib_base = NULL;
2714 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2715 if (INVALID_HANDLE_VALUE != This->file)
2717 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2718 if (This->mapping)
2720 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2721 if(This->typelib_base)
2723 /* retrieve file size */
2724 *pdwTLBLength = GetFileSize(This->file, NULL);
2725 *ppBase = This->typelib_base;
2726 *ppFile = (IUnknown *)&This->lpvtbl;
2727 return S_OK;
2732 IUnknown_Release((IUnknown *)&This->lpvtbl);
2733 return TYPE_E_CANTLOADLIBRARY;
2736 /****************************************************************************
2737 * TLB_ReadTypeLib
2739 * find the type of the typelib file and map the typelib resource into
2740 * the memory
2743 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2744 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2746 ITypeLibImpl *entry;
2747 HRESULT ret;
2748 INT index = 1;
2749 LPWSTR index_str, file = (LPWSTR)pszFileName;
2750 LPVOID pBase = NULL;
2751 DWORD dwTLBLength = 0;
2752 IUnknown *pFile = NULL;
2754 *ppTypeLib = NULL;
2756 index_str = strrchrW(pszFileName, '\\');
2757 if(index_str && *++index_str != '\0')
2759 LPWSTR end_ptr;
2760 LONG idx = strtolW(index_str, &end_ptr, 10);
2761 if(*end_ptr == '\0')
2763 int str_len = index_str - pszFileName - 1;
2764 index = idx;
2765 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
2766 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2767 file[str_len] = 0;
2771 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2773 if(strchrW(file, '\\'))
2775 lstrcpyW(pszPath, file);
2777 else
2779 int len = GetSystemDirectoryW(pszPath, cchPath);
2780 pszPath[len] = '\\';
2781 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2785 if(file != pszFileName) heap_free(file);
2787 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2789 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2790 EnterCriticalSection(&cache_section);
2791 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2793 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2795 TRACE("cache hit\n");
2796 *ppTypeLib = (ITypeLib2*)entry;
2797 ITypeLib_AddRef(*ppTypeLib);
2798 LeaveCriticalSection(&cache_section);
2799 return S_OK;
2802 LeaveCriticalSection(&cache_section);
2804 /* now actually load and parse the typelib */
2806 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2807 if (ret == TYPE_E_CANTLOADLIBRARY)
2808 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2809 if (ret == TYPE_E_CANTLOADLIBRARY)
2810 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2811 if (SUCCEEDED(ret))
2813 if (dwTLBLength >= 4)
2815 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2816 if (dwSignature == MSFT_SIGNATURE)
2817 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2818 else if (dwSignature == SLTG_SIGNATURE)
2819 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2820 else
2822 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2823 ret = TYPE_E_CANTLOADLIBRARY;
2826 else
2827 ret = TYPE_E_CANTLOADLIBRARY;
2828 IUnknown_Release(pFile);
2831 if(*ppTypeLib) {
2832 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2834 TRACE("adding to cache\n");
2835 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
2836 lstrcpyW(impl->path, pszPath);
2837 /* We should really canonicalise the path here. */
2838 impl->index = index;
2840 /* FIXME: check if it has added already in the meantime */
2841 EnterCriticalSection(&cache_section);
2842 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2843 impl->prev = NULL;
2844 tlb_cache_first = impl;
2845 LeaveCriticalSection(&cache_section);
2846 ret = S_OK;
2847 } else
2848 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2850 return ret;
2853 /*================== ITypeLib(2) Methods ===================================*/
2855 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2857 ITypeLibImpl* pTypeLibImpl;
2859 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
2860 if (!pTypeLibImpl) return NULL;
2862 pTypeLibImpl->lpVtbl = &tlbvt;
2863 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2864 pTypeLibImpl->ref = 1;
2866 list_init(&pTypeLibImpl->ref_list);
2867 pTypeLibImpl->dispatch_href = -1;
2869 return pTypeLibImpl;
2872 /****************************************************************************
2873 * ITypeLib2_Constructor_MSFT
2875 * loading an MSFT typelib from an in-memory image
2877 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2879 TLBContext cx;
2880 LONG lPSegDir;
2881 MSFT_Header tlbHeader;
2882 MSFT_SegDir tlbSegDir;
2883 ITypeLibImpl * pTypeLibImpl;
2885 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2887 pTypeLibImpl = TypeLibImpl_Constructor();
2888 if (!pTypeLibImpl) return NULL;
2890 /* get pointer to beginning of typelib data */
2891 cx.pos = 0;
2892 cx.oStart=0;
2893 cx.mapping = pLib;
2894 cx.pLibInfo = pTypeLibImpl;
2895 cx.length = dwTLBLength;
2897 /* read header */
2898 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2899 TRACE_(typelib)("header:\n");
2900 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2901 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2902 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2903 return NULL;
2905 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2907 /* there is a small amount of information here until the next important
2908 * part:
2909 * the segment directory . Try to calculate the amount of data */
2910 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2912 /* now read the segment directory */
2913 TRACE("read segment directory (at %d)\n",lPSegDir);
2914 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2915 cx.pTblDir = &tlbSegDir;
2917 /* just check two entries */
2918 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2920 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
2921 heap_free(pTypeLibImpl);
2922 return NULL;
2925 /* now fill our internal data */
2926 /* TLIBATTR fields */
2927 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2929 pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid2;
2930 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2931 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2932 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2933 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2935 pTypeLibImpl->lcid = tlbHeader.lcid;
2937 /* name, eventually add to a hash table */
2938 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2940 /* help info */
2941 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2942 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2944 if( tlbHeader.varflags & HELPDLLFLAG)
2946 int offset;
2947 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2948 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2951 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2953 /* custom data */
2954 if(tlbHeader.CustomDataOffset >= 0)
2956 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2959 /* fill in type descriptions */
2960 if(tlbSegDir.pTypdescTab.length > 0)
2962 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2963 INT16 td[4];
2964 pTypeLibImpl->ctTypeDesc = cTD;
2965 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
2966 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2967 for(i=0; i<cTD; )
2969 /* FIXME: add several sanity checks here */
2970 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2971 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2973 /* FIXME: check safearray */
2974 if(td[3] < 0)
2975 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2976 else
2977 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2979 else if(td[0] == VT_CARRAY)
2981 /* array descr table here */
2982 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
2984 else if(td[0] == VT_USERDEFINED)
2986 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2988 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2991 /* second time around to fill the array subscript info */
2992 for(i=0;i<cTD;i++)
2994 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2995 if(tlbSegDir.pArrayDescriptions.offset>0)
2997 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2998 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3000 if(td[1]<0)
3001 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3002 else
3003 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3005 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3007 for(j = 0; j<td[2]; j++)
3009 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3010 sizeof(INT), &cx, DO_NOT_SEEK);
3011 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3012 sizeof(INT), &cx, DO_NOT_SEEK);
3015 else
3017 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3018 ERR("didn't find array description data\n");
3023 /* imported type libs */
3024 if(tlbSegDir.pImpFiles.offset>0)
3026 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
3027 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3028 UINT16 size;
3030 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3032 char *name;
3034 *ppImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3035 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
3036 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3038 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3039 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3040 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3041 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3043 size >>= 2;
3044 name = heap_alloc_zero(size+1);
3045 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3046 (*ppImpLib)->name = TLB_MultiByteToBSTR(name);
3047 heap_free(name);
3049 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
3050 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3052 ppImpLib = &(*ppImpLib)->next;
3056 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3057 if(pTypeLibImpl->dispatch_href != -1)
3058 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
3060 /* type info's */
3061 if(tlbHeader.nrtypeinfos >= 0 )
3063 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
3064 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
3065 int i;
3067 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3069 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3071 ppTI = &((*ppTI)->next);
3072 (pTypeLibImpl->TypeInfoCount)++;
3076 TRACE("(%p)\n", pTypeLibImpl);
3077 return (ITypeLib2*) pTypeLibImpl;
3081 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3083 char b[3];
3084 int i;
3085 short s;
3087 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3088 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3089 return FALSE;
3092 guid->Data4[0] = s >> 8;
3093 guid->Data4[1] = s & 0xff;
3095 b[2] = '\0';
3096 for(i = 0; i < 6; i++) {
3097 memcpy(b, str + 24 + 2 * i, 2);
3098 guid->Data4[i + 2] = strtol(b, NULL, 16);
3100 return TRUE;
3103 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
3105 WORD bytelen;
3106 DWORD len;
3108 *pBstr = NULL;
3109 bytelen = *(const WORD*)ptr;
3110 if(bytelen == 0xffff) return 2;
3111 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3112 *pBstr = SysAllocStringLen(NULL, len);
3113 if (*pBstr)
3114 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
3115 return bytelen + 2;
3118 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3120 WORD bytelen;
3122 *str = NULL;
3123 bytelen = *(const WORD*)ptr;
3124 if(bytelen == 0xffff) return 2;
3125 *str = heap_alloc(bytelen + 1);
3126 memcpy(*str, ptr + 2, bytelen);
3127 (*str)[bytelen] = '\0';
3128 return bytelen + 2;
3131 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3133 char *ptr = pLibBlk;
3134 WORD w;
3136 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3137 FIXME("libblk magic = %04x\n", w);
3138 return 0;
3141 ptr += 6;
3142 if((w = *(WORD*)ptr) != 0xffff) {
3143 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3144 ptr += w;
3146 ptr += 2;
3148 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
3150 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
3152 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3153 ptr += 4;
3155 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
3156 ptr += 2;
3158 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3159 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3160 else
3161 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = 0;
3162 ptr += 2;
3164 ptr += 4; /* skip res12 */
3166 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
3167 ptr += 2;
3169 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
3170 ptr += 2;
3172 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
3173 ptr += 2;
3175 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
3176 ptr += sizeof(GUID);
3178 return ptr - (char*)pLibBlk;
3181 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3182 typedef struct
3184 unsigned int num;
3185 HREFTYPE refs[1];
3186 } sltg_ref_lookup_t;
3188 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3189 HREFTYPE *typelib_ref)
3191 if(table && typeinfo_ref < table->num)
3193 *typelib_ref = table->refs[typeinfo_ref];
3194 return S_OK;
3197 ERR_(typelib)("Unable to find reference\n");
3198 *typelib_ref = -1;
3199 return E_FAIL;
3202 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3204 BOOL done = FALSE;
3206 while(!done) {
3207 if((*pType & 0xe00) == 0xe00) {
3208 pTD->vt = VT_PTR;
3209 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3210 pTD = pTD->u.lptdesc;
3212 switch(*pType & 0x3f) {
3213 case VT_PTR:
3214 pTD->vt = VT_PTR;
3215 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3216 pTD = pTD->u.lptdesc;
3217 break;
3219 case VT_USERDEFINED:
3220 pTD->vt = VT_USERDEFINED;
3221 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3222 done = TRUE;
3223 break;
3225 case VT_CARRAY:
3227 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3228 array */
3230 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3232 pTD->vt = VT_CARRAY;
3233 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3234 pTD->u.lpadesc->cDims = pSA->cDims;
3235 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3236 pSA->cDims * sizeof(SAFEARRAYBOUND));
3238 pTD = &pTD->u.lpadesc->tdescElem;
3239 break;
3242 case VT_SAFEARRAY:
3244 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3245 useful? */
3247 pType++;
3248 pTD->vt = VT_SAFEARRAY;
3249 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3250 pTD = pTD->u.lptdesc;
3251 break;
3253 default:
3254 pTD->vt = *pType & 0x3f;
3255 done = TRUE;
3256 break;
3258 pType++;
3260 return pType;
3263 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3264 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3266 /* Handle [in/out] first */
3267 if((*pType & 0xc000) == 0xc000)
3268 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3269 else if(*pType & 0x8000)
3270 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3271 else if(*pType & 0x4000)
3272 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3273 else
3274 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3276 if(*pType & 0x2000)
3277 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3279 if(*pType & 0x80)
3280 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3282 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3286 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3287 char *pNameTable)
3289 unsigned int ref;
3290 char *name;
3291 TLBRefType *ref_type;
3292 sltg_ref_lookup_t *table;
3293 HREFTYPE typelib_ref;
3295 if(pRef->magic != SLTG_REF_MAGIC) {
3296 FIXME("Ref magic = %x\n", pRef->magic);
3297 return NULL;
3299 name = ( (char*)pRef->names + pRef->number);
3301 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3302 table->num = pRef->number >> 3;
3304 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3306 /* We don't want the first href to be 0 */
3307 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3309 for(ref = 0; ref < pRef->number >> 3; ref++) {
3310 char *refname;
3311 unsigned int lib_offs, type_num;
3313 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3315 name += SLTG_ReadStringA(name, &refname);
3316 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3317 FIXME_(typelib)("Can't sscanf ref\n");
3318 if(lib_offs != 0xffff) {
3319 TLBImpLib **import = &pTL->pImpLibs;
3321 while(*import) {
3322 if((*import)->offset == lib_offs)
3323 break;
3324 import = &(*import)->next;
3326 if(!*import) {
3327 char fname[MAX_PATH+1];
3328 int len;
3330 *import = heap_alloc_zero(sizeof(**import));
3331 (*import)->offset = lib_offs;
3332 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3333 &(*import)->guid);
3334 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3335 &(*import)->wVersionMajor,
3336 &(*import)->wVersionMinor,
3337 &(*import)->lcid, fname) != 4) {
3338 FIXME_(typelib)("can't sscanf ref %s\n",
3339 pNameTable + lib_offs + 40);
3341 len = strlen(fname);
3342 if(fname[len-1] != '#')
3343 FIXME("fname = %s\n", fname);
3344 fname[len-1] = '\0';
3345 (*import)->name = TLB_MultiByteToBSTR(fname);
3347 ref_type->pImpTLInfo = *import;
3349 /* Store a reference to IDispatch */
3350 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
3351 pTL->dispatch_href = typelib_ref;
3353 } else { /* internal ref */
3354 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3356 ref_type->reference = typelib_ref;
3357 ref_type->index = type_num;
3359 heap_free(refname);
3360 list_add_tail(&pTL->ref_list, &ref_type->entry);
3362 table->refs[ref] = typelib_ref;
3363 typelib_ref += 4;
3365 if((BYTE)*name != SLTG_REF_MAGIC)
3366 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3367 dump_TLBRefType(pTL);
3368 return table;
3371 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3372 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3374 SLTG_ImplInfo *info;
3375 TLBImplType **ppImplType = &pTI->impltypelist;
3376 /* I don't really get this structure, usually it's 0x16 bytes
3377 long, but iuser.tlb contains some that are 0x18 bytes long.
3378 That's ok because we can use the next ptr to jump to the next
3379 one. But how do we know the length of the last one? The WORD
3380 at offs 0x8 might be the clue. For now I'm just assuming that
3381 the last one is the regular 0x16 bytes. */
3383 info = (SLTG_ImplInfo*)pBlk;
3384 while(1) {
3385 *ppImplType = heap_alloc_zero(sizeof(**ppImplType));
3386 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef);
3387 (*ppImplType)->implflags = info->impltypeflags;
3388 pTI->TypeAttr.cImplTypes++;
3389 ppImplType = &(*ppImplType)->next;
3391 if(info->next == 0xffff)
3392 break;
3393 if(OneOnly)
3394 FIXME_(typelib)("Interface inheriting more than one interface\n");
3395 info = (SLTG_ImplInfo*)(pBlk + info->next);
3397 info++; /* see comment at top of function */
3398 return (char*)info;
3401 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3402 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3404 TLBVarDesc **ppVarDesc = &pTI->varlist;
3405 BSTR bstrPrevName = NULL;
3406 SLTG_Variable *pItem;
3407 unsigned short i;
3408 WORD *pType;
3410 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3411 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
3413 *ppVarDesc = heap_alloc_zero(sizeof(**ppVarDesc));
3414 (*ppVarDesc)->vardesc.memid = pItem->memid;
3416 if (pItem->magic != SLTG_VAR_MAGIC &&
3417 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3418 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3419 return;
3422 if (pItem->name == 0xfffe)
3423 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
3424 else
3425 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3427 TRACE_(typelib)("name: %s\n", debugstr_w((*ppVarDesc)->Name));
3428 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3429 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3431 if(pItem->flags & 0x02)
3432 pType = &pItem->type;
3433 else
3434 pType = (WORD*)(pBlk + pItem->type);
3436 if (pItem->flags & ~0xda)
3437 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3439 SLTG_DoElem(pType, pBlk,
3440 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup);
3442 if (TRACE_ON(typelib)) {
3443 char buf[300];
3444 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3445 TRACE_(typelib)("elemdescVar: %s\n", buf);
3448 if (pItem->flags & 0x40) {
3449 TRACE_(typelib)("VAR_DISPATCH\n");
3450 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
3452 else if (pItem->flags & 0x10) {
3453 TRACE_(typelib)("VAR_CONST\n");
3454 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3455 (*ppVarDesc)->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
3456 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3457 if (pItem->flags & 0x08)
3458 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) = pItem->byte_offs;
3459 else {
3460 switch ((*ppVarDesc)->vardesc.elemdescVar.tdesc.vt)
3462 case VT_LPSTR:
3463 case VT_LPWSTR:
3464 case VT_BSTR:
3466 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3467 BSTR str;
3468 TRACE_(typelib)("len = %u\n", len);
3469 if (len == 0xffff) {
3470 str = NULL;
3471 } else {
3472 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3473 str = SysAllocStringLen(NULL, alloc_len);
3474 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3476 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_BSTR;
3477 V_BSTR((*ppVarDesc)->vardesc.u.lpvarValue) = str;
3478 break;
3480 case VT_I2:
3481 case VT_UI2:
3482 case VT_I4:
3483 case VT_UI4:
3484 case VT_INT:
3485 case VT_UINT:
3486 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) =
3487 *(INT*)(pBlk + pItem->byte_offs);
3488 break;
3489 default:
3490 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt);
3494 else {
3495 TRACE_(typelib)("VAR_PERINSTANCE\n");
3496 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3497 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3500 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3501 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
3503 if (pItem->flags & 0x80)
3504 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3506 bstrPrevName = (*ppVarDesc)->Name;
3507 ppVarDesc = &((*ppVarDesc)->next);
3509 pTI->TypeAttr.cVars = cVars;
3512 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3513 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3515 SLTG_Function *pFunc;
3516 unsigned short i;
3517 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3519 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3520 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3522 int param;
3523 WORD *pType, *pArg;
3525 *ppFuncDesc = heap_alloc_zero(sizeof(**ppFuncDesc));
3527 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3528 case SLTG_FUNCTION_MAGIC:
3529 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3530 break;
3531 case SLTG_DISPATCH_FUNCTION_MAGIC:
3532 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3533 break;
3534 case SLTG_STATIC_FUNCTION_MAGIC:
3535 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3536 break;
3537 default:
3538 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3539 heap_free(*ppFuncDesc);
3540 *ppFuncDesc = NULL;
3541 return;
3543 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3545 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3546 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3547 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3548 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3549 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3550 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3552 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3553 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3555 if(pFunc->retnextopt & 0x80)
3556 pType = &pFunc->rettype;
3557 else
3558 pType = (WORD*)(pBlk + pFunc->rettype);
3560 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3562 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3563 heap_alloc_zero((*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3564 (*ppFuncDesc)->pParamDesc =
3565 heap_alloc_zero((*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3567 pArg = (WORD*)(pBlk + pFunc->arg_off);
3569 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3570 char *paramName = pNameTable + *pArg;
3571 BOOL HaveOffs;
3572 /* If arg type follows then paramName points to the 2nd
3573 letter of the name, else the next WORD is an offset to
3574 the arg type and paramName points to the first letter.
3575 So let's take one char off paramName and see if we're
3576 pointing at an alpha-numeric char. However if *pArg is
3577 0xffff or 0xfffe then the param has no name, the former
3578 meaning that the next WORD is the type, the latter
3579 meaning that the next WORD is an offset to the type. */
3581 HaveOffs = FALSE;
3582 if(*pArg == 0xffff)
3583 paramName = NULL;
3584 else if(*pArg == 0xfffe) {
3585 paramName = NULL;
3586 HaveOffs = TRUE;
3588 else if(paramName[-1] && !isalnum(paramName[-1]))
3589 HaveOffs = TRUE;
3591 pArg++;
3593 if(HaveOffs) { /* the next word is an offset to type */
3594 pType = (WORD*)(pBlk + *pArg);
3595 SLTG_DoElem(pType, pBlk,
3596 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3597 pArg++;
3598 } else {
3599 if(paramName)
3600 paramName--;
3601 pArg = SLTG_DoElem(pArg, pBlk,
3602 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3605 /* Are we an optional param ? */
3606 if((*ppFuncDesc)->funcdesc.cParams - param <=
3607 (*ppFuncDesc)->funcdesc.cParamsOpt)
3608 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3610 if(paramName) {
3611 (*ppFuncDesc)->pParamDesc[param].Name =
3612 TLB_MultiByteToBSTR(paramName);
3613 } else {
3614 (*ppFuncDesc)->pParamDesc[param].Name =
3615 SysAllocString((*ppFuncDesc)->Name);
3619 ppFuncDesc = &((*ppFuncDesc)->next);
3620 if(pFunc->next == 0xffff) break;
3622 pTI->TypeAttr.cFuncs = cFuncs;
3625 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3626 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3627 SLTG_TypeInfoTail *pTITail)
3629 char *pFirstItem;
3630 sltg_ref_lookup_t *ref_lookup = NULL;
3632 if(pTIHeader->href_table != 0xffffffff) {
3633 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3634 pNameTable);
3637 pFirstItem = pBlk;
3639 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3640 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3642 heap_free(ref_lookup);
3646 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3647 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3648 const SLTG_TypeInfoTail *pTITail)
3650 char *pFirstItem;
3651 sltg_ref_lookup_t *ref_lookup = NULL;
3653 if(pTIHeader->href_table != 0xffffffff) {
3654 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3655 pNameTable);
3658 pFirstItem = pBlk;
3660 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3661 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3664 if (pTITail->funcs_off != 0xffff)
3665 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3667 heap_free(ref_lookup);
3669 if (TRACE_ON(typelib))
3670 dump_TLBFuncDesc(pTI->funclist);
3673 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3674 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3675 const SLTG_TypeInfoTail *pTITail)
3677 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3680 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3681 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3682 const SLTG_TypeInfoTail *pTITail)
3684 WORD *pType;
3685 sltg_ref_lookup_t *ref_lookup = NULL;
3687 if (pTITail->simple_alias) {
3688 /* if simple alias, no more processing required */
3689 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3690 return;
3693 if(pTIHeader->href_table != 0xffffffff) {
3694 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3695 pNameTable);
3698 /* otherwise it is an offset to a type */
3699 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3701 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3703 heap_free(ref_lookup);
3706 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3707 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3708 const SLTG_TypeInfoTail *pTITail)
3710 sltg_ref_lookup_t *ref_lookup = NULL;
3711 if (pTIHeader->href_table != 0xffffffff)
3712 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3713 pNameTable);
3715 if (pTITail->vars_off != 0xffff)
3716 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3718 if (pTITail->funcs_off != 0xffff)
3719 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3721 if (pTITail->impls_off != 0xffff)
3722 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
3724 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3725 * of dispinterface functions including the IDispatch ones, so
3726 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3727 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3729 heap_free(ref_lookup);
3730 if (TRACE_ON(typelib))
3731 dump_TLBFuncDesc(pTI->funclist);
3734 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3735 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3736 const SLTG_TypeInfoTail *pTITail)
3738 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3741 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3742 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3743 const SLTG_TypeInfoTail *pTITail)
3745 sltg_ref_lookup_t *ref_lookup = NULL;
3746 if (pTIHeader->href_table != 0xffffffff)
3747 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3748 pNameTable);
3750 if (pTITail->vars_off != 0xffff)
3751 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3753 if (pTITail->funcs_off != 0xffff)
3754 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3755 heap_free(ref_lookup);
3756 if (TRACE_ON(typelib))
3757 dump_TypeInfo(pTI);
3760 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3761 managable copy of it into this */
3762 typedef struct {
3763 WORD small_no;
3764 char *index_name;
3765 char *other_name;
3766 WORD res1a;
3767 WORD name_offs;
3768 WORD more_bytes;
3769 char *extra;
3770 WORD res20;
3771 DWORD helpcontext;
3772 WORD res26;
3773 GUID uuid;
3774 } SLTG_InternalOtherTypeInfo;
3776 /****************************************************************************
3777 * ITypeLib2_Constructor_SLTG
3779 * loading a SLTG typelib from an in-memory image
3781 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3783 ITypeLibImpl *pTypeLibImpl;
3784 SLTG_Header *pHeader;
3785 SLTG_BlkEntry *pBlkEntry;
3786 SLTG_Magic *pMagic;
3787 SLTG_Index *pIndex;
3788 SLTG_Pad9 *pPad9;
3789 LPVOID pBlk, pFirstBlk;
3790 SLTG_LibBlk *pLibBlk;
3791 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3792 char *pAfterOTIBlks = NULL;
3793 char *pNameTable, *ptr;
3794 int i;
3795 DWORD len, order;
3796 ITypeInfoImpl **ppTypeInfoImpl;
3798 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3801 pTypeLibImpl = TypeLibImpl_Constructor();
3802 if (!pTypeLibImpl) return NULL;
3804 pHeader = pLib;
3806 TRACE_(typelib)("header:\n");
3807 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3808 pHeader->nrOfFileBlks );
3809 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3810 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3811 pHeader->SLTG_magic);
3812 return NULL;
3815 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3816 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3818 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3819 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3821 /* Next we have a magic block */
3822 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3824 /* Let's see if we're still in sync */
3825 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3826 sizeof(SLTG_COMPOBJ_MAGIC))) {
3827 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3828 return NULL;
3830 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3831 sizeof(SLTG_DIR_MAGIC))) {
3832 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
3833 return NULL;
3836 pIndex = (SLTG_Index*)(pMagic+1);
3838 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3840 pFirstBlk = pPad9 + 1;
3842 /* We'll set up a ptr to the main library block, which is the last one. */
3844 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3845 pBlkEntry[order].next != 0;
3846 order = pBlkEntry[order].next - 1, i++) {
3847 pBlk = (char*)pBlk + pBlkEntry[order].len;
3849 pLibBlk = pBlk;
3851 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3853 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3854 interspersed */
3856 len += 0x40;
3858 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3860 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
3863 ptr = (char*)pLibBlk + len;
3865 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3866 WORD w, extra;
3867 len = 0;
3869 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3871 w = *(WORD*)(ptr + 2);
3872 if(w != 0xffff) {
3873 len += w;
3874 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
3875 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3876 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3878 w = *(WORD*)(ptr + 4 + len);
3879 if(w != 0xffff) {
3880 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3881 len += w;
3882 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
3883 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3884 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3886 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3887 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3888 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3889 if(extra) {
3890 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
3891 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3892 len += extra;
3894 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3895 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3896 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3897 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3898 len += sizeof(SLTG_OtherTypeInfo);
3899 ptr += len;
3902 pAfterOTIBlks = ptr;
3904 /* Skip this WORD and get the next DWORD */
3905 len = *(DWORD*)(pAfterOTIBlks + 2);
3907 /* Now add this to pLibBLk look at what we're pointing at and
3908 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3909 dust and we should be pointing at the beginning of the name
3910 table */
3912 pNameTable = (char*)pLibBlk + len;
3914 switch(*(WORD*)pNameTable) {
3915 case 0xffff:
3916 break;
3917 case 0x0200:
3918 pNameTable += 0x20;
3919 break;
3920 default:
3921 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
3922 break;
3925 pNameTable += 0x216;
3927 pNameTable += 2;
3929 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
3931 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3934 /* Hopefully we now have enough ptrs set up to actually read in
3935 some TypeInfos. It's not clear which order to do them in, so
3936 I'll just follow the links along the BlkEntry chain and read
3937 them in the order in which they are in the file */
3939 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3941 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3942 pBlkEntry[order].next != 0;
3943 order = pBlkEntry[order].next - 1, i++) {
3945 SLTG_TypeInfoHeader *pTIHeader;
3946 SLTG_TypeInfoTail *pTITail;
3947 SLTG_MemberHeader *pMemHeader;
3949 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3950 pOtherTypeInfoBlks[i].index_name)) {
3951 FIXME_(typelib)("Index strings don't match\n");
3952 return NULL;
3955 pTIHeader = pBlk;
3956 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3957 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3958 return NULL;
3960 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
3961 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3962 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3964 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
3965 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3966 (*ppTypeInfoImpl)->index = i;
3967 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3968 pOtherTypeInfoBlks[i].name_offs +
3969 pNameTable);
3970 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3971 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
3972 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3973 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3974 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3975 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3976 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3978 if((*ppTypeInfoImpl)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
3979 (*ppTypeInfoImpl)->TypeAttr.typekind = TKIND_DISPATCH;
3981 if((pTIHeader->typeflags1 & 7) != 2)
3982 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
3983 if(pTIHeader->typeflags3 != 2)
3984 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
3986 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3987 debugstr_w((*ppTypeInfoImpl)->Name),
3988 typekind_desc[pTIHeader->typekind],
3989 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3990 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3992 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3994 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3996 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3997 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3998 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
4000 switch(pTIHeader->typekind) {
4001 case TKIND_ENUM:
4002 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4003 pTIHeader, pTITail);
4004 break;
4006 case TKIND_RECORD:
4007 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4008 pTIHeader, pTITail);
4009 break;
4011 case TKIND_INTERFACE:
4012 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4013 pTIHeader, pTITail);
4014 break;
4016 case TKIND_COCLASS:
4017 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4018 pTIHeader, pTITail);
4019 break;
4021 case TKIND_ALIAS:
4022 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4023 pTIHeader, pTITail);
4024 break;
4026 case TKIND_DISPATCH:
4027 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4028 pTIHeader, pTITail);
4029 break;
4031 case TKIND_MODULE:
4032 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4033 pTIHeader, pTITail);
4034 break;
4036 default:
4037 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4038 break;
4042 /* could get cFuncs, cVars and cImplTypes from here
4043 but we've already set those */
4044 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4045 X(06);
4046 X(16);
4047 X(18);
4048 X(1a);
4049 X(1e);
4050 X(24);
4051 X(26);
4052 X(2a);
4053 X(2c);
4054 X(2e);
4055 X(30);
4056 X(32);
4057 X(34);
4058 #undef X
4059 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
4060 pBlk = (char*)pBlk + pBlkEntry[order].len;
4063 if(i != pTypeLibImpl->TypeInfoCount) {
4064 FIXME("Somehow processed %d TypeInfos\n", i);
4065 return NULL;
4068 heap_free(pOtherTypeInfoBlks);
4069 return (ITypeLib2*)pTypeLibImpl;
4072 /* ITypeLib::QueryInterface
4074 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
4075 ITypeLib2 * iface,
4076 REFIID riid,
4077 VOID **ppvObject)
4079 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4081 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4083 *ppvObject=NULL;
4084 if(IsEqualIID(riid, &IID_IUnknown) ||
4085 IsEqualIID(riid,&IID_ITypeLib)||
4086 IsEqualIID(riid,&IID_ITypeLib2))
4088 *ppvObject = This;
4091 if(*ppvObject)
4093 ITypeLib2_AddRef(iface);
4094 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4095 return S_OK;
4097 TRACE("-- Interface: E_NOINTERFACE\n");
4098 return E_NOINTERFACE;
4101 /* ITypeLib::AddRef
4103 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4105 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4106 ULONG ref = InterlockedIncrement(&This->ref);
4108 TRACE("(%p)->ref was %u\n",This, ref - 1);
4110 return ref;
4113 /* ITypeLib::Release
4115 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4117 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4118 ULONG ref = InterlockedDecrement(&This->ref);
4120 TRACE("(%p)->(%u)\n",This, ref);
4122 if (!ref)
4124 TLBImpLib *pImpLib, *pImpLibNext;
4125 TLBCustData *pCustData, *pCustDataNext;
4126 TLBRefType *ref_type;
4127 void *cursor2;
4128 int i;
4129 ITypeInfoImpl *pTI, *pTINext;
4131 /* remove cache entry */
4132 if(This->path)
4134 TRACE("removing from cache list\n");
4135 EnterCriticalSection(&cache_section);
4136 if (This->next) This->next->prev = This->prev;
4137 if (This->prev) This->prev->next = This->next;
4138 else tlb_cache_first = This->next;
4139 LeaveCriticalSection(&cache_section);
4140 heap_free(This->path);
4142 TRACE(" destroying ITypeLib(%p)\n",This);
4144 SysFreeString(This->Name);
4145 This->Name = NULL;
4147 SysFreeString(This->DocString);
4148 This->DocString = NULL;
4150 SysFreeString(This->HelpFile);
4151 This->HelpFile = NULL;
4153 SysFreeString(This->HelpStringDll);
4154 This->HelpStringDll = NULL;
4156 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
4158 VariantClear(&pCustData->data);
4160 pCustDataNext = pCustData->next;
4161 heap_free(pCustData);
4164 for (i = 0; i < This->ctTypeDesc; i++)
4165 if (This->pTypeDesc[i].vt == VT_CARRAY)
4166 heap_free(This->pTypeDesc[i].u.lpadesc);
4168 heap_free(This->pTypeDesc);
4170 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
4172 if (pImpLib->pImpTypeLib)
4173 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
4174 SysFreeString(pImpLib->name);
4176 pImpLibNext = pImpLib->next;
4177 heap_free(pImpLib);
4180 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4182 list_remove(&ref_type->entry);
4183 heap_free(ref_type);
4186 for (pTI = This->pTypeInfo; pTI; pTI = pTINext)
4188 pTINext = pTI->next;
4189 ITypeInfoImpl_Destroy(pTI);
4191 heap_free(This);
4192 return 0;
4195 return ref;
4198 /* ITypeLib::GetTypeInfoCount
4200 * Returns the number of type descriptions in the type library
4202 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4204 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4205 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4206 return This->TypeInfoCount;
4209 /* ITypeLib::GetTypeInfo
4211 * retrieves the specified type description in the library.
4213 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4214 ITypeLib2 *iface,
4215 UINT index,
4216 ITypeInfo **ppTInfo)
4218 UINT i;
4220 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4221 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
4223 TRACE("(%p)->(index=%d)\n", This, index);
4225 if (!ppTInfo) return E_INVALIDARG;
4227 /* search element n in list */
4228 for(i=0; i < index; i++)
4230 pTypeInfo = pTypeInfo->next;
4231 if (!pTypeInfo)
4233 TRACE("-- element not found\n");
4234 return TYPE_E_ELEMENTNOTFOUND;
4238 *ppTInfo = (ITypeInfo *) pTypeInfo;
4240 ITypeInfo_AddRef(*ppTInfo);
4241 TRACE("-- found (%p)\n",*ppTInfo);
4242 return S_OK;
4246 /* ITypeLibs::GetTypeInfoType
4248 * Retrieves the type of a type description.
4250 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4251 ITypeLib2 *iface,
4252 UINT index,
4253 TYPEKIND *pTKind)
4255 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4256 UINT i;
4257 ITypeInfoImpl *pTInfo = This->pTypeInfo;
4259 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4261 if(!pTKind) return E_INVALIDARG;
4263 if(ITypeLib2_GetTypeInfoCount(iface) <= index)
4264 return TYPE_E_ELEMENTNOTFOUND;
4266 /* search element n in list */
4267 for(i=0; i < index; i++)
4269 if(!pTInfo)
4271 TRACE("-- element not found\n");
4272 return TYPE_E_ELEMENTNOTFOUND;
4274 pTInfo = pTInfo->next;
4277 *pTKind = pTInfo->TypeAttr.typekind;
4278 TRACE("-- found Type (%d)\n", *pTKind);
4279 return S_OK;
4282 /* ITypeLib::GetTypeInfoOfGuid
4284 * Retrieves the type description that corresponds to the specified GUID.
4287 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4288 ITypeLib2 *iface,
4289 REFGUID guid,
4290 ITypeInfo **ppTInfo)
4292 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4293 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
4295 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
4297 if (!pTypeInfo)
4299 WARN("-- element not found\n");
4300 return TYPE_E_ELEMENTNOTFOUND;
4303 /* search linked list for guid */
4304 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
4306 pTypeInfo = pTypeInfo->next;
4308 if (!pTypeInfo)
4310 /* end of list reached */
4311 WARN("-- element not found\n");
4312 return TYPE_E_ELEMENTNOTFOUND;
4316 TRACE("-- found (%p, %s)\n",
4317 pTypeInfo,
4318 debugstr_w(pTypeInfo->Name));
4320 *ppTInfo = (ITypeInfo*)pTypeInfo;
4321 ITypeInfo_AddRef(*ppTInfo);
4322 return S_OK;
4325 /* ITypeLib::GetLibAttr
4327 * Retrieves the structure that contains the library's attributes.
4330 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4331 ITypeLib2 *iface,
4332 LPTLIBATTR *attr)
4334 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4336 TRACE("(%p, %p)\n", This, attr);
4338 if (!attr) return E_INVALIDARG;
4340 *attr = heap_alloc(sizeof(**attr));
4341 if (!*attr) return E_OUTOFMEMORY;
4343 **attr = This->LibAttr;
4344 return S_OK;
4347 /* ITypeLib::GetTypeComp
4349 * Enables a client compiler to bind to a library's types, variables,
4350 * constants, and global functions.
4353 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4354 ITypeLib2 *iface,
4355 ITypeComp **ppTComp)
4357 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4359 TRACE("(%p)->(%p)\n",This,ppTComp);
4360 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4361 ITypeComp_AddRef(*ppTComp);
4363 return S_OK;
4366 /* ITypeLib::GetDocumentation
4368 * Retrieves the library's documentation string, the complete Help file name
4369 * and path, and the context identifier for the library Help topic in the Help
4370 * file.
4372 * On a successful return all non-null BSTR pointers will have been set,
4373 * possibly to NULL.
4375 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4376 ITypeLib2 *iface,
4377 INT index,
4378 BSTR *pBstrName,
4379 BSTR *pBstrDocString,
4380 DWORD *pdwHelpContext,
4381 BSTR *pBstrHelpFile)
4383 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4385 HRESULT result = E_INVALIDARG;
4387 ITypeInfo *pTInfo;
4390 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4391 This, index,
4392 pBstrName, pBstrDocString,
4393 pdwHelpContext, pBstrHelpFile);
4395 if(index<0)
4397 /* documentation for the typelib */
4398 if(pBstrName)
4400 if (This->Name)
4402 if(!(*pBstrName = SysAllocString(This->Name)))
4403 goto memerr1;
4405 else
4406 *pBstrName = NULL;
4408 if(pBstrDocString)
4410 if (This->DocString)
4412 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4413 goto memerr2;
4415 else if (This->Name)
4417 if(!(*pBstrDocString = SysAllocString(This->Name)))
4418 goto memerr2;
4420 else
4421 *pBstrDocString = NULL;
4423 if(pdwHelpContext)
4425 *pdwHelpContext = This->dwHelpContext;
4427 if(pBstrHelpFile)
4429 if (This->HelpFile)
4431 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4432 goto memerr3;
4434 else
4435 *pBstrHelpFile = NULL;
4438 result = S_OK;
4440 else
4442 /* for a typeinfo */
4443 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4445 if(SUCCEEDED(result))
4447 result = ITypeInfo_GetDocumentation(pTInfo,
4448 MEMBERID_NIL,
4449 pBstrName,
4450 pBstrDocString,
4451 pdwHelpContext, pBstrHelpFile);
4453 ITypeInfo_Release(pTInfo);
4456 return result;
4457 memerr3:
4458 if (pBstrDocString) SysFreeString (*pBstrDocString);
4459 memerr2:
4460 if (pBstrName) SysFreeString (*pBstrName);
4461 memerr1:
4462 return STG_E_INSUFFICIENTMEMORY;
4465 /* ITypeLib::IsName
4467 * Indicates whether a passed-in string contains the name of a type or member
4468 * described in the library.
4471 static HRESULT WINAPI ITypeLib2_fnIsName(
4472 ITypeLib2 *iface,
4473 LPOLESTR szNameBuf,
4474 ULONG lHashVal,
4475 BOOL *pfName)
4477 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4478 ITypeInfoImpl *pTInfo;
4479 TLBFuncDesc *pFInfo;
4480 TLBVarDesc *pVInfo;
4481 int i;
4482 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4484 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4485 pfName);
4487 *pfName=TRUE;
4488 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
4489 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4490 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4491 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4492 for(i=0;i<pFInfo->funcdesc.cParams;i++)
4493 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
4494 goto ITypeLib2_fnIsName_exit;
4496 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4497 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4500 *pfName=FALSE;
4502 ITypeLib2_fnIsName_exit:
4503 TRACE("(%p)slow! search for %s: %s found!\n", This,
4504 debugstr_w(szNameBuf), *pfName?"NOT":"");
4506 return S_OK;
4509 /* ITypeLib::FindName
4511 * Finds occurrences of a type description in a type library. This may be used
4512 * to quickly verify that a name exists in a type library.
4515 static HRESULT WINAPI ITypeLib2_fnFindName(
4516 ITypeLib2 *iface,
4517 LPOLESTR szNameBuf,
4518 ULONG lHashVal,
4519 ITypeInfo **ppTInfo,
4520 MEMBERID *rgMemId,
4521 UINT16 *pcFound)
4523 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4524 ITypeInfoImpl *pTInfo;
4525 TLBFuncDesc *pFInfo;
4526 TLBVarDesc *pVInfo;
4527 int i,j = 0;
4528 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4530 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
4531 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4532 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4533 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4534 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
4535 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
4536 goto ITypeLib2_fnFindName_exit;
4539 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4540 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4541 continue;
4542 ITypeLib2_fnFindName_exit:
4543 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4544 ppTInfo[j]=(LPTYPEINFO)pTInfo;
4545 j++;
4547 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4548 This, *pcFound, debugstr_w(szNameBuf), j);
4550 *pcFound=j;
4552 return S_OK;
4555 /* ITypeLib::ReleaseTLibAttr
4557 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4560 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4561 ITypeLib2 *iface,
4562 TLIBATTR *pTLibAttr)
4564 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4565 TRACE("freeing (%p)\n",This);
4566 heap_free(pTLibAttr);
4570 /* ITypeLib2::GetCustData
4572 * gets the custom data
4574 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4575 ITypeLib2 * iface,
4576 REFGUID guid,
4577 VARIANT *pVarVal)
4579 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4580 TLBCustData *pCData;
4582 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4584 if( IsEqualIID(guid, &pCData->guid)) break;
4587 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4589 if(pCData)
4591 VariantInit( pVarVal);
4592 VariantCopy( pVarVal, &pCData->data);
4593 return S_OK;
4595 return E_INVALIDARG; /* FIXME: correct? */
4598 /* ITypeLib2::GetLibStatistics
4600 * Returns statistics about a type library that are required for efficient
4601 * sizing of hash tables.
4604 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4605 ITypeLib2 * iface,
4606 ULONG *pcUniqueNames,
4607 ULONG *pcchUniqueNames)
4609 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4611 FIXME("(%p): stub!\n", This);
4613 if(pcUniqueNames) *pcUniqueNames=1;
4614 if(pcchUniqueNames) *pcchUniqueNames=1;
4615 return S_OK;
4618 /* ITypeLib2::GetDocumentation2
4620 * Retrieves the library's documentation string, the complete Help file name
4621 * and path, the localization context to use, and the context ID for the
4622 * library Help topic in the Help file.
4625 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4626 ITypeLib2 * iface,
4627 INT index,
4628 LCID lcid,
4629 BSTR *pbstrHelpString,
4630 DWORD *pdwHelpStringContext,
4631 BSTR *pbstrHelpStringDll)
4633 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4634 HRESULT result;
4635 ITypeInfo *pTInfo;
4637 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4639 /* the help string should be obtained from the helpstringdll,
4640 * using the _DLLGetDocumentation function, based on the supplied
4641 * lcid. Nice to do sometime...
4643 if(index<0)
4645 /* documentation for the typelib */
4646 if(pbstrHelpString)
4647 *pbstrHelpString=SysAllocString(This->DocString);
4648 if(pdwHelpStringContext)
4649 *pdwHelpStringContext=This->dwHelpContext;
4650 if(pbstrHelpStringDll)
4651 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4653 result = S_OK;
4655 else
4657 /* for a typeinfo */
4658 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4660 if(SUCCEEDED(result))
4662 ITypeInfo2 * pTInfo2;
4663 result = ITypeInfo_QueryInterface(pTInfo,
4664 &IID_ITypeInfo2,
4665 (LPVOID*) &pTInfo2);
4667 if(SUCCEEDED(result))
4669 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4670 MEMBERID_NIL,
4671 lcid,
4672 pbstrHelpString,
4673 pdwHelpStringContext,
4674 pbstrHelpStringDll);
4676 ITypeInfo2_Release(pTInfo2);
4679 ITypeInfo_Release(pTInfo);
4682 return result;
4685 /* ITypeLib2::GetAllCustData
4687 * Gets all custom data items for the library.
4690 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4691 ITypeLib2 * iface,
4692 CUSTDATA *pCustData)
4694 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4695 TLBCustData *pCData;
4696 int i;
4697 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4698 pCustData->prgCustData = heap_alloc_zero(This->ctCustData * sizeof(CUSTDATAITEM));
4699 if(pCustData->prgCustData ){
4700 pCustData->cCustData=This->ctCustData;
4701 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4702 pCustData->prgCustData[i].guid=pCData->guid;
4703 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4705 }else{
4706 ERR(" OUT OF MEMORY!\n");
4707 return E_OUTOFMEMORY;
4709 return S_OK;
4712 static const ITypeLib2Vtbl tlbvt = {
4713 ITypeLib2_fnQueryInterface,
4714 ITypeLib2_fnAddRef,
4715 ITypeLib2_fnRelease,
4716 ITypeLib2_fnGetTypeInfoCount,
4717 ITypeLib2_fnGetTypeInfo,
4718 ITypeLib2_fnGetTypeInfoType,
4719 ITypeLib2_fnGetTypeInfoOfGuid,
4720 ITypeLib2_fnGetLibAttr,
4721 ITypeLib2_fnGetTypeComp,
4722 ITypeLib2_fnGetDocumentation,
4723 ITypeLib2_fnIsName,
4724 ITypeLib2_fnFindName,
4725 ITypeLib2_fnReleaseTLibAttr,
4727 ITypeLib2_fnGetCustData,
4728 ITypeLib2_fnGetLibStatistics,
4729 ITypeLib2_fnGetDocumentation2,
4730 ITypeLib2_fnGetAllCustData
4734 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4736 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4738 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4741 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4743 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4745 return ITypeLib2_AddRef((ITypeLib2 *)This);
4748 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4750 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4752 return ITypeLib2_Release((ITypeLib2 *)This);
4755 static HRESULT WINAPI ITypeLibComp_fnBind(
4756 ITypeComp * iface,
4757 OLECHAR * szName,
4758 ULONG lHash,
4759 WORD wFlags,
4760 ITypeInfo ** ppTInfo,
4761 DESCKIND * pDescKind,
4762 BINDPTR * pBindPtr)
4764 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4765 ITypeInfoImpl *pTypeInfo;
4766 int typemismatch=0;
4768 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4770 *pDescKind = DESCKIND_NONE;
4771 pBindPtr->lptcomp = NULL;
4772 *ppTInfo = NULL;
4774 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4776 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4778 /* FIXME: check wFlags here? */
4779 /* FIXME: we should use a hash table to look this info up using lHash
4780 * instead of an O(n) search */
4781 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4782 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4784 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4786 *pDescKind = DESCKIND_TYPECOMP;
4787 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4788 ITypeComp_AddRef(pBindPtr->lptcomp);
4789 TRACE("module or enum: %s\n", debugstr_w(szName));
4790 return S_OK;
4794 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4795 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4797 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4798 HRESULT hr;
4800 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4801 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4803 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4804 return S_OK;
4806 else if (hr == TYPE_E_TYPEMISMATCH)
4807 typemismatch = 1;
4810 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4811 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4813 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4814 HRESULT hr;
4815 ITypeInfo *subtypeinfo;
4816 BINDPTR subbindptr;
4817 DESCKIND subdesckind;
4819 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4820 &subtypeinfo, &subdesckind, &subbindptr);
4821 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4823 TYPEDESC tdesc_appobject;
4824 const VARDESC vardesc_appobject =
4826 -2, /* memid */
4827 NULL, /* lpstrSchema */
4829 0 /* oInst */
4832 /* ELEMDESC */
4834 /* TYPEDESC */
4836 &tdesc_appobject
4838 VT_PTR
4841 0, /* wVarFlags */
4842 VAR_STATIC /* varkind */
4845 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
4846 tdesc_appobject.vt = VT_USERDEFINED;
4848 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4850 /* cleanup things filled in by Bind call so we can put our
4851 * application object data in there instead */
4852 switch (subdesckind)
4854 case DESCKIND_FUNCDESC:
4855 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4856 break;
4857 case DESCKIND_VARDESC:
4858 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4859 break;
4860 default:
4861 break;
4863 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4865 if (pTypeInfo->hreftype == -1)
4866 FIXME("no hreftype for interface %p\n", pTypeInfo);
4868 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4869 if (FAILED(hr))
4870 return hr;
4872 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4873 *ppTInfo = (ITypeInfo *)pTypeInfo;
4874 ITypeInfo_AddRef(*ppTInfo);
4875 return S_OK;
4877 else if (hr == TYPE_E_TYPEMISMATCH)
4878 typemismatch = 1;
4882 if (typemismatch)
4884 TRACE("type mismatch %s\n", debugstr_w(szName));
4885 return TYPE_E_TYPEMISMATCH;
4887 else
4889 TRACE("name not found %s\n", debugstr_w(szName));
4890 return S_OK;
4894 static HRESULT WINAPI ITypeLibComp_fnBindType(
4895 ITypeComp * iface,
4896 OLECHAR * szName,
4897 ULONG lHash,
4898 ITypeInfo ** ppTInfo,
4899 ITypeComp ** ppTComp)
4901 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4902 ITypeInfoImpl *pTypeInfo;
4904 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4906 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4908 /* FIXME: should use lHash to do the search */
4909 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4911 TRACE("returning %p\n", pTypeInfo);
4912 *ppTInfo = (ITypeInfo *)&pTypeInfo->lpVtbl;
4913 ITypeInfo_AddRef(*ppTInfo);
4914 *ppTComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4915 ITypeComp_AddRef(*ppTComp);
4916 return S_OK;
4920 TRACE("not found\n");
4921 *ppTInfo = NULL;
4922 *ppTComp = NULL;
4923 return S_OK;
4926 static const ITypeCompVtbl tlbtcvt =
4929 ITypeLibComp_fnQueryInterface,
4930 ITypeLibComp_fnAddRef,
4931 ITypeLibComp_fnRelease,
4933 ITypeLibComp_fnBind,
4934 ITypeLibComp_fnBindType
4937 /*================== ITypeInfo(2) Methods ===================================*/
4938 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
4940 ITypeInfoImpl *pTypeInfoImpl;
4942 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
4943 if (pTypeInfoImpl)
4945 pTypeInfoImpl->lpVtbl = &tinfvt;
4946 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4947 pTypeInfoImpl->ref = 0;
4948 pTypeInfoImpl->hreftype = -1;
4949 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4950 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4952 TRACE("(%p)\n", pTypeInfoImpl);
4953 return pTypeInfoImpl;
4956 /* ITypeInfo::QueryInterface
4958 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4959 ITypeInfo2 *iface,
4960 REFIID riid,
4961 VOID **ppvObject)
4963 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4965 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4967 *ppvObject=NULL;
4968 if(IsEqualIID(riid, &IID_IUnknown) ||
4969 IsEqualIID(riid,&IID_ITypeInfo)||
4970 IsEqualIID(riid,&IID_ITypeInfo2))
4971 *ppvObject = This;
4973 if(*ppvObject){
4974 ITypeInfo_AddRef(iface);
4975 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4976 return S_OK;
4978 TRACE("-- Interface: E_NOINTERFACE\n");
4979 return E_NOINTERFACE;
4982 /* ITypeInfo::AddRef
4984 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4986 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4987 ULONG ref = InterlockedIncrement(&This->ref);
4989 TRACE("(%p)->ref is %u\n",This, ref);
4991 if (ref == 1 /* incremented from 0 */)
4992 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4994 return ref;
4997 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
4999 TLBFuncDesc *pFInfo, *pFInfoNext;
5000 TLBVarDesc *pVInfo, *pVInfoNext;
5001 TLBImplType *pImpl, *pImplNext;
5003 TRACE("destroying ITypeInfo(%p)\n",This);
5005 SysFreeString(This->Name);
5006 This->Name = NULL;
5008 SysFreeString(This->DocString);
5009 This->DocString = NULL;
5011 SysFreeString(This->DllName);
5012 This->DllName = NULL;
5014 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
5016 INT i;
5017 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
5019 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
5020 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5022 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5023 heap_free(elemdesc->u.paramdesc.pparamdescex);
5025 SysFreeString(pFInfo->pParamDesc[i].Name);
5027 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5028 heap_free(pFInfo->pParamDesc);
5029 TLB_FreeCustData(pFInfo->pCustData);
5030 if (!IS_INTRESOURCE(pFInfo->Entry) && pFInfo->Entry != (BSTR)-1)
5031 SysFreeString(pFInfo->Entry);
5032 SysFreeString(pFInfo->HelpString);
5033 SysFreeString(pFInfo->Name);
5035 pFInfoNext = pFInfo->next;
5036 heap_free(pFInfo);
5038 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
5040 if (pVInfo->vardesc.varkind == VAR_CONST)
5042 VariantClear(pVInfo->vardesc.u.lpvarValue);
5043 heap_free(pVInfo->vardesc.u.lpvarValue);
5045 TLB_FreeCustData(pVInfo->pCustData);
5046 SysFreeString(pVInfo->Name);
5047 pVInfoNext = pVInfo->next;
5048 heap_free(pVInfo);
5050 for (pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
5052 TLB_FreeCustData(pImpl->pCustData);
5053 pImplNext = pImpl->next;
5054 heap_free(pImpl);
5056 TLB_FreeCustData(This->pCustData);
5058 heap_free(This);
5061 /* ITypeInfo::Release
5063 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5065 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5066 ULONG ref = InterlockedDecrement(&This->ref);
5068 TRACE("(%p)->(%u)\n",This, ref);
5070 if (!ref)
5072 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5073 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
5074 if (not_attached_to_typelib)
5075 heap_free(This);
5076 /* otherwise This will be freed when typelib is freed */
5079 return ref;
5082 /* ITypeInfo::GetTypeAttr
5084 * Retrieves a TYPEATTR structure that contains the attributes of the type
5085 * description.
5088 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5089 LPTYPEATTR *ppTypeAttr)
5091 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5092 SIZE_T size;
5094 TRACE("(%p)\n",This);
5096 size = sizeof(**ppTypeAttr);
5097 if (This->TypeAttr.typekind == TKIND_ALIAS)
5098 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
5100 *ppTypeAttr = heap_alloc(size);
5101 if (!*ppTypeAttr)
5102 return E_OUTOFMEMORY;
5104 **ppTypeAttr = This->TypeAttr;
5106 if (This->TypeAttr.typekind == TKIND_ALIAS)
5107 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5108 &This->TypeAttr.tdescAlias, *ppTypeAttr + 1);
5110 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5111 /* This should include all the inherited funcs */
5112 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
5113 (*ppTypeAttr)->cbSizeVft = 7 * sizeof(void *); /* This is always the size of IDispatch's vtbl */
5114 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5116 return S_OK;
5119 /* ITypeInfo::GetTypeComp
5121 * Retrieves the ITypeComp interface for the type description, which enables a
5122 * client compiler to bind to the type description's members.
5125 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5126 ITypeComp * *ppTComp)
5128 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5130 TRACE("(%p)->(%p)\n", This, ppTComp);
5132 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
5133 ITypeComp_AddRef(*ppTComp);
5134 return S_OK;
5137 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5139 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5140 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5141 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5142 return size;
5145 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5147 *dest = *src;
5148 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5149 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5151 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5152 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5153 *buffer += sizeof(PARAMDESCEX);
5154 *pparamdescex_dest = *pparamdescex_src;
5155 VariantInit(&pparamdescex_dest->varDefaultValue);
5156 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5157 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5159 else
5160 dest->u.paramdesc.pparamdescex = NULL;
5161 return S_OK;
5164 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5166 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5167 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5170 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5172 FUNCDESC *dest;
5173 char *buffer;
5174 SIZE_T size = sizeof(*src);
5175 SHORT i;
5176 HRESULT hr;
5178 size += sizeof(*src->lprgscode) * src->cScodes;
5179 size += TLB_SizeElemDesc(&src->elemdescFunc);
5180 for (i = 0; i < src->cParams; i++)
5182 size += sizeof(ELEMDESC);
5183 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5186 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5187 if (!dest) return E_OUTOFMEMORY;
5189 *dest = *src;
5190 if (dispinterface) /* overwrite funckind */
5191 dest->funckind = FUNC_DISPATCH;
5192 buffer = (char *)(dest + 1);
5194 dest->lprgscode = (SCODE *)buffer;
5195 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5196 buffer += sizeof(*src->lprgscode) * src->cScodes;
5198 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5199 if (FAILED(hr))
5201 SysFreeString((BSTR)dest);
5202 return hr;
5205 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5206 buffer += sizeof(ELEMDESC) * src->cParams;
5207 for (i = 0; i < src->cParams; i++)
5209 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5210 if (FAILED(hr))
5211 break;
5213 if (FAILED(hr))
5215 /* undo the above actions */
5216 for (i = i - 1; i >= 0; i--)
5217 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5218 TLB_FreeElemDesc(&dest->elemdescFunc);
5219 SysFreeString((BSTR)dest);
5220 return hr;
5223 /* special treatment for dispinterfaces: this makes functions appear
5224 * to return their [retval] value when it is really returning an
5225 * HRESULT */
5226 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5228 if (dest->cParams &&
5229 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5231 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5232 if (elemdesc->tdesc.vt != VT_PTR)
5234 ERR("elemdesc should have started with VT_PTR instead of:\n");
5235 if (ERR_ON(ole))
5236 dump_ELEMDESC(elemdesc);
5237 return E_UNEXPECTED;
5240 /* copy last parameter to the return value. we are using a flat
5241 * buffer so there is no danger of leaking memory in
5242 * elemdescFunc */
5243 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5245 /* remove the last parameter */
5246 dest->cParams--;
5248 else
5249 /* otherwise this function is made to appear to have no return
5250 * value */
5251 dest->elemdescFunc.tdesc.vt = VT_VOID;
5255 *dest_ptr = dest;
5256 return S_OK;
5259 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5261 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5262 const TLBFuncDesc *pFDesc;
5263 UINT i;
5265 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
5268 if (pFDesc)
5270 *ppFuncDesc = &pFDesc->funcdesc;
5271 return S_OK;
5274 return TYPE_E_ELEMENTNOTFOUND;
5277 /* internal function to make the inherited interfaces' methods appear
5278 * part of the interface */
5279 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5280 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5282 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5283 HRESULT hr;
5284 UINT implemented_funcs = 0;
5286 if (funcs)
5287 *funcs = 0;
5288 else
5289 *hrefoffset = DISPATCH_HREF_OFFSET;
5291 if(This->impltypelist)
5293 ITypeInfo *pSubTypeInfo;
5294 UINT sub_funcs;
5296 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
5297 if (FAILED(hr))
5298 return hr;
5300 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5301 index,
5302 ppFuncDesc,
5303 &sub_funcs, hrefoffset);
5304 implemented_funcs += sub_funcs;
5305 ITypeInfo_Release(pSubTypeInfo);
5306 if (SUCCEEDED(hr))
5307 return hr;
5308 *hrefoffset += DISPATCH_HREF_OFFSET;
5311 if (funcs)
5312 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
5313 else
5314 *hrefoffset = 0;
5316 if (index < implemented_funcs)
5317 return E_INVALIDARG;
5318 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5319 ppFuncDesc);
5322 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5324 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5325 while (TRUE)
5327 switch (pTypeDesc->vt)
5329 case VT_USERDEFINED:
5330 pTypeDesc->u.hreftype += hrefoffset;
5331 return;
5332 case VT_PTR:
5333 case VT_SAFEARRAY:
5334 pTypeDesc = pTypeDesc->u.lptdesc;
5335 break;
5336 case VT_CARRAY:
5337 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5338 break;
5339 default:
5340 return;
5345 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5347 SHORT i;
5348 for (i = 0; i < pFuncDesc->cParams; i++)
5349 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5350 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5353 /* ITypeInfo::GetFuncDesc
5355 * Retrieves the FUNCDESC structure that contains information about a
5356 * specified function.
5359 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5360 LPFUNCDESC *ppFuncDesc)
5362 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5363 const FUNCDESC *internal_funcdesc;
5364 HRESULT hr;
5365 UINT hrefoffset = 0;
5367 TRACE("(%p) index %d\n", This, index);
5369 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5370 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5371 &internal_funcdesc, NULL,
5372 &hrefoffset);
5373 else
5374 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5375 &internal_funcdesc);
5376 if (FAILED(hr))
5378 WARN("description for function %d not found\n", index);
5379 return hr;
5382 hr = TLB_AllocAndInitFuncDesc(
5383 internal_funcdesc,
5384 ppFuncDesc,
5385 This->TypeAttr.typekind == TKIND_DISPATCH);
5387 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5388 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5390 TRACE("-- 0x%08x\n", hr);
5391 return hr;
5394 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5396 VARDESC *dest;
5397 char *buffer;
5398 SIZE_T size = sizeof(*src);
5399 HRESULT hr;
5401 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5402 if (src->varkind == VAR_CONST)
5403 size += sizeof(VARIANT);
5404 size += TLB_SizeElemDesc(&src->elemdescVar);
5406 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5407 if (!dest) return E_OUTOFMEMORY;
5409 *dest = *src;
5410 buffer = (char *)(dest + 1);
5411 if (src->lpstrSchema)
5413 int len;
5414 dest->lpstrSchema = (LPOLESTR)buffer;
5415 len = strlenW(src->lpstrSchema);
5416 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5417 buffer += (len + 1) * sizeof(WCHAR);
5420 if (src->varkind == VAR_CONST)
5422 HRESULT hr;
5424 dest->u.lpvarValue = (VARIANT *)buffer;
5425 *dest->u.lpvarValue = *src->u.lpvarValue;
5426 buffer += sizeof(VARIANT);
5427 VariantInit(dest->u.lpvarValue);
5428 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5429 if (FAILED(hr))
5431 SysFreeString((BSTR)dest);
5432 return hr;
5435 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5436 if (FAILED(hr))
5438 if (src->varkind == VAR_CONST)
5439 VariantClear(dest->u.lpvarValue);
5440 SysFreeString((BSTR)dest);
5441 return hr;
5443 *dest_ptr = dest;
5444 return S_OK;
5447 /* ITypeInfo::GetVarDesc
5449 * Retrieves a VARDESC structure that describes the specified variable.
5452 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5453 LPVARDESC *ppVarDesc)
5455 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5456 UINT i;
5457 const TLBVarDesc *pVDesc;
5459 TRACE("(%p) index %d\n", This, index);
5461 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
5464 if (pVDesc)
5465 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5467 return E_INVALIDARG;
5470 /* ITypeInfo_GetNames
5472 * Retrieves the variable with the specified member ID (or the name of the
5473 * property or method and its parameters) that correspond to the specified
5474 * function ID.
5476 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5477 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5479 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5480 const TLBFuncDesc *pFDesc;
5481 const TLBVarDesc *pVDesc;
5482 int i;
5483 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5484 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
5485 if(pFDesc)
5487 /* function found, now return function and parameter names */
5488 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5490 if(!i)
5491 *rgBstrNames=SysAllocString(pFDesc->Name);
5492 else
5493 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5495 *pcNames=i;
5497 else
5499 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
5500 if(pVDesc)
5502 *rgBstrNames=SysAllocString(pVDesc->Name);
5503 *pcNames=1;
5505 else
5507 if(This->impltypelist &&
5508 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5509 /* recursive search */
5510 ITypeInfo *pTInfo;
5511 HRESULT result;
5512 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5513 &pTInfo);
5514 if(SUCCEEDED(result))
5516 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5517 ITypeInfo_Release(pTInfo);
5518 return result;
5520 WARN("Could not search inherited interface!\n");
5522 else
5524 WARN("no names found\n");
5526 *pcNames=0;
5527 return TYPE_E_ELEMENTNOTFOUND;
5530 return S_OK;
5534 /* ITypeInfo::GetRefTypeOfImplType
5536 * If a type description describes a COM class, it retrieves the type
5537 * description of the implemented interface types. For an interface,
5538 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5539 * if any exist.
5542 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5543 ITypeInfo2 *iface,
5544 UINT index,
5545 HREFTYPE *pRefType)
5547 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5548 UINT i;
5549 HRESULT hr = S_OK;
5550 const TLBImplType *pImpl = This->impltypelist;
5552 TRACE("(%p) index %d\n", This, index);
5553 if (TRACE_ON(ole)) dump_TypeInfo(This);
5555 if(index==(UINT)-1)
5557 /* only valid on dual interfaces;
5558 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5560 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5562 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
5564 *pRefType = -1;
5566 else
5568 hr = TYPE_E_ELEMENTNOTFOUND;
5571 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5573 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5574 *pRefType = This->pTypeLib->dispatch_href;
5576 else
5578 /* get element n from linked list */
5579 for(i=0; pImpl && i<index; i++)
5581 pImpl = pImpl->next;
5584 if (pImpl)
5585 *pRefType = pImpl->hRef;
5586 else
5587 hr = TYPE_E_ELEMENTNOTFOUND;
5590 if(TRACE_ON(ole))
5592 if(SUCCEEDED(hr))
5593 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5594 else
5595 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5598 return hr;
5601 /* ITypeInfo::GetImplTypeFlags
5603 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5604 * or base interface in a type description.
5606 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5607 UINT index, INT *pImplTypeFlags)
5609 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5610 UINT i;
5611 TLBImplType *pImpl;
5613 TRACE("(%p) index %d\n", This, index);
5614 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5615 i++, pImpl=pImpl->next)
5617 if(i==index && pImpl){
5618 *pImplTypeFlags=pImpl->implflags;
5619 return S_OK;
5621 *pImplTypeFlags=0;
5623 if(This->TypeAttr.typekind==TKIND_DISPATCH && !index)
5624 return S_OK;
5626 WARN("ImplType %d not found\n", index);
5627 return TYPE_E_ELEMENTNOTFOUND;
5630 /* GetIDsOfNames
5631 * Maps between member names and member IDs, and parameter names and
5632 * parameter IDs.
5634 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5635 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5637 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5638 const TLBFuncDesc *pFDesc;
5639 const TLBVarDesc *pVDesc;
5640 HRESULT ret=S_OK;
5641 UINT i;
5643 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5644 cNames);
5646 /* init out parameters in case of failure */
5647 for (i = 0; i < cNames; i++)
5648 pMemId[i] = MEMBERID_NIL;
5650 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5651 int j;
5652 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5653 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5654 for(i=1; i < cNames; i++){
5655 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5656 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5657 break;
5658 if( j<pFDesc->funcdesc.cParams)
5659 pMemId[i]=j;
5660 else
5661 ret=DISP_E_UNKNOWNNAME;
5663 TRACE("-- 0x%08x\n", ret);
5664 return ret;
5667 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5668 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5669 if(cNames) *pMemId=pVDesc->vardesc.memid;
5670 return ret;
5673 /* not found, see if it can be found in an inherited interface */
5674 if(This->impltypelist) {
5675 /* recursive search */
5676 ITypeInfo *pTInfo;
5677 ret=ITypeInfo_GetRefTypeInfo(iface,
5678 This->impltypelist->hRef, &pTInfo);
5679 if(SUCCEEDED(ret)){
5680 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5681 ITypeInfo_Release(pTInfo);
5682 return ret;
5684 WARN("Could not search inherited interface!\n");
5685 } else
5686 WARN("no names found\n");
5687 return DISP_E_UNKNOWNNAME;
5691 #ifdef __i386__
5693 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
5694 __ASM_GLOBAL_FUNC( call_method,
5695 "pushl %ebp\n\t"
5696 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
5697 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
5698 "movl %esp,%ebp\n\t"
5699 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
5700 "pushl %esi\n\t"
5701 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
5702 "pushl %edi\n\t"
5703 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
5704 "movl 12(%ebp),%edx\n\t"
5705 "movl %esp,%edi\n\t"
5706 "shll $2,%edx\n\t"
5707 "jz 1f\n\t"
5708 "subl %edx,%edi\n\t"
5709 "andl $~15,%edi\n\t"
5710 "movl %edi,%esp\n\t"
5711 "movl 12(%ebp),%ecx\n\t"
5712 "movl 16(%ebp),%esi\n\t"
5713 "cld\n\t"
5714 "rep; movsl\n"
5715 "1:\tcall *8(%ebp)\n\t"
5716 "subl %esp,%edi\n\t"
5717 "movl 20(%ebp),%ecx\n\t"
5718 "movl %edi,(%ecx)\n\t"
5719 "leal -8(%ebp),%esp\n\t"
5720 "popl %edi\n\t"
5721 __ASM_CFI(".cfi_same_value %edi\n\t")
5722 "popl %esi\n\t"
5723 __ASM_CFI(".cfi_same_value %esi\n\t")
5724 "popl %ebp\n\t"
5725 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
5726 __ASM_CFI(".cfi_same_value %ebp\n\t")
5727 "ret" )
5729 /* same function but returning floating point */
5730 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
5732 /* ITypeInfo::Invoke
5734 * Invokes a method, or accesses a property of an object, that implements the
5735 * interface described by the type description.
5737 DWORD
5738 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5739 DWORD res;
5740 int stack_offset;
5742 if (TRACE_ON(ole)) {
5743 int i;
5744 TRACE("Calling %p(",func);
5745 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
5746 if (nrargs > 30) TRACE("...");
5747 TRACE(")\n");
5750 switch (callconv) {
5751 case CC_STDCALL:
5752 case CC_CDECL:
5753 res = call_method( func, nrargs, args, &stack_offset );
5754 break;
5755 default:
5756 FIXME("unsupported calling convention %d\n",callconv);
5757 res = -1;
5758 break;
5760 TRACE("returns %08x\n",res);
5761 return res;
5764 #elif defined(__x86_64__)
5766 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
5767 __ASM_GLOBAL_FUNC( call_method,
5768 "pushq %rbp\n\t"
5769 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
5770 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
5771 "movq %rsp,%rbp\n\t"
5772 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
5773 "pushq %rsi\n\t"
5774 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
5775 "pushq %rdi\n\t"
5776 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
5777 "movq %rcx,%rax\n\t"
5778 "movq $4,%rcx\n\t"
5779 "cmp %rcx,%rdx\n\t"
5780 "cmovgq %rdx,%rcx\n\t"
5781 "leaq 0(,%rcx,8),%rdx\n\t"
5782 "subq %rdx,%rsp\n\t"
5783 "andq $~15,%rsp\n\t"
5784 "movq %rsp,%rdi\n\t"
5785 "movq %r8,%rsi\n\t"
5786 "rep; movsq\n\t"
5787 "movq 0(%rsp),%rcx\n\t"
5788 "movq 8(%rsp),%rdx\n\t"
5789 "movq 16(%rsp),%r8\n\t"
5790 "movq 24(%rsp),%r9\n\t"
5791 "movq %rcx,%xmm0\n\t"
5792 "movq %rdx,%xmm1\n\t"
5793 "movq %r8,%xmm2\n\t"
5794 "movq %r9,%xmm3\n\t"
5795 "callq *%rax\n\t"
5796 "leaq -16(%rbp),%rsp\n\t"
5797 "popq %rdi\n\t"
5798 __ASM_CFI(".cfi_same_value %rdi\n\t")
5799 "popq %rsi\n\t"
5800 __ASM_CFI(".cfi_same_value %rsi\n\t")
5801 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
5802 "popq %rbp\n\t"
5803 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
5804 __ASM_CFI(".cfi_same_value %rbp\n\t")
5805 "ret")
5807 /* same function but returning floating point */
5808 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
5810 #endif /* __x86_64__ */
5812 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5814 HRESULT hr = S_OK;
5815 ITypeInfo *tinfo2 = NULL;
5816 TYPEATTR *tattr = NULL;
5818 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5819 if (hr)
5821 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5822 "hr = 0x%08x\n",
5823 tdesc->u.hreftype, hr);
5824 return hr;
5826 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5827 if (hr)
5829 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5830 ITypeInfo_Release(tinfo2);
5831 return hr;
5834 switch (tattr->typekind)
5836 case TKIND_ENUM:
5837 *vt |= VT_I4;
5838 break;
5840 case TKIND_ALIAS:
5841 tdesc = &tattr->tdescAlias;
5842 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5843 break;
5845 case TKIND_INTERFACE:
5846 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5847 *vt |= VT_DISPATCH;
5848 else
5849 *vt |= VT_UNKNOWN;
5850 break;
5852 case TKIND_DISPATCH:
5853 *vt |= VT_DISPATCH;
5854 break;
5856 case TKIND_COCLASS:
5857 *vt |= VT_DISPATCH;
5858 break;
5860 case TKIND_RECORD:
5861 FIXME("TKIND_RECORD unhandled.\n");
5862 hr = E_NOTIMPL;
5863 break;
5865 case TKIND_UNION:
5866 FIXME("TKIND_UNION unhandled.\n");
5867 hr = E_NOTIMPL;
5868 break;
5870 default:
5871 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5872 hr = E_NOTIMPL;
5873 break;
5875 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5876 ITypeInfo_Release(tinfo2);
5877 return hr;
5880 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5882 HRESULT hr = S_OK;
5884 /* enforce only one level of pointer indirection */
5885 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5887 tdesc = tdesc->u.lptdesc;
5889 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5890 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5891 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5892 if ((tdesc->vt == VT_USERDEFINED) ||
5893 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5895 VARTYPE vt_userdefined = 0;
5896 const TYPEDESC *tdesc_userdefined = tdesc;
5897 if (tdesc->vt == VT_PTR)
5899 vt_userdefined = VT_BYREF;
5900 tdesc_userdefined = tdesc->u.lptdesc;
5902 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5903 if ((hr == S_OK) &&
5904 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5905 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5907 *vt |= vt_userdefined;
5908 return S_OK;
5911 *vt = VT_BYREF;
5914 switch (tdesc->vt)
5916 case VT_HRESULT:
5917 *vt |= VT_ERROR;
5918 break;
5919 case VT_USERDEFINED:
5920 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5921 break;
5922 case VT_VOID:
5923 case VT_CARRAY:
5924 case VT_PTR:
5925 case VT_LPSTR:
5926 case VT_LPWSTR:
5927 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5928 hr = DISP_E_BADVARTYPE;
5929 break;
5930 case VT_SAFEARRAY:
5931 *vt |= VT_ARRAY;
5932 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5933 break;
5934 case VT_INT:
5935 *vt |= VT_I4;
5936 break;
5937 case VT_UINT:
5938 *vt |= VT_UI4;
5939 break;
5940 default:
5941 *vt |= tdesc->vt;
5942 break;
5944 return hr;
5947 /***********************************************************************
5948 * DispCallFunc (OLEAUT32.@)
5950 * Invokes a function of the specified calling convention, passing the
5951 * specified arguments and returns the result.
5953 * PARAMS
5954 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5955 * oVft [I] The offset in the vtable. See notes.
5956 * cc [I] Calling convention of the function to call.
5957 * vtReturn [I] The return type of the function.
5958 * cActuals [I] Number of parameters.
5959 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5960 * prgpvarg [I] The arguments to pass.
5961 * pvargResult [O] The return value of the function. Can be NULL.
5963 * RETURNS
5964 * Success: S_OK.
5965 * Failure: HRESULT code.
5967 * NOTES
5968 * The HRESULT return value of this function is not affected by the return
5969 * value of the user supplied function, which is returned in pvargResult.
5971 * If pvInstance is NULL then a non-object function is to be called and oVft
5972 * is the address of the function to call.
5974 * The cc parameter can be one of the following values:
5975 *|CC_FASTCALL
5976 *|CC_CDECL
5977 *|CC_PASCAL
5978 *|CC_STDCALL
5979 *|CC_FPFASTCALL
5980 *|CC_SYSCALL
5981 *|CC_MPWCDECL
5982 *|CC_MPWPASCAL
5985 HRESULT WINAPI
5986 DispCallFunc(
5987 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5988 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5990 #ifdef __i386__
5991 int argspos, stack_offset;
5992 void *func;
5993 UINT i;
5994 DWORD *args;
5996 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5997 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5998 pvargResult, V_VT(pvargResult));
6000 if (cc != CC_STDCALL && cc != CC_CDECL)
6002 FIXME("unsupported calling convention %d\n",cc);
6003 return E_INVALIDARG;
6006 /* maximum size for an argument is sizeof(VARIANT) */
6007 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6009 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6010 argspos = 1;
6011 if (pvInstance)
6013 const FARPROC *vtable = *(FARPROC **)pvInstance;
6014 func = vtable[oVft/sizeof(void *)];
6015 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6017 else func = (void *)oVft;
6019 for (i = 0; i < cActuals; i++)
6021 VARIANT *arg = prgpvarg[i];
6023 switch (prgvt[i])
6025 case VT_EMPTY:
6026 break;
6027 case VT_I8:
6028 case VT_UI8:
6029 case VT_R8:
6030 case VT_DATE:
6031 case VT_CY:
6032 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6033 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6034 break;
6035 case VT_DECIMAL:
6036 case VT_VARIANT:
6037 memcpy( &args[argspos], arg, sizeof(*arg) );
6038 argspos += sizeof(*arg) / sizeof(DWORD);
6039 break;
6040 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6041 args[argspos++] = V_BOOL(arg);
6042 break;
6043 default:
6044 args[argspos++] = V_UI4(arg);
6045 break;
6047 TRACE("arg %u: type %d\n",i,prgvt[i]);
6048 dump_Variant(arg);
6051 switch (vtReturn)
6053 case VT_EMPTY:
6054 call_method( func, argspos - 1, args + 1, &stack_offset );
6055 break;
6056 case VT_R4:
6057 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6058 break;
6059 case VT_R8:
6060 case VT_DATE:
6061 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6062 break;
6063 case VT_DECIMAL:
6064 case VT_VARIANT:
6065 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6066 call_method( func, argspos, args, &stack_offset );
6067 break;
6068 case VT_I8:
6069 case VT_UI8:
6070 case VT_CY:
6071 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6072 break;
6073 default:
6074 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6075 break;
6077 heap_free( args );
6078 if (stack_offset && cc == CC_STDCALL)
6080 WARN( "stack pointer off by %d\n", stack_offset );
6081 return DISP_E_BADCALLEE;
6083 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6084 TRACE("retval: "); dump_Variant(pvargResult);
6085 return S_OK;
6087 #elif defined(__x86_64__)
6088 int argspos;
6089 UINT i;
6090 DWORD_PTR *args;
6091 void *func;
6093 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6094 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6095 pvargResult, V_VT(pvargResult));
6097 if (cc != CC_STDCALL && cc != CC_CDECL)
6099 FIXME("unsupported calling convention %d\n",cc);
6100 return E_INVALIDARG;
6103 /* maximum size for an argument is sizeof(DWORD_PTR) */
6104 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6106 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6107 argspos = 1;
6108 if (pvInstance)
6110 const FARPROC *vtable = *(FARPROC **)pvInstance;
6111 func = vtable[oVft/sizeof(void *)];
6112 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6114 else func = (void *)oVft;
6116 for (i = 0; i < cActuals; i++)
6118 VARIANT *arg = prgpvarg[i];
6120 switch (prgvt[i])
6122 case VT_DECIMAL:
6123 case VT_VARIANT:
6124 args[argspos++] = (ULONG_PTR)arg;
6125 break;
6126 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6127 args[argspos++] = V_BOOL(arg);
6128 break;
6129 default:
6130 args[argspos++] = V_UI8(arg);
6131 break;
6133 TRACE("arg %u: type %d\n",i,prgvt[i]);
6134 dump_Variant(arg);
6137 switch (vtReturn)
6139 case VT_R4:
6140 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6141 break;
6142 case VT_R8:
6143 case VT_DATE:
6144 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6145 break;
6146 case VT_DECIMAL:
6147 case VT_VARIANT:
6148 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6149 call_method( func, argspos, args );
6150 break;
6151 default:
6152 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6153 break;
6155 heap_free( args );
6156 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6157 TRACE("retval: "); dump_Variant(pvargResult);
6158 return S_OK;
6160 #else
6161 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6162 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6163 return E_NOTIMPL;
6164 #endif
6167 #define INVBUF_ELEMENT_SIZE \
6168 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6169 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6170 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6171 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6172 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6173 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6174 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6175 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6177 static HRESULT WINAPI ITypeInfo_fnInvoke(
6178 ITypeInfo2 *iface,
6179 VOID *pIUnk,
6180 MEMBERID memid,
6181 UINT16 wFlags,
6182 DISPPARAMS *pDispParams,
6183 VARIANT *pVarResult,
6184 EXCEPINFO *pExcepInfo,
6185 UINT *pArgErr)
6187 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6188 int i;
6189 unsigned int var_index;
6190 TYPEKIND type_kind;
6191 HRESULT hres;
6192 const TLBFuncDesc *pFuncInfo;
6194 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6195 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6198 if( This->TypeAttr.wTypeFlags & TYPEFLAG_FRESTRICTED )
6199 return DISP_E_MEMBERNOTFOUND;
6201 if (!pDispParams)
6203 ERR("NULL pDispParams not allowed\n");
6204 return E_INVALIDARG;
6207 dump_DispParms(pDispParams);
6209 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6211 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6212 pDispParams->cNamedArgs, pDispParams->cArgs);
6213 return E_INVALIDARG;
6216 /* we do this instead of using GetFuncDesc since it will return a fake
6217 * FUNCDESC for dispinterfaces and we want the real function description */
6218 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
6219 if ((memid == pFuncInfo->funcdesc.memid) &&
6220 (wFlags & pFuncInfo->funcdesc.invkind) &&
6221 (pFuncInfo->funcdesc.wFuncFlags & FUNCFLAG_FRESTRICTED) == 0)
6222 break;
6224 if (pFuncInfo) {
6225 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6227 if (TRACE_ON(ole))
6229 TRACE("invoking:\n");
6230 dump_TLBFuncDescOne(pFuncInfo);
6233 switch (func_desc->funckind) {
6234 case FUNC_PUREVIRTUAL:
6235 case FUNC_VIRTUAL: {
6236 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
6237 VARIANT varresult;
6238 VARIANT retval; /* pointer for storing byref retvals in */
6239 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6240 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6241 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6242 UINT cNamedArgs = pDispParams->cNamedArgs;
6243 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6244 UINT vargs_converted=0;
6246 hres = S_OK;
6248 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6250 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6252 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6253 hres = DISP_E_PARAMNOTFOUND;
6254 goto func_fail;
6258 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6260 ERR("functions with the vararg attribute do not support named arguments\n");
6261 hres = DISP_E_NONAMEDARGS;
6262 goto func_fail;
6265 for (i = 0; i < func_desc->cParams; i++)
6267 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6268 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6269 if (FAILED(hres))
6270 goto func_fail;
6273 TRACE("changing args\n");
6274 for (i = 0; i < func_desc->cParams; i++)
6276 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6277 VARIANTARG *src_arg;
6279 if (wParamFlags & PARAMFLAG_FLCID)
6281 VARIANTARG *arg;
6282 arg = prgpvarg[i] = &rgvarg[i];
6283 V_VT(arg) = VT_I4;
6284 V_I4(arg) = This->pTypeLib->lcid;
6285 continue;
6288 src_arg = NULL;
6290 if (cNamedArgs)
6292 USHORT j;
6293 for (j = 0; j < cNamedArgs; j++)
6294 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
6296 src_arg = &pDispParams->rgvarg[j];
6297 break;
6301 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
6303 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6304 vargs_converted++;
6307 if (wParamFlags & PARAMFLAG_FRETVAL)
6309 /* under most conditions the caller is not allowed to
6310 * pass in a dispparam arg in the index of what would be
6311 * the retval parameter. however, there is an exception
6312 * where the extra parameter is used in an extra
6313 * IDispatch::Invoke below */
6314 if ((i < pDispParams->cArgs) &&
6315 ((func_desc->cParams != 1) || !pVarResult ||
6316 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6318 hres = DISP_E_BADPARAMCOUNT;
6319 break;
6322 /* note: this check is placed so that if the caller passes
6323 * in a VARIANTARG for the retval we just ignore it, like
6324 * native does */
6325 if (i == func_desc->cParams - 1)
6327 VARIANTARG *arg;
6328 arg = prgpvarg[i] = &rgvarg[i];
6329 memset(arg, 0, sizeof(*arg));
6330 V_VT(arg) = rgvt[i];
6331 memset(&retval, 0, sizeof(retval));
6332 V_BYREF(arg) = &retval;
6334 else
6336 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6337 hres = E_UNEXPECTED;
6338 break;
6341 else if (src_arg)
6343 dump_Variant(src_arg);
6345 if (rgvt[i] == VT_VARIANT)
6346 hres = VariantCopy(&rgvarg[i], src_arg);
6347 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6349 if (rgvt[i] == V_VT(src_arg))
6350 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6351 else
6353 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6354 if (wParamFlags & PARAMFLAG_FIN)
6355 hres = VariantCopy(&missing_arg[i], src_arg);
6356 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6358 V_VT(&rgvarg[i]) = rgvt[i];
6360 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6362 SAFEARRAY *a;
6363 SAFEARRAYBOUND bound;
6364 VARIANT *v;
6365 LONG j;
6366 bound.lLbound = 0;
6367 bound.cElements = pDispParams->cArgs-i;
6368 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6370 ERR("SafeArrayCreate failed\n");
6371 break;
6373 hres = SafeArrayAccessData(a, (LPVOID)&v);
6374 if (hres != S_OK)
6376 ERR("SafeArrayAccessData failed with %x\n", hres);
6377 break;
6379 for (j = 0; j < bound.cElements; j++)
6380 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6381 hres = SafeArrayUnaccessData(a);
6382 if (hres != S_OK)
6384 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6385 break;
6387 V_ARRAY(&rgvarg[i]) = a;
6388 V_VT(&rgvarg[i]) = rgvt[i];
6390 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6392 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6393 if (wParamFlags & PARAMFLAG_FIN)
6394 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6395 else
6396 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
6397 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6398 V_VT(&rgvarg[i]) = rgvt[i];
6400 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6402 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6403 V_VT(&rgvarg[i]) = rgvt[i];
6405 else
6407 /* FIXME: this doesn't work for VT_BYREF arguments if
6408 * they are not the same type as in the paramdesc */
6409 V_VT(&rgvarg[i]) = V_VT(src_arg);
6410 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6411 V_VT(&rgvarg[i]) = rgvt[i];
6414 if (FAILED(hres))
6416 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6417 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6418 debugstr_VT(src_arg), debugstr_VF(src_arg));
6419 break;
6421 prgpvarg[i] = &rgvarg[i];
6423 else if (wParamFlags & PARAMFLAG_FOPT)
6425 VARIANTARG *arg;
6426 arg = prgpvarg[i] = &rgvarg[i];
6427 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6429 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6430 if (FAILED(hres))
6431 break;
6433 else
6435 VARIANTARG *missing_arg;
6436 /* if the function wants a pointer to a variant then
6437 * set that up, otherwise just pass the VT_ERROR in
6438 * the argument by value */
6439 if (rgvt[i] & VT_BYREF)
6441 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6442 V_VT(arg) = VT_VARIANT | VT_BYREF;
6443 V_VARIANTREF(arg) = missing_arg;
6445 else
6446 missing_arg = arg;
6447 V_VT(missing_arg) = VT_ERROR;
6448 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6451 else
6453 hres = DISP_E_BADPARAMCOUNT;
6454 break;
6457 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6459 /* VT_VOID is a special case for return types, so it is not
6460 * handled in the general function */
6461 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6462 V_VT(&varresult) = VT_EMPTY;
6463 else
6465 V_VT(&varresult) = 0;
6466 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6467 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6470 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6471 V_VT(&varresult), func_desc->cParams, rgvt,
6472 prgpvarg, &varresult);
6474 vargs_converted = 0;
6476 for (i = 0; i < func_desc->cParams; i++)
6478 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6479 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6481 if (wParamFlags & PARAMFLAG_FLCID)
6482 continue;
6483 else if (wParamFlags & PARAMFLAG_FRETVAL)
6485 if (TRACE_ON(ole))
6487 TRACE("[retval] value: ");
6488 dump_Variant(prgpvarg[i]);
6491 if (pVarResult)
6493 VariantInit(pVarResult);
6494 /* deref return value */
6495 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6498 VARIANT_ClearInd(prgpvarg[i]);
6500 else if (vargs_converted < pDispParams->cArgs)
6502 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6503 if (wParamFlags & PARAMFLAG_FOUT)
6505 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
6507 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6509 if (FAILED(hres))
6511 ERR("failed to convert param %d to vt %d\n", i,
6512 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
6513 break;
6517 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6518 func_desc->cParamsOpt < 0 &&
6519 i == func_desc->cParams-1)
6521 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6522 LONG j, ubound;
6523 VARIANT *v;
6524 hres = SafeArrayGetUBound(a, 1, &ubound);
6525 if (hres != S_OK)
6527 ERR("SafeArrayGetUBound failed with %x\n", hres);
6528 break;
6530 hres = SafeArrayAccessData(a, (LPVOID)&v);
6531 if (hres != S_OK)
6533 ERR("SafeArrayAccessData failed with %x\n", hres);
6534 break;
6536 for (j = 0; j <= ubound; j++)
6537 VariantClear(&v[j]);
6538 hres = SafeArrayUnaccessData(a);
6539 if (hres != S_OK)
6541 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6542 break;
6545 VariantClear(&rgvarg[i]);
6546 vargs_converted++;
6548 else if (wParamFlags & PARAMFLAG_FOPT)
6550 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6551 VariantClear(&rgvarg[i]);
6554 VariantClear(&missing_arg[i]);
6557 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6559 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6560 hres = DISP_E_EXCEPTION;
6561 if (pExcepInfo)
6563 IErrorInfo *pErrorInfo;
6564 pExcepInfo->scode = V_ERROR(&varresult);
6565 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6567 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6568 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6569 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6570 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6572 IErrorInfo_Release(pErrorInfo);
6576 if (V_VT(&varresult) != VT_ERROR)
6578 TRACE("varresult value: ");
6579 dump_Variant(&varresult);
6581 if (pVarResult)
6583 VariantClear(pVarResult);
6584 *pVarResult = varresult;
6586 else
6587 VariantClear(&varresult);
6590 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6591 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6592 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6593 (pDispParams->cArgs != 0))
6595 if (V_VT(pVarResult) == VT_DISPATCH)
6597 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6598 /* Note: not VariantClear; we still need the dispatch
6599 * pointer to be valid */
6600 VariantInit(pVarResult);
6601 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6602 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6603 pDispParams, pVarResult, pExcepInfo, pArgErr);
6604 IDispatch_Release(pDispatch);
6606 else
6608 VariantClear(pVarResult);
6609 hres = DISP_E_NOTACOLLECTION;
6613 func_fail:
6614 heap_free(buffer);
6615 break;
6617 case FUNC_DISPATCH: {
6618 IDispatch *disp;
6620 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6621 if (SUCCEEDED(hres)) {
6622 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6623 hres = IDispatch_Invoke(
6624 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6625 pVarResult,pExcepInfo,pArgErr
6627 if (FAILED(hres))
6628 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6629 IDispatch_Release(disp);
6630 } else
6631 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6632 break;
6634 default:
6635 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6636 hres = E_FAIL;
6637 break;
6640 TRACE("-- 0x%08x\n", hres);
6641 return hres;
6643 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6644 VARDESC *var_desc;
6646 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6647 if(FAILED(hres)) return hres;
6649 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6650 dump_VARDESC(var_desc);
6651 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6652 return E_NOTIMPL;
6655 /* not found, look for it in inherited interfaces */
6656 ITypeInfo2_GetTypeKind(iface, &type_kind);
6657 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6658 if(This->impltypelist) {
6659 /* recursive search */
6660 ITypeInfo *pTInfo;
6661 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6662 if(SUCCEEDED(hres)){
6663 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6664 ITypeInfo_Release(pTInfo);
6665 return hres;
6667 WARN("Could not search inherited interface!\n");
6670 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6671 return DISP_E_MEMBERNOTFOUND;
6674 /* ITypeInfo::GetDocumentation
6676 * Retrieves the documentation string, the complete Help file name and path,
6677 * and the context ID for the Help topic for a specified type description.
6679 * (Can be tested by the Visual Basic Editor in Word for instance.)
6681 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6682 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6683 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6685 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6686 const TLBFuncDesc *pFDesc;
6687 const TLBVarDesc *pVDesc;
6688 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6689 " HelpContext(%p) HelpFile(%p)\n",
6690 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6691 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6692 if(pBstrName)
6693 *pBstrName=SysAllocString(This->Name);
6694 if(pBstrDocString)
6695 *pBstrDocString=SysAllocString(This->DocString);
6696 if(pdwHelpContext)
6697 *pdwHelpContext=This->dwHelpContext;
6698 if(pBstrHelpFile)
6699 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6700 return S_OK;
6701 }else {/* for a member */
6702 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6703 if(pFDesc->funcdesc.memid==memid){
6704 if(pBstrName)
6705 *pBstrName = SysAllocString(pFDesc->Name);
6706 if(pBstrDocString)
6707 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6708 if(pdwHelpContext)
6709 *pdwHelpContext=pFDesc->helpcontext;
6710 return S_OK;
6712 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6713 if(pVDesc->vardesc.memid==memid){
6714 if(pBstrName)
6715 *pBstrName = SysAllocString(pVDesc->Name);
6716 if(pBstrDocString)
6717 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6718 if(pdwHelpContext)
6719 *pdwHelpContext=pVDesc->HelpContext;
6720 return S_OK;
6724 if(This->impltypelist &&
6725 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6726 /* recursive search */
6727 ITypeInfo *pTInfo;
6728 HRESULT result;
6729 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6730 &pTInfo);
6731 if(SUCCEEDED(result)) {
6732 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6733 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6734 ITypeInfo_Release(pTInfo);
6735 return result;
6737 WARN("Could not search inherited interface!\n");
6740 WARN("member %d not found\n", memid);
6741 return TYPE_E_ELEMENTNOTFOUND;
6744 /* ITypeInfo::GetDllEntry
6746 * Retrieves a description or specification of an entry point for a function
6747 * in a DLL.
6749 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6750 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6751 WORD *pwOrdinal)
6753 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6754 const TLBFuncDesc *pFDesc;
6756 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6758 if (pBstrDllName) *pBstrDllName = NULL;
6759 if (pBstrName) *pBstrName = NULL;
6760 if (pwOrdinal) *pwOrdinal = 0;
6762 if (This->TypeAttr.typekind != TKIND_MODULE)
6763 return TYPE_E_BADMODULEKIND;
6765 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6766 if(pFDesc->funcdesc.memid==memid){
6767 dump_TypeInfo(This);
6768 if (TRACE_ON(ole))
6769 dump_TLBFuncDescOne(pFDesc);
6771 if (pBstrDllName)
6772 *pBstrDllName = SysAllocString(This->DllName);
6774 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6775 if (pBstrName)
6776 *pBstrName = SysAllocString(pFDesc->Entry);
6777 if (pwOrdinal)
6778 *pwOrdinal = -1;
6779 return S_OK;
6781 if (pBstrName)
6782 *pBstrName = NULL;
6783 if (pwOrdinal)
6784 *pwOrdinal = LOWORD(pFDesc->Entry);
6785 return S_OK;
6787 return TYPE_E_ELEMENTNOTFOUND;
6790 /* internal function to make the inherited interfaces' methods appear
6791 * part of the interface */
6792 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6793 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6795 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6796 HRESULT hr;
6798 TRACE("%p, 0x%x\n", iface, *hRefType);
6800 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK))
6802 ITypeInfo *pSubTypeInfo;
6804 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
6805 if (FAILED(hr))
6806 return hr;
6808 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6809 hRefType, ppTInfo);
6810 ITypeInfo_Release(pSubTypeInfo);
6811 if (SUCCEEDED(hr))
6812 return hr;
6814 *hRefType -= DISPATCH_HREF_OFFSET;
6816 if (!(*hRefType & DISPATCH_HREF_MASK))
6817 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6818 else
6819 return E_FAIL;
6822 /* ITypeInfo::GetRefTypeInfo
6824 * If a type description references other type descriptions, it retrieves
6825 * the referenced type descriptions.
6827 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6828 ITypeInfo2 *iface,
6829 HREFTYPE hRefType,
6830 ITypeInfo **ppTInfo)
6832 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6833 HRESULT result = E_FAIL;
6835 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6837 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6838 ITypeInfo_AddRef(*ppTInfo);
6839 result = S_OK;
6841 else if (hRefType == -1 &&
6842 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6843 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6845 /* when we meet a DUAL dispinterface, we must create the interface
6846 * version of it.
6848 ITypeInfoImpl *pTypeInfoImpl = ITypeInfoImpl_Constructor();
6851 /* the interface version contains the same information as the dispinterface
6852 * copy the contents of the structs.
6854 *pTypeInfoImpl = *This;
6855 pTypeInfoImpl->ref = 0;
6857 /* change the type to interface */
6858 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6860 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6862 /* the AddRef implicitly adds a reference to the parent typelib, which
6863 * stops the copied data from being destroyed until the new typeinfo's
6864 * refcount goes to zero, but we need to signal to the new instance to
6865 * not free its data structures when it is destroyed */
6866 pTypeInfoImpl->not_attached_to_typelib = TRUE;
6868 ITypeInfo_AddRef(*ppTInfo);
6870 result = S_OK;
6872 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6873 (This->TypeAttr.typekind == TKIND_DISPATCH))
6875 HREFTYPE href_dispatch = hRefType;
6876 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6877 } else {
6878 TLBRefType *ref_type;
6879 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6881 if(ref_type->reference == hRefType)
6882 break;
6884 if(&ref_type->entry == &This->pTypeLib->ref_list)
6886 FIXME("Can't find pRefType for ref %x\n", hRefType);
6887 goto end;
6889 if(hRefType != -1) {
6890 ITypeLib *pTLib = NULL;
6892 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6893 UINT Index;
6894 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6895 } else {
6896 if(ref_type->pImpTLInfo->pImpTypeLib) {
6897 TRACE("typeinfo in imported typelib that is already loaded\n");
6898 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6899 ITypeLib2_AddRef(pTLib);
6900 result = S_OK;
6901 } else {
6902 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6903 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6904 ref_type->pImpTLInfo->wVersionMajor,
6905 ref_type->pImpTLInfo->wVersionMinor,
6906 ref_type->pImpTLInfo->lcid,
6907 &pTLib);
6909 if(FAILED(result)) {
6910 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6911 result=LoadTypeLib(libnam, &pTLib);
6912 SysFreeString(libnam);
6914 if(SUCCEEDED(result)) {
6915 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6916 ITypeLib2_AddRef(pTLib);
6920 if(SUCCEEDED(result)) {
6921 if(ref_type->index == TLB_REF_USE_GUID)
6922 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6923 &ref_type->guid,
6924 ppTInfo);
6925 else
6926 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6927 ppTInfo);
6929 if (pTLib != NULL)
6930 ITypeLib2_Release(pTLib);
6934 end:
6935 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6936 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6937 return result;
6940 /* ITypeInfo::AddressOfMember
6942 * Retrieves the addresses of static functions or variables, such as those
6943 * defined in a DLL.
6945 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6946 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6948 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6949 HRESULT hr;
6950 BSTR dll, entry;
6951 WORD ordinal;
6952 HMODULE module;
6954 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6956 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6957 if (FAILED(hr))
6958 return hr;
6960 module = LoadLibraryW(dll);
6961 if (!module)
6963 ERR("couldn't load %s\n", debugstr_w(dll));
6964 SysFreeString(dll);
6965 SysFreeString(entry);
6966 return STG_E_FILENOTFOUND;
6968 /* FIXME: store library somewhere where we can free it */
6970 if (entry)
6972 LPSTR entryA;
6973 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6974 entryA = heap_alloc(len);
6975 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6977 *ppv = GetProcAddress(module, entryA);
6978 if (!*ppv)
6979 ERR("function not found %s\n", debugstr_a(entryA));
6981 heap_free(entryA);
6983 else
6985 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6986 if (!*ppv)
6987 ERR("function not found %d\n", ordinal);
6990 SysFreeString(dll);
6991 SysFreeString(entry);
6993 if (!*ppv)
6994 return TYPE_E_DLLFUNCTIONNOTFOUND;
6996 return S_OK;
6999 /* ITypeInfo::CreateInstance
7001 * Creates a new instance of a type that describes a component object class
7002 * (coclass).
7004 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7005 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7007 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7008 HRESULT hr;
7009 TYPEATTR *pTA;
7011 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7013 *ppvObj = NULL;
7015 if(pOuterUnk)
7017 WARN("Not able to aggregate\n");
7018 return CLASS_E_NOAGGREGATION;
7021 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
7022 if(FAILED(hr)) return hr;
7024 if(pTA->typekind != TKIND_COCLASS)
7026 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7027 hr = E_INVALIDARG;
7028 goto end;
7031 hr = S_FALSE;
7032 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7034 IUnknown *pUnk;
7035 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7036 TRACE("GetActiveObject rets %08x\n", hr);
7037 if(hr == S_OK)
7039 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7040 IUnknown_Release(pUnk);
7044 if(hr != S_OK)
7045 hr = CoCreateInstance(&pTA->guid, NULL,
7046 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7047 riid, ppvObj);
7049 end:
7050 ITypeInfo_ReleaseTypeAttr(iface, pTA);
7051 return hr;
7054 /* ITypeInfo::GetMops
7056 * Retrieves marshalling information.
7058 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7059 BSTR *pBstrMops)
7061 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7062 FIXME("(%p %d) stub!\n", This, memid);
7063 *pBstrMops = NULL;
7064 return S_OK;
7067 /* ITypeInfo::GetContainingTypeLib
7069 * Retrieves the containing type library and the index of the type description
7070 * within that type library.
7072 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7073 ITypeLib * *ppTLib, UINT *pIndex)
7075 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7077 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7078 if (pIndex) {
7079 *pIndex=This->index;
7080 TRACE("returning pIndex=%d\n", *pIndex);
7083 if (ppTLib) {
7084 *ppTLib=(LPTYPELIB )(This->pTypeLib);
7085 ITypeLib2_AddRef(*ppTLib);
7086 TRACE("returning ppTLib=%p\n", *ppTLib);
7089 return S_OK;
7092 /* ITypeInfo::ReleaseTypeAttr
7094 * Releases a TYPEATTR previously returned by GetTypeAttr.
7097 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7098 TYPEATTR* pTypeAttr)
7100 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7101 TRACE("(%p)->(%p)\n", This, pTypeAttr);
7102 heap_free(pTypeAttr);
7105 /* ITypeInfo::ReleaseFuncDesc
7107 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7109 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7110 ITypeInfo2 *iface,
7111 FUNCDESC *pFuncDesc)
7113 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7114 SHORT i;
7116 TRACE("(%p)->(%p)\n", This, pFuncDesc);
7118 for (i = 0; i < pFuncDesc->cParams; i++)
7119 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7120 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7122 SysFreeString((BSTR)pFuncDesc);
7125 /* ITypeInfo::ReleaseVarDesc
7127 * Releases a VARDESC previously returned by GetVarDesc.
7129 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7130 VARDESC *pVarDesc)
7132 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7133 TRACE("(%p)->(%p)\n", This, pVarDesc);
7135 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
7136 if (pVarDesc->varkind == VAR_CONST)
7137 VariantClear(pVarDesc->u.lpvarValue);
7138 SysFreeString((BSTR)pVarDesc);
7141 /* ITypeInfo2::GetTypeKind
7143 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7146 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7147 TYPEKIND *pTypeKind)
7149 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7150 *pTypeKind=This->TypeAttr.typekind;
7151 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7152 return S_OK;
7155 /* ITypeInfo2::GetTypeFlags
7157 * Returns the type flags without any allocations. This returns a DWORD type
7158 * flag, which expands the type flags without growing the TYPEATTR (type
7159 * attribute).
7162 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7164 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7165 *pTypeFlags=This->TypeAttr.wTypeFlags;
7166 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7167 return S_OK;
7170 /* ITypeInfo2::GetFuncIndexOfMemId
7171 * Binds to a specific member based on a known DISPID, where the member name
7172 * is not known (for example, when binding to a default member).
7175 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7176 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7178 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7179 const TLBFuncDesc *pFuncInfo;
7180 int i;
7181 HRESULT result;
7183 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
7184 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7185 break;
7186 if(pFuncInfo) {
7187 *pFuncIndex = i;
7188 result = S_OK;
7189 } else
7190 result = TYPE_E_ELEMENTNOTFOUND;
7192 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7193 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7194 return result;
7197 /* TypeInfo2::GetVarIndexOfMemId
7199 * Binds to a specific member based on a known DISPID, where the member name
7200 * is not known (for example, when binding to a default member).
7203 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7204 MEMBERID memid, UINT *pVarIndex)
7206 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7207 TLBVarDesc *pVarInfo;
7208 int i;
7209 HRESULT result;
7210 for(i=0, pVarInfo=This->varlist; pVarInfo &&
7211 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
7213 if(pVarInfo) {
7214 *pVarIndex = i;
7215 result = S_OK;
7216 } else
7217 result = TYPE_E_ELEMENTNOTFOUND;
7219 TRACE("(%p) memid 0x%08x -> %s\n", This,
7220 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7221 return result;
7224 /* ITypeInfo2::GetCustData
7226 * Gets the custom data
7228 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7229 ITypeInfo2 * iface,
7230 REFGUID guid,
7231 VARIANT *pVarVal)
7233 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7234 TLBCustData *pCData;
7236 for(pCData=This->pCustData; pCData; pCData = pCData->next)
7237 if( IsEqualIID(guid, &pCData->guid)) break;
7239 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7241 VariantInit( pVarVal);
7242 if (pCData)
7243 VariantCopy( pVarVal, &pCData->data);
7244 else
7245 VariantClear( pVarVal );
7246 return S_OK;
7249 /* ITypeInfo2::GetFuncCustData
7251 * Gets the custom data
7253 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7254 ITypeInfo2 * iface,
7255 UINT index,
7256 REFGUID guid,
7257 VARIANT *pVarVal)
7259 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7260 TLBCustData *pCData=NULL;
7261 TLBFuncDesc * pFDesc;
7262 UINT i;
7263 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7264 pFDesc=pFDesc->next);
7266 if(pFDesc)
7267 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
7268 if( IsEqualIID(guid, &pCData->guid)) break;
7270 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7272 if(pCData){
7273 VariantInit( pVarVal);
7274 VariantCopy( pVarVal, &pCData->data);
7275 return S_OK;
7277 return E_INVALIDARG; /* FIXME: correct? */
7280 /* ITypeInfo2::GetParamCustData
7282 * Gets the custom data
7284 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7285 ITypeInfo2 * iface,
7286 UINT indexFunc,
7287 UINT indexParam,
7288 REFGUID guid,
7289 VARIANT *pVarVal)
7291 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7292 TLBCustData *pCData=NULL;
7293 TLBFuncDesc * pFDesc;
7294 UINT i;
7296 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
7298 if(pFDesc && indexParam<pFDesc->funcdesc.cParams)
7299 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
7300 pCData = pCData->next)
7301 if( IsEqualIID(guid, &pCData->guid)) break;
7303 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7305 if(pCData)
7307 VariantInit( pVarVal);
7308 VariantCopy( pVarVal, &pCData->data);
7309 return S_OK;
7311 return E_INVALIDARG; /* FIXME: correct? */
7314 /* ITypeInfo2::GetVarCustData
7316 * Gets the custom data
7318 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7319 ITypeInfo2 * iface,
7320 UINT index,
7321 REFGUID guid,
7322 VARIANT *pVarVal)
7324 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7325 TLBCustData *pCData=NULL;
7326 TLBVarDesc * pVDesc;
7327 UINT i;
7329 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
7331 if(pVDesc)
7333 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
7335 if( IsEqualIID(guid, &pCData->guid)) break;
7339 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7341 if(pCData)
7343 VariantInit( pVarVal);
7344 VariantCopy( pVarVal, &pCData->data);
7345 return S_OK;
7347 return E_INVALIDARG; /* FIXME: correct? */
7350 /* ITypeInfo2::GetImplCustData
7352 * Gets the custom data
7354 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7355 ITypeInfo2 * iface,
7356 UINT index,
7357 REFGUID guid,
7358 VARIANT *pVarVal)
7360 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7361 TLBCustData *pCData=NULL;
7362 TLBImplType * pRDesc;
7363 UINT i;
7365 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
7367 if(pRDesc)
7369 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
7371 if( IsEqualIID(guid, &pCData->guid)) break;
7375 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7377 if(pCData)
7379 VariantInit( pVarVal);
7380 VariantCopy( pVarVal, &pCData->data);
7381 return S_OK;
7383 return E_INVALIDARG; /* FIXME: correct? */
7386 /* ITypeInfo2::GetDocumentation2
7388 * Retrieves the documentation string, the complete Help file name and path,
7389 * the localization context to use, and the context ID for the library Help
7390 * topic in the Help file.
7393 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7394 ITypeInfo2 * iface,
7395 MEMBERID memid,
7396 LCID lcid,
7397 BSTR *pbstrHelpString,
7398 DWORD *pdwHelpStringContext,
7399 BSTR *pbstrHelpStringDll)
7401 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7402 const TLBFuncDesc *pFDesc;
7403 const TLBVarDesc *pVDesc;
7404 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7405 "HelpStringContext(%p) HelpStringDll(%p)\n",
7406 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7407 pbstrHelpStringDll );
7408 /* the help string should be obtained from the helpstringdll,
7409 * using the _DLLGetDocumentation function, based on the supplied
7410 * lcid. Nice to do sometime...
7412 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7413 if(pbstrHelpString)
7414 *pbstrHelpString=SysAllocString(This->Name);
7415 if(pdwHelpStringContext)
7416 *pdwHelpStringContext=This->dwHelpStringContext;
7417 if(pbstrHelpStringDll)
7418 *pbstrHelpStringDll=
7419 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7420 return S_OK;
7421 }else {/* for a member */
7422 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
7423 if(pFDesc->funcdesc.memid==memid){
7424 if(pbstrHelpString)
7425 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
7426 if(pdwHelpStringContext)
7427 *pdwHelpStringContext=pFDesc->HelpStringContext;
7428 if(pbstrHelpStringDll)
7429 *pbstrHelpStringDll=
7430 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7431 return S_OK;
7433 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
7434 if(pVDesc->vardesc.memid==memid){
7435 if(pbstrHelpString)
7436 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
7437 if(pdwHelpStringContext)
7438 *pdwHelpStringContext=pVDesc->HelpStringContext;
7439 if(pbstrHelpStringDll)
7440 *pbstrHelpStringDll=
7441 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7442 return S_OK;
7445 return TYPE_E_ELEMENTNOTFOUND;
7448 /* ITypeInfo2::GetAllCustData
7450 * Gets all custom data items for the Type info.
7453 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7454 ITypeInfo2 * iface,
7455 CUSTDATA *pCustData)
7457 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7458 TLBCustData *pCData;
7459 int i;
7461 TRACE("(%p) returning %d items\n", This, This->ctCustData);
7463 pCustData->prgCustData = heap_alloc_zero(This->ctCustData * sizeof(CUSTDATAITEM));
7464 if(pCustData->prgCustData ){
7465 pCustData->cCustData=This->ctCustData;
7466 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
7467 pCustData->prgCustData[i].guid=pCData->guid;
7468 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
7470 }else{
7471 ERR(" OUT OF MEMORY!\n");
7472 return E_OUTOFMEMORY;
7474 return S_OK;
7477 /* ITypeInfo2::GetAllFuncCustData
7479 * Gets all custom data items for the specified Function
7482 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7483 ITypeInfo2 * iface,
7484 UINT index,
7485 CUSTDATA *pCustData)
7487 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7488 TLBCustData *pCData;
7489 TLBFuncDesc * pFDesc;
7490 UINT i;
7491 TRACE("(%p) index %d\n", This, index);
7492 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7493 pFDesc=pFDesc->next)
7495 if(pFDesc){
7496 pCustData->prgCustData =
7497 heap_alloc_zero(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
7498 if(pCustData->prgCustData ){
7499 pCustData->cCustData=pFDesc->ctCustData;
7500 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
7501 pCData = pCData->next){
7502 pCustData->prgCustData[i].guid=pCData->guid;
7503 VariantCopy(& pCustData->prgCustData[i].varValue,
7504 & pCData->data);
7506 }else{
7507 ERR(" OUT OF MEMORY!\n");
7508 return E_OUTOFMEMORY;
7510 return S_OK;
7512 return TYPE_E_ELEMENTNOTFOUND;
7515 /* ITypeInfo2::GetAllParamCustData
7517 * Gets all custom data items for the Functions
7520 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7521 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7523 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7524 TLBCustData *pCData=NULL;
7525 TLBFuncDesc * pFDesc;
7526 UINT i;
7527 TRACE("(%p) index %d\n", This, indexFunc);
7528 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
7529 pFDesc=pFDesc->next)
7531 if(pFDesc && indexParam<pFDesc->funcdesc.cParams){
7532 pCustData->prgCustData =
7533 heap_alloc_zero(pFDesc->pParamDesc[indexParam].ctCustData *
7534 sizeof(CUSTDATAITEM));
7535 if(pCustData->prgCustData ){
7536 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
7537 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
7538 pCData; i++, pCData = pCData->next){
7539 pCustData->prgCustData[i].guid=pCData->guid;
7540 VariantCopy(& pCustData->prgCustData[i].varValue,
7541 & pCData->data);
7543 }else{
7544 ERR(" OUT OF MEMORY!\n");
7545 return E_OUTOFMEMORY;
7547 return S_OK;
7549 return TYPE_E_ELEMENTNOTFOUND;
7552 /* ITypeInfo2::GetAllVarCustData
7554 * Gets all custom data items for the specified Variable
7557 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7558 UINT index, CUSTDATA *pCustData)
7560 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7561 TLBCustData *pCData;
7562 TLBVarDesc * pVDesc;
7563 UINT i;
7564 TRACE("(%p) index %d\n", This, index);
7565 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
7566 pVDesc=pVDesc->next)
7568 if(pVDesc){
7569 pCustData->prgCustData =
7570 heap_alloc_zero(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
7571 if(pCustData->prgCustData ){
7572 pCustData->cCustData=pVDesc->ctCustData;
7573 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
7574 pCData = pCData->next){
7575 pCustData->prgCustData[i].guid=pCData->guid;
7576 VariantCopy(& pCustData->prgCustData[i].varValue,
7577 & pCData->data);
7579 }else{
7580 ERR(" OUT OF MEMORY!\n");
7581 return E_OUTOFMEMORY;
7583 return S_OK;
7585 return TYPE_E_ELEMENTNOTFOUND;
7588 /* ITypeInfo2::GetAllImplCustData
7590 * Gets all custom data items for the specified implementation type
7593 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7594 ITypeInfo2 * iface,
7595 UINT index,
7596 CUSTDATA *pCustData)
7598 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7599 TLBCustData *pCData;
7600 TLBImplType * pRDesc;
7601 UINT i;
7602 TRACE("(%p) index %d\n", This, index);
7603 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
7604 pRDesc=pRDesc->next)
7606 if(pRDesc){
7607 pCustData->prgCustData =
7608 heap_alloc_zero(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
7609 if(pCustData->prgCustData ){
7610 pCustData->cCustData=pRDesc->ctCustData;
7611 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
7612 pCData = pCData->next){
7613 pCustData->prgCustData[i].guid=pCData->guid;
7614 VariantCopy(& pCustData->prgCustData[i].varValue,
7615 & pCData->data);
7617 }else{
7618 ERR(" OUT OF MEMORY!\n");
7619 return E_OUTOFMEMORY;
7621 return S_OK;
7623 return TYPE_E_ELEMENTNOTFOUND;
7626 static const ITypeInfo2Vtbl tinfvt =
7629 ITypeInfo_fnQueryInterface,
7630 ITypeInfo_fnAddRef,
7631 ITypeInfo_fnRelease,
7633 ITypeInfo_fnGetTypeAttr,
7634 ITypeInfo_fnGetTypeComp,
7635 ITypeInfo_fnGetFuncDesc,
7636 ITypeInfo_fnGetVarDesc,
7637 ITypeInfo_fnGetNames,
7638 ITypeInfo_fnGetRefTypeOfImplType,
7639 ITypeInfo_fnGetImplTypeFlags,
7640 ITypeInfo_fnGetIDsOfNames,
7641 ITypeInfo_fnInvoke,
7642 ITypeInfo_fnGetDocumentation,
7643 ITypeInfo_fnGetDllEntry,
7644 ITypeInfo_fnGetRefTypeInfo,
7645 ITypeInfo_fnAddressOfMember,
7646 ITypeInfo_fnCreateInstance,
7647 ITypeInfo_fnGetMops,
7648 ITypeInfo_fnGetContainingTypeLib,
7649 ITypeInfo_fnReleaseTypeAttr,
7650 ITypeInfo_fnReleaseFuncDesc,
7651 ITypeInfo_fnReleaseVarDesc,
7653 ITypeInfo2_fnGetTypeKind,
7654 ITypeInfo2_fnGetTypeFlags,
7655 ITypeInfo2_fnGetFuncIndexOfMemId,
7656 ITypeInfo2_fnGetVarIndexOfMemId,
7657 ITypeInfo2_fnGetCustData,
7658 ITypeInfo2_fnGetFuncCustData,
7659 ITypeInfo2_fnGetParamCustData,
7660 ITypeInfo2_fnGetVarCustData,
7661 ITypeInfo2_fnGetImplTypeCustData,
7662 ITypeInfo2_fnGetDocumentation2,
7663 ITypeInfo2_fnGetAllCustData,
7664 ITypeInfo2_fnGetAllFuncCustData,
7665 ITypeInfo2_fnGetAllParamCustData,
7666 ITypeInfo2_fnGetAllVarCustData,
7667 ITypeInfo2_fnGetAllImplTypeCustData,
7670 /******************************************************************************
7671 * CreateDispTypeInfo [OLEAUT32.31]
7673 * Build type information for an object so it can be called through an
7674 * IDispatch interface.
7676 * RETURNS
7677 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7678 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7680 * NOTES
7681 * This call allows an objects methods to be accessed through IDispatch, by
7682 * building an ITypeInfo object that IDispatch can use to call through.
7684 HRESULT WINAPI CreateDispTypeInfo(
7685 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7686 LCID lcid, /* [I] Locale Id */
7687 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7689 ITypeInfoImpl *pTIClass, *pTIIface;
7690 ITypeLibImpl *pTypeLibImpl;
7691 unsigned int param, func;
7692 TLBFuncDesc **ppFuncDesc;
7693 TLBRefType *ref;
7695 TRACE("\n");
7696 pTypeLibImpl = TypeLibImpl_Constructor();
7697 if (!pTypeLibImpl) return E_FAIL;
7699 pTIIface = ITypeInfoImpl_Constructor();
7700 pTIIface->pTypeLib = pTypeLibImpl;
7701 pTIIface->index = 0;
7702 pTIIface->Name = NULL;
7703 pTIIface->dwHelpContext = -1;
7704 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7705 pTIIface->TypeAttr.lcid = lcid;
7706 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7707 pTIIface->TypeAttr.wMajorVerNum = 0;
7708 pTIIface->TypeAttr.wMinorVerNum = 0;
7709 pTIIface->TypeAttr.cbAlignment = 2;
7710 pTIIface->TypeAttr.cbSizeInstance = -1;
7711 pTIIface->TypeAttr.cbSizeVft = -1;
7712 pTIIface->TypeAttr.cFuncs = 0;
7713 pTIIface->TypeAttr.cImplTypes = 0;
7714 pTIIface->TypeAttr.cVars = 0;
7715 pTIIface->TypeAttr.wTypeFlags = 0;
7717 ppFuncDesc = &pTIIface->funclist;
7718 for(func = 0; func < pidata->cMembers; func++) {
7719 METHODDATA *md = pidata->pmethdata + func;
7720 *ppFuncDesc = heap_alloc(sizeof(**ppFuncDesc));
7721 (*ppFuncDesc)->Name = SysAllocString(md->szName);
7722 (*ppFuncDesc)->funcdesc.memid = md->dispid;
7723 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
7724 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
7725 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
7726 (*ppFuncDesc)->funcdesc.callconv = md->cc;
7727 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
7728 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
7729 (*ppFuncDesc)->funcdesc.oVft = md->iMeth * sizeof(void *);
7730 (*ppFuncDesc)->funcdesc.cScodes = 0;
7731 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
7732 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7733 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7734 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7735 (*ppFuncDesc)->funcdesc.lprgelemdescParam = heap_alloc_zero(md->cArgs * sizeof(ELEMDESC));
7736 (*ppFuncDesc)->pParamDesc = heap_alloc_zero(md->cArgs * sizeof(TLBParDesc));
7737 for(param = 0; param < md->cArgs; param++) {
7738 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7739 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7741 (*ppFuncDesc)->helpcontext = 0;
7742 (*ppFuncDesc)->HelpStringContext = 0;
7743 (*ppFuncDesc)->HelpString = NULL;
7744 (*ppFuncDesc)->Entry = NULL;
7745 (*ppFuncDesc)->ctCustData = 0;
7746 (*ppFuncDesc)->pCustData = NULL;
7747 (*ppFuncDesc)->next = NULL;
7748 pTIIface->TypeAttr.cFuncs++;
7749 ppFuncDesc = &(*ppFuncDesc)->next;
7752 dump_TypeInfo(pTIIface);
7754 pTypeLibImpl->pTypeInfo = pTIIface;
7755 pTypeLibImpl->TypeInfoCount++;
7757 pTIClass = ITypeInfoImpl_Constructor();
7758 pTIClass->pTypeLib = pTypeLibImpl;
7759 pTIClass->index = 1;
7760 pTIClass->Name = NULL;
7761 pTIClass->dwHelpContext = -1;
7762 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7763 pTIClass->TypeAttr.lcid = lcid;
7764 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7765 pTIClass->TypeAttr.wMajorVerNum = 0;
7766 pTIClass->TypeAttr.wMinorVerNum = 0;
7767 pTIClass->TypeAttr.cbAlignment = 2;
7768 pTIClass->TypeAttr.cbSizeInstance = -1;
7769 pTIClass->TypeAttr.cbSizeVft = -1;
7770 pTIClass->TypeAttr.cFuncs = 0;
7771 pTIClass->TypeAttr.cImplTypes = 1;
7772 pTIClass->TypeAttr.cVars = 0;
7773 pTIClass->TypeAttr.wTypeFlags = 0;
7775 pTIClass->impltypelist = heap_alloc_zero(sizeof(*pTIClass->impltypelist));
7776 pTIClass->impltypelist->hRef = 0;
7778 ref = heap_alloc_zero(sizeof(*ref));
7779 ref->index = 0;
7780 ref->reference = 0;
7781 ref->pImpTLInfo = TLB_REF_INTERNAL;
7782 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7784 dump_TypeInfo(pTIClass);
7786 pTIIface->next = pTIClass;
7787 pTypeLibImpl->TypeInfoCount++;
7789 *pptinfo = (ITypeInfo*)pTIClass;
7791 ITypeInfo_AddRef(*pptinfo);
7792 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7794 return S_OK;
7798 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7800 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7802 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7805 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7807 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7809 return ITypeInfo_AddRef((ITypeInfo *)This);
7812 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7814 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7816 return ITypeInfo_Release((ITypeInfo *)This);
7819 static HRESULT WINAPI ITypeComp_fnBind(
7820 ITypeComp * iface,
7821 OLECHAR * szName,
7822 ULONG lHash,
7823 WORD wFlags,
7824 ITypeInfo ** ppTInfo,
7825 DESCKIND * pDescKind,
7826 BINDPTR * pBindPtr)
7828 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7829 const TLBFuncDesc *pFDesc;
7830 const TLBVarDesc *pVDesc;
7831 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7833 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7835 *pDescKind = DESCKIND_NONE;
7836 pBindPtr->lpfuncdesc = NULL;
7837 *ppTInfo = NULL;
7839 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
7840 if (!strcmpiW(pFDesc->Name, szName)) {
7841 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7842 break;
7843 else
7844 /* name found, but wrong flags */
7845 hr = TYPE_E_TYPEMISMATCH;
7848 if (pFDesc)
7850 HRESULT hr = TLB_AllocAndInitFuncDesc(
7851 &pFDesc->funcdesc,
7852 &pBindPtr->lpfuncdesc,
7853 This->TypeAttr.typekind == TKIND_DISPATCH);
7854 if (FAILED(hr))
7855 return hr;
7856 *pDescKind = DESCKIND_FUNCDESC;
7857 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7858 ITypeInfo_AddRef(*ppTInfo);
7859 return S_OK;
7860 } else {
7861 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7862 if (!strcmpiW(pVDesc->Name, szName)) {
7863 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7864 if (FAILED(hr))
7865 return hr;
7866 *pDescKind = DESCKIND_VARDESC;
7867 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7868 ITypeInfo_AddRef(*ppTInfo);
7869 return S_OK;
7873 /* FIXME: search each inherited interface, not just the first */
7874 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7875 /* recursive search */
7876 ITypeInfo *pTInfo;
7877 ITypeComp *pTComp;
7878 HRESULT hr;
7879 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7880 if (SUCCEEDED(hr))
7882 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7883 ITypeInfo_Release(pTInfo);
7885 if (SUCCEEDED(hr))
7887 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7888 ITypeComp_Release(pTComp);
7889 return hr;
7891 WARN("Could not search inherited interface!\n");
7893 if (hr == DISP_E_MEMBERNOTFOUND)
7894 hr = S_OK;
7895 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
7896 return hr;
7899 static HRESULT WINAPI ITypeComp_fnBindType(
7900 ITypeComp * iface,
7901 OLECHAR * szName,
7902 ULONG lHash,
7903 ITypeInfo ** ppTInfo,
7904 ITypeComp ** ppTComp)
7906 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7908 /* strange behaviour (does nothing) but like the
7909 * original */
7911 if (!ppTInfo || !ppTComp)
7912 return E_POINTER;
7914 *ppTInfo = NULL;
7915 *ppTComp = NULL;
7917 return S_OK;
7920 static const ITypeCompVtbl tcompvt =
7923 ITypeComp_fnQueryInterface,
7924 ITypeComp_fnAddRef,
7925 ITypeComp_fnRelease,
7927 ITypeComp_fnBind,
7928 ITypeComp_fnBindType