notepad: Fix the position of the Encoding combobox.
[wine/multimedia.git] / dlls / oleaut32 / typelib.c
blob95cdc364467500c37da0150a2453887de4fb8592
1 /*
2 * TYPELIB
4 * Copyright 1997 Marcus Meissner
5 * 1999 Rein Klazes
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 2005 Robert Shearman, for CodeWeavers
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 * --------------------------------------------------------------------------------------
25 * Known problems (2000, Francois Jacques)
27 * - Tested using OLEVIEW (Platform SDK tool) only.
29 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
30 * creating by doing a straight copy of the dispinterface instance and just changing
31 * its typekind. Pointed structures aren't copied - only the address of the pointers.
33 * - locale stuff is partially implemented but hasn't been tested.
35 * - typelib file is still read in its entirety, but it is released now.
37 * --------------------------------------------------------------------------------------
38 * Known problems left from previous implementation (1999, Rein Klazes) :
40 * -. Data structures are straightforward, but slow for look-ups.
41 * -. (related) nothing is hashed
42 * -. Most error return values are just guessed not checked with windows
43 * behaviour.
44 * -. lousy fatal error handling
48 #include "config.h"
49 #include "wine/port.h"
51 #include <stdlib.h>
52 #include <string.h>
53 #include <stdarg.h>
54 #include <stdio.h>
55 #include <ctype.h>
57 #define COBJMACROS
58 #define NONAMELESSUNION
59 #define NONAMELESSSTRUCT
61 #include "winerror.h"
62 #include "windef.h"
63 #include "winbase.h"
64 #include "winnls.h"
65 #include "winreg.h"
66 #include "winuser.h"
67 #include "lzexpand.h"
69 #include "wine/unicode.h"
70 #include "objbase.h"
71 #include "typelib.h"
72 #include "wine/debug.h"
73 #include "variant.h"
74 #include "wine/list.h"
76 WINE_DEFAULT_DEBUG_CHANNEL(ole);
77 WINE_DECLARE_DEBUG_CHANNEL(typelib);
79 typedef struct
81 WORD offset;
82 WORD length;
83 WORD flags;
84 WORD id;
85 WORD handle;
86 WORD usage;
87 } NE_NAMEINFO;
89 typedef struct
91 WORD type_id; /* Type identifier */
92 WORD count; /* Number of resources of this type */
93 DWORD resloader; /* SetResourceHandler() */
95 * Name info array.
97 } NE_TYPEINFO;
99 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
100 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
102 /****************************************************************************
103 * FromLExxx
105 * Takes p_iVal (which is in little endian) and returns it
106 * in the host machine's byte order.
108 #ifdef WORDS_BIGENDIAN
109 static WORD FromLEWord(WORD p_iVal)
111 return (((p_iVal & 0x00FF) << 8) |
112 ((p_iVal & 0xFF00) >> 8));
116 static DWORD FromLEDWord(DWORD p_iVal)
118 return (((p_iVal & 0x000000FF) << 24) |
119 ((p_iVal & 0x0000FF00) << 8) |
120 ((p_iVal & 0x00FF0000) >> 8) |
121 ((p_iVal & 0xFF000000) >> 24));
123 #else
124 #define FromLEWord(X) (X)
125 #define FromLEDWord(X) (X)
126 #endif
128 #define DISPATCH_HREF_OFFSET 0x01000000
129 #define DISPATCH_HREF_MASK 0xff000000
131 /****************************************************************************
132 * FromLExxx
134 * Fix byte order in any structure if necessary
136 #ifdef WORDS_BIGENDIAN
137 static void FromLEWords(void *p_Val, int p_iSize)
139 WORD *Val = p_Val;
141 p_iSize /= sizeof(WORD);
143 while (p_iSize) {
144 *Val = FromLEWord(*Val);
145 Val++;
146 p_iSize--;
151 static void FromLEDWords(void *p_Val, int p_iSize)
153 DWORD *Val = p_Val;
155 p_iSize /= sizeof(DWORD);
157 while (p_iSize) {
158 *Val = FromLEDWord(*Val);
159 Val++;
160 p_iSize--;
163 #else
164 #define FromLEWords(X,Y) /*nothing*/
165 #define FromLEDWords(X,Y) /*nothing*/
166 #endif
169 * Find a typelib key which matches a requested maj.min version.
171 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
173 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
174 WCHAR buffer[60];
175 char key_name[16];
176 DWORD len, i;
177 INT best_maj = -1, best_min = -1;
178 HKEY hkey;
180 memcpy( buffer, typelibW, sizeof(typelibW) );
181 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
183 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
184 return FALSE;
186 len = sizeof(key_name);
187 i = 0;
188 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
190 INT v_maj, v_min;
192 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
194 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
196 if (*wMaj == 0xffff && *wMin == 0xffff)
198 if (v_maj > best_maj) best_maj = v_maj;
199 if (v_min > best_min) best_min = v_min;
201 else if (*wMaj == v_maj)
203 best_maj = v_maj;
205 if (*wMin == v_min)
207 best_min = v_min;
208 break; /* exact match */
210 if (*wMin != 0xffff && v_min > best_min) best_min = v_min;
213 len = sizeof(key_name);
215 RegCloseKey( hkey );
217 TRACE("found best_maj %d, best_min %d\n", best_maj, best_min);
219 if (*wMaj == 0xffff && *wMin == 0xffff)
221 if (best_maj >= 0 && best_min >= 0)
223 *wMaj = best_maj;
224 *wMin = best_min;
225 return TRUE;
229 if (*wMaj == best_maj && best_min >= 0)
231 *wMin = best_min;
232 return TRUE;
234 return FALSE;
237 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
238 /* buffer must be at least 60 characters long */
239 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
241 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
242 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
244 memcpy( buffer, TypelibW, sizeof(TypelibW) );
245 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
246 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
247 return buffer;
250 /* get the path of an interface key, in the form "Interface\\<guid>" */
251 /* buffer must be at least 50 characters long */
252 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
254 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
256 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
257 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
258 return buffer;
261 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
262 /* buffer must be at least 16 characters long */
263 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
265 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
266 static const WCHAR win16W[] = {'w','i','n','1','6',0};
267 static const WCHAR win32W[] = {'w','i','n','3','2',0};
268 static const WCHAR win64W[] = {'w','i','n','6','4',0};
270 sprintfW( buffer, LcidFormatW, lcid );
271 switch(syskind)
273 case SYS_WIN16: strcatW( buffer, win16W ); break;
274 case SYS_WIN32: strcatW( buffer, win32W ); break;
275 case SYS_WIN64: strcatW( buffer, win64W ); break;
276 default:
277 TRACE("Typelib is for unsupported syskind %i\n", syskind);
278 return NULL;
280 return buffer;
283 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
286 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
287 static HRESULT query_typelib_path( REFGUID guid, WORD wMaj, WORD wMin,
288 SYSKIND syskind, LCID lcid, LPBSTR path )
290 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
291 LCID myLCID = lcid;
292 HKEY hkey;
293 WCHAR buffer[60];
294 WCHAR Path[MAX_PATH];
295 LONG res;
297 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
299 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
300 get_typelib_key( guid, wMaj, wMin, buffer );
302 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
303 if (res == ERROR_FILE_NOT_FOUND)
305 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
306 return TYPE_E_LIBNOTREGISTERED;
308 else if (res != ERROR_SUCCESS)
310 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
311 return TYPE_E_REGISTRYACCESS;
314 while (hr != S_OK)
316 LONG dwPathLen = sizeof(Path);
318 get_lcid_subkey( myLCID, syskind, buffer );
320 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
322 if (!lcid)
323 break;
324 else if (myLCID == lcid)
326 /* try with sub-langid */
327 myLCID = SUBLANGID(lcid);
329 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
331 /* try with system langid */
332 myLCID = 0;
334 else
336 break;
339 else
341 *path = SysAllocString( Path );
342 hr = S_OK;
345 RegCloseKey( hkey );
346 TRACE_(typelib)("-- 0x%08x\n", hr);
347 return hr;
350 /****************************************************************************
351 * QueryPathOfRegTypeLib [OLEAUT32.164]
353 * Gets the path to a registered type library.
355 * PARAMS
356 * guid [I] referenced guid
357 * wMaj [I] major version
358 * wMin [I] minor version
359 * lcid [I] locale id
360 * path [O] path of typelib
362 * RETURNS
363 * Success: S_OK.
364 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
365 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
366 * opened.
368 HRESULT WINAPI QueryPathOfRegTypeLib( REFGUID guid, WORD wMaj, WORD wMin, LCID lcid, LPBSTR path )
370 #ifdef _WIN64
371 HRESULT hres = query_typelib_path( guid, wMaj, wMin, SYS_WIN64, lcid, path );
372 if(SUCCEEDED(hres))
373 return hres;
374 #endif
375 return query_typelib_path( guid, wMaj, wMin, SYS_WIN32, lcid, path );
378 /******************************************************************************
379 * CreateTypeLib [OLEAUT32.160] creates a typelib
381 * RETURNS
382 * Success: S_OK
383 * Failure: Status
385 HRESULT WINAPI CreateTypeLib(
386 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
388 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
389 return E_FAIL;
392 /******************************************************************************
393 * LoadTypeLib [OLEAUT32.161]
395 * Loads a type library
397 * PARAMS
398 * szFile [I] Name of file to load from.
399 * pptLib [O] Pointer that receives ITypeLib object on success.
401 * RETURNS
402 * Success: S_OK
403 * Failure: Status
405 * SEE
406 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
408 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
410 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
411 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
414 /******************************************************************************
415 * LoadTypeLibEx [OLEAUT32.183]
417 * Loads and optionally registers a type library
419 * RETURNS
420 * Success: S_OK
421 * Failure: Status
423 HRESULT WINAPI LoadTypeLibEx(
424 LPCOLESTR szFile, /* [in] Name of file to load from */
425 REGKIND regkind, /* [in] Specify kind of registration */
426 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
428 WCHAR szPath[MAX_PATH+1];
429 HRESULT res;
431 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
433 *pptLib = NULL;
435 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
437 if (SUCCEEDED(res))
438 switch(regkind)
440 case REGKIND_DEFAULT:
441 /* don't register typelibs supplied with full path. Experimentation confirms the following */
442 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
443 (szFile[0] && (szFile[1] == ':'))) break;
444 /* else fall-through */
446 case REGKIND_REGISTER:
447 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
449 IUnknown_Release(*pptLib);
450 *pptLib = 0;
452 break;
453 case REGKIND_NONE:
454 break;
457 TRACE(" returns %08x\n",res);
458 return res;
461 /******************************************************************************
462 * LoadRegTypeLib [OLEAUT32.162]
464 * Loads a registered type library.
466 * PARAMS
467 * rguid [I] GUID of the registered type library.
468 * wVerMajor [I] major version.
469 * wVerMinor [I] minor version.
470 * lcid [I] locale ID.
471 * ppTLib [O] pointer that receives an ITypeLib object on success.
473 * RETURNS
474 * Success: S_OK.
475 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
476 * LoadTypeLib.
478 HRESULT WINAPI LoadRegTypeLib(
479 REFGUID rguid,
480 WORD wVerMajor,
481 WORD wVerMinor,
482 LCID lcid,
483 ITypeLib **ppTLib)
485 BSTR bstr=NULL;
486 HRESULT res;
488 *ppTLib = NULL;
490 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
492 if(SUCCEEDED(res))
494 res= LoadTypeLib(bstr, ppTLib);
495 SysFreeString(bstr);
498 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
500 return res;
504 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
505 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
506 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
507 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
508 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
509 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
511 /******************************************************************************
512 * RegisterTypeLib [OLEAUT32.163]
513 * Adds information about a type library to the System Registry
514 * NOTES
515 * Docs: ITypeLib FAR * ptlib
516 * Docs: OLECHAR FAR* szFullPath
517 * Docs: OLECHAR FAR* szHelpDir
519 * RETURNS
520 * Success: S_OK
521 * Failure: Status
523 HRESULT WINAPI RegisterTypeLib(
524 ITypeLib * ptlib, /* [in] Pointer to the library*/
525 OLECHAR * szFullPath, /* [in] full Path of the library*/
526 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
527 may be NULL*/
529 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
530 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
531 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
532 HRESULT res;
533 TLIBATTR *attr;
534 WCHAR keyName[60];
535 WCHAR tmp[16];
536 HKEY key, subKey;
537 UINT types, tidx;
538 TYPEKIND kind;
539 DWORD disposition;
541 if (ptlib == NULL || szFullPath == NULL)
542 return E_INVALIDARG;
544 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
545 return E_FAIL;
547 #ifdef _WIN64
548 if (attr->syskind != SYS_WIN64) return TYPE_E_BADMODULEKIND;
549 #else
550 if (attr->syskind != SYS_WIN32 && attr->syskind != SYS_WIN16) return TYPE_E_BADMODULEKIND;
551 #endif
553 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
555 res = S_OK;
556 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
557 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
559 LPOLESTR doc;
561 /* Set the human-readable name of the typelib */
562 if (FAILED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
563 res = E_FAIL;
564 else if (doc)
566 if (RegSetValueExW(key, NULL, 0, REG_SZ,
567 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
568 res = E_FAIL;
570 SysFreeString(doc);
573 /* Make up the name of the typelib path subkey */
574 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
576 /* Create the typelib path subkey */
577 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
578 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
580 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
581 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
582 res = E_FAIL;
584 RegCloseKey(subKey);
586 else
587 res = E_FAIL;
589 /* Create the flags subkey */
590 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
591 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
593 /* FIXME: is %u correct? */
594 static const WCHAR formatW[] = {'%','u',0};
595 WCHAR buf[20];
596 sprintfW(buf, formatW, attr->wLibFlags);
597 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
598 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
599 res = E_FAIL;
601 RegCloseKey(subKey);
603 else
604 res = E_FAIL;
606 /* create the helpdir subkey */
607 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
608 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
610 BOOL freeHelpDir = FALSE;
611 OLECHAR* pIndexStr;
613 /* if we created a new key, and helpDir was null, set the helpdir
614 to the directory which contains the typelib. However,
615 if we just opened an existing key, we leave the helpdir alone */
616 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
617 szHelpDir = SysAllocString(szFullPath);
618 pIndexStr = strrchrW(szHelpDir, '\\');
619 if (pIndexStr) {
620 *pIndexStr = 0;
622 freeHelpDir = TRUE;
625 /* if we have an szHelpDir, set it! */
626 if (szHelpDir != NULL) {
627 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
628 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
629 res = E_FAIL;
633 /* tidy up */
634 if (freeHelpDir) SysFreeString(szHelpDir);
635 RegCloseKey(subKey);
637 } else {
638 res = E_FAIL;
641 RegCloseKey(key);
643 else
644 res = E_FAIL;
646 /* register OLE Automation-compatible interfaces for this typelib */
647 types = ITypeLib_GetTypeInfoCount(ptlib);
648 for (tidx=0; tidx<types; tidx++) {
649 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
650 LPOLESTR name = NULL;
651 ITypeInfo *tinfo = NULL;
653 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
655 switch (kind) {
656 case TKIND_INTERFACE:
657 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
658 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
659 break;
661 case TKIND_DISPATCH:
662 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
663 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
664 break;
666 default:
667 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
668 break;
671 if (tinfo) {
672 TYPEATTR *tattr = NULL;
673 ITypeInfo_GetTypeAttr(tinfo, &tattr);
675 if (tattr) {
676 TRACE_(typelib)("guid=%s, flags=%04x (",
677 debugstr_guid(&tattr->guid),
678 tattr->wTypeFlags);
680 if (TRACE_ON(typelib)) {
681 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
682 XX(FAPPOBJECT);
683 XX(FCANCREATE);
684 XX(FLICENSED);
685 XX(FPREDECLID);
686 XX(FHIDDEN);
687 XX(FCONTROL);
688 XX(FDUAL);
689 XX(FNONEXTENSIBLE);
690 XX(FOLEAUTOMATION);
691 XX(FRESTRICTED);
692 XX(FAGGREGATABLE);
693 XX(FREPLACEABLE);
694 XX(FDISPATCHABLE);
695 XX(FREVERSEBIND);
696 XX(FPROXY);
697 #undef XX
698 MESSAGE("\n");
701 /* Register all dispinterfaces (which includes dual interfaces) and
702 oleautomation interfaces */
703 if ((kind == TKIND_INTERFACE && (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
704 kind == TKIND_DISPATCH)
706 /* register interface<->typelib coupling */
707 get_interface_key( &tattr->guid, keyName );
708 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
709 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
711 if (name)
712 RegSetValueExW(key, NULL, 0, REG_SZ,
713 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
715 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
716 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
717 RegSetValueExW(subKey, NULL, 0, REG_SZ,
718 (const BYTE *)PSOA, sizeof PSOA);
719 RegCloseKey(subKey);
722 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
723 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
724 RegSetValueExW(subKey, NULL, 0, REG_SZ,
725 (const BYTE *)PSOA, sizeof PSOA);
726 RegCloseKey(subKey);
729 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
730 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
732 WCHAR buffer[40];
733 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
734 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
736 StringFromGUID2(&attr->guid, buffer, 40);
737 RegSetValueExW(subKey, NULL, 0, REG_SZ,
738 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
739 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
740 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
741 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
742 RegCloseKey(subKey);
745 RegCloseKey(key);
749 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
752 ITypeInfo_Release(tinfo);
755 SysFreeString(name);
759 ITypeLib_ReleaseTLibAttr(ptlib, attr);
761 return res;
765 /******************************************************************************
766 * UnRegisterTypeLib [OLEAUT32.186]
767 * Removes information about a type library from the System Registry
768 * NOTES
770 * RETURNS
771 * Success: S_OK
772 * Failure: Status
774 HRESULT WINAPI UnRegisterTypeLib(
775 REFGUID libid, /* [in] Guid of the library */
776 WORD wVerMajor, /* [in] major version */
777 WORD wVerMinor, /* [in] minor version */
778 LCID lcid, /* [in] locale id */
779 SYSKIND syskind)
781 BSTR tlibPath = NULL;
782 DWORD tmpLength;
783 WCHAR keyName[60];
784 WCHAR subKeyName[50];
785 int result = S_OK;
786 DWORD i = 0;
787 BOOL deleteOtherStuff;
788 HKEY key = NULL;
789 HKEY subKey = NULL;
790 TYPEATTR* typeAttr = NULL;
791 TYPEKIND kind;
792 ITypeInfo* typeInfo = NULL;
793 ITypeLib* typeLib = NULL;
794 int numTypes;
796 TRACE("(IID: %s)\n",debugstr_guid(libid));
798 /* Create the path to the key */
799 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
801 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
803 TRACE("Unsupported syskind %i\n", syskind);
804 result = E_INVALIDARG;
805 goto end;
808 /* get the path to the typelib on disk */
809 if (query_typelib_path(libid, wVerMajor, wVerMinor, syskind, lcid, &tlibPath) != S_OK) {
810 result = E_INVALIDARG;
811 goto end;
814 /* Try and open the key to the type library. */
815 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
816 result = E_INVALIDARG;
817 goto end;
820 /* Try and load the type library */
821 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib) != S_OK) {
822 result = TYPE_E_INVALIDSTATE;
823 goto end;
826 /* remove any types registered with this typelib */
827 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
828 for (i=0; i<numTypes; i++) {
829 /* get the kind of type */
830 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
831 goto enddeleteloop;
834 /* skip non-interfaces, and get type info for the type */
835 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
836 goto enddeleteloop;
838 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
839 goto enddeleteloop;
841 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
842 goto enddeleteloop;
845 if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
846 kind == TKIND_DISPATCH)
848 /* the path to the type */
849 get_interface_key( &typeAttr->guid, subKeyName );
851 /* Delete its bits */
852 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS)
853 goto enddeleteloop;
855 RegDeleteKeyW(subKey, ProxyStubClsidW);
856 RegDeleteKeyW(subKey, ProxyStubClsid32W);
857 RegDeleteKeyW(subKey, TypeLibW);
858 RegCloseKey(subKey);
859 subKey = NULL;
860 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
863 enddeleteloop:
864 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
865 typeAttr = NULL;
866 if (typeInfo) ITypeInfo_Release(typeInfo);
867 typeInfo = NULL;
870 /* Now, delete the type library path subkey */
871 get_lcid_subkey( lcid, syskind, subKeyName );
872 RegDeleteKeyW(key, subKeyName);
873 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
874 RegDeleteKeyW(key, subKeyName);
876 /* check if there is anything besides the FLAGS/HELPDIR keys.
877 If there is, we don't delete them */
878 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
879 deleteOtherStuff = TRUE;
880 i = 0;
881 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
882 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
884 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
885 if (!strcmpW(subKeyName, FLAGSW)) continue;
886 if (!strcmpW(subKeyName, HELPDIRW)) continue;
887 deleteOtherStuff = FALSE;
888 break;
891 /* only delete the other parts of the key if we're absolutely sure */
892 if (deleteOtherStuff) {
893 RegDeleteKeyW(key, FLAGSW);
894 RegDeleteKeyW(key, HELPDIRW);
895 RegCloseKey(key);
896 key = NULL;
898 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
899 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
900 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
903 end:
904 SysFreeString(tlibPath);
905 if (typeLib) ITypeLib_Release(typeLib);
906 if (subKey) RegCloseKey(subKey);
907 if (key) RegCloseKey(key);
908 return result;
911 /******************************************************************************
912 * RegisterTypeLibForUser [OLEAUT32.442]
913 * Adds information about a type library to the user registry
914 * NOTES
915 * Docs: ITypeLib FAR * ptlib
916 * Docs: OLECHAR FAR* szFullPath
917 * Docs: OLECHAR FAR* szHelpDir
919 * RETURNS
920 * Success: S_OK
921 * Failure: Status
923 HRESULT WINAPI RegisterTypeLibForUser(
924 ITypeLib * ptlib, /* [in] Pointer to the library*/
925 OLECHAR * szFullPath, /* [in] full Path of the library*/
926 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
927 may be NULL*/
929 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib,
930 debugstr_w(szFullPath), debugstr_w(szHelpDir));
931 return RegisterTypeLib(ptlib, szFullPath, szHelpDir);
934 /******************************************************************************
935 * UnRegisterTypeLibForUser [OLEAUT32.443]
936 * Removes information about a type library from the user registry
938 * RETURNS
939 * Success: S_OK
940 * Failure: Status
942 HRESULT WINAPI UnRegisterTypeLibForUser(
943 REFGUID libid, /* [in] GUID of the library */
944 WORD wVerMajor, /* [in] major version */
945 WORD wVerMinor, /* [in] minor version */
946 LCID lcid, /* [in] locale id */
947 SYSKIND syskind)
949 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
950 debugstr_guid(libid), wVerMajor, wVerMinor, lcid, syskind);
951 return UnRegisterTypeLib(libid, wVerMajor, wVerMinor, lcid, syskind);
954 /*======================= ITypeLib implementation =======================*/
956 typedef struct tagTLBCustData
958 GUID guid;
959 VARIANT data;
960 struct list entry;
961 } TLBCustData;
963 /* data structure for import typelibs */
964 typedef struct tagTLBImpLib
966 int offset; /* offset in the file (MSFT)
967 offset in nametable (SLTG)
968 just used to identify library while reading
969 data from file */
970 GUID guid; /* libid */
971 BSTR name; /* name */
973 LCID lcid; /* lcid of imported typelib */
975 WORD wVersionMajor; /* major version number */
976 WORD wVersionMinor; /* minor version number */
978 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
979 NULL if not yet loaded */
980 struct list entry;
981 } TLBImpLib;
983 /* internal ITypeLib data */
984 typedef struct tagITypeLibImpl
986 const ITypeLib2Vtbl *lpVtbl;
987 const ITypeCompVtbl *lpVtblTypeComp;
988 LONG ref;
989 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
990 LCID lcid;
992 /* strings can be stored in tlb as multibyte strings BUT they are *always*
993 * exported to the application as a UNICODE string.
995 BSTR Name;
996 BSTR DocString;
997 BSTR HelpFile;
998 BSTR HelpStringDll;
999 DWORD dwHelpContext;
1000 int TypeInfoCount; /* nr of typeinfo's in librarry */
1001 struct tagITypeInfoImpl **typeinfos;
1002 struct list custdata_list;
1003 struct list implib_list;
1004 int ctTypeDesc; /* number of items in type desc array */
1005 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1006 library. Only used while reading MSFT
1007 typelibs */
1008 struct list ref_list; /* list of ref types in this typelib */
1009 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1012 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1013 struct list entry;
1014 WCHAR *path;
1015 INT index;
1016 } ITypeLibImpl;
1018 static const ITypeLib2Vtbl tlbvt;
1019 static const ITypeCompVtbl tlbtcvt;
1021 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1023 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
1026 /* ITypeLib methods */
1027 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1028 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1030 /*======================= ITypeInfo implementation =======================*/
1032 /* data for referenced types */
1033 typedef struct tagTLBRefType
1035 INT index; /* Type index for internal ref or for external ref
1036 it the format is SLTG. -2 indicates to
1037 use guid */
1039 GUID guid; /* guid of the referenced type */
1040 /* if index == TLB_REF_USE_GUID */
1042 HREFTYPE reference; /* The href of this ref */
1043 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1044 TLB_REF_INTERNAL for internal refs
1045 TLB_REF_NOT_FOUND for broken refs */
1047 struct list entry;
1048 } TLBRefType;
1050 #define TLB_REF_USE_GUID -2
1052 #define TLB_REF_INTERNAL (void*)-2
1053 #define TLB_REF_NOT_FOUND (void*)-1
1055 /* internal Parameter data */
1056 typedef struct tagTLBParDesc
1058 BSTR Name;
1059 struct list custdata_list;
1060 } TLBParDesc;
1062 /* internal Function data */
1063 typedef struct tagTLBFuncDesc
1065 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1066 BSTR Name; /* the name of this function */
1067 TLBParDesc *pParamDesc; /* array with param names and custom data */
1068 int helpcontext;
1069 int HelpStringContext;
1070 BSTR HelpString;
1071 BSTR Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1072 struct list custdata_list;
1073 } TLBFuncDesc;
1075 /* internal Variable data */
1076 typedef struct tagTLBVarDesc
1078 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1079 BSTR Name; /* the name of this variable */
1080 int HelpContext;
1081 int HelpStringContext;
1082 BSTR HelpString;
1083 struct list custdata_list;
1084 } TLBVarDesc;
1086 /* internal implemented interface data */
1087 typedef struct tagTLBImplType
1089 HREFTYPE hRef; /* hRef of interface */
1090 int implflags; /* IMPLFLAG_*s */
1091 struct list custdata_list;
1092 } TLBImplType;
1094 /* internal TypeInfo data */
1095 typedef struct tagITypeInfoImpl
1097 const ITypeInfo2Vtbl *lpVtbl;
1098 const ITypeCompVtbl *lpVtblTypeComp;
1099 LONG ref;
1100 BOOL not_attached_to_typelib;
1101 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1102 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1103 int index; /* index in this typelib; */
1104 HREFTYPE hreftype; /* hreftype for app object binding */
1105 /* type libs seem to store the doc strings in ascii
1106 * so why should we do it in unicode?
1108 BSTR Name;
1109 BSTR DocString;
1110 BSTR DllName;
1111 DWORD dwHelpContext;
1112 DWORD dwHelpStringContext;
1114 /* functions */
1115 TLBFuncDesc *funcdescs;
1117 /* variables */
1118 TLBVarDesc *vardescs;
1120 /* Implemented Interfaces */
1121 TLBImplType *impltypes;
1123 struct list custdata_list;
1124 } ITypeInfoImpl;
1126 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1128 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1131 static const ITypeInfo2Vtbl tinfvt;
1132 static const ITypeCompVtbl tcompvt;
1134 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1135 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1137 typedef struct tagTLBContext
1139 unsigned int oStart; /* start of TLB in file */
1140 unsigned int pos; /* current pos */
1141 unsigned int length; /* total length */
1142 void *mapping; /* memory mapping */
1143 MSFT_SegDir * pTblDir;
1144 ITypeLibImpl* pLibInfo;
1145 } TLBContext;
1148 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1151 debug
1153 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1154 if (pTD->vt & VT_RESERVED)
1155 szVarType += strlen(strcpy(szVarType, "reserved | "));
1156 if (pTD->vt & VT_BYREF)
1157 szVarType += strlen(strcpy(szVarType, "ref to "));
1158 if (pTD->vt & VT_ARRAY)
1159 szVarType += strlen(strcpy(szVarType, "array of "));
1160 if (pTD->vt & VT_VECTOR)
1161 szVarType += strlen(strcpy(szVarType, "vector of "));
1162 switch(pTD->vt & VT_TYPEMASK) {
1163 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1164 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1165 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1166 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1167 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1168 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1169 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1170 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1171 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1172 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1173 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1174 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1175 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1176 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1177 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1178 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1179 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1180 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1181 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1182 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1183 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1184 pTD->u.hreftype); break;
1185 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1186 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1187 case VT_PTR: sprintf(szVarType, "ptr to ");
1188 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1189 break;
1190 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1191 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1192 break;
1193 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1194 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1195 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1196 break;
1198 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1202 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1203 char buf[200];
1204 USHORT flags = edesc->u.paramdesc.wParamFlags;
1205 dump_TypeDesc(&edesc->tdesc,buf);
1206 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1207 MESSAGE("\t\tu.paramdesc.wParamFlags");
1208 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1209 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1210 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1211 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1212 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1213 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1214 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1215 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1216 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1218 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1219 int i;
1220 MESSAGE("memid is %08x\n",funcdesc->memid);
1221 for (i=0;i<funcdesc->cParams;i++) {
1222 MESSAGE("Param %d:\n",i);
1223 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1225 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1226 switch (funcdesc->funckind) {
1227 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1228 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1229 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1230 case FUNC_STATIC: MESSAGE("static");break;
1231 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1232 default: MESSAGE("unknown");break;
1234 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1235 switch (funcdesc->invkind) {
1236 case INVOKE_FUNC: MESSAGE("func");break;
1237 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1238 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1239 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1241 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1242 switch (funcdesc->callconv) {
1243 case CC_CDECL: MESSAGE("cdecl");break;
1244 case CC_PASCAL: MESSAGE("pascal");break;
1245 case CC_STDCALL: MESSAGE("stdcall");break;
1246 case CC_SYSCALL: MESSAGE("syscall");break;
1247 default:break;
1249 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1250 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1251 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1253 MESSAGE("\telemdescFunc (return value type):\n");
1254 dump_ELEMDESC(&funcdesc->elemdescFunc);
1257 static const char * const typekind_desc[] =
1259 "TKIND_ENUM",
1260 "TKIND_RECORD",
1261 "TKIND_MODULE",
1262 "TKIND_INTERFACE",
1263 "TKIND_DISPATCH",
1264 "TKIND_COCLASS",
1265 "TKIND_ALIAS",
1266 "TKIND_UNION",
1267 "TKIND_MAX"
1270 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1272 int i;
1273 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1274 for (i=0;i<pfd->funcdesc.cParams;i++)
1275 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1278 dump_FUNCDESC(&(pfd->funcdesc));
1280 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1281 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1283 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1285 while (n)
1287 dump_TLBFuncDescOne(pfd);
1288 ++pfd;
1289 --n;
1292 static void dump_TLBVarDesc(const TLBVarDesc * pvd, UINT n)
1294 while (n)
1296 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1297 ++pvd;
1298 --n;
1302 static void dump_TLBImpLib(const TLBImpLib *import)
1304 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1305 debugstr_w(import->name));
1306 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1307 import->wVersionMinor, import->lcid, import->offset);
1310 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1312 TLBRefType *ref;
1314 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1316 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1317 if(ref->index == -1)
1318 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1319 else
1320 TRACE_(typelib)("type no: %d\n", ref->index);
1322 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1324 TRACE_(typelib)("in lib\n");
1325 dump_TLBImpLib(ref->pImpTLInfo);
1330 static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1332 if(!impl)
1333 return;
1334 while (n) {
1335 TRACE_(typelib)("implementing/inheriting interface hRef = %x implflags %x\n",
1336 impl->hRef, impl->implflags);
1337 ++impl;
1338 --n;
1342 static void dump_Variant(const VARIANT * pvar)
1344 SYSTEMTIME st;
1346 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1348 if (pvar)
1350 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1351 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1353 TRACE(",%p", V_BYREF(pvar));
1355 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1357 TRACE(",%p", V_ARRAY(pvar));
1359 else switch (V_TYPE(pvar))
1361 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1362 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1363 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1364 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1365 case VT_INT:
1366 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1367 case VT_UINT:
1368 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1369 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1370 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1371 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1372 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1373 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1374 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1375 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1376 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1377 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1378 V_CY(pvar).s.Lo); break;
1379 case VT_DATE:
1380 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1381 TRACE(",<invalid>");
1382 else
1383 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1384 st.wHour, st.wMinute, st.wSecond);
1385 break;
1386 case VT_ERROR:
1387 case VT_VOID:
1388 case VT_USERDEFINED:
1389 case VT_EMPTY:
1390 case VT_NULL: break;
1391 default: TRACE(",?"); break;
1394 TRACE("}\n");
1397 static void dump_DispParms(const DISPPARAMS * pdp)
1399 unsigned int index;
1401 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1403 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1405 TRACE("named args:\n");
1406 for (index = 0; index < pdp->cNamedArgs; index++)
1407 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1410 if (pdp->cArgs && pdp->rgvarg)
1412 TRACE("args:\n");
1413 for (index = 0; index < pdp->cArgs; index++)
1414 dump_Variant( &pdp->rgvarg[index] );
1418 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1420 TRACE("%p ref=%u\n", pty, pty->ref);
1421 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1422 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1423 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1424 TRACE("fct:%u var:%u impl:%u\n",
1425 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1426 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1427 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1428 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1429 if (TRACE_ON(ole))
1430 dump_TLBFuncDesc(pty->funcdescs, pty->TypeAttr.cFuncs);
1431 dump_TLBVarDesc(pty->vardescs, pty->TypeAttr.cVars);
1432 dump_TLBImplType(pty->impltypes, pty->TypeAttr.cImplTypes);
1435 static void dump_VARDESC(const VARDESC *v)
1437 MESSAGE("memid %d\n",v->memid);
1438 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1439 MESSAGE("oInst %d\n",v->u.oInst);
1440 dump_ELEMDESC(&(v->elemdescVar));
1441 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1442 MESSAGE("varkind %d\n",v->varkind);
1445 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1447 /* VT_LPWSTR is largest type that, may appear in type description */
1448 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1449 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1450 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1451 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1452 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1453 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1454 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1455 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1458 static void TLB_abort(void)
1460 DebugBreak();
1463 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size)
1465 void *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
1466 if (!ret) ERR("cannot allocate memory\n");
1467 return ret;
1470 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size)
1472 void *ret = HeapAlloc(GetProcessHeap(), 0, size);
1473 if (!ret) ERR("cannot allocate memory\n");
1474 return ret;
1477 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr, unsigned size)
1479 return HeapReAlloc(GetProcessHeap(), 0, ptr, size);
1482 void heap_free(void *ptr)
1484 HeapFree(GetProcessHeap(), 0, ptr);
1487 /* returns the size required for a deep copy of a typedesc into a
1488 * flat buffer */
1489 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1491 SIZE_T size = 0;
1493 if (alloc_initial_space)
1494 size += sizeof(TYPEDESC);
1496 switch (tdesc->vt)
1498 case VT_PTR:
1499 case VT_SAFEARRAY:
1500 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1501 break;
1502 case VT_CARRAY:
1503 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1504 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1505 break;
1507 return size;
1510 /* deep copy a typedesc into a flat buffer */
1511 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1513 if (!dest)
1515 dest = buffer;
1516 buffer = (char *)buffer + sizeof(TYPEDESC);
1519 *dest = *src;
1521 switch (src->vt)
1523 case VT_PTR:
1524 case VT_SAFEARRAY:
1525 dest->u.lptdesc = buffer;
1526 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1527 break;
1528 case VT_CARRAY:
1529 dest->u.lpadesc = buffer;
1530 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1531 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1532 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1533 break;
1535 return buffer;
1538 /* free custom data allocated by MSFT_CustData */
1539 static inline void TLB_FreeCustData(struct list *custdata_list)
1541 TLBCustData *cd, *cdn;
1542 LIST_FOR_EACH_ENTRY_SAFE(cd, cdn, custdata_list, TLBCustData, entry)
1544 list_remove(&cd->entry);
1545 VariantClear(&cd->data);
1546 heap_free(cd);
1550 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1552 DWORD len;
1553 BSTR ret;
1555 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1556 ret = SysAllocStringLen(NULL, len - 1);
1557 if (!ret) return ret;
1558 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1559 return ret;
1562 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(TLBFuncDesc *funcdescs,
1563 UINT n, MEMBERID memid)
1565 while(n){
1566 if(funcdescs->funcdesc.memid == memid)
1567 return funcdescs;
1568 ++funcdescs;
1569 --n;
1571 return NULL;
1574 static inline TLBFuncDesc *TLB_get_funcdesc_by_name(TLBFuncDesc *funcdescs,
1575 UINT n, const OLECHAR *name)
1577 while(n){
1578 if(!lstrcmpiW(funcdescs->Name, name))
1579 return funcdescs;
1580 ++funcdescs;
1581 --n;
1583 return NULL;
1586 static inline TLBVarDesc *TLB_get_vardesc_by_memberid(TLBVarDesc *vardescs,
1587 UINT n, MEMBERID memid)
1589 while(n){
1590 if(vardescs->vardesc.memid == memid)
1591 return vardescs;
1592 ++vardescs;
1593 --n;
1595 return NULL;
1598 static inline TLBVarDesc *TLB_get_vardesc_by_name(TLBVarDesc *vardescs,
1599 UINT n, const OLECHAR *name)
1601 while(n){
1602 if(!lstrcmpiW(vardescs->Name, name))
1603 return vardescs;
1604 ++vardescs;
1605 --n;
1607 return NULL;
1610 static inline TLBCustData *TLB_get_custdata_by_guid(struct list *custdata_list, REFGUID guid)
1612 TLBCustData *cust_data;
1613 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1614 if(IsEqualIID(&cust_data->guid, guid))
1615 return cust_data;
1616 return NULL;
1619 static TLBVarDesc *TLBVarDesc_Constructor(UINT n)
1621 TLBVarDesc *ret;
1623 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1624 if(!ret)
1625 return NULL;
1627 while(n){
1628 list_init(&ret[n-1].custdata_list);
1629 --n;
1632 return ret;
1635 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1637 TLBParDesc *ret;
1639 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1640 if(!ret)
1641 return NULL;
1643 while(n){
1644 list_init(&ret[n-1].custdata_list);
1645 --n;
1648 return ret;
1651 static TLBFuncDesc *TLBFuncDesc_Constructor(UINT n)
1653 TLBFuncDesc *ret;
1655 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1656 if(!ret)
1657 return NULL;
1659 while(n){
1660 list_init(&ret[n-1].custdata_list);
1661 --n;
1664 return ret;
1667 static TLBImplType *TLBImplType_Constructor(UINT n)
1669 TLBImplType *ret;
1671 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1672 if(!ret)
1673 return NULL;
1675 while(n){
1676 list_init(&ret[n-1].custdata_list);
1677 --n;
1680 return ret;
1683 /**********************************************************************
1685 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1687 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1689 return pcx->pos;
1692 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
1694 if (where != DO_NOT_SEEK)
1696 where += pcx->oStart;
1697 if (where > pcx->length)
1699 /* FIXME */
1700 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
1701 TLB_abort();
1703 pcx->pos = where;
1707 /* read function */
1708 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
1710 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
1711 pcx->pos, count, pcx->oStart, pcx->length, where);
1713 MSFT_Seek(pcx, where);
1714 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1715 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1716 pcx->pos += count;
1717 return count;
1720 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1721 LONG where )
1723 DWORD ret;
1725 ret = MSFT_Read(buffer, count, pcx, where);
1726 FromLEDWords(buffer, ret);
1728 return ret;
1731 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1732 LONG where )
1734 DWORD ret;
1736 ret = MSFT_Read(buffer, count, pcx, where);
1737 FromLEWords(buffer, ret);
1739 return ret;
1742 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1744 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1745 memset(pGuid,0, sizeof(GUID));
1746 return;
1748 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1749 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1750 pGuid->Data2 = FromLEWord(pGuid->Data2);
1751 pGuid->Data3 = FromLEWord(pGuid->Data3);
1752 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1755 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1757 MSFT_NameIntro niName;
1759 if (offset < 0)
1761 ERR_(typelib)("bad offset %d\n", offset);
1762 return -1;
1765 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1766 pcx->pTblDir->pNametab.offset+offset);
1768 return niName.hreftype;
1771 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1773 char * name;
1774 MSFT_NameIntro niName;
1775 int lengthInChars;
1776 BSTR bstrName = NULL;
1778 if (offset < 0)
1780 ERR_(typelib)("bad offset %d\n", offset);
1781 return NULL;
1783 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1784 pcx->pTblDir->pNametab.offset+offset);
1785 niName.namelen &= 0xFF; /* FIXME: correct ? */
1786 name = heap_alloc_zero((niName.namelen & 0xff) +1);
1787 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1788 name[niName.namelen & 0xff]='\0';
1790 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1791 name, -1, NULL, 0);
1793 /* no invalid characters in string */
1794 if (lengthInChars)
1796 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1798 /* don't check for invalid character since this has been done previously */
1799 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1801 heap_free(name);
1803 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1804 return bstrName;
1807 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1809 char * string;
1810 INT16 length;
1811 int lengthInChars;
1812 BSTR bstr = NULL;
1814 if(offset<0) return NULL;
1815 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1816 if(length <= 0) return 0;
1817 string = heap_alloc_zero(length +1);
1818 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1819 string[length]='\0';
1821 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1822 string, -1, NULL, 0);
1824 /* no invalid characters in string */
1825 if (lengthInChars)
1827 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1829 /* don't check for invalid character since this has been done previously */
1830 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1832 heap_free(string);
1834 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1835 return bstr;
1838 * read a value and fill a VARIANT structure
1840 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1842 int size;
1844 TRACE_(typelib)("\n");
1846 if(offset <0) { /* data are packed in here */
1847 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1848 V_I4(pVar) = offset & 0x3ffffff;
1849 return;
1851 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1852 pcx->pTblDir->pCustData.offset + offset );
1853 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1854 switch (V_VT(pVar)){
1855 case VT_EMPTY: /* FIXME: is this right? */
1856 case VT_NULL: /* FIXME: is this right? */
1857 case VT_I2 : /* this should not happen */
1858 case VT_I4 :
1859 case VT_R4 :
1860 case VT_ERROR :
1861 case VT_BOOL :
1862 case VT_I1 :
1863 case VT_UI1 :
1864 case VT_UI2 :
1865 case VT_UI4 :
1866 case VT_INT :
1867 case VT_UINT :
1868 case VT_VOID : /* FIXME: is this right? */
1869 case VT_HRESULT :
1870 size=4; break;
1871 case VT_R8 :
1872 case VT_CY :
1873 case VT_DATE :
1874 case VT_I8 :
1875 case VT_UI8 :
1876 case VT_DECIMAL : /* FIXME: is this right? */
1877 case VT_FILETIME :
1878 size=8;break;
1879 /* pointer types with known behaviour */
1880 case VT_BSTR :{
1881 char * ptr;
1882 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1883 if(size < 0) {
1884 char next;
1885 DWORD origPos = MSFT_Tell(pcx), nullPos;
1887 do {
1888 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1889 } while (next);
1890 nullPos = MSFT_Tell(pcx);
1891 size = nullPos - origPos;
1892 MSFT_Seek(pcx, origPos);
1894 ptr = heap_alloc_zero(size);/* allocate temp buffer */
1895 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1896 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1897 /* FIXME: do we need a AtoW conversion here? */
1898 V_UNION(pVar, bstrVal[size])='\0';
1899 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1900 heap_free(ptr);
1902 size=-4; break;
1903 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1904 case VT_DISPATCH :
1905 case VT_VARIANT :
1906 case VT_UNKNOWN :
1907 case VT_PTR :
1908 case VT_SAFEARRAY :
1909 case VT_CARRAY :
1910 case VT_USERDEFINED :
1911 case VT_LPSTR :
1912 case VT_LPWSTR :
1913 case VT_BLOB :
1914 case VT_STREAM :
1915 case VT_STORAGE :
1916 case VT_STREAMED_OBJECT :
1917 case VT_STORED_OBJECT :
1918 case VT_BLOB_OBJECT :
1919 case VT_CF :
1920 case VT_CLSID :
1921 default:
1922 size=0;
1923 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1924 V_VT(pVar));
1927 if(size>0) /* (big|small) endian correct? */
1928 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1929 return;
1932 * create a linked list with custom data
1934 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
1936 MSFT_CDGuid entry;
1937 TLBCustData* pNew;
1938 int count=0;
1940 TRACE_(typelib)("\n");
1942 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
1944 while(offset >=0){
1945 count++;
1946 pNew=heap_alloc_zero(sizeof(TLBCustData));
1947 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1948 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1949 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1950 list_add_head(custdata_list, &pNew->entry);
1951 offset = entry.next;
1953 return count;
1956 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1957 ITypeInfoImpl *pTI)
1959 if(type <0)
1960 pTd->vt=type & VT_TYPEMASK;
1961 else
1962 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1964 if(pTd->vt == VT_USERDEFINED)
1965 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1967 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1970 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1972 /* resolve referenced type if any */
1973 while (lpTypeDesc)
1975 switch (lpTypeDesc->vt)
1977 case VT_PTR:
1978 lpTypeDesc = lpTypeDesc->u.lptdesc;
1979 break;
1981 case VT_CARRAY:
1982 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1983 break;
1985 case VT_USERDEFINED:
1986 MSFT_DoRefType(pcx, pTI->pTypeLib,
1987 lpTypeDesc->u.hreftype);
1989 lpTypeDesc = NULL;
1990 break;
1992 default:
1993 lpTypeDesc = NULL;
1998 static void
1999 MSFT_DoFuncs(TLBContext* pcx,
2000 ITypeInfoImpl* pTI,
2001 int cFuncs,
2002 int cVars,
2003 int offset,
2004 TLBFuncDesc** pptfd)
2007 * member information is stored in a data structure at offset
2008 * indicated by the memoffset field of the typeinfo structure
2009 * There are several distinctive parts.
2010 * The first part starts with a field that holds the total length
2011 * of this (first) part excluding this field. Then follow the records,
2012 * for each member there is one record.
2014 * The first entry is always the length of the record (including this
2015 * length word).
2016 * The rest of the record depends on the type of the member. If there is
2017 * a field indicating the member type (function, variable, interface, etc)
2018 * I have not found it yet. At this time we depend on the information
2019 * in the type info and the usual order how things are stored.
2021 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2022 * for each member;
2024 * Third is an equal sized array with file offsets to the name entry
2025 * of each member.
2027 * The fourth and last (?) part is an array with offsets to the records
2028 * in the first part of this file segment.
2031 int infolen, nameoffset, reclength, i;
2032 int recoffset = offset + sizeof(INT);
2034 char *recbuf = heap_alloc(0xffff);
2035 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2036 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2038 TRACE_(typelib)("\n");
2040 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2042 *pptfd = TLBFuncDesc_Constructor(cFuncs);
2043 ptfd = *pptfd;
2044 for ( i = 0; i < cFuncs ; i++ )
2046 int optional;
2048 /* name, eventually add to a hash table */
2049 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2050 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2052 /* nameoffset is sometimes -1 on the second half of a propget/propput
2053 * pair of functions */
2054 if ((nameoffset == -1) && (i > 0))
2055 ptfd->Name = SysAllocString(ptfd_prev->Name);
2056 else
2057 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2059 /* read the function information record */
2060 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2062 reclength &= 0xffff;
2064 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2066 /* size without argument data */
2067 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2069 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2070 ptfd->helpcontext = pFuncRec->HelpContext;
2072 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2073 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2075 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2077 if (pFuncRec->FKCCIC & 0x2000 )
2079 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2080 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2081 ptfd->Entry = (BSTR)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2083 else
2084 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2086 else
2087 ptfd->Entry = (BSTR)-1;
2089 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2090 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2092 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2093 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2095 /* fill the FuncDesc Structure */
2096 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2097 offset + infolen + ( i + 1) * sizeof(INT));
2099 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2100 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2101 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2102 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2103 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2104 ptfd->funcdesc.oVft = pFuncRec->VtableOffset & ~1;
2105 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2107 MSFT_GetTdesc(pcx,
2108 pFuncRec->DataType,
2109 &ptfd->funcdesc.elemdescFunc.tdesc,
2110 pTI);
2111 MSFT_ResolveReferencedTypes(pcx, pTI, &ptfd->funcdesc.elemdescFunc.tdesc);
2113 /* do the parameters/arguments */
2114 if(pFuncRec->nrargs)
2116 int j = 0;
2117 MSFT_ParameterInfo paraminfo;
2119 ptfd->funcdesc.lprgelemdescParam =
2120 heap_alloc_zero(pFuncRec->nrargs * sizeof(ELEMDESC));
2122 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2124 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2125 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2127 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2129 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2131 MSFT_GetTdesc(pcx,
2132 paraminfo.DataType,
2133 &elemdesc->tdesc,
2134 pTI);
2136 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2138 /* name */
2139 if (paraminfo.oName == -1)
2140 /* this occurs for [propput] or [propget] methods, so
2141 * we should just set the name of the parameter to the
2142 * name of the method. */
2143 ptfd->pParamDesc[j].Name = SysAllocString(ptfd->Name);
2144 else
2145 ptfd->pParamDesc[j].Name =
2146 MSFT_ReadName( pcx, paraminfo.oName );
2147 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(ptfd->pParamDesc[j].Name));
2149 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
2151 /* default value */
2152 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2153 (pFuncRec->FKCCIC & 0x1000) )
2155 INT* pInt = (INT *)((char *)pFuncRec +
2156 reclength -
2157 (pFuncRec->nrargs * 4) * sizeof(INT) );
2159 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2161 pParamDesc->pparamdescex = heap_alloc_zero(sizeof(PARAMDESCEX));
2162 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2164 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2165 pInt[j], pcx);
2167 else
2168 elemdesc->u.paramdesc.pparamdescex = NULL;
2170 /* custom info */
2171 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2172 j*sizeof(pFuncRec->oArgCustData[0])) &&
2173 pFuncRec->FKCCIC & 0x80 )
2175 MSFT_CustData(pcx,
2176 pFuncRec->oArgCustData[j],
2177 &ptfd->pParamDesc[j].custdata_list);
2180 /* SEEK value = jump to offset,
2181 * from there jump to the end of record,
2182 * go back by (j-1) arguments
2184 MSFT_ReadLEDWords( &paraminfo ,
2185 sizeof(MSFT_ParameterInfo), pcx,
2186 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2187 * sizeof(MSFT_ParameterInfo)));
2191 /* scode is not used: archaic win16 stuff FIXME: right? */
2192 ptfd->funcdesc.cScodes = 0 ;
2193 ptfd->funcdesc.lprgscode = NULL ;
2195 ptfd_prev = ptfd;
2196 ++ptfd;
2197 recoffset += reclength;
2199 heap_free(recbuf);
2202 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2203 int cVars, int offset, TLBVarDesc ** pptvd)
2205 int infolen, nameoffset, reclength;
2206 char recbuf[256];
2207 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2208 TLBVarDesc *ptvd;
2209 int i;
2210 int recoffset;
2212 TRACE_(typelib)("\n");
2214 ptvd = *pptvd = TLBVarDesc_Constructor(cVars);
2215 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2216 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2217 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2218 recoffset += offset+sizeof(INT);
2219 for(i=0;i<cVars;i++, ++ptvd){
2220 /* name, eventually add to a hash table */
2221 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2222 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2223 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2224 /* read the variable information record */
2225 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2226 reclength &= 0xff;
2227 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2229 /* optional data */
2230 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2231 ptvd->HelpContext = pVarRec->HelpContext;
2233 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2234 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2236 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2237 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2239 /* fill the VarDesc Structure */
2240 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2241 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2242 ptvd->vardesc.varkind = pVarRec->VarKind;
2243 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2244 MSFT_GetTdesc(pcx, pVarRec->DataType,
2245 &ptvd->vardesc.elemdescVar.tdesc, pTI);
2246 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2247 if(pVarRec->VarKind == VAR_CONST ){
2248 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2249 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2250 pVarRec->OffsValue, pcx);
2251 } else
2252 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2253 MSFT_ResolveReferencedTypes(pcx, pTI, &ptvd->vardesc.elemdescVar.tdesc);
2254 recoffset += reclength;
2258 /* fill in data for a hreftype (offset). When the referenced type is contained
2259 * in the typelib, it's just an (file) offset in the type info base dir.
2260 * If comes from import, it's an offset+1 in the ImpInfo table
2261 * */
2262 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2263 int offset)
2265 TLBRefType *ref;
2267 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2269 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2271 if(ref->reference == offset) return;
2274 ref = heap_alloc_zero(sizeof(TLBRefType));
2275 list_add_tail(&pTL->ref_list, &ref->entry);
2277 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2278 /* external typelib */
2279 MSFT_ImpInfo impinfo;
2280 TLBImpLib *pImpLib;
2282 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2284 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2285 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2287 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2288 if(pImpLib->offset==impinfo.oImpFile)
2289 break;
2291 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2292 ref->reference = offset;
2293 ref->pImpTLInfo = pImpLib;
2294 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2295 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2296 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2297 ref->index = TLB_REF_USE_GUID;
2298 } else
2299 ref->index = impinfo.oGuid;
2300 }else{
2301 ERR("Cannot find a reference\n");
2302 ref->reference = -1;
2303 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2305 }else{
2306 /* in this typelib */
2307 ref->index = MSFT_HREFTYPE_INDEX(offset);
2308 ref->reference = offset;
2309 ref->pImpTLInfo = TLB_REF_INTERNAL;
2313 /* process Implemented Interfaces of a com class */
2314 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2315 int offset)
2317 int i;
2318 MSFT_RefRecord refrec;
2319 TLBImplType *pImpl;
2321 TRACE_(typelib)("\n");
2323 pTI->impltypes = TLBImplType_Constructor(count);
2324 pImpl = pTI->impltypes;
2325 for(i=0;i<count;i++){
2326 if(offset<0) break; /* paranoia */
2327 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2328 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2329 pImpl->hRef = refrec.reftype;
2330 pImpl->implflags=refrec.flags;
2331 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2332 offset=refrec.onext;
2333 ++pImpl;
2337 * process a typeinfo record
2339 static ITypeInfoImpl * MSFT_DoTypeInfo(
2340 TLBContext *pcx,
2341 int count,
2342 ITypeLibImpl * pLibInfo)
2344 MSFT_TypeInfoBase tiBase;
2345 ITypeInfoImpl *ptiRet;
2347 TRACE_(typelib)("count=%u\n", count);
2349 ptiRet = ITypeInfoImpl_Constructor();
2350 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2351 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2353 /* this is where we are coming from */
2354 ptiRet->pTypeLib = pLibInfo;
2355 ptiRet->index=count;
2356 /* fill in the typeattr fields */
2358 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2359 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2360 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2361 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2362 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2363 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2364 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2365 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2366 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2367 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2368 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2369 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2370 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2371 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2372 MSFT_GetTdesc(pcx, tiBase.datatype1,
2373 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2375 /* FIXME: */
2376 /* IDLDESC idldescType; *//* never saw this one != zero */
2378 /* name, eventually add to a hash table */
2379 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2380 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2381 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2382 /* help info */
2383 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2384 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2385 ptiRet->dwHelpContext=tiBase.helpcontext;
2387 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2388 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2390 /* note: InfoType's Help file and HelpStringDll come from the containing
2391 * library. Further HelpString and Docstring appear to be the same thing :(
2393 /* functions */
2394 if(ptiRet->TypeAttr.cFuncs >0 )
2395 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2396 ptiRet->TypeAttr.cVars,
2397 tiBase.memoffset, &ptiRet->funcdescs);
2398 /* variables */
2399 if(ptiRet->TypeAttr.cVars >0 )
2400 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2401 ptiRet->TypeAttr.cVars,
2402 tiBase.memoffset, &ptiRet->vardescs);
2403 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2404 switch(ptiRet->TypeAttr.typekind)
2406 case TKIND_COCLASS:
2407 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2408 tiBase.datatype1);
2409 break;
2410 case TKIND_DISPATCH:
2411 /* This is not -1 when the interface is a non-base dual interface or
2412 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2413 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2414 not this interface.
2417 if (tiBase.datatype1 != -1)
2419 ptiRet->impltypes = TLBImplType_Constructor(1);
2420 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2421 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2423 break;
2424 default:
2425 ptiRet->impltypes = TLBImplType_Constructor(1);
2426 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2427 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2428 break;
2431 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->custdata_list);
2433 TRACE_(typelib)("%s guid: %s kind:%s\n",
2434 debugstr_w(ptiRet->Name),
2435 debugstr_guid(&ptiRet->TypeAttr.guid),
2436 typekind_desc[ptiRet->TypeAttr.typekind]);
2437 if (TRACE_ON(typelib))
2438 dump_TypeInfo(ptiRet);
2440 return ptiRet;
2443 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2444 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2445 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2446 * tradeoff here.
2448 static struct list tlb_cache = LIST_INIT(tlb_cache);
2449 static CRITICAL_SECTION cache_section;
2450 static CRITICAL_SECTION_DEBUG cache_section_debug =
2452 0, 0, &cache_section,
2453 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2454 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2456 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2459 typedef struct TLB_PEFile
2461 const IUnknownVtbl *lpvtbl;
2462 LONG refs;
2463 HMODULE dll;
2464 HRSRC typelib_resource;
2465 HGLOBAL typelib_global;
2466 LPVOID typelib_base;
2467 } TLB_PEFile;
2469 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2471 if (IsEqualIID(riid, &IID_IUnknown))
2473 *ppv = iface;
2474 IUnknown_AddRef(iface);
2475 return S_OK;
2477 *ppv = NULL;
2478 return E_NOINTERFACE;
2481 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2483 TLB_PEFile *This = (TLB_PEFile *)iface;
2484 return InterlockedIncrement(&This->refs);
2487 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2489 TLB_PEFile *This = (TLB_PEFile *)iface;
2490 ULONG refs = InterlockedDecrement(&This->refs);
2491 if (!refs)
2493 if (This->typelib_global)
2494 FreeResource(This->typelib_global);
2495 if (This->dll)
2496 FreeLibrary(This->dll);
2497 heap_free(This);
2499 return refs;
2502 static const IUnknownVtbl TLB_PEFile_Vtable =
2504 TLB_PEFile_QueryInterface,
2505 TLB_PEFile_AddRef,
2506 TLB_PEFile_Release
2509 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2511 TLB_PEFile *This;
2513 This = heap_alloc(sizeof(TLB_PEFile));
2514 if (!This)
2515 return E_OUTOFMEMORY;
2517 This->lpvtbl = &TLB_PEFile_Vtable;
2518 This->refs = 1;
2519 This->dll = NULL;
2520 This->typelib_resource = NULL;
2521 This->typelib_global = NULL;
2522 This->typelib_base = NULL;
2524 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2525 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2527 if (This->dll)
2529 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2530 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2531 if (This->typelib_resource)
2533 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2534 if (This->typelib_global)
2536 This->typelib_base = LockResource(This->typelib_global);
2538 if (This->typelib_base)
2540 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2541 *ppBase = This->typelib_base;
2542 *ppFile = (IUnknown *)&This->lpvtbl;
2543 return S_OK;
2549 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2550 return TYPE_E_CANTLOADLIBRARY;
2553 typedef struct TLB_NEFile
2555 const IUnknownVtbl *lpvtbl;
2556 LONG refs;
2557 LPVOID typelib_base;
2558 } TLB_NEFile;
2560 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2562 if (IsEqualIID(riid, &IID_IUnknown))
2564 *ppv = iface;
2565 IUnknown_AddRef(iface);
2566 return S_OK;
2568 *ppv = NULL;
2569 return E_NOINTERFACE;
2572 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2574 TLB_NEFile *This = (TLB_NEFile *)iface;
2575 return InterlockedIncrement(&This->refs);
2578 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2580 TLB_NEFile *This = (TLB_NEFile *)iface;
2581 ULONG refs = InterlockedDecrement(&This->refs);
2582 if (!refs)
2584 heap_free(This->typelib_base);
2585 heap_free(This);
2587 return refs;
2590 static const IUnknownVtbl TLB_NEFile_Vtable =
2592 TLB_NEFile_QueryInterface,
2593 TLB_NEFile_AddRef,
2594 TLB_NEFile_Release
2597 /***********************************************************************
2598 * read_xx_header [internal]
2600 static int read_xx_header( HFILE lzfd )
2602 IMAGE_DOS_HEADER mzh;
2603 char magic[3];
2605 LZSeek( lzfd, 0, SEEK_SET );
2606 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2607 return 0;
2608 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2609 return 0;
2611 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2612 if ( 2 != LZRead( lzfd, magic, 2 ) )
2613 return 0;
2615 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2617 if ( magic[0] == 'N' && magic[1] == 'E' )
2618 return IMAGE_OS2_SIGNATURE;
2619 if ( magic[0] == 'P' && magic[1] == 'E' )
2620 return IMAGE_NT_SIGNATURE;
2622 magic[2] = '\0';
2623 WARN("Can't handle %s files.\n", magic );
2624 return 0;
2628 /***********************************************************************
2629 * find_ne_resource [internal]
2631 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2632 DWORD *resLen, DWORD *resOff )
2634 IMAGE_OS2_HEADER nehd;
2635 NE_TYPEINFO *typeInfo;
2636 NE_NAMEINFO *nameInfo;
2637 DWORD nehdoffset;
2638 LPBYTE resTab;
2639 DWORD resTabSize;
2640 int count;
2642 /* Read in NE header */
2643 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2644 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2646 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2647 if ( !resTabSize )
2649 TRACE("No resources in NE dll\n" );
2650 return FALSE;
2653 /* Read in resource table */
2654 resTab = heap_alloc( resTabSize );
2655 if ( !resTab ) return FALSE;
2657 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2658 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2660 heap_free( resTab );
2661 return FALSE;
2664 /* Find resource */
2665 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2667 if (!IS_INTRESOURCE(typeid)) /* named type */
2669 BYTE len = strlen( typeid );
2670 while (typeInfo->type_id)
2672 if (!(typeInfo->type_id & 0x8000))
2674 BYTE *p = resTab + typeInfo->type_id;
2675 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2677 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2678 typeInfo->count * sizeof(NE_NAMEINFO));
2681 else /* numeric type id */
2683 WORD id = LOWORD(typeid) | 0x8000;
2684 while (typeInfo->type_id)
2686 if (typeInfo->type_id == id) goto found_type;
2687 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2688 typeInfo->count * sizeof(NE_NAMEINFO));
2691 TRACE("No typeid entry found for %p\n", typeid );
2692 heap_free( resTab );
2693 return FALSE;
2695 found_type:
2696 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2698 if (!IS_INTRESOURCE(resid)) /* named resource */
2700 BYTE len = strlen( resid );
2701 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2703 BYTE *p = resTab + nameInfo->id;
2704 if (nameInfo->id & 0x8000) continue;
2705 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2708 else /* numeric resource id */
2710 WORD id = LOWORD(resid) | 0x8000;
2711 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2712 if (nameInfo->id == id) goto found_name;
2714 TRACE("No resid entry found for %p\n", typeid );
2715 heap_free( resTab );
2716 return FALSE;
2718 found_name:
2719 /* Return resource data */
2720 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2721 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2723 heap_free( resTab );
2724 return TRUE;
2727 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
2729 HFILE lzfd = -1;
2730 OFSTRUCT ofs;
2731 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2732 TLB_NEFile *This;
2734 This = heap_alloc(sizeof(TLB_NEFile));
2735 if (!This) return E_OUTOFMEMORY;
2737 This->lpvtbl = &TLB_NEFile_Vtable;
2738 This->refs = 1;
2739 This->typelib_base = NULL;
2741 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
2742 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
2744 DWORD reslen, offset;
2745 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
2747 This->typelib_base = heap_alloc(reslen);
2748 if( !This->typelib_base )
2749 hr = E_OUTOFMEMORY;
2750 else
2752 LZSeek( lzfd, offset, SEEK_SET );
2753 reslen = LZRead( lzfd, This->typelib_base, reslen );
2754 LZClose( lzfd );
2755 *ppBase = This->typelib_base;
2756 *pdwTLBLength = reslen;
2757 *ppFile = (IUnknown *)&This->lpvtbl;
2758 return S_OK;
2763 if( lzfd >= 0) LZClose( lzfd );
2764 TLB_NEFile_Release((IUnknown *)&This->lpvtbl);
2765 return hr;
2768 typedef struct TLB_Mapping
2770 const IUnknownVtbl *lpvtbl;
2771 LONG refs;
2772 HANDLE file;
2773 HANDLE mapping;
2774 LPVOID typelib_base;
2775 } TLB_Mapping;
2777 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2779 if (IsEqualIID(riid, &IID_IUnknown))
2781 *ppv = iface;
2782 IUnknown_AddRef(iface);
2783 return S_OK;
2785 *ppv = NULL;
2786 return E_NOINTERFACE;
2789 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2791 TLB_Mapping *This = (TLB_Mapping *)iface;
2792 return InterlockedIncrement(&This->refs);
2795 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2797 TLB_Mapping *This = (TLB_Mapping *)iface;
2798 ULONG refs = InterlockedDecrement(&This->refs);
2799 if (!refs)
2801 if (This->typelib_base)
2802 UnmapViewOfFile(This->typelib_base);
2803 if (This->mapping)
2804 CloseHandle(This->mapping);
2805 if (This->file != INVALID_HANDLE_VALUE)
2806 CloseHandle(This->file);
2807 heap_free(This);
2809 return refs;
2812 static const IUnknownVtbl TLB_Mapping_Vtable =
2814 TLB_Mapping_QueryInterface,
2815 TLB_Mapping_AddRef,
2816 TLB_Mapping_Release
2819 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2821 TLB_Mapping *This;
2823 This = heap_alloc(sizeof(TLB_Mapping));
2824 if (!This)
2825 return E_OUTOFMEMORY;
2827 This->lpvtbl = &TLB_Mapping_Vtable;
2828 This->refs = 1;
2829 This->file = INVALID_HANDLE_VALUE;
2830 This->mapping = NULL;
2831 This->typelib_base = NULL;
2833 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2834 if (INVALID_HANDLE_VALUE != This->file)
2836 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2837 if (This->mapping)
2839 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2840 if(This->typelib_base)
2842 /* retrieve file size */
2843 *pdwTLBLength = GetFileSize(This->file, NULL);
2844 *ppBase = This->typelib_base;
2845 *ppFile = (IUnknown *)&This->lpvtbl;
2846 return S_OK;
2851 IUnknown_Release((IUnknown *)&This->lpvtbl);
2852 return TYPE_E_CANTLOADLIBRARY;
2855 /****************************************************************************
2856 * TLB_ReadTypeLib
2858 * find the type of the typelib file and map the typelib resource into
2859 * the memory
2862 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2863 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2865 ITypeLibImpl *entry;
2866 HRESULT ret;
2867 INT index = 1;
2868 LPWSTR index_str, file = (LPWSTR)pszFileName;
2869 LPVOID pBase = NULL;
2870 DWORD dwTLBLength = 0;
2871 IUnknown *pFile = NULL;
2873 *ppTypeLib = NULL;
2875 index_str = strrchrW(pszFileName, '\\');
2876 if(index_str && *++index_str != '\0')
2878 LPWSTR end_ptr;
2879 LONG idx = strtolW(index_str, &end_ptr, 10);
2880 if(*end_ptr == '\0')
2882 int str_len = index_str - pszFileName - 1;
2883 index = idx;
2884 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
2885 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2886 file[str_len] = 0;
2890 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2892 if(strchrW(file, '\\'))
2894 lstrcpyW(pszPath, file);
2896 else
2898 int len = GetSystemDirectoryW(pszPath, cchPath);
2899 pszPath[len] = '\\';
2900 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2904 if(file != pszFileName) heap_free(file);
2906 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2908 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2909 EnterCriticalSection(&cache_section);
2910 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
2912 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2914 TRACE("cache hit\n");
2915 *ppTypeLib = (ITypeLib2*)entry;
2916 ITypeLib_AddRef(*ppTypeLib);
2917 LeaveCriticalSection(&cache_section);
2918 return S_OK;
2921 LeaveCriticalSection(&cache_section);
2923 /* now actually load and parse the typelib */
2925 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2926 if (ret == TYPE_E_CANTLOADLIBRARY)
2927 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2928 if (ret == TYPE_E_CANTLOADLIBRARY)
2929 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2930 if (SUCCEEDED(ret))
2932 if (dwTLBLength >= 4)
2934 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2935 if (dwSignature == MSFT_SIGNATURE)
2936 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2937 else if (dwSignature == SLTG_SIGNATURE)
2938 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2939 else
2941 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2942 ret = TYPE_E_CANTLOADLIBRARY;
2945 else
2946 ret = TYPE_E_CANTLOADLIBRARY;
2947 IUnknown_Release(pFile);
2950 if(*ppTypeLib) {
2951 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2953 TRACE("adding to cache\n");
2954 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
2955 lstrcpyW(impl->path, pszPath);
2956 /* We should really canonicalise the path here. */
2957 impl->index = index;
2959 /* FIXME: check if it has added already in the meantime */
2960 EnterCriticalSection(&cache_section);
2961 list_add_head(&tlb_cache, &impl->entry);
2962 LeaveCriticalSection(&cache_section);
2963 ret = S_OK;
2964 } else
2965 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2967 return ret;
2970 /*================== ITypeLib(2) Methods ===================================*/
2972 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2974 ITypeLibImpl* pTypeLibImpl;
2976 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
2977 if (!pTypeLibImpl) return NULL;
2979 pTypeLibImpl->lpVtbl = &tlbvt;
2980 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2981 pTypeLibImpl->ref = 1;
2983 list_init(&pTypeLibImpl->implib_list);
2984 list_init(&pTypeLibImpl->custdata_list);
2985 list_init(&pTypeLibImpl->ref_list);
2986 pTypeLibImpl->dispatch_href = -1;
2988 return pTypeLibImpl;
2991 /****************************************************************************
2992 * ITypeLib2_Constructor_MSFT
2994 * loading an MSFT typelib from an in-memory image
2996 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2998 TLBContext cx;
2999 LONG lPSegDir;
3000 MSFT_Header tlbHeader;
3001 MSFT_SegDir tlbSegDir;
3002 ITypeLibImpl * pTypeLibImpl;
3004 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3006 pTypeLibImpl = TypeLibImpl_Constructor();
3007 if (!pTypeLibImpl) return NULL;
3009 /* get pointer to beginning of typelib data */
3010 cx.pos = 0;
3011 cx.oStart=0;
3012 cx.mapping = pLib;
3013 cx.pLibInfo = pTypeLibImpl;
3014 cx.length = dwTLBLength;
3016 /* read header */
3017 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
3018 TRACE_(typelib)("header:\n");
3019 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3020 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3021 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3022 return NULL;
3024 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3026 /* there is a small amount of information here until the next important
3027 * part:
3028 * the segment directory . Try to calculate the amount of data */
3029 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3031 /* now read the segment directory */
3032 TRACE("read segment directory (at %d)\n",lPSegDir);
3033 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3034 cx.pTblDir = &tlbSegDir;
3036 /* just check two entries */
3037 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3039 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3040 heap_free(pTypeLibImpl);
3041 return NULL;
3044 /* now fill our internal data */
3045 /* TLIBATTR fields */
3046 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
3048 pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid2;
3049 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3050 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
3051 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
3052 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
3054 pTypeLibImpl->lcid = tlbHeader.lcid;
3056 /* name, eventually add to a hash table */
3057 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3059 /* help info */
3060 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3061 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3063 if( tlbHeader.varflags & HELPDLLFLAG)
3065 int offset;
3066 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3067 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3070 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3072 /* custom data */
3073 if(tlbHeader.CustomDataOffset >= 0)
3075 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3078 /* fill in type descriptions */
3079 if(tlbSegDir.pTypdescTab.length > 0)
3081 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3082 INT16 td[4];
3083 pTypeLibImpl->ctTypeDesc = cTD;
3084 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3085 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3086 for(i=0; i<cTD; )
3088 /* FIXME: add several sanity checks here */
3089 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3090 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3092 /* FIXME: check safearray */
3093 if(td[3] < 0)
3094 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3095 else
3096 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3098 else if(td[0] == VT_CARRAY)
3100 /* array descr table here */
3101 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3103 else if(td[0] == VT_USERDEFINED)
3105 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3107 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3110 /* second time around to fill the array subscript info */
3111 for(i=0;i<cTD;i++)
3113 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3114 if(tlbSegDir.pArrayDescriptions.offset>0)
3116 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3117 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3119 if(td[1]<0)
3120 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3121 else
3122 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3124 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3126 for(j = 0; j<td[2]; j++)
3128 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3129 sizeof(INT), &cx, DO_NOT_SEEK);
3130 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3131 sizeof(INT), &cx, DO_NOT_SEEK);
3134 else
3136 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3137 ERR("didn't find array description data\n");
3142 /* imported type libs */
3143 if(tlbSegDir.pImpFiles.offset>0)
3145 TLBImpLib *pImpLib;
3146 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3147 UINT16 size;
3149 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3151 char *name;
3153 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3154 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3155 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3157 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3158 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3159 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3160 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3162 size >>= 2;
3163 name = heap_alloc_zero(size+1);
3164 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3165 pImpLib->name = TLB_MultiByteToBSTR(name);
3166 heap_free(name);
3168 MSFT_ReadGuid(&pImpLib->guid, oGuid, &cx);
3169 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3171 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3175 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3176 if(pTypeLibImpl->dispatch_href != -1)
3177 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
3179 /* type infos */
3180 if(tlbHeader.nrtypeinfos >= 0 )
3182 ITypeInfoImpl **ppTI;
3183 int i;
3185 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3187 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3189 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3191 ++ppTI;
3192 (pTypeLibImpl->TypeInfoCount)++;
3196 TRACE("(%p)\n", pTypeLibImpl);
3197 return (ITypeLib2*) pTypeLibImpl;
3201 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3203 char b[3];
3204 int i;
3205 short s;
3207 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3208 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3209 return FALSE;
3212 guid->Data4[0] = s >> 8;
3213 guid->Data4[1] = s & 0xff;
3215 b[2] = '\0';
3216 for(i = 0; i < 6; i++) {
3217 memcpy(b, str + 24 + 2 * i, 2);
3218 guid->Data4[i + 2] = strtol(b, NULL, 16);
3220 return TRUE;
3223 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
3225 WORD bytelen;
3226 DWORD len;
3228 *pBstr = NULL;
3229 bytelen = *(const WORD*)ptr;
3230 if(bytelen == 0xffff) return 2;
3231 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3232 *pBstr = SysAllocStringLen(NULL, len);
3233 if (*pBstr)
3234 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
3235 return bytelen + 2;
3238 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3240 WORD bytelen;
3242 *str = NULL;
3243 bytelen = *(const WORD*)ptr;
3244 if(bytelen == 0xffff) return 2;
3245 *str = heap_alloc(bytelen + 1);
3246 memcpy(*str, ptr + 2, bytelen);
3247 (*str)[bytelen] = '\0';
3248 return bytelen + 2;
3251 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3253 char *ptr = pLibBlk;
3254 WORD w;
3256 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3257 FIXME("libblk magic = %04x\n", w);
3258 return 0;
3261 ptr += 6;
3262 if((w = *(WORD*)ptr) != 0xffff) {
3263 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3264 ptr += w;
3266 ptr += 2;
3268 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
3270 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
3272 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3273 ptr += 4;
3275 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
3276 ptr += 2;
3278 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3279 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3280 else
3281 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = 0;
3282 ptr += 2;
3284 ptr += 4; /* skip res12 */
3286 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
3287 ptr += 2;
3289 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
3290 ptr += 2;
3292 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
3293 ptr += 2;
3295 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
3296 ptr += sizeof(GUID);
3298 return ptr - (char*)pLibBlk;
3301 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3302 typedef struct
3304 unsigned int num;
3305 HREFTYPE refs[1];
3306 } sltg_ref_lookup_t;
3308 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3309 HREFTYPE *typelib_ref)
3311 if(table && typeinfo_ref < table->num)
3313 *typelib_ref = table->refs[typeinfo_ref];
3314 return S_OK;
3317 ERR_(typelib)("Unable to find reference\n");
3318 *typelib_ref = -1;
3319 return E_FAIL;
3322 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3324 BOOL done = FALSE;
3326 while(!done) {
3327 if((*pType & 0xe00) == 0xe00) {
3328 pTD->vt = VT_PTR;
3329 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3330 pTD = pTD->u.lptdesc;
3332 switch(*pType & 0x3f) {
3333 case VT_PTR:
3334 pTD->vt = VT_PTR;
3335 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3336 pTD = pTD->u.lptdesc;
3337 break;
3339 case VT_USERDEFINED:
3340 pTD->vt = VT_USERDEFINED;
3341 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3342 done = TRUE;
3343 break;
3345 case VT_CARRAY:
3347 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3348 array */
3350 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3352 pTD->vt = VT_CARRAY;
3353 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3354 pTD->u.lpadesc->cDims = pSA->cDims;
3355 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3356 pSA->cDims * sizeof(SAFEARRAYBOUND));
3358 pTD = &pTD->u.lpadesc->tdescElem;
3359 break;
3362 case VT_SAFEARRAY:
3364 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3365 useful? */
3367 pType++;
3368 pTD->vt = VT_SAFEARRAY;
3369 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3370 pTD = pTD->u.lptdesc;
3371 break;
3373 default:
3374 pTD->vt = *pType & 0x3f;
3375 done = TRUE;
3376 break;
3378 pType++;
3380 return pType;
3383 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3384 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3386 /* Handle [in/out] first */
3387 if((*pType & 0xc000) == 0xc000)
3388 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3389 else if(*pType & 0x8000)
3390 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3391 else if(*pType & 0x4000)
3392 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3393 else
3394 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3396 if(*pType & 0x2000)
3397 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3399 if(*pType & 0x80)
3400 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3402 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3406 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3407 char *pNameTable)
3409 unsigned int ref;
3410 char *name;
3411 TLBRefType *ref_type;
3412 sltg_ref_lookup_t *table;
3413 HREFTYPE typelib_ref;
3415 if(pRef->magic != SLTG_REF_MAGIC) {
3416 FIXME("Ref magic = %x\n", pRef->magic);
3417 return NULL;
3419 name = ( (char*)pRef->names + pRef->number);
3421 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3422 table->num = pRef->number >> 3;
3424 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3426 /* We don't want the first href to be 0 */
3427 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3429 for(ref = 0; ref < pRef->number >> 3; ref++) {
3430 char *refname;
3431 unsigned int lib_offs, type_num;
3433 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3435 name += SLTG_ReadStringA(name, &refname);
3436 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3437 FIXME_(typelib)("Can't sscanf ref\n");
3438 if(lib_offs != 0xffff) {
3439 TLBImpLib *import;
3441 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
3442 if(import->offset == lib_offs)
3443 break;
3445 if(&import->entry == &pTL->implib_list) {
3446 char fname[MAX_PATH+1];
3447 int len;
3449 import = heap_alloc_zero(sizeof(*import));
3450 import->offset = lib_offs;
3451 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3452 &import->guid);
3453 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3454 &import->wVersionMajor,
3455 &import->wVersionMinor,
3456 &import->lcid, fname) != 4) {
3457 FIXME_(typelib)("can't sscanf ref %s\n",
3458 pNameTable + lib_offs + 40);
3460 len = strlen(fname);
3461 if(fname[len-1] != '#')
3462 FIXME("fname = %s\n", fname);
3463 fname[len-1] = '\0';
3464 import->name = TLB_MultiByteToBSTR(fname);
3465 list_add_tail(&pTL->implib_list, &import->entry);
3467 ref_type->pImpTLInfo = import;
3469 /* Store a reference to IDispatch */
3470 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid, &IID_StdOle) && type_num == 4)
3471 pTL->dispatch_href = typelib_ref;
3473 } else { /* internal ref */
3474 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3476 ref_type->reference = typelib_ref;
3477 ref_type->index = type_num;
3479 heap_free(refname);
3480 list_add_tail(&pTL->ref_list, &ref_type->entry);
3482 table->refs[ref] = typelib_ref;
3483 typelib_ref += 4;
3485 if((BYTE)*name != SLTG_REF_MAGIC)
3486 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3487 dump_TLBRefType(pTL);
3488 return table;
3491 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3492 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3494 SLTG_ImplInfo *info;
3495 TLBImplType *pImplType;
3496 /* I don't really get this structure, usually it's 0x16 bytes
3497 long, but iuser.tlb contains some that are 0x18 bytes long.
3498 That's ok because we can use the next ptr to jump to the next
3499 one. But how do we know the length of the last one? The WORD
3500 at offs 0x8 might be the clue. For now I'm just assuming that
3501 the last one is the regular 0x16 bytes. */
3503 info = (SLTG_ImplInfo*)pBlk;
3504 while(1){
3505 pTI->TypeAttr.cImplTypes++;
3506 if(info->next == 0xffff)
3507 break;
3508 info = (SLTG_ImplInfo*)(pBlk + info->next);
3511 info = (SLTG_ImplInfo*)pBlk;
3512 pTI->impltypes = TLBImplType_Constructor(pTI->TypeAttr.cImplTypes);
3513 pImplType = pTI->impltypes;
3514 while(1) {
3515 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
3516 pImplType->implflags = info->impltypeflags;
3517 ++pImplType;
3519 if(info->next == 0xffff)
3520 break;
3521 if(OneOnly)
3522 FIXME_(typelib)("Interface inheriting more than one interface\n");
3523 info = (SLTG_ImplInfo*)(pBlk + info->next);
3525 info++; /* see comment at top of function */
3526 return (char*)info;
3529 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3530 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3532 TLBVarDesc *pVarDesc;
3533 BSTR bstrPrevName = NULL;
3534 SLTG_Variable *pItem;
3535 unsigned short i;
3536 WORD *pType;
3538 pVarDesc = pTI->vardescs = TLBVarDesc_Constructor(cVars);
3540 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3541 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
3543 pVarDesc->vardesc.memid = pItem->memid;
3545 if (pItem->magic != SLTG_VAR_MAGIC &&
3546 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3547 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3548 return;
3551 if (pItem->name == 0xfffe)
3552 pVarDesc->Name = SysAllocString(bstrPrevName);
3553 else
3554 pVarDesc->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3556 TRACE_(typelib)("name: %s\n", debugstr_w(pVarDesc->Name));
3557 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3558 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3560 if(pItem->flags & 0x02)
3561 pType = &pItem->type;
3562 else
3563 pType = (WORD*)(pBlk + pItem->type);
3565 if (pItem->flags & ~0xda)
3566 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3568 SLTG_DoElem(pType, pBlk,
3569 &pVarDesc->vardesc.elemdescVar, ref_lookup);
3571 if (TRACE_ON(typelib)) {
3572 char buf[300];
3573 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
3574 TRACE_(typelib)("elemdescVar: %s\n", buf);
3577 if (pItem->flags & 0x40) {
3578 TRACE_(typelib)("VAR_DISPATCH\n");
3579 pVarDesc->vardesc.varkind = VAR_DISPATCH;
3581 else if (pItem->flags & 0x10) {
3582 TRACE_(typelib)("VAR_CONST\n");
3583 pVarDesc->vardesc.varkind = VAR_CONST;
3584 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
3585 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
3586 if (pItem->flags & 0x08)
3587 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
3588 else {
3589 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
3591 case VT_LPSTR:
3592 case VT_LPWSTR:
3593 case VT_BSTR:
3595 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3596 BSTR str;
3597 TRACE_(typelib)("len = %u\n", len);
3598 if (len == 0xffff) {
3599 str = NULL;
3600 } else {
3601 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3602 str = SysAllocStringLen(NULL, alloc_len);
3603 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3605 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
3606 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
3607 break;
3609 case VT_I2:
3610 case VT_UI2:
3611 case VT_I4:
3612 case VT_UI4:
3613 case VT_INT:
3614 case VT_UINT:
3615 V_INT(pVarDesc->vardesc.u.lpvarValue) =
3616 *(INT*)(pBlk + pItem->byte_offs);
3617 break;
3618 default:
3619 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
3623 else {
3624 TRACE_(typelib)("VAR_PERINSTANCE\n");
3625 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
3626 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
3629 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3630 pVarDesc->vardesc.wVarFlags = pItem->varflags;
3632 if (pItem->flags & 0x80)
3633 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3635 bstrPrevName = pVarDesc->Name;
3637 pTI->TypeAttr.cVars = cVars;
3640 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3641 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3643 SLTG_Function *pFunc;
3644 unsigned short i;
3645 TLBFuncDesc *pFuncDesc;
3647 pTI->funcdescs = TLBFuncDesc_Constructor(cFuncs);
3649 pFuncDesc = pTI->funcdescs;
3650 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
3651 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
3653 int param;
3654 WORD *pType, *pArg;
3656 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3657 case SLTG_FUNCTION_MAGIC:
3658 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
3659 break;
3660 case SLTG_DISPATCH_FUNCTION_MAGIC:
3661 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
3662 break;
3663 case SLTG_STATIC_FUNCTION_MAGIC:
3664 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
3665 break;
3666 default:
3667 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3668 continue;
3670 pFuncDesc->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3672 pFuncDesc->funcdesc.memid = pFunc->dispid;
3673 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
3674 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
3675 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
3676 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3677 pFuncDesc->funcdesc.oVft = pFunc->vtblpos & ~1;
3679 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3680 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
3682 if(pFunc->retnextopt & 0x80)
3683 pType = &pFunc->rettype;
3684 else
3685 pType = (WORD*)(pBlk + pFunc->rettype);
3687 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
3689 pFuncDesc->funcdesc.lprgelemdescParam =
3690 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
3691 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
3693 pArg = (WORD*)(pBlk + pFunc->arg_off);
3695 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
3696 char *paramName = pNameTable + *pArg;
3697 BOOL HaveOffs;
3698 /* If arg type follows then paramName points to the 2nd
3699 letter of the name, else the next WORD is an offset to
3700 the arg type and paramName points to the first letter.
3701 So let's take one char off paramName and see if we're
3702 pointing at an alpha-numeric char. However if *pArg is
3703 0xffff or 0xfffe then the param has no name, the former
3704 meaning that the next WORD is the type, the latter
3705 meaning that the next WORD is an offset to the type. */
3707 HaveOffs = FALSE;
3708 if(*pArg == 0xffff)
3709 paramName = NULL;
3710 else if(*pArg == 0xfffe) {
3711 paramName = NULL;
3712 HaveOffs = TRUE;
3714 else if(paramName[-1] && !isalnum(paramName[-1]))
3715 HaveOffs = TRUE;
3717 pArg++;
3719 if(HaveOffs) { /* the next word is an offset to type */
3720 pType = (WORD*)(pBlk + *pArg);
3721 SLTG_DoElem(pType, pBlk,
3722 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
3723 pArg++;
3724 } else {
3725 if(paramName)
3726 paramName--;
3727 pArg = SLTG_DoElem(pArg, pBlk,
3728 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
3731 /* Are we an optional param ? */
3732 if(pFuncDesc->funcdesc.cParams - param <=
3733 pFuncDesc->funcdesc.cParamsOpt)
3734 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3736 if(paramName) {
3737 pFuncDesc->pParamDesc[param].Name =
3738 TLB_MultiByteToBSTR(paramName);
3739 } else {
3740 pFuncDesc->pParamDesc[param].Name =
3741 SysAllocString(pFuncDesc->Name);
3745 pTI->TypeAttr.cFuncs = cFuncs;
3748 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3749 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3750 SLTG_TypeInfoTail *pTITail)
3752 char *pFirstItem;
3753 sltg_ref_lookup_t *ref_lookup = NULL;
3755 if(pTIHeader->href_table != 0xffffffff) {
3756 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3757 pNameTable);
3760 pFirstItem = pBlk;
3762 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3763 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3765 heap_free(ref_lookup);
3769 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3770 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3771 const SLTG_TypeInfoTail *pTITail)
3773 char *pFirstItem;
3774 sltg_ref_lookup_t *ref_lookup = NULL;
3776 if(pTIHeader->href_table != 0xffffffff) {
3777 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3778 pNameTable);
3781 pFirstItem = pBlk;
3783 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3784 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3787 if (pTITail->funcs_off != 0xffff)
3788 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3790 heap_free(ref_lookup);
3792 if (TRACE_ON(typelib))
3793 dump_TLBFuncDesc(pTI->funcdescs, pTI->TypeAttr.cFuncs);
3796 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3797 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3798 const SLTG_TypeInfoTail *pTITail)
3800 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3803 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3804 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3805 const SLTG_TypeInfoTail *pTITail)
3807 WORD *pType;
3808 sltg_ref_lookup_t *ref_lookup = NULL;
3810 if (pTITail->simple_alias) {
3811 /* if simple alias, no more processing required */
3812 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3813 return;
3816 if(pTIHeader->href_table != 0xffffffff) {
3817 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3818 pNameTable);
3821 /* otherwise it is an offset to a type */
3822 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3824 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3826 heap_free(ref_lookup);
3829 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3830 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3831 const SLTG_TypeInfoTail *pTITail)
3833 sltg_ref_lookup_t *ref_lookup = NULL;
3834 if (pTIHeader->href_table != 0xffffffff)
3835 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3836 pNameTable);
3838 if (pTITail->vars_off != 0xffff)
3839 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3841 if (pTITail->funcs_off != 0xffff)
3842 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3844 if (pTITail->impls_off != 0xffff)
3845 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
3847 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3848 * of dispinterface functions including the IDispatch ones, so
3849 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3850 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3852 heap_free(ref_lookup);
3853 if (TRACE_ON(typelib))
3854 dump_TLBFuncDesc(pTI->funcdescs, pTI->TypeAttr.cFuncs);
3857 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3858 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3859 const SLTG_TypeInfoTail *pTITail)
3861 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3864 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3865 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3866 const SLTG_TypeInfoTail *pTITail)
3868 sltg_ref_lookup_t *ref_lookup = NULL;
3869 if (pTIHeader->href_table != 0xffffffff)
3870 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3871 pNameTable);
3873 if (pTITail->vars_off != 0xffff)
3874 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3876 if (pTITail->funcs_off != 0xffff)
3877 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3878 heap_free(ref_lookup);
3879 if (TRACE_ON(typelib))
3880 dump_TypeInfo(pTI);
3883 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3884 manageable copy of it into this */
3885 typedef struct {
3886 WORD small_no;
3887 char *index_name;
3888 char *other_name;
3889 WORD res1a;
3890 WORD name_offs;
3891 WORD more_bytes;
3892 char *extra;
3893 WORD res20;
3894 DWORD helpcontext;
3895 WORD res26;
3896 GUID uuid;
3897 } SLTG_InternalOtherTypeInfo;
3899 /****************************************************************************
3900 * ITypeLib2_Constructor_SLTG
3902 * loading a SLTG typelib from an in-memory image
3904 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3906 ITypeLibImpl *pTypeLibImpl;
3907 SLTG_Header *pHeader;
3908 SLTG_BlkEntry *pBlkEntry;
3909 SLTG_Magic *pMagic;
3910 SLTG_Index *pIndex;
3911 SLTG_Pad9 *pPad9;
3912 LPVOID pBlk, pFirstBlk;
3913 SLTG_LibBlk *pLibBlk;
3914 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3915 char *pAfterOTIBlks = NULL;
3916 char *pNameTable, *ptr;
3917 int i;
3918 DWORD len, order;
3919 ITypeInfoImpl **ppTypeInfoImpl;
3921 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3924 pTypeLibImpl = TypeLibImpl_Constructor();
3925 if (!pTypeLibImpl) return NULL;
3927 pHeader = pLib;
3929 TRACE_(typelib)("header:\n");
3930 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3931 pHeader->nrOfFileBlks );
3932 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3933 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3934 pHeader->SLTG_magic);
3935 return NULL;
3938 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3939 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3941 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3942 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3944 /* Next we have a magic block */
3945 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3947 /* Let's see if we're still in sync */
3948 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3949 sizeof(SLTG_COMPOBJ_MAGIC))) {
3950 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3951 return NULL;
3953 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3954 sizeof(SLTG_DIR_MAGIC))) {
3955 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
3956 return NULL;
3959 pIndex = (SLTG_Index*)(pMagic+1);
3961 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3963 pFirstBlk = pPad9 + 1;
3965 /* We'll set up a ptr to the main library block, which is the last one. */
3967 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3968 pBlkEntry[order].next != 0;
3969 order = pBlkEntry[order].next - 1, i++) {
3970 pBlk = (char*)pBlk + pBlkEntry[order].len;
3972 pLibBlk = pBlk;
3974 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3976 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3977 interspersed */
3979 len += 0x40;
3981 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3983 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
3986 ptr = (char*)pLibBlk + len;
3988 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3989 WORD w, extra;
3990 len = 0;
3992 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3994 w = *(WORD*)(ptr + 2);
3995 if(w != 0xffff) {
3996 len += w;
3997 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
3998 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3999 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4001 w = *(WORD*)(ptr + 4 + len);
4002 if(w != 0xffff) {
4003 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4004 len += w;
4005 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4006 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4007 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4009 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4010 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4011 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4012 if(extra) {
4013 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4014 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4015 len += extra;
4017 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4018 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4019 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4020 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4021 len += sizeof(SLTG_OtherTypeInfo);
4022 ptr += len;
4025 pAfterOTIBlks = ptr;
4027 /* Skip this WORD and get the next DWORD */
4028 len = *(DWORD*)(pAfterOTIBlks + 2);
4030 /* Now add this to pLibBLk look at what we're pointing at and
4031 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4032 dust and we should be pointing at the beginning of the name
4033 table */
4035 pNameTable = (char*)pLibBlk + len;
4037 switch(*(WORD*)pNameTable) {
4038 case 0xffff:
4039 break;
4040 case 0x0200:
4041 pNameTable += 0x20;
4042 break;
4043 default:
4044 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4045 break;
4048 pNameTable += 0x216;
4050 pNameTable += 2;
4052 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4054 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
4057 /* Hopefully we now have enough ptrs set up to actually read in
4058 some TypeInfos. It's not clear which order to do them in, so
4059 I'll just follow the links along the BlkEntry chain and read
4060 them in the order in which they are in the file */
4062 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4063 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4065 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4066 pBlkEntry[order].next != 0;
4067 order = pBlkEntry[order].next - 1, i++) {
4069 SLTG_TypeInfoHeader *pTIHeader;
4070 SLTG_TypeInfoTail *pTITail;
4071 SLTG_MemberHeader *pMemHeader;
4073 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
4074 pOtherTypeInfoBlks[i].index_name)) {
4075 FIXME_(typelib)("Index strings don't match\n");
4076 return NULL;
4079 pTIHeader = pBlk;
4080 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4081 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4082 return NULL;
4084 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4085 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4086 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4088 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4089 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4090 (*ppTypeInfoImpl)->index = i;
4091 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
4092 pOtherTypeInfoBlks[i].name_offs +
4093 pNameTable);
4094 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4095 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
4096 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
4097 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
4098 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
4099 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
4100 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4102 if((*ppTypeInfoImpl)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
4103 (*ppTypeInfoImpl)->TypeAttr.typekind = TKIND_DISPATCH;
4105 if((pTIHeader->typeflags1 & 7) != 2)
4106 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4107 if(pTIHeader->typeflags3 != 2)
4108 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4110 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4111 debugstr_w((*ppTypeInfoImpl)->Name),
4112 typekind_desc[pTIHeader->typekind],
4113 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
4114 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
4116 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4118 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4120 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
4121 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
4122 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
4124 switch(pTIHeader->typekind) {
4125 case TKIND_ENUM:
4126 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4127 pTIHeader, pTITail);
4128 break;
4130 case TKIND_RECORD:
4131 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4132 pTIHeader, pTITail);
4133 break;
4135 case TKIND_INTERFACE:
4136 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4137 pTIHeader, pTITail);
4138 break;
4140 case TKIND_COCLASS:
4141 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4142 pTIHeader, pTITail);
4143 break;
4145 case TKIND_ALIAS:
4146 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4147 pTIHeader, pTITail);
4148 break;
4150 case TKIND_DISPATCH:
4151 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4152 pTIHeader, pTITail);
4153 break;
4155 case TKIND_MODULE:
4156 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4157 pTIHeader, pTITail);
4158 break;
4160 default:
4161 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4162 break;
4166 /* could get cFuncs, cVars and cImplTypes from here
4167 but we've already set those */
4168 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4169 X(06);
4170 X(16);
4171 X(18);
4172 X(1a);
4173 X(1e);
4174 X(24);
4175 X(26);
4176 X(2a);
4177 X(2c);
4178 X(2e);
4179 X(30);
4180 X(32);
4181 X(34);
4182 #undef X
4183 ++ppTypeInfoImpl;
4184 pBlk = (char*)pBlk + pBlkEntry[order].len;
4187 if(i != pTypeLibImpl->TypeInfoCount) {
4188 FIXME("Somehow processed %d TypeInfos\n", i);
4189 return NULL;
4192 heap_free(pOtherTypeInfoBlks);
4193 return (ITypeLib2*)pTypeLibImpl;
4196 /* ITypeLib::QueryInterface
4198 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
4199 ITypeLib2 * iface,
4200 REFIID riid,
4201 VOID **ppvObject)
4203 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4205 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4207 *ppvObject=NULL;
4208 if(IsEqualIID(riid, &IID_IUnknown) ||
4209 IsEqualIID(riid,&IID_ITypeLib)||
4210 IsEqualIID(riid,&IID_ITypeLib2))
4212 *ppvObject = This;
4215 if(*ppvObject)
4217 ITypeLib2_AddRef(iface);
4218 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4219 return S_OK;
4221 TRACE("-- Interface: E_NOINTERFACE\n");
4222 return E_NOINTERFACE;
4225 /* ITypeLib::AddRef
4227 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4229 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4230 ULONG ref = InterlockedIncrement(&This->ref);
4232 TRACE("(%p)->ref was %u\n",This, ref - 1);
4234 return ref;
4237 /* ITypeLib::Release
4239 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4241 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4242 ULONG ref = InterlockedDecrement(&This->ref);
4244 TRACE("(%p)->(%u)\n",This, ref);
4246 if (!ref)
4248 TLBImpLib *pImpLib, *pImpLibNext;
4249 TLBRefType *ref_type;
4250 void *cursor2;
4251 int i;
4253 /* remove cache entry */
4254 if(This->path)
4256 TRACE("removing from cache list\n");
4257 EnterCriticalSection(&cache_section);
4258 if(This->entry.next)
4259 list_remove(&This->entry);
4260 LeaveCriticalSection(&cache_section);
4261 heap_free(This->path);
4263 TRACE(" destroying ITypeLib(%p)\n",This);
4265 SysFreeString(This->Name);
4266 This->Name = NULL;
4268 SysFreeString(This->DocString);
4269 This->DocString = NULL;
4271 SysFreeString(This->HelpFile);
4272 This->HelpFile = NULL;
4274 SysFreeString(This->HelpStringDll);
4275 This->HelpStringDll = NULL;
4277 TLB_FreeCustData(&This->custdata_list);
4279 for (i = 0; i < This->ctTypeDesc; i++)
4280 if (This->pTypeDesc[i].vt == VT_CARRAY)
4281 heap_free(This->pTypeDesc[i].u.lpadesc);
4283 heap_free(This->pTypeDesc);
4285 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4287 if (pImpLib->pImpTypeLib)
4288 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
4289 SysFreeString(pImpLib->name);
4291 list_remove(&pImpLib->entry);
4292 heap_free(pImpLib);
4295 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4297 list_remove(&ref_type->entry);
4298 heap_free(ref_type);
4301 for (i = 0; i < This->TypeInfoCount; ++i)
4302 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4303 heap_free(This->typeinfos);
4304 heap_free(This);
4305 return 0;
4308 return ref;
4311 /* ITypeLib::GetTypeInfoCount
4313 * Returns the number of type descriptions in the type library
4315 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4317 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4318 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4319 return This->TypeInfoCount;
4322 /* ITypeLib::GetTypeInfo
4324 * retrieves the specified type description in the library.
4326 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4327 ITypeLib2 *iface,
4328 UINT index,
4329 ITypeInfo **ppTInfo)
4331 ITypeLibImpl *This = (ITypeLibImpl*)iface;
4333 TRACE("%p %u %p\n", This, index, ppTInfo);
4335 if(!ppTInfo)
4336 return E_INVALIDARG;
4338 if(index >= This->TypeInfoCount)
4339 return TYPE_E_ELEMENTNOTFOUND;
4341 *ppTInfo = (ITypeInfo*)This->typeinfos[index];
4342 ITypeInfo_AddRef(*ppTInfo);
4344 return S_OK;
4348 /* ITypeLibs::GetTypeInfoType
4350 * Retrieves the type of a type description.
4352 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4353 ITypeLib2 *iface,
4354 UINT index,
4355 TYPEKIND *pTKind)
4357 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4359 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4361 if(!pTKind)
4362 return E_INVALIDARG;
4364 if(index >= This->TypeInfoCount)
4365 return TYPE_E_ELEMENTNOTFOUND;
4367 *pTKind = This->typeinfos[index]->TypeAttr.typekind;
4369 return S_OK;
4372 /* ITypeLib::GetTypeInfoOfGuid
4374 * Retrieves the type description that corresponds to the specified GUID.
4377 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4378 ITypeLib2 *iface,
4379 REFGUID guid,
4380 ITypeInfo **ppTInfo)
4382 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4383 UINT i;
4385 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4387 for(i = 0; i < This->TypeInfoCount; ++i){
4388 if(IsEqualIID(&This->typeinfos[i]->TypeAttr.guid, guid)){
4389 *ppTInfo = (ITypeInfo*)This->typeinfos[i];
4390 ITypeInfo_AddRef(*ppTInfo);
4391 return S_OK;
4395 return TYPE_E_ELEMENTNOTFOUND;
4398 /* ITypeLib::GetLibAttr
4400 * Retrieves the structure that contains the library's attributes.
4403 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4404 ITypeLib2 *iface,
4405 LPTLIBATTR *attr)
4407 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4409 TRACE("(%p, %p)\n", This, attr);
4411 if (!attr) return E_INVALIDARG;
4413 *attr = heap_alloc(sizeof(**attr));
4414 if (!*attr) return E_OUTOFMEMORY;
4416 **attr = This->LibAttr;
4417 return S_OK;
4420 /* ITypeLib::GetTypeComp
4422 * Enables a client compiler to bind to a library's types, variables,
4423 * constants, and global functions.
4426 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4427 ITypeLib2 *iface,
4428 ITypeComp **ppTComp)
4430 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4432 TRACE("(%p)->(%p)\n",This,ppTComp);
4433 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4434 ITypeComp_AddRef(*ppTComp);
4436 return S_OK;
4439 /* ITypeLib::GetDocumentation
4441 * Retrieves the library's documentation string, the complete Help file name
4442 * and path, and the context identifier for the library Help topic in the Help
4443 * file.
4445 * On a successful return all non-null BSTR pointers will have been set,
4446 * possibly to NULL.
4448 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4449 ITypeLib2 *iface,
4450 INT index,
4451 BSTR *pBstrName,
4452 BSTR *pBstrDocString,
4453 DWORD *pdwHelpContext,
4454 BSTR *pBstrHelpFile)
4456 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4458 HRESULT result = E_INVALIDARG;
4460 ITypeInfo *pTInfo;
4463 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4464 This, index,
4465 pBstrName, pBstrDocString,
4466 pdwHelpContext, pBstrHelpFile);
4468 if(index<0)
4470 /* documentation for the typelib */
4471 if(pBstrName)
4473 if (This->Name)
4475 if(!(*pBstrName = SysAllocString(This->Name)))
4476 goto memerr1;
4478 else
4479 *pBstrName = NULL;
4481 if(pBstrDocString)
4483 if (This->DocString)
4485 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4486 goto memerr2;
4488 else if (This->Name)
4490 if(!(*pBstrDocString = SysAllocString(This->Name)))
4491 goto memerr2;
4493 else
4494 *pBstrDocString = NULL;
4496 if(pdwHelpContext)
4498 *pdwHelpContext = This->dwHelpContext;
4500 if(pBstrHelpFile)
4502 if (This->HelpFile)
4504 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4505 goto memerr3;
4507 else
4508 *pBstrHelpFile = NULL;
4511 result = S_OK;
4513 else
4515 /* for a typeinfo */
4516 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4518 if(SUCCEEDED(result))
4520 result = ITypeInfo_GetDocumentation(pTInfo,
4521 MEMBERID_NIL,
4522 pBstrName,
4523 pBstrDocString,
4524 pdwHelpContext, pBstrHelpFile);
4526 ITypeInfo_Release(pTInfo);
4529 return result;
4530 memerr3:
4531 if (pBstrDocString) SysFreeString (*pBstrDocString);
4532 memerr2:
4533 if (pBstrName) SysFreeString (*pBstrName);
4534 memerr1:
4535 return STG_E_INSUFFICIENTMEMORY;
4538 /* ITypeLib::IsName
4540 * Indicates whether a passed-in string contains the name of a type or member
4541 * described in the library.
4544 static HRESULT WINAPI ITypeLib2_fnIsName(
4545 ITypeLib2 *iface,
4546 LPOLESTR szNameBuf,
4547 ULONG lHashVal,
4548 BOOL *pfName)
4550 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4551 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), tic, fdc, vrc, pc;
4553 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4554 pfName);
4556 *pfName=TRUE;
4557 for(tic = 0; tic < This->TypeInfoCount; ++tic){
4558 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
4559 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4560 for(fdc = 0; fdc < pTInfo->TypeAttr.cFuncs; ++fdc) {
4561 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
4562 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4563 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++)
4564 if(!memcmp(szNameBuf,pFInfo->pParamDesc[pc].Name, nNameBufLen))
4565 goto ITypeLib2_fnIsName_exit;
4567 for(vrc = 0; vrc < pTInfo->TypeAttr.cVars; ++vrc){
4568 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
4569 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4573 *pfName=FALSE;
4575 ITypeLib2_fnIsName_exit:
4576 TRACE("(%p)slow! search for %s: %s found!\n", This,
4577 debugstr_w(szNameBuf), *pfName?"NOT":"");
4579 return S_OK;
4582 /* ITypeLib::FindName
4584 * Finds occurrences of a type description in a type library. This may be used
4585 * to quickly verify that a name exists in a type library.
4588 static HRESULT WINAPI ITypeLib2_fnFindName(
4589 ITypeLib2 *iface,
4590 LPOLESTR name,
4591 ULONG hash,
4592 ITypeInfo **ppTInfo,
4593 MEMBERID *memid,
4594 UINT16 *found)
4596 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4597 UINT tic, count = 0;
4598 UINT len;
4600 TRACE("(%p)->(%s %u %p %p %p)\n", This, debugstr_w(name), hash, ppTInfo, memid, found);
4602 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
4603 return E_INVALIDARG;
4605 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
4606 for(tic = 0; tic < This->TypeInfoCount; ++tic) {
4607 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
4608 TLBVarDesc *var;
4609 UINT fdc;
4611 if(!memcmp(name, pTInfo->Name, len)) goto ITypeLib2_fnFindName_exit;
4612 for(fdc = 0; fdc < pTInfo->TypeAttr.cFuncs; ++fdc) {
4613 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
4614 UINT pc;
4616 if(!memcmp(name, func->Name, len)) goto ITypeLib2_fnFindName_exit;
4617 for(pc = 0; pc < func->funcdesc.cParams; pc++) {
4618 if(!memcmp(name, func->pParamDesc[pc].Name, len))
4619 goto ITypeLib2_fnFindName_exit;
4623 var = TLB_get_vardesc_by_name(pTInfo->vardescs, pTInfo->TypeAttr.cVars, name);
4624 if (var)
4625 goto ITypeLib2_fnFindName_exit;
4627 continue;
4628 ITypeLib2_fnFindName_exit:
4629 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4630 ppTInfo[count]=(LPTYPEINFO)pTInfo;
4631 count++;
4633 TRACE("found %d typeinfos\n", count);
4635 *found = count;
4637 return S_OK;
4640 /* ITypeLib::ReleaseTLibAttr
4642 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4645 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4646 ITypeLib2 *iface,
4647 TLIBATTR *pTLibAttr)
4649 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4650 TRACE("freeing (%p)\n",This);
4651 heap_free(pTLibAttr);
4655 /* ITypeLib2::GetCustData
4657 * gets the custom data
4659 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4660 ITypeLib2 * iface,
4661 REFGUID guid,
4662 VARIANT *pVarVal)
4664 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4665 TLBCustData *pCData;
4667 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
4669 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
4670 if(!pCData)
4671 return TYPE_E_ELEMENTNOTFOUND;
4673 VariantInit(pVarVal);
4674 VariantCopy(pVarVal, &pCData->data);
4676 return S_OK;
4679 /* ITypeLib2::GetLibStatistics
4681 * Returns statistics about a type library that are required for efficient
4682 * sizing of hash tables.
4685 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4686 ITypeLib2 * iface,
4687 ULONG *pcUniqueNames,
4688 ULONG *pcchUniqueNames)
4690 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4692 FIXME("(%p): stub!\n", This);
4694 if(pcUniqueNames) *pcUniqueNames=1;
4695 if(pcchUniqueNames) *pcchUniqueNames=1;
4696 return S_OK;
4699 /* ITypeLib2::GetDocumentation2
4701 * Retrieves the library's documentation string, the complete Help file name
4702 * and path, the localization context to use, and the context ID for the
4703 * library Help topic in the Help file.
4706 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4707 ITypeLib2 * iface,
4708 INT index,
4709 LCID lcid,
4710 BSTR *pbstrHelpString,
4711 DWORD *pdwHelpStringContext,
4712 BSTR *pbstrHelpStringDll)
4714 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4715 HRESULT result;
4716 ITypeInfo *pTInfo;
4718 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4720 /* the help string should be obtained from the helpstringdll,
4721 * using the _DLLGetDocumentation function, based on the supplied
4722 * lcid. Nice to do sometime...
4724 if(index<0)
4726 /* documentation for the typelib */
4727 if(pbstrHelpString)
4728 *pbstrHelpString=SysAllocString(This->DocString);
4729 if(pdwHelpStringContext)
4730 *pdwHelpStringContext=This->dwHelpContext;
4731 if(pbstrHelpStringDll)
4732 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4734 result = S_OK;
4736 else
4738 /* for a typeinfo */
4739 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4741 if(SUCCEEDED(result))
4743 ITypeInfo2 * pTInfo2;
4744 result = ITypeInfo_QueryInterface(pTInfo,
4745 &IID_ITypeInfo2,
4746 (LPVOID*) &pTInfo2);
4748 if(SUCCEEDED(result))
4750 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4751 MEMBERID_NIL,
4752 lcid,
4753 pbstrHelpString,
4754 pdwHelpStringContext,
4755 pbstrHelpStringDll);
4757 ITypeInfo2_Release(pTInfo2);
4760 ITypeInfo_Release(pTInfo);
4763 return result;
4766 static HRESULT TLB_copy_all_custdata(struct list *custdata_list, CUSTDATA *pCustData)
4768 TLBCustData *pCData;
4769 unsigned int ct;
4770 CUSTDATAITEM *cdi;
4772 ct = list_count(custdata_list);
4774 pCustData->prgCustData = heap_alloc_zero(ct * sizeof(CUSTDATAITEM));
4775 if(!pCustData->prgCustData)
4776 return E_OUTOFMEMORY;
4778 pCustData->cCustData = ct;
4780 cdi = pCustData->prgCustData;
4781 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
4782 cdi->guid = pCData->guid;
4783 VariantCopy(&cdi->varValue, &pCData->data);
4784 ++cdi;
4787 return S_OK;
4791 /* ITypeLib2::GetAllCustData
4793 * Gets all custom data items for the library.
4796 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4797 ITypeLib2 * iface,
4798 CUSTDATA *pCustData)
4800 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4801 TRACE("%p %p\n", iface, pCustData);
4802 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
4805 static const ITypeLib2Vtbl tlbvt = {
4806 ITypeLib2_fnQueryInterface,
4807 ITypeLib2_fnAddRef,
4808 ITypeLib2_fnRelease,
4809 ITypeLib2_fnGetTypeInfoCount,
4810 ITypeLib2_fnGetTypeInfo,
4811 ITypeLib2_fnGetTypeInfoType,
4812 ITypeLib2_fnGetTypeInfoOfGuid,
4813 ITypeLib2_fnGetLibAttr,
4814 ITypeLib2_fnGetTypeComp,
4815 ITypeLib2_fnGetDocumentation,
4816 ITypeLib2_fnIsName,
4817 ITypeLib2_fnFindName,
4818 ITypeLib2_fnReleaseTLibAttr,
4820 ITypeLib2_fnGetCustData,
4821 ITypeLib2_fnGetLibStatistics,
4822 ITypeLib2_fnGetDocumentation2,
4823 ITypeLib2_fnGetAllCustData
4827 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4829 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4831 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4834 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4836 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4838 return ITypeLib2_AddRef((ITypeLib2 *)This);
4841 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4843 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4845 return ITypeLib2_Release((ITypeLib2 *)This);
4848 static HRESULT WINAPI ITypeLibComp_fnBind(
4849 ITypeComp * iface,
4850 OLECHAR * szName,
4851 ULONG lHash,
4852 WORD wFlags,
4853 ITypeInfo ** ppTInfo,
4854 DESCKIND * pDescKind,
4855 BINDPTR * pBindPtr)
4857 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4858 int typemismatch=0, i;
4860 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4862 *pDescKind = DESCKIND_NONE;
4863 pBindPtr->lptcomp = NULL;
4864 *ppTInfo = NULL;
4866 for(i = 0; i < This->TypeInfoCount; ++i){
4867 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
4868 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4870 /* FIXME: check wFlags here? */
4871 /* FIXME: we should use a hash table to look this info up using lHash
4872 * instead of an O(n) search */
4873 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4874 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4876 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4878 *pDescKind = DESCKIND_TYPECOMP;
4879 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4880 ITypeComp_AddRef(pBindPtr->lptcomp);
4881 TRACE("module or enum: %s\n", debugstr_w(szName));
4882 return S_OK;
4886 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4887 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4889 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4890 HRESULT hr;
4892 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4893 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4895 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4896 return S_OK;
4898 else if (hr == TYPE_E_TYPEMISMATCH)
4899 typemismatch = 1;
4902 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4903 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4905 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4906 HRESULT hr;
4907 ITypeInfo *subtypeinfo;
4908 BINDPTR subbindptr;
4909 DESCKIND subdesckind;
4911 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4912 &subtypeinfo, &subdesckind, &subbindptr);
4913 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4915 TYPEDESC tdesc_appobject;
4916 const VARDESC vardesc_appobject =
4918 -2, /* memid */
4919 NULL, /* lpstrSchema */
4921 0 /* oInst */
4924 /* ELEMDESC */
4926 /* TYPEDESC */
4928 &tdesc_appobject
4930 VT_PTR
4933 0, /* wVarFlags */
4934 VAR_STATIC /* varkind */
4937 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
4938 tdesc_appobject.vt = VT_USERDEFINED;
4940 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4942 /* cleanup things filled in by Bind call so we can put our
4943 * application object data in there instead */
4944 switch (subdesckind)
4946 case DESCKIND_FUNCDESC:
4947 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4948 break;
4949 case DESCKIND_VARDESC:
4950 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4951 break;
4952 default:
4953 break;
4955 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4957 if (pTypeInfo->hreftype == -1)
4958 FIXME("no hreftype for interface %p\n", pTypeInfo);
4960 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4961 if (FAILED(hr))
4962 return hr;
4964 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4965 *ppTInfo = (ITypeInfo *)pTypeInfo;
4966 ITypeInfo_AddRef(*ppTInfo);
4967 return S_OK;
4969 else if (hr == TYPE_E_TYPEMISMATCH)
4970 typemismatch = 1;
4974 if (typemismatch)
4976 TRACE("type mismatch %s\n", debugstr_w(szName));
4977 return TYPE_E_TYPEMISMATCH;
4979 else
4981 TRACE("name not found %s\n", debugstr_w(szName));
4982 return S_OK;
4986 static HRESULT WINAPI ITypeLibComp_fnBindType(
4987 ITypeComp * iface,
4988 OLECHAR * szName,
4989 ULONG lHash,
4990 ITypeInfo ** ppTInfo,
4991 ITypeComp ** ppTComp)
4993 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4994 UINT i;
4996 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4998 if(!szName || !ppTInfo || !ppTComp)
4999 return E_INVALIDARG;
5001 for(i = 0; i < This->TypeInfoCount; ++i)
5003 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5004 /* FIXME: should use lHash to do the search */
5005 if (pTypeInfo->Name && !strcmpiW(pTypeInfo->Name, szName))
5007 TRACE("returning %p\n", pTypeInfo);
5008 *ppTInfo = (ITypeInfo *)&pTypeInfo->lpVtbl;
5009 ITypeInfo_AddRef(*ppTInfo);
5010 *ppTComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
5011 ITypeComp_AddRef(*ppTComp);
5012 return S_OK;
5016 TRACE("not found\n");
5017 *ppTInfo = NULL;
5018 *ppTComp = NULL;
5019 return S_OK;
5022 static const ITypeCompVtbl tlbtcvt =
5025 ITypeLibComp_fnQueryInterface,
5026 ITypeLibComp_fnAddRef,
5027 ITypeLibComp_fnRelease,
5029 ITypeLibComp_fnBind,
5030 ITypeLibComp_fnBindType
5033 /*================== ITypeInfo(2) Methods ===================================*/
5034 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5036 ITypeInfoImpl *pTypeInfoImpl;
5038 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5039 if (pTypeInfoImpl)
5041 pTypeInfoImpl->lpVtbl = &tinfvt;
5042 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
5043 pTypeInfoImpl->ref = 0;
5044 pTypeInfoImpl->hreftype = -1;
5045 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
5046 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
5047 list_init(&pTypeInfoImpl->custdata_list);
5049 TRACE("(%p)\n", pTypeInfoImpl);
5050 return pTypeInfoImpl;
5053 /* ITypeInfo::QueryInterface
5055 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5056 ITypeInfo2 *iface,
5057 REFIID riid,
5058 VOID **ppvObject)
5060 ITypeLibImpl *This = (ITypeLibImpl *)iface;
5062 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5064 *ppvObject=NULL;
5065 if(IsEqualIID(riid, &IID_IUnknown) ||
5066 IsEqualIID(riid,&IID_ITypeInfo)||
5067 IsEqualIID(riid,&IID_ITypeInfo2))
5068 *ppvObject = This;
5070 if(*ppvObject){
5071 ITypeInfo_AddRef(iface);
5072 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5073 return S_OK;
5075 TRACE("-- Interface: E_NOINTERFACE\n");
5076 return E_NOINTERFACE;
5079 /* ITypeInfo::AddRef
5081 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5083 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5084 ULONG ref = InterlockedIncrement(&This->ref);
5086 TRACE("(%p)->ref is %u\n",This, ref);
5088 if (ref == 1 /* incremented from 0 */)
5089 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
5091 return ref;
5094 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5096 UINT i, j;
5098 TRACE("destroying ITypeInfo(%p)\n",This);
5100 SysFreeString(This->Name);
5101 This->Name = NULL;
5103 SysFreeString(This->DocString);
5104 This->DocString = NULL;
5106 SysFreeString(This->DllName);
5107 This->DllName = NULL;
5109 for (i = 0; i < This->TypeAttr.cFuncs; ++i)
5111 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5112 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5114 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5115 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5117 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5118 heap_free(elemdesc->u.paramdesc.pparamdescex);
5120 TLB_FreeCustData(&pFInfo->pParamDesc[j].custdata_list);
5121 SysFreeString(pFInfo->pParamDesc[j].Name);
5123 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5124 heap_free(pFInfo->pParamDesc);
5125 TLB_FreeCustData(&pFInfo->custdata_list);
5126 if (!IS_INTRESOURCE(pFInfo->Entry) && pFInfo->Entry != (BSTR)-1)
5127 SysFreeString(pFInfo->Entry);
5128 SysFreeString(pFInfo->HelpString);
5129 SysFreeString(pFInfo->Name);
5131 heap_free(This->funcdescs);
5133 for(i = 0; i < This->TypeAttr.cVars; ++i)
5135 TLBVarDesc *pVInfo = &This->vardescs[i];
5136 if (pVInfo->vardesc.varkind == VAR_CONST)
5138 VariantClear(pVInfo->vardesc.u.lpvarValue);
5139 heap_free(pVInfo->vardesc.u.lpvarValue);
5141 TLB_FreeCustData(&pVInfo->custdata_list);
5142 SysFreeString(pVInfo->Name);
5143 SysFreeString(pVInfo->HelpString);
5145 heap_free(This->vardescs);
5147 if(This->impltypes){
5148 for (i = 0; i < This->TypeAttr.cImplTypes; ++i){
5149 TLBImplType *pImpl = &This->impltypes[i];
5150 TLB_FreeCustData(&pImpl->custdata_list);
5152 heap_free(This->impltypes);
5155 TLB_FreeCustData(&This->custdata_list);
5157 heap_free(This);
5160 /* ITypeInfo::Release
5162 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5164 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5165 ULONG ref = InterlockedDecrement(&This->ref);
5167 TRACE("(%p)->(%u)\n",This, ref);
5169 if (!ref)
5171 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5172 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
5173 if (not_attached_to_typelib)
5174 heap_free(This);
5175 /* otherwise This will be freed when typelib is freed */
5178 return ref;
5181 /* ITypeInfo::GetTypeAttr
5183 * Retrieves a TYPEATTR structure that contains the attributes of the type
5184 * description.
5187 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5188 LPTYPEATTR *ppTypeAttr)
5190 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5191 SIZE_T size;
5193 TRACE("(%p)\n",This);
5195 size = sizeof(**ppTypeAttr);
5196 if (This->TypeAttr.typekind == TKIND_ALIAS)
5197 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
5199 *ppTypeAttr = heap_alloc(size);
5200 if (!*ppTypeAttr)
5201 return E_OUTOFMEMORY;
5203 **ppTypeAttr = This->TypeAttr;
5205 if (This->TypeAttr.typekind == TKIND_ALIAS)
5206 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5207 &This->TypeAttr.tdescAlias, *ppTypeAttr + 1);
5209 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5210 /* This should include all the inherited funcs */
5211 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
5212 /* This is always the size of IDispatch's vtbl */
5213 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5214 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5216 return S_OK;
5219 /* ITypeInfo::GetTypeComp
5221 * Retrieves the ITypeComp interface for the type description, which enables a
5222 * client compiler to bind to the type description's members.
5225 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5226 ITypeComp * *ppTComp)
5228 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5230 TRACE("(%p)->(%p)\n", This, ppTComp);
5232 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
5233 ITypeComp_AddRef(*ppTComp);
5234 return S_OK;
5237 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5239 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5240 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5241 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5242 return size;
5245 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5247 *dest = *src;
5248 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5249 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5251 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5252 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5253 *buffer += sizeof(PARAMDESCEX);
5254 *pparamdescex_dest = *pparamdescex_src;
5255 VariantInit(&pparamdescex_dest->varDefaultValue);
5256 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5257 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5259 else
5260 dest->u.paramdesc.pparamdescex = NULL;
5261 return S_OK;
5264 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5266 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5267 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5270 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5272 FUNCDESC *dest;
5273 char *buffer;
5274 SIZE_T size = sizeof(*src);
5275 SHORT i;
5276 HRESULT hr;
5278 size += sizeof(*src->lprgscode) * src->cScodes;
5279 size += TLB_SizeElemDesc(&src->elemdescFunc);
5280 for (i = 0; i < src->cParams; i++)
5282 size += sizeof(ELEMDESC);
5283 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5286 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5287 if (!dest) return E_OUTOFMEMORY;
5289 *dest = *src;
5290 if (dispinterface) /* overwrite funckind */
5291 dest->funckind = FUNC_DISPATCH;
5292 buffer = (char *)(dest + 1);
5294 dest->lprgscode = (SCODE *)buffer;
5295 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5296 buffer += sizeof(*src->lprgscode) * src->cScodes;
5298 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5299 if (FAILED(hr))
5301 SysFreeString((BSTR)dest);
5302 return hr;
5305 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5306 buffer += sizeof(ELEMDESC) * src->cParams;
5307 for (i = 0; i < src->cParams; i++)
5309 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5310 if (FAILED(hr))
5311 break;
5313 if (FAILED(hr))
5315 /* undo the above actions */
5316 for (i = i - 1; i >= 0; i--)
5317 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5318 TLB_FreeElemDesc(&dest->elemdescFunc);
5319 SysFreeString((BSTR)dest);
5320 return hr;
5323 /* special treatment for dispinterfaces: this makes functions appear
5324 * to return their [retval] value when it is really returning an
5325 * HRESULT */
5326 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5328 if (dest->cParams &&
5329 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5331 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5332 if (elemdesc->tdesc.vt != VT_PTR)
5334 ERR("elemdesc should have started with VT_PTR instead of:\n");
5335 if (ERR_ON(ole))
5336 dump_ELEMDESC(elemdesc);
5337 return E_UNEXPECTED;
5340 /* copy last parameter to the return value. we are using a flat
5341 * buffer so there is no danger of leaking memory in
5342 * elemdescFunc */
5343 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5345 /* remove the last parameter */
5346 dest->cParams--;
5348 else
5349 /* otherwise this function is made to appear to have no return
5350 * value */
5351 dest->elemdescFunc.tdesc.vt = VT_VOID;
5355 *dest_ptr = dest;
5356 return S_OK;
5359 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5361 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5363 if (index >= This->TypeAttr.cFuncs)
5364 return TYPE_E_ELEMENTNOTFOUND;
5366 *ppFuncDesc = &This->funcdescs[index].funcdesc;
5367 return S_OK;
5370 /* internal function to make the inherited interfaces' methods appear
5371 * part of the interface */
5372 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5373 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5375 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5376 HRESULT hr;
5377 UINT implemented_funcs = 0;
5379 if (funcs)
5380 *funcs = 0;
5381 else
5382 *hrefoffset = DISPATCH_HREF_OFFSET;
5384 if(This->impltypes)
5386 ITypeInfo *pSubTypeInfo;
5387 UINT sub_funcs;
5389 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5390 if (FAILED(hr))
5391 return hr;
5393 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5394 index,
5395 ppFuncDesc,
5396 &sub_funcs, hrefoffset);
5397 implemented_funcs += sub_funcs;
5398 ITypeInfo_Release(pSubTypeInfo);
5399 if (SUCCEEDED(hr))
5400 return hr;
5401 *hrefoffset += DISPATCH_HREF_OFFSET;
5404 if (funcs)
5405 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
5406 else
5407 *hrefoffset = 0;
5409 if (index < implemented_funcs)
5410 return E_INVALIDARG;
5411 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5412 ppFuncDesc);
5415 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5417 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5418 while (TRUE)
5420 switch (pTypeDesc->vt)
5422 case VT_USERDEFINED:
5423 pTypeDesc->u.hreftype += hrefoffset;
5424 return;
5425 case VT_PTR:
5426 case VT_SAFEARRAY:
5427 pTypeDesc = pTypeDesc->u.lptdesc;
5428 break;
5429 case VT_CARRAY:
5430 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5431 break;
5432 default:
5433 return;
5438 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5440 SHORT i;
5441 for (i = 0; i < pFuncDesc->cParams; i++)
5442 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5443 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5446 /* ITypeInfo::GetFuncDesc
5448 * Retrieves the FUNCDESC structure that contains information about a
5449 * specified function.
5452 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5453 LPFUNCDESC *ppFuncDesc)
5455 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5456 const FUNCDESC *internal_funcdesc;
5457 HRESULT hr;
5458 UINT hrefoffset = 0;
5460 TRACE("(%p) index %d\n", This, index);
5462 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5463 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5464 &internal_funcdesc, NULL,
5465 &hrefoffset);
5466 else
5467 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5468 &internal_funcdesc);
5469 if (FAILED(hr))
5471 WARN("description for function %d not found\n", index);
5472 return hr;
5475 hr = TLB_AllocAndInitFuncDesc(
5476 internal_funcdesc,
5477 ppFuncDesc,
5478 This->TypeAttr.typekind == TKIND_DISPATCH);
5480 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5481 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5483 TRACE("-- 0x%08x\n", hr);
5484 return hr;
5487 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5489 VARDESC *dest;
5490 char *buffer;
5491 SIZE_T size = sizeof(*src);
5492 HRESULT hr;
5494 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5495 if (src->varkind == VAR_CONST)
5496 size += sizeof(VARIANT);
5497 size += TLB_SizeElemDesc(&src->elemdescVar);
5499 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5500 if (!dest) return E_OUTOFMEMORY;
5502 *dest = *src;
5503 buffer = (char *)(dest + 1);
5504 if (src->lpstrSchema)
5506 int len;
5507 dest->lpstrSchema = (LPOLESTR)buffer;
5508 len = strlenW(src->lpstrSchema);
5509 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5510 buffer += (len + 1) * sizeof(WCHAR);
5513 if (src->varkind == VAR_CONST)
5515 HRESULT hr;
5517 dest->u.lpvarValue = (VARIANT *)buffer;
5518 *dest->u.lpvarValue = *src->u.lpvarValue;
5519 buffer += sizeof(VARIANT);
5520 VariantInit(dest->u.lpvarValue);
5521 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5522 if (FAILED(hr))
5524 SysFreeString((BSTR)dest);
5525 return hr;
5528 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5529 if (FAILED(hr))
5531 if (src->varkind == VAR_CONST)
5532 VariantClear(dest->u.lpvarValue);
5533 SysFreeString((BSTR)dest);
5534 return hr;
5536 *dest_ptr = dest;
5537 return S_OK;
5540 /* ITypeInfo::GetVarDesc
5542 * Retrieves a VARDESC structure that describes the specified variable.
5545 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5546 LPVARDESC *ppVarDesc)
5548 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5549 const TLBVarDesc *pVDesc = &This->vardescs[index];
5551 TRACE("(%p) index %d\n", This, index);
5553 if(index >= This->TypeAttr.cVars)
5554 return TYPE_E_ELEMENTNOTFOUND;
5556 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5559 /* ITypeInfo_GetNames
5561 * Retrieves the variable with the specified member ID (or the name of the
5562 * property or method and its parameters) that correspond to the specified
5563 * function ID.
5565 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5566 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5568 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5569 const TLBFuncDesc *pFDesc;
5570 const TLBVarDesc *pVDesc;
5571 int i;
5572 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5573 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
5574 if(pFDesc)
5576 /* function found, now return function and parameter names */
5577 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5579 if(!i)
5580 *rgBstrNames=SysAllocString(pFDesc->Name);
5581 else
5582 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5584 *pcNames=i;
5586 else
5588 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
5589 if(pVDesc)
5591 *rgBstrNames=SysAllocString(pVDesc->Name);
5592 *pcNames=1;
5594 else
5596 if(This->impltypes &&
5597 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5598 /* recursive search */
5599 ITypeInfo *pTInfo;
5600 HRESULT result;
5601 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef,
5602 &pTInfo);
5603 if(SUCCEEDED(result))
5605 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5606 ITypeInfo_Release(pTInfo);
5607 return result;
5609 WARN("Could not search inherited interface!\n");
5611 else
5613 WARN("no names found\n");
5615 *pcNames=0;
5616 return TYPE_E_ELEMENTNOTFOUND;
5619 return S_OK;
5623 /* ITypeInfo::GetRefTypeOfImplType
5625 * If a type description describes a COM class, it retrieves the type
5626 * description of the implemented interface types. For an interface,
5627 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5628 * if any exist.
5631 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5632 ITypeInfo2 *iface,
5633 UINT index,
5634 HREFTYPE *pRefType)
5636 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5637 HRESULT hr = S_OK;
5639 TRACE("(%p) index %d\n", This, index);
5640 if (TRACE_ON(ole)) dump_TypeInfo(This);
5642 if(index==(UINT)-1)
5644 /* only valid on dual interfaces;
5645 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5647 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5649 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
5651 *pRefType = -1;
5653 else
5655 hr = TYPE_E_ELEMENTNOTFOUND;
5658 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5660 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5661 *pRefType = This->pTypeLib->dispatch_href;
5663 else
5665 if(index >= This->TypeAttr.cImplTypes)
5666 hr = TYPE_E_ELEMENTNOTFOUND;
5667 else
5668 *pRefType = This->impltypes[index].hRef;
5671 if(TRACE_ON(ole))
5673 if(SUCCEEDED(hr))
5674 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5675 else
5676 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5679 return hr;
5682 /* ITypeInfo::GetImplTypeFlags
5684 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5685 * or base interface in a type description.
5687 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5688 UINT index, INT *pImplTypeFlags)
5690 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5692 TRACE("(%p) index %d\n", This, index);
5694 if(This->TypeAttr.typekind == TKIND_DISPATCH && index == 0){
5695 *pImplTypeFlags = 0;
5696 return S_OK;
5699 if(index >= This->TypeAttr.cImplTypes)
5700 return TYPE_E_ELEMENTNOTFOUND;
5702 *pImplTypeFlags = This->impltypes[index].implflags;
5704 return S_OK;
5707 /* GetIDsOfNames
5708 * Maps between member names and member IDs, and parameter names and
5709 * parameter IDs.
5711 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5712 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5714 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5715 const TLBVarDesc *pVDesc;
5716 HRESULT ret=S_OK;
5717 UINT i, fdc;
5719 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5720 cNames);
5722 /* init out parameters in case of failure */
5723 for (i = 0; i < cNames; i++)
5724 pMemId[i] = MEMBERID_NIL;
5726 for (fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc) {
5727 int j;
5728 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
5729 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5730 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5731 for(i=1; i < cNames; i++){
5732 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5733 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5734 break;
5735 if( j<pFDesc->funcdesc.cParams)
5736 pMemId[i]=j;
5737 else
5738 ret=DISP_E_UNKNOWNNAME;
5740 TRACE("-- 0x%08x\n", ret);
5741 return ret;
5744 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->TypeAttr.cVars, *rgszNames);
5745 if(pVDesc){
5746 if(cNames)
5747 *pMemId = pVDesc->vardesc.memid;
5748 return ret;
5750 /* not found, see if it can be found in an inherited interface */
5751 if(This->impltypes) {
5752 /* recursive search */
5753 ITypeInfo *pTInfo;
5754 ret=ITypeInfo_GetRefTypeInfo(iface,
5755 This->impltypes[0].hRef, &pTInfo);
5756 if(SUCCEEDED(ret)){
5757 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5758 ITypeInfo_Release(pTInfo);
5759 return ret;
5761 WARN("Could not search inherited interface!\n");
5762 } else
5763 WARN("no names found\n");
5764 return DISP_E_UNKNOWNNAME;
5768 #ifdef __i386__
5770 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
5771 __ASM_GLOBAL_FUNC( call_method,
5772 "pushl %ebp\n\t"
5773 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
5774 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
5775 "movl %esp,%ebp\n\t"
5776 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
5777 "pushl %esi\n\t"
5778 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
5779 "pushl %edi\n\t"
5780 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
5781 "movl 12(%ebp),%edx\n\t"
5782 "movl %esp,%edi\n\t"
5783 "shll $2,%edx\n\t"
5784 "jz 1f\n\t"
5785 "subl %edx,%edi\n\t"
5786 "andl $~15,%edi\n\t"
5787 "movl %edi,%esp\n\t"
5788 "movl 12(%ebp),%ecx\n\t"
5789 "movl 16(%ebp),%esi\n\t"
5790 "cld\n\t"
5791 "rep; movsl\n"
5792 "1:\tcall *8(%ebp)\n\t"
5793 "subl %esp,%edi\n\t"
5794 "movl 20(%ebp),%ecx\n\t"
5795 "movl %edi,(%ecx)\n\t"
5796 "leal -8(%ebp),%esp\n\t"
5797 "popl %edi\n\t"
5798 __ASM_CFI(".cfi_same_value %edi\n\t")
5799 "popl %esi\n\t"
5800 __ASM_CFI(".cfi_same_value %esi\n\t")
5801 "popl %ebp\n\t"
5802 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
5803 __ASM_CFI(".cfi_same_value %ebp\n\t")
5804 "ret" )
5806 /* same function but returning floating point */
5807 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
5809 /* ITypeInfo::Invoke
5811 * Invokes a method, or accesses a property of an object, that implements the
5812 * interface described by the type description.
5814 DWORD
5815 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5816 DWORD res;
5817 int stack_offset;
5819 if (TRACE_ON(ole)) {
5820 int i;
5821 TRACE("Calling %p(",func);
5822 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
5823 if (nrargs > 30) TRACE("...");
5824 TRACE(")\n");
5827 switch (callconv) {
5828 case CC_STDCALL:
5829 case CC_CDECL:
5830 res = call_method( func, nrargs, args, &stack_offset );
5831 break;
5832 default:
5833 FIXME("unsupported calling convention %d\n",callconv);
5834 res = -1;
5835 break;
5837 TRACE("returns %08x\n",res);
5838 return res;
5841 #elif defined(__x86_64__)
5843 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
5844 __ASM_GLOBAL_FUNC( call_method,
5845 "pushq %rbp\n\t"
5846 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
5847 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
5848 "movq %rsp,%rbp\n\t"
5849 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
5850 "pushq %rsi\n\t"
5851 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
5852 "pushq %rdi\n\t"
5853 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
5854 "movq %rcx,%rax\n\t"
5855 "movq $4,%rcx\n\t"
5856 "cmp %rcx,%rdx\n\t"
5857 "cmovgq %rdx,%rcx\n\t"
5858 "leaq 0(,%rcx,8),%rdx\n\t"
5859 "subq %rdx,%rsp\n\t"
5860 "andq $~15,%rsp\n\t"
5861 "movq %rsp,%rdi\n\t"
5862 "movq %r8,%rsi\n\t"
5863 "rep; movsq\n\t"
5864 "movq 0(%rsp),%rcx\n\t"
5865 "movq 8(%rsp),%rdx\n\t"
5866 "movq 16(%rsp),%r8\n\t"
5867 "movq 24(%rsp),%r9\n\t"
5868 "movq %rcx,%xmm0\n\t"
5869 "movq %rdx,%xmm1\n\t"
5870 "movq %r8,%xmm2\n\t"
5871 "movq %r9,%xmm3\n\t"
5872 "callq *%rax\n\t"
5873 "leaq -16(%rbp),%rsp\n\t"
5874 "popq %rdi\n\t"
5875 __ASM_CFI(".cfi_same_value %rdi\n\t")
5876 "popq %rsi\n\t"
5877 __ASM_CFI(".cfi_same_value %rsi\n\t")
5878 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
5879 "popq %rbp\n\t"
5880 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
5881 __ASM_CFI(".cfi_same_value %rbp\n\t")
5882 "ret")
5884 /* same function but returning floating point */
5885 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
5887 #endif /* __x86_64__ */
5889 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5891 HRESULT hr = S_OK;
5892 ITypeInfo *tinfo2 = NULL;
5893 TYPEATTR *tattr = NULL;
5895 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5896 if (hr)
5898 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5899 "hr = 0x%08x\n",
5900 tdesc->u.hreftype, hr);
5901 return hr;
5903 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5904 if (hr)
5906 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5907 ITypeInfo_Release(tinfo2);
5908 return hr;
5911 switch (tattr->typekind)
5913 case TKIND_ENUM:
5914 *vt |= VT_I4;
5915 break;
5917 case TKIND_ALIAS:
5918 tdesc = &tattr->tdescAlias;
5919 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5920 break;
5922 case TKIND_INTERFACE:
5923 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5924 *vt |= VT_DISPATCH;
5925 else
5926 *vt |= VT_UNKNOWN;
5927 break;
5929 case TKIND_DISPATCH:
5930 *vt |= VT_DISPATCH;
5931 break;
5933 case TKIND_COCLASS:
5934 *vt |= VT_DISPATCH;
5935 break;
5937 case TKIND_RECORD:
5938 FIXME("TKIND_RECORD unhandled.\n");
5939 hr = E_NOTIMPL;
5940 break;
5942 case TKIND_UNION:
5943 FIXME("TKIND_UNION unhandled.\n");
5944 hr = E_NOTIMPL;
5945 break;
5947 default:
5948 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5949 hr = E_NOTIMPL;
5950 break;
5952 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5953 ITypeInfo_Release(tinfo2);
5954 return hr;
5957 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5959 HRESULT hr = S_OK;
5961 /* enforce only one level of pointer indirection */
5962 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5964 tdesc = tdesc->u.lptdesc;
5966 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5967 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5968 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5969 if ((tdesc->vt == VT_USERDEFINED) ||
5970 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5972 VARTYPE vt_userdefined = 0;
5973 const TYPEDESC *tdesc_userdefined = tdesc;
5974 if (tdesc->vt == VT_PTR)
5976 vt_userdefined = VT_BYREF;
5977 tdesc_userdefined = tdesc->u.lptdesc;
5979 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5980 if ((hr == S_OK) &&
5981 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5982 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5984 *vt |= vt_userdefined;
5985 return S_OK;
5988 *vt = VT_BYREF;
5991 switch (tdesc->vt)
5993 case VT_HRESULT:
5994 *vt |= VT_ERROR;
5995 break;
5996 case VT_USERDEFINED:
5997 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5998 break;
5999 case VT_VOID:
6000 case VT_CARRAY:
6001 case VT_PTR:
6002 case VT_LPSTR:
6003 case VT_LPWSTR:
6004 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
6005 hr = DISP_E_BADVARTYPE;
6006 break;
6007 case VT_SAFEARRAY:
6008 *vt |= VT_ARRAY;
6009 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
6010 break;
6011 case VT_INT:
6012 *vt |= VT_I4;
6013 break;
6014 case VT_UINT:
6015 *vt |= VT_UI4;
6016 break;
6017 default:
6018 *vt |= tdesc->vt;
6019 break;
6021 return hr;
6024 /***********************************************************************
6025 * DispCallFunc (OLEAUT32.@)
6027 * Invokes a function of the specified calling convention, passing the
6028 * specified arguments and returns the result.
6030 * PARAMS
6031 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6032 * oVft [I] The offset in the vtable. See notes.
6033 * cc [I] Calling convention of the function to call.
6034 * vtReturn [I] The return type of the function.
6035 * cActuals [I] Number of parameters.
6036 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6037 * prgpvarg [I] The arguments to pass.
6038 * pvargResult [O] The return value of the function. Can be NULL.
6040 * RETURNS
6041 * Success: S_OK.
6042 * Failure: HRESULT code.
6044 * NOTES
6045 * The HRESULT return value of this function is not affected by the return
6046 * value of the user supplied function, which is returned in pvargResult.
6048 * If pvInstance is NULL then a non-object function is to be called and oVft
6049 * is the address of the function to call.
6051 * The cc parameter can be one of the following values:
6052 *|CC_FASTCALL
6053 *|CC_CDECL
6054 *|CC_PASCAL
6055 *|CC_STDCALL
6056 *|CC_FPFASTCALL
6057 *|CC_SYSCALL
6058 *|CC_MPWCDECL
6059 *|CC_MPWPASCAL
6062 HRESULT WINAPI
6063 DispCallFunc(
6064 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
6065 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
6067 #ifdef __i386__
6068 int argspos, stack_offset;
6069 void *func;
6070 UINT i;
6071 DWORD *args;
6073 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6074 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6075 pvargResult, V_VT(pvargResult));
6077 if (cc != CC_STDCALL && cc != CC_CDECL)
6079 FIXME("unsupported calling convention %d\n",cc);
6080 return E_INVALIDARG;
6083 /* maximum size for an argument is sizeof(VARIANT) */
6084 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6086 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6087 argspos = 1;
6088 if (pvInstance)
6090 const FARPROC *vtable = *(FARPROC **)pvInstance;
6091 func = vtable[oVft/sizeof(void *)];
6092 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6094 else func = (void *)oVft;
6096 for (i = 0; i < cActuals; i++)
6098 VARIANT *arg = prgpvarg[i];
6100 switch (prgvt[i])
6102 case VT_EMPTY:
6103 break;
6104 case VT_I8:
6105 case VT_UI8:
6106 case VT_R8:
6107 case VT_DATE:
6108 case VT_CY:
6109 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6110 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6111 break;
6112 case VT_DECIMAL:
6113 case VT_VARIANT:
6114 memcpy( &args[argspos], arg, sizeof(*arg) );
6115 argspos += sizeof(*arg) / sizeof(DWORD);
6116 break;
6117 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6118 args[argspos++] = V_BOOL(arg);
6119 break;
6120 default:
6121 args[argspos++] = V_UI4(arg);
6122 break;
6124 TRACE("arg %u: type %d\n",i,prgvt[i]);
6125 dump_Variant(arg);
6128 switch (vtReturn)
6130 case VT_EMPTY:
6131 call_method( func, argspos - 1, args + 1, &stack_offset );
6132 break;
6133 case VT_R4:
6134 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6135 break;
6136 case VT_R8:
6137 case VT_DATE:
6138 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6139 break;
6140 case VT_DECIMAL:
6141 case VT_VARIANT:
6142 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6143 call_method( func, argspos, args, &stack_offset );
6144 break;
6145 case VT_I8:
6146 case VT_UI8:
6147 case VT_CY:
6148 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6149 break;
6150 default:
6151 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6152 break;
6154 heap_free( args );
6155 if (stack_offset && cc == CC_STDCALL)
6157 WARN( "stack pointer off by %d\n", stack_offset );
6158 return DISP_E_BADCALLEE;
6160 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6161 TRACE("retval: "); dump_Variant(pvargResult);
6162 return S_OK;
6164 #elif defined(__x86_64__)
6165 int argspos;
6166 UINT i;
6167 DWORD_PTR *args;
6168 void *func;
6170 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6171 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6172 pvargResult, V_VT(pvargResult));
6174 if (cc != CC_STDCALL && cc != CC_CDECL)
6176 FIXME("unsupported calling convention %d\n",cc);
6177 return E_INVALIDARG;
6180 /* maximum size for an argument is sizeof(DWORD_PTR) */
6181 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6183 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6184 argspos = 1;
6185 if (pvInstance)
6187 const FARPROC *vtable = *(FARPROC **)pvInstance;
6188 func = vtable[oVft/sizeof(void *)];
6189 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6191 else func = (void *)oVft;
6193 for (i = 0; i < cActuals; i++)
6195 VARIANT *arg = prgpvarg[i];
6197 switch (prgvt[i])
6199 case VT_DECIMAL:
6200 case VT_VARIANT:
6201 args[argspos++] = (ULONG_PTR)arg;
6202 break;
6203 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6204 args[argspos++] = V_BOOL(arg);
6205 break;
6206 default:
6207 args[argspos++] = V_UI8(arg);
6208 break;
6210 TRACE("arg %u: type %d\n",i,prgvt[i]);
6211 dump_Variant(arg);
6214 switch (vtReturn)
6216 case VT_R4:
6217 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6218 break;
6219 case VT_R8:
6220 case VT_DATE:
6221 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6222 break;
6223 case VT_DECIMAL:
6224 case VT_VARIANT:
6225 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6226 call_method( func, argspos, args );
6227 break;
6228 default:
6229 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6230 break;
6232 heap_free( args );
6233 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6234 TRACE("retval: "); dump_Variant(pvargResult);
6235 return S_OK;
6237 #else
6238 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6239 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6240 return E_NOTIMPL;
6241 #endif
6244 static inline BOOL func_restricted( const FUNCDESC *desc )
6246 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
6249 #define INVBUF_ELEMENT_SIZE \
6250 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6251 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6252 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6253 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6254 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6255 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6256 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6257 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6259 static HRESULT WINAPI ITypeInfo_fnInvoke(
6260 ITypeInfo2 *iface,
6261 VOID *pIUnk,
6262 MEMBERID memid,
6263 UINT16 wFlags,
6264 DISPPARAMS *pDispParams,
6265 VARIANT *pVarResult,
6266 EXCEPINFO *pExcepInfo,
6267 UINT *pArgErr)
6269 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6270 int i;
6271 unsigned int var_index;
6272 TYPEKIND type_kind;
6273 HRESULT hres;
6274 const TLBFuncDesc *pFuncInfo;
6275 UINT fdc;
6277 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6278 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6281 if( This->TypeAttr.wTypeFlags & TYPEFLAG_FRESTRICTED )
6282 return DISP_E_MEMBERNOTFOUND;
6284 if (!pDispParams)
6286 ERR("NULL pDispParams not allowed\n");
6287 return E_INVALIDARG;
6290 dump_DispParms(pDispParams);
6292 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6294 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6295 pDispParams->cNamedArgs, pDispParams->cArgs);
6296 return E_INVALIDARG;
6299 /* we do this instead of using GetFuncDesc since it will return a fake
6300 * FUNCDESC for dispinterfaces and we want the real function description */
6301 for (fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc){
6302 pFuncInfo = &This->funcdescs[fdc];
6303 if ((memid == pFuncInfo->funcdesc.memid) &&
6304 (wFlags & pFuncInfo->funcdesc.invkind) &&
6305 !func_restricted( &pFuncInfo->funcdesc ))
6306 break;
6309 if (fdc < This->TypeAttr.cFuncs) {
6310 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6312 if (TRACE_ON(ole))
6314 TRACE("invoking:\n");
6315 dump_TLBFuncDescOne(pFuncInfo);
6318 switch (func_desc->funckind) {
6319 case FUNC_PUREVIRTUAL:
6320 case FUNC_VIRTUAL: {
6321 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
6322 VARIANT varresult;
6323 VARIANT retval; /* pointer for storing byref retvals in */
6324 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6325 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6326 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6327 UINT cNamedArgs = pDispParams->cNamedArgs;
6328 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6329 UINT vargs_converted=0;
6331 hres = S_OK;
6333 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6335 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6337 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6338 hres = DISP_E_PARAMNOTFOUND;
6339 goto func_fail;
6343 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6345 ERR("functions with the vararg attribute do not support named arguments\n");
6346 hres = DISP_E_NONAMEDARGS;
6347 goto func_fail;
6350 for (i = 0; i < func_desc->cParams; i++)
6352 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6353 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6354 if (FAILED(hres))
6355 goto func_fail;
6358 TRACE("changing args\n");
6359 for (i = 0; i < func_desc->cParams; i++)
6361 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6362 VARIANTARG *src_arg;
6364 if (wParamFlags & PARAMFLAG_FLCID)
6366 VARIANTARG *arg;
6367 arg = prgpvarg[i] = &rgvarg[i];
6368 V_VT(arg) = VT_I4;
6369 V_I4(arg) = This->pTypeLib->lcid;
6370 continue;
6373 src_arg = NULL;
6375 if (cNamedArgs)
6377 USHORT j;
6378 for (j = 0; j < cNamedArgs; j++)
6379 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
6381 src_arg = &pDispParams->rgvarg[j];
6382 break;
6386 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
6388 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6389 vargs_converted++;
6392 if (wParamFlags & PARAMFLAG_FRETVAL)
6394 /* under most conditions the caller is not allowed to
6395 * pass in a dispparam arg in the index of what would be
6396 * the retval parameter. however, there is an exception
6397 * where the extra parameter is used in an extra
6398 * IDispatch::Invoke below */
6399 if ((i < pDispParams->cArgs) &&
6400 ((func_desc->cParams != 1) || !pVarResult ||
6401 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6403 hres = DISP_E_BADPARAMCOUNT;
6404 break;
6407 /* note: this check is placed so that if the caller passes
6408 * in a VARIANTARG for the retval we just ignore it, like
6409 * native does */
6410 if (i == func_desc->cParams - 1)
6412 VARIANTARG *arg;
6413 arg = prgpvarg[i] = &rgvarg[i];
6414 memset(arg, 0, sizeof(*arg));
6415 V_VT(arg) = rgvt[i];
6416 memset(&retval, 0, sizeof(retval));
6417 V_BYREF(arg) = &retval;
6419 else
6421 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6422 hres = E_UNEXPECTED;
6423 break;
6426 else if (src_arg)
6428 dump_Variant(src_arg);
6430 if (rgvt[i] == VT_VARIANT)
6431 hres = VariantCopy(&rgvarg[i], src_arg);
6432 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6434 if (rgvt[i] == V_VT(src_arg))
6435 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6436 else
6438 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6439 if (wParamFlags & PARAMFLAG_FIN)
6440 hres = VariantCopy(&missing_arg[i], src_arg);
6441 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6443 V_VT(&rgvarg[i]) = rgvt[i];
6445 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6447 SAFEARRAY *a;
6448 SAFEARRAYBOUND bound;
6449 VARIANT *v;
6450 LONG j;
6451 bound.lLbound = 0;
6452 bound.cElements = pDispParams->cArgs-i;
6453 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6455 ERR("SafeArrayCreate failed\n");
6456 break;
6458 hres = SafeArrayAccessData(a, (LPVOID)&v);
6459 if (hres != S_OK)
6461 ERR("SafeArrayAccessData failed with %x\n", hres);
6462 break;
6464 for (j = 0; j < bound.cElements; j++)
6465 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6466 hres = SafeArrayUnaccessData(a);
6467 if (hres != S_OK)
6469 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6470 break;
6472 V_ARRAY(&rgvarg[i]) = a;
6473 V_VT(&rgvarg[i]) = rgvt[i];
6475 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6477 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6478 if (wParamFlags & PARAMFLAG_FIN)
6479 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6480 else
6481 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
6482 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6483 V_VT(&rgvarg[i]) = rgvt[i];
6485 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6487 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6488 V_VT(&rgvarg[i]) = rgvt[i];
6490 else
6492 /* FIXME: this doesn't work for VT_BYREF arguments if
6493 * they are not the same type as in the paramdesc */
6494 V_VT(&rgvarg[i]) = V_VT(src_arg);
6495 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6496 V_VT(&rgvarg[i]) = rgvt[i];
6499 if (FAILED(hres))
6501 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6502 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6503 debugstr_VT(src_arg), debugstr_VF(src_arg));
6504 break;
6506 prgpvarg[i] = &rgvarg[i];
6508 else if (wParamFlags & PARAMFLAG_FOPT)
6510 VARIANTARG *arg;
6511 arg = prgpvarg[i] = &rgvarg[i];
6512 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6514 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6515 if (FAILED(hres))
6516 break;
6518 else
6520 VARIANTARG *missing_arg;
6521 /* if the function wants a pointer to a variant then
6522 * set that up, otherwise just pass the VT_ERROR in
6523 * the argument by value */
6524 if (rgvt[i] & VT_BYREF)
6526 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6527 V_VT(arg) = VT_VARIANT | VT_BYREF;
6528 V_VARIANTREF(arg) = missing_arg;
6530 else
6531 missing_arg = arg;
6532 V_VT(missing_arg) = VT_ERROR;
6533 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6536 else
6538 hres = DISP_E_BADPARAMCOUNT;
6539 break;
6542 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6544 /* VT_VOID is a special case for return types, so it is not
6545 * handled in the general function */
6546 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6547 V_VT(&varresult) = VT_EMPTY;
6548 else
6550 V_VT(&varresult) = 0;
6551 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6552 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6555 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6556 V_VT(&varresult), func_desc->cParams, rgvt,
6557 prgpvarg, &varresult);
6559 vargs_converted = 0;
6561 for (i = 0; i < func_desc->cParams; i++)
6563 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6564 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6566 if (wParamFlags & PARAMFLAG_FLCID)
6567 continue;
6568 else if (wParamFlags & PARAMFLAG_FRETVAL)
6570 if (TRACE_ON(ole))
6572 TRACE("[retval] value: ");
6573 dump_Variant(prgpvarg[i]);
6576 if (pVarResult)
6578 VariantInit(pVarResult);
6579 /* deref return value */
6580 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6583 VARIANT_ClearInd(prgpvarg[i]);
6585 else if (vargs_converted < pDispParams->cArgs)
6587 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6588 if (wParamFlags & PARAMFLAG_FOUT)
6590 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
6592 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6594 if (FAILED(hres))
6596 ERR("failed to convert param %d to vt %d\n", i,
6597 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
6598 break;
6602 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6603 func_desc->cParamsOpt < 0 &&
6604 i == func_desc->cParams-1)
6606 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6607 LONG j, ubound;
6608 VARIANT *v;
6609 hres = SafeArrayGetUBound(a, 1, &ubound);
6610 if (hres != S_OK)
6612 ERR("SafeArrayGetUBound failed with %x\n", hres);
6613 break;
6615 hres = SafeArrayAccessData(a, (LPVOID)&v);
6616 if (hres != S_OK)
6618 ERR("SafeArrayAccessData failed with %x\n", hres);
6619 break;
6621 for (j = 0; j <= ubound; j++)
6622 VariantClear(&v[j]);
6623 hres = SafeArrayUnaccessData(a);
6624 if (hres != S_OK)
6626 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6627 break;
6630 VariantClear(&rgvarg[i]);
6631 vargs_converted++;
6633 else if (wParamFlags & PARAMFLAG_FOPT)
6635 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6636 VariantClear(&rgvarg[i]);
6639 VariantClear(&missing_arg[i]);
6642 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6644 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6645 hres = DISP_E_EXCEPTION;
6646 if (pExcepInfo)
6648 IErrorInfo *pErrorInfo;
6649 pExcepInfo->scode = V_ERROR(&varresult);
6650 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6652 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6653 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6654 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6655 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6657 IErrorInfo_Release(pErrorInfo);
6661 if (V_VT(&varresult) != VT_ERROR)
6663 TRACE("varresult value: ");
6664 dump_Variant(&varresult);
6666 if (pVarResult)
6668 VariantClear(pVarResult);
6669 *pVarResult = varresult;
6671 else
6672 VariantClear(&varresult);
6675 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6676 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6677 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6678 (pDispParams->cArgs != 0))
6680 if (V_VT(pVarResult) == VT_DISPATCH)
6682 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6683 /* Note: not VariantClear; we still need the dispatch
6684 * pointer to be valid */
6685 VariantInit(pVarResult);
6686 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6687 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6688 pDispParams, pVarResult, pExcepInfo, pArgErr);
6689 IDispatch_Release(pDispatch);
6691 else
6693 VariantClear(pVarResult);
6694 hres = DISP_E_NOTACOLLECTION;
6698 func_fail:
6699 heap_free(buffer);
6700 break;
6702 case FUNC_DISPATCH: {
6703 IDispatch *disp;
6705 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6706 if (SUCCEEDED(hres)) {
6707 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6708 hres = IDispatch_Invoke(
6709 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6710 pVarResult,pExcepInfo,pArgErr
6712 if (FAILED(hres))
6713 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6714 IDispatch_Release(disp);
6715 } else
6716 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6717 break;
6719 default:
6720 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6721 hres = E_FAIL;
6722 break;
6725 TRACE("-- 0x%08x\n", hres);
6726 return hres;
6728 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6729 VARDESC *var_desc;
6731 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6732 if(FAILED(hres)) return hres;
6734 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6735 dump_VARDESC(var_desc);
6736 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6737 return E_NOTIMPL;
6740 /* not found, look for it in inherited interfaces */
6741 ITypeInfo2_GetTypeKind(iface, &type_kind);
6742 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6743 if(This->impltypes) {
6744 /* recursive search */
6745 ITypeInfo *pTInfo;
6746 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6747 if(SUCCEEDED(hres)){
6748 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6749 ITypeInfo_Release(pTInfo);
6750 return hres;
6752 WARN("Could not search inherited interface!\n");
6755 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6756 return DISP_E_MEMBERNOTFOUND;
6759 /* ITypeInfo::GetDocumentation
6761 * Retrieves the documentation string, the complete Help file name and path,
6762 * and the context ID for the Help topic for a specified type description.
6764 * (Can be tested by the Visual Basic Editor in Word for instance.)
6766 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6767 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6768 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6770 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6771 const TLBFuncDesc *pFDesc;
6772 const TLBVarDesc *pVDesc;
6773 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6774 " HelpContext(%p) HelpFile(%p)\n",
6775 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6776 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6777 if(pBstrName)
6778 *pBstrName=SysAllocString(This->Name);
6779 if(pBstrDocString)
6780 *pBstrDocString=SysAllocString(This->DocString);
6781 if(pdwHelpContext)
6782 *pdwHelpContext=This->dwHelpContext;
6783 if(pBstrHelpFile)
6784 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6785 return S_OK;
6786 }else {/* for a member */
6787 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
6788 if(pFDesc){
6789 if(pBstrName)
6790 *pBstrName = SysAllocString(pFDesc->Name);
6791 if(pBstrDocString)
6792 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6793 if(pdwHelpContext)
6794 *pdwHelpContext=pFDesc->helpcontext;
6795 return S_OK;
6797 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
6798 if(pVDesc){
6799 if(pBstrName)
6800 *pBstrName = SysAllocString(pVDesc->Name);
6801 if(pBstrDocString)
6802 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6803 if(pdwHelpContext)
6804 *pdwHelpContext=pVDesc->HelpContext;
6805 return S_OK;
6809 if(This->impltypes &&
6810 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6811 /* recursive search */
6812 ITypeInfo *pTInfo;
6813 HRESULT result;
6814 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef,
6815 &pTInfo);
6816 if(SUCCEEDED(result)) {
6817 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6818 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6819 ITypeInfo_Release(pTInfo);
6820 return result;
6822 WARN("Could not search inherited interface!\n");
6825 WARN("member %d not found\n", memid);
6826 return TYPE_E_ELEMENTNOTFOUND;
6829 /* ITypeInfo::GetDllEntry
6831 * Retrieves a description or specification of an entry point for a function
6832 * in a DLL.
6834 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6835 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6836 WORD *pwOrdinal)
6838 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6839 const TLBFuncDesc *pFDesc;
6841 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6843 if (pBstrDllName) *pBstrDllName = NULL;
6844 if (pBstrName) *pBstrName = NULL;
6845 if (pwOrdinal) *pwOrdinal = 0;
6847 if (This->TypeAttr.typekind != TKIND_MODULE)
6848 return TYPE_E_BADMODULEKIND;
6850 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
6851 if(pFDesc){
6852 dump_TypeInfo(This);
6853 if (TRACE_ON(ole))
6854 dump_TLBFuncDescOne(pFDesc);
6856 if (pBstrDllName)
6857 *pBstrDllName = SysAllocString(This->DllName);
6859 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6860 if (pBstrName)
6861 *pBstrName = SysAllocString(pFDesc->Entry);
6862 if (pwOrdinal)
6863 *pwOrdinal = -1;
6864 return S_OK;
6866 if (pBstrName)
6867 *pBstrName = NULL;
6868 if (pwOrdinal)
6869 *pwOrdinal = LOWORD(pFDesc->Entry);
6870 return S_OK;
6872 return TYPE_E_ELEMENTNOTFOUND;
6875 /* internal function to make the inherited interfaces' methods appear
6876 * part of the interface */
6877 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6878 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6880 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6881 HRESULT hr;
6883 TRACE("%p, 0x%x\n", iface, *hRefType);
6885 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
6887 ITypeInfo *pSubTypeInfo;
6889 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
6890 if (FAILED(hr))
6891 return hr;
6893 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6894 hRefType, ppTInfo);
6895 ITypeInfo_Release(pSubTypeInfo);
6896 if (SUCCEEDED(hr))
6897 return hr;
6899 *hRefType -= DISPATCH_HREF_OFFSET;
6901 if (!(*hRefType & DISPATCH_HREF_MASK))
6902 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6903 else
6904 return E_FAIL;
6907 /* ITypeInfo::GetRefTypeInfo
6909 * If a type description references other type descriptions, it retrieves
6910 * the referenced type descriptions.
6912 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6913 ITypeInfo2 *iface,
6914 HREFTYPE hRefType,
6915 ITypeInfo **ppTInfo)
6917 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6918 HRESULT result = E_FAIL;
6920 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6922 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6923 ITypeInfo_AddRef(*ppTInfo);
6924 result = S_OK;
6926 else if (hRefType == -1 &&
6927 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6928 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6930 /* when we meet a DUAL dispinterface, we must create the interface
6931 * version of it.
6933 ITypeInfoImpl *pTypeInfoImpl = ITypeInfoImpl_Constructor();
6936 /* the interface version contains the same information as the dispinterface
6937 * copy the contents of the structs.
6939 *pTypeInfoImpl = *This;
6940 pTypeInfoImpl->ref = 0;
6942 /* change the type to interface */
6943 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6945 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6947 /* the AddRef implicitly adds a reference to the parent typelib, which
6948 * stops the copied data from being destroyed until the new typeinfo's
6949 * refcount goes to zero, but we need to signal to the new instance to
6950 * not free its data structures when it is destroyed */
6951 pTypeInfoImpl->not_attached_to_typelib = TRUE;
6953 ITypeInfo_AddRef(*ppTInfo);
6955 result = S_OK;
6957 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6958 (This->TypeAttr.typekind == TKIND_DISPATCH))
6960 HREFTYPE href_dispatch = hRefType;
6961 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6962 } else {
6963 TLBRefType *ref_type;
6964 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6966 if(ref_type->reference == hRefType)
6967 break;
6969 if(&ref_type->entry == &This->pTypeLib->ref_list)
6971 FIXME("Can't find pRefType for ref %x\n", hRefType);
6972 goto end;
6974 if(hRefType != -1) {
6975 ITypeLib *pTLib = NULL;
6977 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6978 UINT Index;
6979 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6980 } else {
6981 if(ref_type->pImpTLInfo->pImpTypeLib) {
6982 TRACE("typeinfo in imported typelib that is already loaded\n");
6983 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6984 ITypeLib2_AddRef(pTLib);
6985 result = S_OK;
6986 } else {
6987 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6988 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6989 ref_type->pImpTLInfo->wVersionMajor,
6990 ref_type->pImpTLInfo->wVersionMinor,
6991 ref_type->pImpTLInfo->lcid,
6992 &pTLib);
6994 if(FAILED(result)) {
6995 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6996 result=LoadTypeLib(libnam, &pTLib);
6997 SysFreeString(libnam);
6999 if(SUCCEEDED(result)) {
7000 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
7001 ITypeLib2_AddRef(pTLib);
7005 if(SUCCEEDED(result)) {
7006 if(ref_type->index == TLB_REF_USE_GUID)
7007 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
7008 &ref_type->guid,
7009 ppTInfo);
7010 else
7011 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
7012 ppTInfo);
7014 if (pTLib != NULL)
7015 ITypeLib2_Release(pTLib);
7019 end:
7020 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
7021 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
7022 return result;
7025 /* ITypeInfo::AddressOfMember
7027 * Retrieves the addresses of static functions or variables, such as those
7028 * defined in a DLL.
7030 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
7031 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
7033 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7034 HRESULT hr;
7035 BSTR dll, entry;
7036 WORD ordinal;
7037 HMODULE module;
7039 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
7041 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
7042 if (FAILED(hr))
7043 return hr;
7045 module = LoadLibraryW(dll);
7046 if (!module)
7048 ERR("couldn't load %s\n", debugstr_w(dll));
7049 SysFreeString(dll);
7050 SysFreeString(entry);
7051 return STG_E_FILENOTFOUND;
7053 /* FIXME: store library somewhere where we can free it */
7055 if (entry)
7057 LPSTR entryA;
7058 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
7059 entryA = heap_alloc(len);
7060 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
7062 *ppv = GetProcAddress(module, entryA);
7063 if (!*ppv)
7064 ERR("function not found %s\n", debugstr_a(entryA));
7066 heap_free(entryA);
7068 else
7070 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7071 if (!*ppv)
7072 ERR("function not found %d\n", ordinal);
7075 SysFreeString(dll);
7076 SysFreeString(entry);
7078 if (!*ppv)
7079 return TYPE_E_DLLFUNCTIONNOTFOUND;
7081 return S_OK;
7084 /* ITypeInfo::CreateInstance
7086 * Creates a new instance of a type that describes a component object class
7087 * (coclass).
7089 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7090 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7092 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7093 HRESULT hr;
7094 TYPEATTR *pTA;
7096 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7098 *ppvObj = NULL;
7100 if(pOuterUnk)
7102 WARN("Not able to aggregate\n");
7103 return CLASS_E_NOAGGREGATION;
7106 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
7107 if(FAILED(hr)) return hr;
7109 if(pTA->typekind != TKIND_COCLASS)
7111 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7112 hr = E_INVALIDARG;
7113 goto end;
7116 hr = S_FALSE;
7117 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7119 IUnknown *pUnk;
7120 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7121 TRACE("GetActiveObject rets %08x\n", hr);
7122 if(hr == S_OK)
7124 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7125 IUnknown_Release(pUnk);
7129 if(hr != S_OK)
7130 hr = CoCreateInstance(&pTA->guid, NULL,
7131 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7132 riid, ppvObj);
7134 end:
7135 ITypeInfo_ReleaseTypeAttr(iface, pTA);
7136 return hr;
7139 /* ITypeInfo::GetMops
7141 * Retrieves marshalling information.
7143 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7144 BSTR *pBstrMops)
7146 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7147 FIXME("(%p %d) stub!\n", This, memid);
7148 *pBstrMops = NULL;
7149 return S_OK;
7152 /* ITypeInfo::GetContainingTypeLib
7154 * Retrieves the containing type library and the index of the type description
7155 * within that type library.
7157 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7158 ITypeLib * *ppTLib, UINT *pIndex)
7160 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7162 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7163 if (pIndex) {
7164 *pIndex=This->index;
7165 TRACE("returning pIndex=%d\n", *pIndex);
7168 if (ppTLib) {
7169 *ppTLib=(LPTYPELIB )(This->pTypeLib);
7170 ITypeLib2_AddRef(*ppTLib);
7171 TRACE("returning ppTLib=%p\n", *ppTLib);
7174 return S_OK;
7177 /* ITypeInfo::ReleaseTypeAttr
7179 * Releases a TYPEATTR previously returned by GetTypeAttr.
7182 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7183 TYPEATTR* pTypeAttr)
7185 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7186 TRACE("(%p)->(%p)\n", This, pTypeAttr);
7187 heap_free(pTypeAttr);
7190 /* ITypeInfo::ReleaseFuncDesc
7192 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7194 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7195 ITypeInfo2 *iface,
7196 FUNCDESC *pFuncDesc)
7198 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7199 SHORT i;
7201 TRACE("(%p)->(%p)\n", This, pFuncDesc);
7203 for (i = 0; i < pFuncDesc->cParams; i++)
7204 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7205 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7207 SysFreeString((BSTR)pFuncDesc);
7210 /* ITypeInfo::ReleaseVarDesc
7212 * Releases a VARDESC previously returned by GetVarDesc.
7214 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7215 VARDESC *pVarDesc)
7217 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7218 TRACE("(%p)->(%p)\n", This, pVarDesc);
7220 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
7221 if (pVarDesc->varkind == VAR_CONST)
7222 VariantClear(pVarDesc->u.lpvarValue);
7223 SysFreeString((BSTR)pVarDesc);
7226 /* ITypeInfo2::GetTypeKind
7228 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7231 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7232 TYPEKIND *pTypeKind)
7234 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7235 *pTypeKind=This->TypeAttr.typekind;
7236 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7237 return S_OK;
7240 /* ITypeInfo2::GetTypeFlags
7242 * Returns the type flags without any allocations. This returns a DWORD type
7243 * flag, which expands the type flags without growing the TYPEATTR (type
7244 * attribute).
7247 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7249 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7250 *pTypeFlags=This->TypeAttr.wTypeFlags;
7251 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7252 return S_OK;
7255 /* ITypeInfo2::GetFuncIndexOfMemId
7256 * Binds to a specific member based on a known DISPID, where the member name
7257 * is not known (for example, when binding to a default member).
7260 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7261 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7263 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7264 UINT fdc;
7265 HRESULT result;
7267 for (fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc){
7268 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
7269 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7270 break;
7272 if(fdc < This->TypeAttr.cFuncs) {
7273 *pFuncIndex = fdc;
7274 result = S_OK;
7275 } else
7276 result = TYPE_E_ELEMENTNOTFOUND;
7278 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7279 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7280 return result;
7283 /* TypeInfo2::GetVarIndexOfMemId
7285 * Binds to a specific member based on a known DISPID, where the member name
7286 * is not known (for example, when binding to a default member).
7289 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7290 MEMBERID memid, UINT *pVarIndex)
7292 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7293 TLBVarDesc *pVarInfo;
7295 TRACE("%p %d %p\n", iface, memid, pVarIndex);
7297 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
7298 if(!pVarInfo)
7299 return TYPE_E_ELEMENTNOTFOUND;
7301 *pVarIndex = (pVarInfo - This->vardescs);
7303 return S_OK;
7306 /* ITypeInfo2::GetCustData
7308 * Gets the custom data
7310 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7311 ITypeInfo2 * iface,
7312 REFGUID guid,
7313 VARIANT *pVarVal)
7315 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7316 TLBCustData *pCData;
7318 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7320 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
7322 VariantInit( pVarVal);
7323 if (pCData)
7324 VariantCopy( pVarVal, &pCData->data);
7325 else
7326 VariantClear( pVarVal );
7327 return S_OK;
7330 /* ITypeInfo2::GetFuncCustData
7332 * Gets the custom data
7334 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7335 ITypeInfo2 * iface,
7336 UINT index,
7337 REFGUID guid,
7338 VARIANT *pVarVal)
7340 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7341 TLBCustData *pCData;
7342 TLBFuncDesc *pFDesc = &This->funcdescs[index];
7344 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
7346 if(index >= This->TypeAttr.cFuncs)
7347 return TYPE_E_ELEMENTNOTFOUND;
7349 pCData = TLB_get_custdata_by_guid(&pFDesc->custdata_list, guid);
7350 if(!pCData)
7351 return TYPE_E_ELEMENTNOTFOUND;
7353 VariantInit(pVarVal);
7354 VariantCopy(pVarVal, &pCData->data);
7356 return S_OK;
7359 /* ITypeInfo2::GetParamCustData
7361 * Gets the custom data
7363 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7364 ITypeInfo2 * iface,
7365 UINT indexFunc,
7366 UINT indexParam,
7367 REFGUID guid,
7368 VARIANT *pVarVal)
7370 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7371 TLBCustData *pCData;
7372 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
7374 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
7375 debugstr_guid(guid), pVarVal);
7377 if(indexFunc >= This->TypeAttr.cFuncs)
7378 return TYPE_E_ELEMENTNOTFOUND;
7380 if(indexParam >= pFDesc->funcdesc.cParams)
7381 return TYPE_E_ELEMENTNOTFOUND;
7383 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
7384 if(!pCData)
7385 return TYPE_E_ELEMENTNOTFOUND;
7387 VariantInit(pVarVal);
7388 VariantCopy(pVarVal, &pCData->data);
7390 return S_OK;
7393 /* ITypeInfo2::GetVarCustData
7395 * Gets the custom data
7397 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7398 ITypeInfo2 * iface,
7399 UINT index,
7400 REFGUID guid,
7401 VARIANT *pVarVal)
7403 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7404 TLBCustData *pCData;
7405 TLBVarDesc *pVDesc = &This->vardescs[index];
7407 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7409 if(index >= This->TypeAttr.cVars)
7410 return TYPE_E_ELEMENTNOTFOUND;
7412 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
7413 if(!pCData)
7414 return TYPE_E_ELEMENTNOTFOUND;
7416 VariantInit(pVarVal);
7417 VariantCopy(pVarVal, &pCData->data);
7419 return S_OK;
7422 /* ITypeInfo2::GetImplCustData
7424 * Gets the custom data
7426 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7427 ITypeInfo2 * iface,
7428 UINT index,
7429 REFGUID guid,
7430 VARIANT *pVarVal)
7432 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7433 TLBCustData *pCData;
7434 TLBImplType *pRDesc = &This->impltypes[index];
7436 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
7438 if(index >= This->TypeAttr.cImplTypes)
7439 return TYPE_E_ELEMENTNOTFOUND;
7441 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
7442 if(!pCData)
7443 return TYPE_E_ELEMENTNOTFOUND;
7445 VariantInit(pVarVal);
7446 VariantCopy(pVarVal, &pCData->data);
7448 return S_OK;
7451 /* ITypeInfo2::GetDocumentation2
7453 * Retrieves the documentation string, the complete Help file name and path,
7454 * the localization context to use, and the context ID for the library Help
7455 * topic in the Help file.
7458 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7459 ITypeInfo2 * iface,
7460 MEMBERID memid,
7461 LCID lcid,
7462 BSTR *pbstrHelpString,
7463 DWORD *pdwHelpStringContext,
7464 BSTR *pbstrHelpStringDll)
7466 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7467 const TLBFuncDesc *pFDesc;
7468 const TLBVarDesc *pVDesc;
7469 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7470 "HelpStringContext(%p) HelpStringDll(%p)\n",
7471 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7472 pbstrHelpStringDll );
7473 /* the help string should be obtained from the helpstringdll,
7474 * using the _DLLGetDocumentation function, based on the supplied
7475 * lcid. Nice to do sometime...
7477 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7478 if(pbstrHelpString)
7479 *pbstrHelpString=SysAllocString(This->Name);
7480 if(pdwHelpStringContext)
7481 *pdwHelpStringContext=This->dwHelpStringContext;
7482 if(pbstrHelpStringDll)
7483 *pbstrHelpStringDll=
7484 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7485 return S_OK;
7486 }else {/* for a member */
7487 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
7488 if(pFDesc){
7489 if(pbstrHelpString)
7490 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
7491 if(pdwHelpStringContext)
7492 *pdwHelpStringContext=pFDesc->HelpStringContext;
7493 if(pbstrHelpStringDll)
7494 *pbstrHelpStringDll=
7495 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7496 return S_OK;
7498 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
7499 if(pVDesc){
7500 if(pbstrHelpString)
7501 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
7502 if(pdwHelpStringContext)
7503 *pdwHelpStringContext=pVDesc->HelpStringContext;
7504 if(pbstrHelpStringDll)
7505 *pbstrHelpStringDll=
7506 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7507 return S_OK;
7510 return TYPE_E_ELEMENTNOTFOUND;
7513 /* ITypeInfo2::GetAllCustData
7515 * Gets all custom data items for the Type info.
7518 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7519 ITypeInfo2 * iface,
7520 CUSTDATA *pCustData)
7522 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7524 TRACE("%p %p\n", This, pCustData);
7526 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
7529 /* ITypeInfo2::GetAllFuncCustData
7531 * Gets all custom data items for the specified Function
7534 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7535 ITypeInfo2 * iface,
7536 UINT index,
7537 CUSTDATA *pCustData)
7539 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7540 TLBFuncDesc *pFDesc = &This->funcdescs[index];
7542 TRACE("%p %u %p\n", This, index, pCustData);
7544 if(index >= This->TypeAttr.cFuncs)
7545 return TYPE_E_ELEMENTNOTFOUND;
7547 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
7550 /* ITypeInfo2::GetAllParamCustData
7552 * Gets all custom data items for the Functions
7555 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7556 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7558 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7559 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
7561 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
7563 if(indexFunc >= This->TypeAttr.cFuncs)
7564 return TYPE_E_ELEMENTNOTFOUND;
7566 if(indexParam >= pFDesc->funcdesc.cParams)
7567 return TYPE_E_ELEMENTNOTFOUND;
7569 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
7572 /* ITypeInfo2::GetAllVarCustData
7574 * Gets all custom data items for the specified Variable
7577 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7578 UINT index, CUSTDATA *pCustData)
7580 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7581 TLBVarDesc * pVDesc = &This->vardescs[index];
7583 TRACE("%p %u %p\n", This, index, pCustData);
7585 if(index >= This->TypeAttr.cVars)
7586 return TYPE_E_ELEMENTNOTFOUND;
7588 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
7591 /* ITypeInfo2::GetAllImplCustData
7593 * Gets all custom data items for the specified implementation type
7596 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7597 ITypeInfo2 * iface,
7598 UINT index,
7599 CUSTDATA *pCustData)
7601 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7602 TLBImplType *pRDesc = &This->impltypes[index];
7604 TRACE("%p %u %p\n", This, index, pCustData);
7606 if(index >= This->TypeAttr.cImplTypes)
7607 return TYPE_E_ELEMENTNOTFOUND;
7609 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
7612 static const ITypeInfo2Vtbl tinfvt =
7615 ITypeInfo_fnQueryInterface,
7616 ITypeInfo_fnAddRef,
7617 ITypeInfo_fnRelease,
7619 ITypeInfo_fnGetTypeAttr,
7620 ITypeInfo_fnGetTypeComp,
7621 ITypeInfo_fnGetFuncDesc,
7622 ITypeInfo_fnGetVarDesc,
7623 ITypeInfo_fnGetNames,
7624 ITypeInfo_fnGetRefTypeOfImplType,
7625 ITypeInfo_fnGetImplTypeFlags,
7626 ITypeInfo_fnGetIDsOfNames,
7627 ITypeInfo_fnInvoke,
7628 ITypeInfo_fnGetDocumentation,
7629 ITypeInfo_fnGetDllEntry,
7630 ITypeInfo_fnGetRefTypeInfo,
7631 ITypeInfo_fnAddressOfMember,
7632 ITypeInfo_fnCreateInstance,
7633 ITypeInfo_fnGetMops,
7634 ITypeInfo_fnGetContainingTypeLib,
7635 ITypeInfo_fnReleaseTypeAttr,
7636 ITypeInfo_fnReleaseFuncDesc,
7637 ITypeInfo_fnReleaseVarDesc,
7639 ITypeInfo2_fnGetTypeKind,
7640 ITypeInfo2_fnGetTypeFlags,
7641 ITypeInfo2_fnGetFuncIndexOfMemId,
7642 ITypeInfo2_fnGetVarIndexOfMemId,
7643 ITypeInfo2_fnGetCustData,
7644 ITypeInfo2_fnGetFuncCustData,
7645 ITypeInfo2_fnGetParamCustData,
7646 ITypeInfo2_fnGetVarCustData,
7647 ITypeInfo2_fnGetImplTypeCustData,
7648 ITypeInfo2_fnGetDocumentation2,
7649 ITypeInfo2_fnGetAllCustData,
7650 ITypeInfo2_fnGetAllFuncCustData,
7651 ITypeInfo2_fnGetAllParamCustData,
7652 ITypeInfo2_fnGetAllVarCustData,
7653 ITypeInfo2_fnGetAllImplTypeCustData,
7656 /******************************************************************************
7657 * CreateDispTypeInfo [OLEAUT32.31]
7659 * Build type information for an object so it can be called through an
7660 * IDispatch interface.
7662 * RETURNS
7663 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7664 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7666 * NOTES
7667 * This call allows an objects methods to be accessed through IDispatch, by
7668 * building an ITypeInfo object that IDispatch can use to call through.
7670 HRESULT WINAPI CreateDispTypeInfo(
7671 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7672 LCID lcid, /* [I] Locale Id */
7673 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7675 ITypeInfoImpl *pTIClass, *pTIIface;
7676 ITypeLibImpl *pTypeLibImpl;
7677 unsigned int param, func;
7678 TLBFuncDesc *pFuncDesc;
7679 TLBRefType *ref;
7681 TRACE("\n");
7682 pTypeLibImpl = TypeLibImpl_Constructor();
7683 if (!pTypeLibImpl) return E_FAIL;
7685 pTypeLibImpl->TypeInfoCount = 2;
7686 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
7688 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
7689 pTIIface->pTypeLib = pTypeLibImpl;
7690 pTIIface->index = 0;
7691 pTIIface->Name = NULL;
7692 pTIIface->dwHelpContext = -1;
7693 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7694 pTIIface->TypeAttr.lcid = lcid;
7695 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7696 pTIIface->TypeAttr.wMajorVerNum = 0;
7697 pTIIface->TypeAttr.wMinorVerNum = 0;
7698 pTIIface->TypeAttr.cbAlignment = 2;
7699 pTIIface->TypeAttr.cbSizeInstance = -1;
7700 pTIIface->TypeAttr.cbSizeVft = -1;
7701 pTIIface->TypeAttr.cFuncs = 0;
7702 pTIIface->TypeAttr.cImplTypes = 0;
7703 pTIIface->TypeAttr.cVars = 0;
7704 pTIIface->TypeAttr.wTypeFlags = 0;
7706 pTIIface->funcdescs = TLBFuncDesc_Constructor(pidata->cMembers);
7707 pFuncDesc = pTIIface->funcdescs;
7708 for(func = 0; func < pidata->cMembers; func++) {
7709 METHODDATA *md = pidata->pmethdata + func;
7710 pFuncDesc->Name = SysAllocString(md->szName);
7711 pFuncDesc->funcdesc.memid = md->dispid;
7712 pFuncDesc->funcdesc.lprgscode = NULL;
7713 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
7714 pFuncDesc->funcdesc.invkind = md->wFlags;
7715 pFuncDesc->funcdesc.callconv = md->cc;
7716 pFuncDesc->funcdesc.cParams = md->cArgs;
7717 pFuncDesc->funcdesc.cParamsOpt = 0;
7718 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
7719 pFuncDesc->funcdesc.cScodes = 0;
7720 pFuncDesc->funcdesc.wFuncFlags = 0;
7721 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7722 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7723 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7724 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7725 md->cArgs * sizeof(ELEMDESC));
7726 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
7727 for(param = 0; param < md->cArgs; param++) {
7728 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7729 pFuncDesc->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7731 pFuncDesc->helpcontext = 0;
7732 pFuncDesc->HelpStringContext = 0;
7733 pFuncDesc->HelpString = NULL;
7734 pFuncDesc->Entry = NULL;
7735 list_init(&pFuncDesc->custdata_list);
7736 pTIIface->TypeAttr.cFuncs++;
7737 ++pFuncDesc;
7740 dump_TypeInfo(pTIIface);
7742 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
7743 pTIClass->pTypeLib = pTypeLibImpl;
7744 pTIClass->index = 1;
7745 pTIClass->Name = NULL;
7746 pTIClass->dwHelpContext = -1;
7747 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7748 pTIClass->TypeAttr.lcid = lcid;
7749 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7750 pTIClass->TypeAttr.wMajorVerNum = 0;
7751 pTIClass->TypeAttr.wMinorVerNum = 0;
7752 pTIClass->TypeAttr.cbAlignment = 2;
7753 pTIClass->TypeAttr.cbSizeInstance = -1;
7754 pTIClass->TypeAttr.cbSizeVft = -1;
7755 pTIClass->TypeAttr.cFuncs = 0;
7756 pTIClass->TypeAttr.cImplTypes = 1;
7757 pTIClass->TypeAttr.cVars = 0;
7758 pTIClass->TypeAttr.wTypeFlags = 0;
7760 pTIClass->impltypes = TLBImplType_Constructor(1);
7762 ref = heap_alloc_zero(sizeof(*ref));
7763 ref->pImpTLInfo = TLB_REF_INTERNAL;
7764 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7766 dump_TypeInfo(pTIClass);
7768 *pptinfo = (ITypeInfo*)pTIClass;
7770 ITypeInfo_AddRef(*pptinfo);
7771 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7773 return S_OK;
7777 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7779 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7781 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7784 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7786 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7788 return ITypeInfo_AddRef((ITypeInfo *)This);
7791 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7793 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7795 return ITypeInfo_Release((ITypeInfo *)This);
7798 static HRESULT WINAPI ITypeComp_fnBind(
7799 ITypeComp * iface,
7800 OLECHAR * szName,
7801 ULONG lHash,
7802 WORD wFlags,
7803 ITypeInfo ** ppTInfo,
7804 DESCKIND * pDescKind,
7805 BINDPTR * pBindPtr)
7807 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7808 const TLBFuncDesc *pFDesc;
7809 const TLBVarDesc *pVDesc;
7810 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7811 UINT fdc;
7813 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7815 *pDescKind = DESCKIND_NONE;
7816 pBindPtr->lpfuncdesc = NULL;
7817 *ppTInfo = NULL;
7819 for(fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc){
7820 pFDesc = &This->funcdescs[fdc];
7821 if (!strcmpiW(pFDesc->Name, szName)) {
7822 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7823 break;
7824 else
7825 /* name found, but wrong flags */
7826 hr = TYPE_E_TYPEMISMATCH;
7830 if (fdc < This->TypeAttr.cFuncs)
7832 HRESULT hr = TLB_AllocAndInitFuncDesc(
7833 &pFDesc->funcdesc,
7834 &pBindPtr->lpfuncdesc,
7835 This->TypeAttr.typekind == TKIND_DISPATCH);
7836 if (FAILED(hr))
7837 return hr;
7838 *pDescKind = DESCKIND_FUNCDESC;
7839 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7840 ITypeInfo_AddRef(*ppTInfo);
7841 return S_OK;
7842 } else {
7843 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->TypeAttr.cVars, szName);
7844 if(pVDesc){
7845 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7846 if (FAILED(hr))
7847 return hr;
7848 *pDescKind = DESCKIND_VARDESC;
7849 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7850 ITypeInfo_AddRef(*ppTInfo);
7851 return S_OK;
7854 /* FIXME: search each inherited interface, not just the first */
7855 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
7856 /* recursive search */
7857 ITypeInfo *pTInfo;
7858 ITypeComp *pTComp;
7859 HRESULT hr;
7860 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypes[0].hRef, &pTInfo);
7861 if (SUCCEEDED(hr))
7863 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7864 ITypeInfo_Release(pTInfo);
7866 if (SUCCEEDED(hr))
7868 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7869 ITypeComp_Release(pTComp);
7870 return hr;
7872 WARN("Could not search inherited interface!\n");
7874 if (hr == DISP_E_MEMBERNOTFOUND)
7875 hr = S_OK;
7876 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
7877 return hr;
7880 static HRESULT WINAPI ITypeComp_fnBindType(
7881 ITypeComp * iface,
7882 OLECHAR * szName,
7883 ULONG lHash,
7884 ITypeInfo ** ppTInfo,
7885 ITypeComp ** ppTComp)
7887 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7889 /* strange behaviour (does nothing) but like the
7890 * original */
7892 if (!ppTInfo || !ppTComp)
7893 return E_POINTER;
7895 *ppTInfo = NULL;
7896 *ppTComp = NULL;
7898 return S_OK;
7901 static const ITypeCompVtbl tcompvt =
7904 ITypeComp_fnQueryInterface,
7905 ITypeComp_fnAddRef,
7906 ITypeComp_fnRelease,
7908 ITypeComp_fnBind,
7909 ITypeComp_fnBindType