oleaut32: Convert CustData to use standard linked lists.
[wine/multimedia.git] / dlls / oleaut32 / typelib.c
blob4637bf2760ea0fd56ac723d24a3fcb89454d606f
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 tagTLBImpLib * next;
981 } TLBImpLib;
983 /* internal ITypeLib data */
984 typedef struct tagITypeLibImpl
986 const ITypeLib2Vtbl *lpVtbl;
987 const ITypeCompVtbl *lpVtblTypeComp;
988 LONG ref;
989 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
990 LCID lcid;
992 /* strings can be stored in tlb as multibyte strings BUT they are *always*
993 * exported to the application as a UNICODE string.
995 BSTR Name;
996 BSTR DocString;
997 BSTR HelpFile;
998 BSTR HelpStringDll;
999 DWORD dwHelpContext;
1000 int TypeInfoCount; /* nr of typeinfo's in librarry */
1001 struct tagITypeInfoImpl **typeinfos;
1002 struct list custdata_list;
1003 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
1004 int ctTypeDesc; /* number of items in type desc array */
1005 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1006 library. Only used while reading MSFT
1007 typelibs */
1008 struct list ref_list; /* list of ref types in this typelib */
1009 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1012 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1013 struct tagITypeLibImpl *next, *prev;
1014 WCHAR *path;
1015 INT index;
1016 } ITypeLibImpl;
1018 static const ITypeLib2Vtbl tlbvt;
1019 static const ITypeCompVtbl tlbtcvt;
1021 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1023 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
1026 /* ITypeLib methods */
1027 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1028 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1030 /*======================= ITypeInfo implementation =======================*/
1032 /* data for referenced types */
1033 typedef struct tagTLBRefType
1035 INT index; /* Type index for internal ref or for external ref
1036 it the format is SLTG. -2 indicates to
1037 use guid */
1039 GUID guid; /* guid of the referenced type */
1040 /* if index == TLB_REF_USE_GUID */
1042 HREFTYPE reference; /* The href of this ref */
1043 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1044 TLB_REF_INTERNAL for internal refs
1045 TLB_REF_NOT_FOUND for broken refs */
1047 struct list entry;
1048 } TLBRefType;
1050 #define TLB_REF_USE_GUID -2
1052 #define TLB_REF_INTERNAL (void*)-2
1053 #define TLB_REF_NOT_FOUND (void*)-1
1055 /* internal Parameter data */
1056 typedef struct tagTLBParDesc
1058 BSTR Name;
1059 struct list custdata_list;
1060 } TLBParDesc;
1062 /* internal Function data */
1063 typedef struct tagTLBFuncDesc
1065 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1066 BSTR Name; /* the name of this function */
1067 TLBParDesc *pParamDesc; /* array with param names and custom data */
1068 int helpcontext;
1069 int HelpStringContext;
1070 BSTR HelpString;
1071 BSTR Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1072 struct list custdata_list;
1073 } TLBFuncDesc;
1075 /* internal Variable data */
1076 typedef struct tagTLBVarDesc
1078 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1079 BSTR Name; /* the name of this variable */
1080 int HelpContext;
1081 int HelpStringContext;
1082 BSTR HelpString;
1083 struct list custdata_list;
1084 } TLBVarDesc;
1086 /* internal implemented interface data */
1087 typedef struct tagTLBImplType
1089 HREFTYPE hRef; /* hRef of interface */
1090 int implflags; /* IMPLFLAG_*s */
1091 struct list custdata_list;
1092 } TLBImplType;
1094 /* internal TypeInfo data */
1095 typedef struct tagITypeInfoImpl
1097 const ITypeInfo2Vtbl *lpVtbl;
1098 const ITypeCompVtbl *lpVtblTypeComp;
1099 LONG ref;
1100 BOOL not_attached_to_typelib;
1101 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1102 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1103 int index; /* index in this typelib; */
1104 HREFTYPE hreftype; /* hreftype for app object binding */
1105 /* type libs seem to store the doc strings in ascii
1106 * so why should we do it in unicode?
1108 BSTR Name;
1109 BSTR DocString;
1110 BSTR DllName;
1111 DWORD dwHelpContext;
1112 DWORD dwHelpStringContext;
1114 /* functions */
1115 TLBFuncDesc *funcdescs;
1117 /* variables */
1118 TLBVarDesc *vardescs;
1120 /* Implemented Interfaces */
1121 TLBImplType *impltypes;
1123 struct list custdata_list;
1124 } ITypeInfoImpl;
1126 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1128 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1131 static const ITypeInfo2Vtbl tinfvt;
1132 static const ITypeCompVtbl tcompvt;
1134 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1135 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1137 typedef struct tagTLBContext
1139 unsigned int oStart; /* start of TLB in file */
1140 unsigned int pos; /* current pos */
1141 unsigned int length; /* total length */
1142 void *mapping; /* memory mapping */
1143 MSFT_SegDir * pTblDir;
1144 ITypeLibImpl* pLibInfo;
1145 } TLBContext;
1148 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1151 debug
1153 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1154 if (pTD->vt & VT_RESERVED)
1155 szVarType += strlen(strcpy(szVarType, "reserved | "));
1156 if (pTD->vt & VT_BYREF)
1157 szVarType += strlen(strcpy(szVarType, "ref to "));
1158 if (pTD->vt & VT_ARRAY)
1159 szVarType += strlen(strcpy(szVarType, "array of "));
1160 if (pTD->vt & VT_VECTOR)
1161 szVarType += strlen(strcpy(szVarType, "vector of "));
1162 switch(pTD->vt & VT_TYPEMASK) {
1163 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1164 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1165 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1166 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1167 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1168 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1169 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1170 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1171 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1172 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1173 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1174 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1175 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1176 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1177 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1178 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1179 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1180 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1181 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1182 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1183 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1184 pTD->u.hreftype); break;
1185 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1186 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1187 case VT_PTR: sprintf(szVarType, "ptr to ");
1188 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1189 break;
1190 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1191 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1192 break;
1193 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1194 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1195 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1196 break;
1198 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1202 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1203 char buf[200];
1204 USHORT flags = edesc->u.paramdesc.wParamFlags;
1205 dump_TypeDesc(&edesc->tdesc,buf);
1206 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1207 MESSAGE("\t\tu.paramdesc.wParamFlags");
1208 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1209 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1210 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1211 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1212 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1213 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1214 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1215 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1216 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1218 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1219 int i;
1220 MESSAGE("memid is %08x\n",funcdesc->memid);
1221 for (i=0;i<funcdesc->cParams;i++) {
1222 MESSAGE("Param %d:\n",i);
1223 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1225 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1226 switch (funcdesc->funckind) {
1227 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1228 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1229 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1230 case FUNC_STATIC: MESSAGE("static");break;
1231 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1232 default: MESSAGE("unknown");break;
1234 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1235 switch (funcdesc->invkind) {
1236 case INVOKE_FUNC: MESSAGE("func");break;
1237 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1238 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1239 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1241 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1242 switch (funcdesc->callconv) {
1243 case CC_CDECL: MESSAGE("cdecl");break;
1244 case CC_PASCAL: MESSAGE("pascal");break;
1245 case CC_STDCALL: MESSAGE("stdcall");break;
1246 case CC_SYSCALL: MESSAGE("syscall");break;
1247 default:break;
1249 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1250 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1251 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1253 MESSAGE("\telemdescFunc (return value type):\n");
1254 dump_ELEMDESC(&funcdesc->elemdescFunc);
1257 static const char * const typekind_desc[] =
1259 "TKIND_ENUM",
1260 "TKIND_RECORD",
1261 "TKIND_MODULE",
1262 "TKIND_INTERFACE",
1263 "TKIND_DISPATCH",
1264 "TKIND_COCLASS",
1265 "TKIND_ALIAS",
1266 "TKIND_UNION",
1267 "TKIND_MAX"
1270 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1272 int i;
1273 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1274 for (i=0;i<pfd->funcdesc.cParams;i++)
1275 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1278 dump_FUNCDESC(&(pfd->funcdesc));
1280 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1281 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1283 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1285 while (n)
1287 dump_TLBFuncDescOne(pfd);
1288 ++pfd;
1289 --n;
1292 static void dump_TLBVarDesc(const TLBVarDesc * pvd, UINT n)
1294 while (n)
1296 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1297 ++pvd;
1298 --n;
1302 static void dump_TLBImpLib(const TLBImpLib *import)
1304 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1305 debugstr_w(import->name));
1306 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1307 import->wVersionMinor, import->lcid, import->offset);
1310 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1312 TLBRefType *ref;
1314 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1316 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1317 if(ref->index == -1)
1318 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1319 else
1320 TRACE_(typelib)("type no: %d\n", ref->index);
1322 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1324 TRACE_(typelib)("in lib\n");
1325 dump_TLBImpLib(ref->pImpTLInfo);
1330 static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1332 if(!impl)
1333 return;
1334 while (n) {
1335 TRACE_(typelib)("implementing/inheriting interface hRef = %x implflags %x\n",
1336 impl->hRef, impl->implflags);
1337 ++impl;
1338 --n;
1342 static void dump_Variant(const VARIANT * pvar)
1344 SYSTEMTIME st;
1346 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1348 if (pvar)
1350 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1351 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1353 TRACE(",%p", V_BYREF(pvar));
1355 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1357 TRACE(",%p", V_ARRAY(pvar));
1359 else switch (V_TYPE(pvar))
1361 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1362 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1363 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1364 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1365 case VT_INT:
1366 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1367 case VT_UINT:
1368 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1369 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1370 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1371 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1372 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1373 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1374 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1375 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1376 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1377 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1378 V_CY(pvar).s.Lo); break;
1379 case VT_DATE:
1380 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1381 TRACE(",<invalid>");
1382 else
1383 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1384 st.wHour, st.wMinute, st.wSecond);
1385 break;
1386 case VT_ERROR:
1387 case VT_VOID:
1388 case VT_USERDEFINED:
1389 case VT_EMPTY:
1390 case VT_NULL: break;
1391 default: TRACE(",?"); break;
1394 TRACE("}\n");
1397 static void dump_DispParms(const DISPPARAMS * pdp)
1399 unsigned int index;
1401 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1403 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1405 TRACE("named args:\n");
1406 for (index = 0; index < pdp->cNamedArgs; index++)
1407 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1410 if (pdp->cArgs && pdp->rgvarg)
1412 TRACE("args:\n");
1413 for (index = 0; index < pdp->cArgs; index++)
1414 dump_Variant( &pdp->rgvarg[index] );
1418 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1420 TRACE("%p ref=%u\n", pty, pty->ref);
1421 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1422 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1423 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1424 TRACE("fct:%u var:%u impl:%u\n",
1425 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1426 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1427 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1428 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1429 if (TRACE_ON(ole))
1430 dump_TLBFuncDesc(pty->funcdescs, pty->TypeAttr.cFuncs);
1431 dump_TLBVarDesc(pty->vardescs, pty->TypeAttr.cVars);
1432 dump_TLBImplType(pty->impltypes, pty->TypeAttr.cImplTypes);
1435 static void dump_VARDESC(const VARDESC *v)
1437 MESSAGE("memid %d\n",v->memid);
1438 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1439 MESSAGE("oInst %d\n",v->u.oInst);
1440 dump_ELEMDESC(&(v->elemdescVar));
1441 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1442 MESSAGE("varkind %d\n",v->varkind);
1445 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1447 /* VT_LPWSTR is largest type that, may appear in type description */
1448 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1449 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1450 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1451 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1452 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1453 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1454 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1455 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1458 static void TLB_abort(void)
1460 DebugBreak();
1463 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size)
1465 void *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
1466 if (!ret) ERR("cannot allocate memory\n");
1467 return ret;
1470 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size)
1472 void *ret = HeapAlloc(GetProcessHeap(), 0, size);
1473 if (!ret) ERR("cannot allocate memory\n");
1474 return ret;
1477 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr, unsigned size)
1479 return HeapReAlloc(GetProcessHeap(), 0, ptr, size);
1482 void heap_free(void *ptr)
1484 HeapFree(GetProcessHeap(), 0, ptr);
1487 /* returns the size required for a deep copy of a typedesc into a
1488 * flat buffer */
1489 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1491 SIZE_T size = 0;
1493 if (alloc_initial_space)
1494 size += sizeof(TYPEDESC);
1496 switch (tdesc->vt)
1498 case VT_PTR:
1499 case VT_SAFEARRAY:
1500 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1501 break;
1502 case VT_CARRAY:
1503 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1504 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1505 break;
1507 return size;
1510 /* deep copy a typedesc into a flat buffer */
1511 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1513 if (!dest)
1515 dest = buffer;
1516 buffer = (char *)buffer + sizeof(TYPEDESC);
1519 *dest = *src;
1521 switch (src->vt)
1523 case VT_PTR:
1524 case VT_SAFEARRAY:
1525 dest->u.lptdesc = buffer;
1526 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1527 break;
1528 case VT_CARRAY:
1529 dest->u.lpadesc = buffer;
1530 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1531 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1532 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1533 break;
1535 return buffer;
1538 /* free custom data allocated by MSFT_CustData */
1539 static inline void TLB_FreeCustData(struct list *custdata_list)
1541 TLBCustData *cd, *cdn;
1542 LIST_FOR_EACH_ENTRY_SAFE(cd, cdn, custdata_list, TLBCustData, entry)
1544 list_remove(&cd->entry);
1545 VariantClear(&cd->data);
1546 heap_free(cd);
1550 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1552 DWORD len;
1553 BSTR ret;
1555 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1556 ret = SysAllocStringLen(NULL, len - 1);
1557 if (!ret) return ret;
1558 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1559 return ret;
1562 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(TLBFuncDesc *funcdescs,
1563 UINT n, MEMBERID memid)
1565 while(n){
1566 if(funcdescs->funcdesc.memid == memid)
1567 return funcdescs;
1568 ++funcdescs;
1569 --n;
1571 return NULL;
1574 static inline TLBFuncDesc *TLB_get_funcdesc_by_name(TLBFuncDesc *funcdescs,
1575 UINT n, const OLECHAR *name)
1577 while(n){
1578 if(!lstrcmpiW(funcdescs->Name, name))
1579 return funcdescs;
1580 ++funcdescs;
1581 --n;
1583 return NULL;
1586 static inline TLBVarDesc *TLB_get_vardesc_by_memberid(TLBVarDesc *vardescs,
1587 UINT n, MEMBERID memid)
1589 while(n){
1590 if(vardescs->vardesc.memid == memid)
1591 return vardescs;
1592 ++vardescs;
1593 --n;
1595 return NULL;
1598 static inline TLBVarDesc *TLB_get_vardesc_by_name(TLBVarDesc *vardescs,
1599 UINT n, const OLECHAR *name)
1601 while(n){
1602 if(!lstrcmpiW(vardescs->Name, name))
1603 return vardescs;
1604 ++vardescs;
1605 --n;
1607 return NULL;
1610 static inline TLBCustData *TLB_get_custdata_by_guid(struct list *custdata_list, REFGUID guid)
1612 TLBCustData *cust_data;
1613 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1614 if(IsEqualIID(&cust_data->guid, guid))
1615 return cust_data;
1616 return NULL;
1619 static TLBVarDesc *TLBVarDesc_Constructor(UINT n)
1621 TLBVarDesc *ret;
1623 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1624 if(!ret)
1625 return NULL;
1627 while(n){
1628 list_init(&ret[n-1].custdata_list);
1629 --n;
1632 return ret;
1635 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1637 TLBParDesc *ret;
1639 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1640 if(!ret)
1641 return NULL;
1643 while(n){
1644 list_init(&ret[n-1].custdata_list);
1645 --n;
1648 return ret;
1651 static TLBFuncDesc *TLBFuncDesc_Constructor(UINT n)
1653 TLBFuncDesc *ret;
1655 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1656 if(!ret)
1657 return NULL;
1659 while(n){
1660 list_init(&ret[n-1].custdata_list);
1661 --n;
1664 return ret;
1667 static TLBImplType *TLBImplType_Constructor(UINT n)
1669 TLBImplType *ret;
1671 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1672 if(!ret)
1673 return NULL;
1675 while(n){
1676 list_init(&ret[n-1].custdata_list);
1677 --n;
1680 return ret;
1683 /**********************************************************************
1685 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1687 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1689 return pcx->pos;
1692 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
1694 if (where != DO_NOT_SEEK)
1696 where += pcx->oStart;
1697 if (where > pcx->length)
1699 /* FIXME */
1700 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
1701 TLB_abort();
1703 pcx->pos = where;
1707 /* read function */
1708 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
1710 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
1711 pcx->pos, count, pcx->oStart, pcx->length, where);
1713 MSFT_Seek(pcx, where);
1714 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1715 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1716 pcx->pos += count;
1717 return count;
1720 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1721 LONG where )
1723 DWORD ret;
1725 ret = MSFT_Read(buffer, count, pcx, where);
1726 FromLEDWords(buffer, ret);
1728 return ret;
1731 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1732 LONG where )
1734 DWORD ret;
1736 ret = MSFT_Read(buffer, count, pcx, where);
1737 FromLEWords(buffer, ret);
1739 return ret;
1742 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1744 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1745 memset(pGuid,0, sizeof(GUID));
1746 return;
1748 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1749 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1750 pGuid->Data2 = FromLEWord(pGuid->Data2);
1751 pGuid->Data3 = FromLEWord(pGuid->Data3);
1752 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1755 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1757 MSFT_NameIntro niName;
1759 if (offset < 0)
1761 ERR_(typelib)("bad offset %d\n", offset);
1762 return -1;
1765 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1766 pcx->pTblDir->pNametab.offset+offset);
1768 return niName.hreftype;
1771 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1773 char * name;
1774 MSFT_NameIntro niName;
1775 int lengthInChars;
1776 BSTR bstrName = NULL;
1778 if (offset < 0)
1780 ERR_(typelib)("bad offset %d\n", offset);
1781 return NULL;
1783 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1784 pcx->pTblDir->pNametab.offset+offset);
1785 niName.namelen &= 0xFF; /* FIXME: correct ? */
1786 name = heap_alloc_zero((niName.namelen & 0xff) +1);
1787 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1788 name[niName.namelen & 0xff]='\0';
1790 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1791 name, -1, NULL, 0);
1793 /* no invalid characters in string */
1794 if (lengthInChars)
1796 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1798 /* don't check for invalid character since this has been done previously */
1799 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1801 heap_free(name);
1803 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1804 return bstrName;
1807 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1809 char * string;
1810 INT16 length;
1811 int lengthInChars;
1812 BSTR bstr = NULL;
1814 if(offset<0) return NULL;
1815 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1816 if(length <= 0) return 0;
1817 string = heap_alloc_zero(length +1);
1818 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1819 string[length]='\0';
1821 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1822 string, -1, NULL, 0);
1824 /* no invalid characters in string */
1825 if (lengthInChars)
1827 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1829 /* don't check for invalid character since this has been done previously */
1830 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1832 heap_free(string);
1834 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1835 return bstr;
1838 * read a value and fill a VARIANT structure
1840 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1842 int size;
1844 TRACE_(typelib)("\n");
1846 if(offset <0) { /* data are packed in here */
1847 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1848 V_I4(pVar) = offset & 0x3ffffff;
1849 return;
1851 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1852 pcx->pTblDir->pCustData.offset + offset );
1853 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1854 switch (V_VT(pVar)){
1855 case VT_EMPTY: /* FIXME: is this right? */
1856 case VT_NULL: /* FIXME: is this right? */
1857 case VT_I2 : /* this should not happen */
1858 case VT_I4 :
1859 case VT_R4 :
1860 case VT_ERROR :
1861 case VT_BOOL :
1862 case VT_I1 :
1863 case VT_UI1 :
1864 case VT_UI2 :
1865 case VT_UI4 :
1866 case VT_INT :
1867 case VT_UINT :
1868 case VT_VOID : /* FIXME: is this right? */
1869 case VT_HRESULT :
1870 size=4; break;
1871 case VT_R8 :
1872 case VT_CY :
1873 case VT_DATE :
1874 case VT_I8 :
1875 case VT_UI8 :
1876 case VT_DECIMAL : /* FIXME: is this right? */
1877 case VT_FILETIME :
1878 size=8;break;
1879 /* pointer types with known behaviour */
1880 case VT_BSTR :{
1881 char * ptr;
1882 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1883 if(size < 0) {
1884 char next;
1885 DWORD origPos = MSFT_Tell(pcx), nullPos;
1887 do {
1888 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1889 } while (next);
1890 nullPos = MSFT_Tell(pcx);
1891 size = nullPos - origPos;
1892 MSFT_Seek(pcx, origPos);
1894 ptr = heap_alloc_zero(size);/* allocate temp buffer */
1895 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1896 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1897 /* FIXME: do we need a AtoW conversion here? */
1898 V_UNION(pVar, bstrVal[size])='\0';
1899 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1900 heap_free(ptr);
1902 size=-4; break;
1903 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1904 case VT_DISPATCH :
1905 case VT_VARIANT :
1906 case VT_UNKNOWN :
1907 case VT_PTR :
1908 case VT_SAFEARRAY :
1909 case VT_CARRAY :
1910 case VT_USERDEFINED :
1911 case VT_LPSTR :
1912 case VT_LPWSTR :
1913 case VT_BLOB :
1914 case VT_STREAM :
1915 case VT_STORAGE :
1916 case VT_STREAMED_OBJECT :
1917 case VT_STORED_OBJECT :
1918 case VT_BLOB_OBJECT :
1919 case VT_CF :
1920 case VT_CLSID :
1921 default:
1922 size=0;
1923 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1924 V_VT(pVar));
1927 if(size>0) /* (big|small) endian correct? */
1928 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1929 return;
1932 * create a linked list with custom data
1934 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
1936 MSFT_CDGuid entry;
1937 TLBCustData* pNew;
1938 int count=0;
1940 TRACE_(typelib)("\n");
1942 while(offset >=0){
1943 count++;
1944 pNew=heap_alloc_zero(sizeof(TLBCustData));
1945 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1946 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1947 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1948 list_add_head(custdata_list, &pNew->entry);
1949 offset = entry.next;
1951 return count;
1954 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1955 ITypeInfoImpl *pTI)
1957 if(type <0)
1958 pTd->vt=type & VT_TYPEMASK;
1959 else
1960 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1962 if(pTd->vt == VT_USERDEFINED)
1963 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1965 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1968 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1970 /* resolve referenced type if any */
1971 while (lpTypeDesc)
1973 switch (lpTypeDesc->vt)
1975 case VT_PTR:
1976 lpTypeDesc = lpTypeDesc->u.lptdesc;
1977 break;
1979 case VT_CARRAY:
1980 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1981 break;
1983 case VT_USERDEFINED:
1984 MSFT_DoRefType(pcx, pTI->pTypeLib,
1985 lpTypeDesc->u.hreftype);
1987 lpTypeDesc = NULL;
1988 break;
1990 default:
1991 lpTypeDesc = NULL;
1996 static void
1997 MSFT_DoFuncs(TLBContext* pcx,
1998 ITypeInfoImpl* pTI,
1999 int cFuncs,
2000 int cVars,
2001 int offset,
2002 TLBFuncDesc** pptfd)
2005 * member information is stored in a data structure at offset
2006 * indicated by the memoffset field of the typeinfo structure
2007 * There are several distinctive parts.
2008 * The first part starts with a field that holds the total length
2009 * of this (first) part excluding this field. Then follow the records,
2010 * for each member there is one record.
2012 * The first entry is always the length of the record (including this
2013 * length word).
2014 * The rest of the record depends on the type of the member. If there is
2015 * a field indicating the member type (function, variable, interface, etc)
2016 * I have not found it yet. At this time we depend on the information
2017 * in the type info and the usual order how things are stored.
2019 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2020 * for each member;
2022 * Third is an equal sized array with file offsets to the name entry
2023 * of each member.
2025 * The fourth and last (?) part is an array with offsets to the records
2026 * in the first part of this file segment.
2029 int infolen, nameoffset, reclength, i;
2030 int recoffset = offset + sizeof(INT);
2032 char *recbuf = heap_alloc(0xffff);
2033 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2034 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2036 TRACE_(typelib)("\n");
2038 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2040 *pptfd = TLBFuncDesc_Constructor(cFuncs);
2041 ptfd = *pptfd;
2042 for ( i = 0; i < cFuncs ; i++ )
2044 int optional;
2046 /* name, eventually add to a hash table */
2047 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2048 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2050 /* nameoffset is sometimes -1 on the second half of a propget/propput
2051 * pair of functions */
2052 if ((nameoffset == -1) && (i > 0))
2053 ptfd->Name = SysAllocString(ptfd_prev->Name);
2054 else
2055 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2057 /* read the function information record */
2058 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2060 reclength &= 0xffff;
2062 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2064 /* size without argument data */
2065 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2067 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2068 ptfd->helpcontext = pFuncRec->HelpContext;
2070 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2071 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2073 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2075 if (pFuncRec->FKCCIC & 0x2000 )
2077 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2078 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2079 ptfd->Entry = (BSTR)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2081 else
2082 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2084 else
2085 ptfd->Entry = (BSTR)-1;
2087 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2088 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2090 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2091 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2093 /* fill the FuncDesc Structure */
2094 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2095 offset + infolen + ( i + 1) * sizeof(INT));
2097 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2098 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2099 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2100 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2101 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2102 ptfd->funcdesc.oVft = pFuncRec->VtableOffset & ~1;
2103 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2105 MSFT_GetTdesc(pcx,
2106 pFuncRec->DataType,
2107 &ptfd->funcdesc.elemdescFunc.tdesc,
2108 pTI);
2109 MSFT_ResolveReferencedTypes(pcx, pTI, &ptfd->funcdesc.elemdescFunc.tdesc);
2111 /* do the parameters/arguments */
2112 if(pFuncRec->nrargs)
2114 int j = 0;
2115 MSFT_ParameterInfo paraminfo;
2117 ptfd->funcdesc.lprgelemdescParam =
2118 heap_alloc_zero(pFuncRec->nrargs * sizeof(ELEMDESC));
2120 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2122 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2123 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2125 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2127 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2129 MSFT_GetTdesc(pcx,
2130 paraminfo.DataType,
2131 &elemdesc->tdesc,
2132 pTI);
2134 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2136 /* name */
2137 if (paraminfo.oName == -1)
2138 /* this occurs for [propput] or [propget] methods, so
2139 * we should just set the name of the parameter to the
2140 * name of the method. */
2141 ptfd->pParamDesc[j].Name = SysAllocString(ptfd->Name);
2142 else
2143 ptfd->pParamDesc[j].Name =
2144 MSFT_ReadName( pcx, paraminfo.oName );
2145 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(ptfd->pParamDesc[j].Name));
2147 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
2149 /* default value */
2150 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2151 (pFuncRec->FKCCIC & 0x1000) )
2153 INT* pInt = (INT *)((char *)pFuncRec +
2154 reclength -
2155 (pFuncRec->nrargs * 4) * sizeof(INT) );
2157 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2159 pParamDesc->pparamdescex = heap_alloc_zero(sizeof(PARAMDESCEX));
2160 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2162 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2163 pInt[j], pcx);
2165 else
2166 elemdesc->u.paramdesc.pparamdescex = NULL;
2168 /* custom info */
2169 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2170 j*sizeof(pFuncRec->oArgCustData[0])) &&
2171 pFuncRec->FKCCIC & 0x80 )
2173 MSFT_CustData(pcx,
2174 pFuncRec->oArgCustData[j],
2175 &ptfd->pParamDesc[j].custdata_list);
2178 /* SEEK value = jump to offset,
2179 * from there jump to the end of record,
2180 * go back by (j-1) arguments
2182 MSFT_ReadLEDWords( &paraminfo ,
2183 sizeof(MSFT_ParameterInfo), pcx,
2184 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2185 * sizeof(MSFT_ParameterInfo)));
2189 /* scode is not used: archaic win16 stuff FIXME: right? */
2190 ptfd->funcdesc.cScodes = 0 ;
2191 ptfd->funcdesc.lprgscode = NULL ;
2193 ptfd_prev = ptfd;
2194 ++ptfd;
2195 recoffset += reclength;
2197 heap_free(recbuf);
2200 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2201 int cVars, int offset, TLBVarDesc ** pptvd)
2203 int infolen, nameoffset, reclength;
2204 char recbuf[256];
2205 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2206 TLBVarDesc *ptvd;
2207 int i;
2208 int recoffset;
2210 TRACE_(typelib)("\n");
2212 ptvd = *pptvd = TLBVarDesc_Constructor(cVars);
2213 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2214 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2215 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2216 recoffset += offset+sizeof(INT);
2217 for(i=0;i<cVars;i++, ++ptvd){
2218 /* name, eventually add to a hash table */
2219 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2220 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2221 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2222 /* read the variable information record */
2223 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2224 reclength &= 0xff;
2225 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2227 /* optional data */
2228 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2229 ptvd->HelpContext = pVarRec->HelpContext;
2231 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2232 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2234 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2235 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2237 /* fill the VarDesc Structure */
2238 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2239 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2240 ptvd->vardesc.varkind = pVarRec->VarKind;
2241 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2242 MSFT_GetTdesc(pcx, pVarRec->DataType,
2243 &ptvd->vardesc.elemdescVar.tdesc, pTI);
2244 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2245 if(pVarRec->VarKind == VAR_CONST ){
2246 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2247 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2248 pVarRec->OffsValue, pcx);
2249 } else
2250 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2251 MSFT_ResolveReferencedTypes(pcx, pTI, &ptvd->vardesc.elemdescVar.tdesc);
2252 recoffset += reclength;
2256 /* fill in data for a hreftype (offset). When the referenced type is contained
2257 * in the typelib, it's just an (file) offset in the type info base dir.
2258 * If comes from import, it's an offset+1 in the ImpInfo table
2259 * */
2260 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2261 int offset)
2263 TLBRefType *ref;
2265 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2267 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2269 if(ref->reference == offset) return;
2272 ref = heap_alloc_zero(sizeof(TLBRefType));
2273 list_add_tail(&pTL->ref_list, &ref->entry);
2275 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2276 /* external typelib */
2277 MSFT_ImpInfo impinfo;
2278 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2280 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2282 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2283 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2284 while (pImpLib){ /* search the known offsets of all import libraries */
2285 if(pImpLib->offset==impinfo.oImpFile) break;
2286 pImpLib=pImpLib->next;
2288 if(pImpLib){
2289 ref->reference = offset;
2290 ref->pImpTLInfo = pImpLib;
2291 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2292 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2293 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2294 ref->index = TLB_REF_USE_GUID;
2295 } else
2296 ref->index = impinfo.oGuid;
2297 }else{
2298 ERR("Cannot find a reference\n");
2299 ref->reference = -1;
2300 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2302 }else{
2303 /* in this typelib */
2304 ref->index = MSFT_HREFTYPE_INDEX(offset);
2305 ref->reference = offset;
2306 ref->pImpTLInfo = TLB_REF_INTERNAL;
2310 /* process Implemented Interfaces of a com class */
2311 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2312 int offset)
2314 int i;
2315 MSFT_RefRecord refrec;
2316 TLBImplType *pImpl;
2318 TRACE_(typelib)("\n");
2320 pTI->impltypes = TLBImplType_Constructor(count);
2321 pImpl = pTI->impltypes;
2322 for(i=0;i<count;i++){
2323 if(offset<0) break; /* paranoia */
2324 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2325 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2326 pImpl->hRef = refrec.reftype;
2327 pImpl->implflags=refrec.flags;
2328 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2329 offset=refrec.onext;
2330 ++pImpl;
2334 * process a typeinfo record
2336 static ITypeInfoImpl * MSFT_DoTypeInfo(
2337 TLBContext *pcx,
2338 int count,
2339 ITypeLibImpl * pLibInfo)
2341 MSFT_TypeInfoBase tiBase;
2342 ITypeInfoImpl *ptiRet;
2344 TRACE_(typelib)("count=%u\n", count);
2346 ptiRet = ITypeInfoImpl_Constructor();
2347 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2348 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2350 /* this is where we are coming from */
2351 ptiRet->pTypeLib = pLibInfo;
2352 ptiRet->index=count;
2353 /* fill in the typeattr fields */
2355 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2356 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2357 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2358 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2359 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2360 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2361 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2362 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2363 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2364 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2365 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2366 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2367 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2368 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2369 MSFT_GetTdesc(pcx, tiBase.datatype1,
2370 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2372 /* FIXME: */
2373 /* IDLDESC idldescType; *//* never saw this one != zero */
2375 /* name, eventually add to a hash table */
2376 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2377 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2378 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2379 /* help info */
2380 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2381 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2382 ptiRet->dwHelpContext=tiBase.helpcontext;
2384 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2385 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2387 /* note: InfoType's Help file and HelpStringDll come from the containing
2388 * library. Further HelpString and Docstring appear to be the same thing :(
2390 /* functions */
2391 if(ptiRet->TypeAttr.cFuncs >0 )
2392 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2393 ptiRet->TypeAttr.cVars,
2394 tiBase.memoffset, &ptiRet->funcdescs);
2395 /* variables */
2396 if(ptiRet->TypeAttr.cVars >0 )
2397 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2398 ptiRet->TypeAttr.cVars,
2399 tiBase.memoffset, &ptiRet->vardescs);
2400 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2401 switch(ptiRet->TypeAttr.typekind)
2403 case TKIND_COCLASS:
2404 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2405 tiBase.datatype1);
2406 break;
2407 case TKIND_DISPATCH:
2408 /* This is not -1 when the interface is a non-base dual interface or
2409 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2410 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2411 not this interface.
2414 if (tiBase.datatype1 != -1)
2416 ptiRet->impltypes = TLBImplType_Constructor(1);
2417 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2418 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2420 break;
2421 default:
2422 ptiRet->impltypes = TLBImplType_Constructor(1);
2423 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2424 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2425 break;
2428 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->custdata_list);
2430 TRACE_(typelib)("%s guid: %s kind:%s\n",
2431 debugstr_w(ptiRet->Name),
2432 debugstr_guid(&ptiRet->TypeAttr.guid),
2433 typekind_desc[ptiRet->TypeAttr.typekind]);
2434 if (TRACE_ON(typelib))
2435 dump_TypeInfo(ptiRet);
2437 return ptiRet;
2440 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2441 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2442 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2443 * tradeoff here.
2445 static ITypeLibImpl *tlb_cache_first;
2446 static CRITICAL_SECTION cache_section;
2447 static CRITICAL_SECTION_DEBUG cache_section_debug =
2449 0, 0, &cache_section,
2450 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2451 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2453 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2456 typedef struct TLB_PEFile
2458 const IUnknownVtbl *lpvtbl;
2459 LONG refs;
2460 HMODULE dll;
2461 HRSRC typelib_resource;
2462 HGLOBAL typelib_global;
2463 LPVOID typelib_base;
2464 } TLB_PEFile;
2466 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2468 if (IsEqualIID(riid, &IID_IUnknown))
2470 *ppv = iface;
2471 IUnknown_AddRef(iface);
2472 return S_OK;
2474 *ppv = NULL;
2475 return E_NOINTERFACE;
2478 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2480 TLB_PEFile *This = (TLB_PEFile *)iface;
2481 return InterlockedIncrement(&This->refs);
2484 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2486 TLB_PEFile *This = (TLB_PEFile *)iface;
2487 ULONG refs = InterlockedDecrement(&This->refs);
2488 if (!refs)
2490 if (This->typelib_global)
2491 FreeResource(This->typelib_global);
2492 if (This->dll)
2493 FreeLibrary(This->dll);
2494 heap_free(This);
2496 return refs;
2499 static const IUnknownVtbl TLB_PEFile_Vtable =
2501 TLB_PEFile_QueryInterface,
2502 TLB_PEFile_AddRef,
2503 TLB_PEFile_Release
2506 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2508 TLB_PEFile *This;
2510 This = heap_alloc(sizeof(TLB_PEFile));
2511 if (!This)
2512 return E_OUTOFMEMORY;
2514 This->lpvtbl = &TLB_PEFile_Vtable;
2515 This->refs = 1;
2516 This->dll = NULL;
2517 This->typelib_resource = NULL;
2518 This->typelib_global = NULL;
2519 This->typelib_base = NULL;
2521 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2522 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2524 if (This->dll)
2526 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2527 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2528 if (This->typelib_resource)
2530 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2531 if (This->typelib_global)
2533 This->typelib_base = LockResource(This->typelib_global);
2535 if (This->typelib_base)
2537 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2538 *ppBase = This->typelib_base;
2539 *ppFile = (IUnknown *)&This->lpvtbl;
2540 return S_OK;
2546 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2547 return TYPE_E_CANTLOADLIBRARY;
2550 typedef struct TLB_NEFile
2552 const IUnknownVtbl *lpvtbl;
2553 LONG refs;
2554 LPVOID typelib_base;
2555 } TLB_NEFile;
2557 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2559 if (IsEqualIID(riid, &IID_IUnknown))
2561 *ppv = iface;
2562 IUnknown_AddRef(iface);
2563 return S_OK;
2565 *ppv = NULL;
2566 return E_NOINTERFACE;
2569 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2571 TLB_NEFile *This = (TLB_NEFile *)iface;
2572 return InterlockedIncrement(&This->refs);
2575 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2577 TLB_NEFile *This = (TLB_NEFile *)iface;
2578 ULONG refs = InterlockedDecrement(&This->refs);
2579 if (!refs)
2581 heap_free(This->typelib_base);
2582 heap_free(This);
2584 return refs;
2587 static const IUnknownVtbl TLB_NEFile_Vtable =
2589 TLB_NEFile_QueryInterface,
2590 TLB_NEFile_AddRef,
2591 TLB_NEFile_Release
2594 /***********************************************************************
2595 * read_xx_header [internal]
2597 static int read_xx_header( HFILE lzfd )
2599 IMAGE_DOS_HEADER mzh;
2600 char magic[3];
2602 LZSeek( lzfd, 0, SEEK_SET );
2603 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2604 return 0;
2605 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2606 return 0;
2608 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2609 if ( 2 != LZRead( lzfd, magic, 2 ) )
2610 return 0;
2612 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2614 if ( magic[0] == 'N' && magic[1] == 'E' )
2615 return IMAGE_OS2_SIGNATURE;
2616 if ( magic[0] == 'P' && magic[1] == 'E' )
2617 return IMAGE_NT_SIGNATURE;
2619 magic[2] = '\0';
2620 WARN("Can't handle %s files.\n", magic );
2621 return 0;
2625 /***********************************************************************
2626 * find_ne_resource [internal]
2628 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2629 DWORD *resLen, DWORD *resOff )
2631 IMAGE_OS2_HEADER nehd;
2632 NE_TYPEINFO *typeInfo;
2633 NE_NAMEINFO *nameInfo;
2634 DWORD nehdoffset;
2635 LPBYTE resTab;
2636 DWORD resTabSize;
2637 int count;
2639 /* Read in NE header */
2640 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2641 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2643 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2644 if ( !resTabSize )
2646 TRACE("No resources in NE dll\n" );
2647 return FALSE;
2650 /* Read in resource table */
2651 resTab = heap_alloc( resTabSize );
2652 if ( !resTab ) return FALSE;
2654 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2655 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2657 heap_free( resTab );
2658 return FALSE;
2661 /* Find resource */
2662 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2664 if (!IS_INTRESOURCE(typeid)) /* named type */
2666 BYTE len = strlen( typeid );
2667 while (typeInfo->type_id)
2669 if (!(typeInfo->type_id & 0x8000))
2671 BYTE *p = resTab + typeInfo->type_id;
2672 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2674 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2675 typeInfo->count * sizeof(NE_NAMEINFO));
2678 else /* numeric type id */
2680 WORD id = LOWORD(typeid) | 0x8000;
2681 while (typeInfo->type_id)
2683 if (typeInfo->type_id == id) goto found_type;
2684 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2685 typeInfo->count * sizeof(NE_NAMEINFO));
2688 TRACE("No typeid entry found for %p\n", typeid );
2689 heap_free( resTab );
2690 return FALSE;
2692 found_type:
2693 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2695 if (!IS_INTRESOURCE(resid)) /* named resource */
2697 BYTE len = strlen( resid );
2698 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2700 BYTE *p = resTab + nameInfo->id;
2701 if (nameInfo->id & 0x8000) continue;
2702 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2705 else /* numeric resource id */
2707 WORD id = LOWORD(resid) | 0x8000;
2708 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2709 if (nameInfo->id == id) goto found_name;
2711 TRACE("No resid entry found for %p\n", typeid );
2712 heap_free( resTab );
2713 return FALSE;
2715 found_name:
2716 /* Return resource data */
2717 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2718 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2720 heap_free( resTab );
2721 return TRUE;
2724 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
2726 HFILE lzfd = -1;
2727 OFSTRUCT ofs;
2728 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2729 TLB_NEFile *This;
2731 This = heap_alloc(sizeof(TLB_NEFile));
2732 if (!This) return E_OUTOFMEMORY;
2734 This->lpvtbl = &TLB_NEFile_Vtable;
2735 This->refs = 1;
2736 This->typelib_base = NULL;
2738 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
2739 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
2741 DWORD reslen, offset;
2742 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
2744 This->typelib_base = heap_alloc(reslen);
2745 if( !This->typelib_base )
2746 hr = E_OUTOFMEMORY;
2747 else
2749 LZSeek( lzfd, offset, SEEK_SET );
2750 reslen = LZRead( lzfd, This->typelib_base, reslen );
2751 LZClose( lzfd );
2752 *ppBase = This->typelib_base;
2753 *pdwTLBLength = reslen;
2754 *ppFile = (IUnknown *)&This->lpvtbl;
2755 return S_OK;
2760 if( lzfd >= 0) LZClose( lzfd );
2761 TLB_NEFile_Release((IUnknown *)&This->lpvtbl);
2762 return hr;
2765 typedef struct TLB_Mapping
2767 const IUnknownVtbl *lpvtbl;
2768 LONG refs;
2769 HANDLE file;
2770 HANDLE mapping;
2771 LPVOID typelib_base;
2772 } TLB_Mapping;
2774 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2776 if (IsEqualIID(riid, &IID_IUnknown))
2778 *ppv = iface;
2779 IUnknown_AddRef(iface);
2780 return S_OK;
2782 *ppv = NULL;
2783 return E_NOINTERFACE;
2786 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2788 TLB_Mapping *This = (TLB_Mapping *)iface;
2789 return InterlockedIncrement(&This->refs);
2792 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2794 TLB_Mapping *This = (TLB_Mapping *)iface;
2795 ULONG refs = InterlockedDecrement(&This->refs);
2796 if (!refs)
2798 if (This->typelib_base)
2799 UnmapViewOfFile(This->typelib_base);
2800 if (This->mapping)
2801 CloseHandle(This->mapping);
2802 if (This->file != INVALID_HANDLE_VALUE)
2803 CloseHandle(This->file);
2804 heap_free(This);
2806 return refs;
2809 static const IUnknownVtbl TLB_Mapping_Vtable =
2811 TLB_Mapping_QueryInterface,
2812 TLB_Mapping_AddRef,
2813 TLB_Mapping_Release
2816 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2818 TLB_Mapping *This;
2820 This = heap_alloc(sizeof(TLB_Mapping));
2821 if (!This)
2822 return E_OUTOFMEMORY;
2824 This->lpvtbl = &TLB_Mapping_Vtable;
2825 This->refs = 1;
2826 This->file = INVALID_HANDLE_VALUE;
2827 This->mapping = NULL;
2828 This->typelib_base = NULL;
2830 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2831 if (INVALID_HANDLE_VALUE != This->file)
2833 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2834 if (This->mapping)
2836 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2837 if(This->typelib_base)
2839 /* retrieve file size */
2840 *pdwTLBLength = GetFileSize(This->file, NULL);
2841 *ppBase = This->typelib_base;
2842 *ppFile = (IUnknown *)&This->lpvtbl;
2843 return S_OK;
2848 IUnknown_Release((IUnknown *)&This->lpvtbl);
2849 return TYPE_E_CANTLOADLIBRARY;
2852 /****************************************************************************
2853 * TLB_ReadTypeLib
2855 * find the type of the typelib file and map the typelib resource into
2856 * the memory
2859 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2860 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2862 ITypeLibImpl *entry;
2863 HRESULT ret;
2864 INT index = 1;
2865 LPWSTR index_str, file = (LPWSTR)pszFileName;
2866 LPVOID pBase = NULL;
2867 DWORD dwTLBLength = 0;
2868 IUnknown *pFile = NULL;
2870 *ppTypeLib = NULL;
2872 index_str = strrchrW(pszFileName, '\\');
2873 if(index_str && *++index_str != '\0')
2875 LPWSTR end_ptr;
2876 LONG idx = strtolW(index_str, &end_ptr, 10);
2877 if(*end_ptr == '\0')
2879 int str_len = index_str - pszFileName - 1;
2880 index = idx;
2881 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
2882 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2883 file[str_len] = 0;
2887 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2889 if(strchrW(file, '\\'))
2891 lstrcpyW(pszPath, file);
2893 else
2895 int len = GetSystemDirectoryW(pszPath, cchPath);
2896 pszPath[len] = '\\';
2897 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2901 if(file != pszFileName) heap_free(file);
2903 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2905 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2906 EnterCriticalSection(&cache_section);
2907 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2909 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2911 TRACE("cache hit\n");
2912 *ppTypeLib = (ITypeLib2*)entry;
2913 ITypeLib_AddRef(*ppTypeLib);
2914 LeaveCriticalSection(&cache_section);
2915 return S_OK;
2918 LeaveCriticalSection(&cache_section);
2920 /* now actually load and parse the typelib */
2922 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2923 if (ret == TYPE_E_CANTLOADLIBRARY)
2924 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2925 if (ret == TYPE_E_CANTLOADLIBRARY)
2926 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2927 if (SUCCEEDED(ret))
2929 if (dwTLBLength >= 4)
2931 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2932 if (dwSignature == MSFT_SIGNATURE)
2933 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2934 else if (dwSignature == SLTG_SIGNATURE)
2935 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2936 else
2938 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2939 ret = TYPE_E_CANTLOADLIBRARY;
2942 else
2943 ret = TYPE_E_CANTLOADLIBRARY;
2944 IUnknown_Release(pFile);
2947 if(*ppTypeLib) {
2948 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2950 TRACE("adding to cache\n");
2951 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
2952 lstrcpyW(impl->path, pszPath);
2953 /* We should really canonicalise the path here. */
2954 impl->index = index;
2956 /* FIXME: check if it has added already in the meantime */
2957 EnterCriticalSection(&cache_section);
2958 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2959 impl->prev = NULL;
2960 tlb_cache_first = impl;
2961 LeaveCriticalSection(&cache_section);
2962 ret = S_OK;
2963 } else
2964 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2966 return ret;
2969 /*================== ITypeLib(2) Methods ===================================*/
2971 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2973 ITypeLibImpl* pTypeLibImpl;
2975 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
2976 if (!pTypeLibImpl) return NULL;
2978 pTypeLibImpl->lpVtbl = &tlbvt;
2979 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2980 pTypeLibImpl->ref = 1;
2982 list_init(&pTypeLibImpl->custdata_list);
2983 list_init(&pTypeLibImpl->ref_list);
2984 pTypeLibImpl->dispatch_href = -1;
2986 return pTypeLibImpl;
2989 /****************************************************************************
2990 * ITypeLib2_Constructor_MSFT
2992 * loading an MSFT typelib from an in-memory image
2994 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2996 TLBContext cx;
2997 LONG lPSegDir;
2998 MSFT_Header tlbHeader;
2999 MSFT_SegDir tlbSegDir;
3000 ITypeLibImpl * pTypeLibImpl;
3002 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3004 pTypeLibImpl = TypeLibImpl_Constructor();
3005 if (!pTypeLibImpl) return NULL;
3007 /* get pointer to beginning of typelib data */
3008 cx.pos = 0;
3009 cx.oStart=0;
3010 cx.mapping = pLib;
3011 cx.pLibInfo = pTypeLibImpl;
3012 cx.length = dwTLBLength;
3014 /* read header */
3015 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
3016 TRACE_(typelib)("header:\n");
3017 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3018 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3019 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3020 return NULL;
3022 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3024 /* there is a small amount of information here until the next important
3025 * part:
3026 * the segment directory . Try to calculate the amount of data */
3027 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3029 /* now read the segment directory */
3030 TRACE("read segment directory (at %d)\n",lPSegDir);
3031 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3032 cx.pTblDir = &tlbSegDir;
3034 /* just check two entries */
3035 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3037 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3038 heap_free(pTypeLibImpl);
3039 return NULL;
3042 /* now fill our internal data */
3043 /* TLIBATTR fields */
3044 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
3046 pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid2;
3047 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3048 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
3049 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
3050 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
3052 pTypeLibImpl->lcid = tlbHeader.lcid;
3054 /* name, eventually add to a hash table */
3055 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3057 /* help info */
3058 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3059 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3061 if( tlbHeader.varflags & HELPDLLFLAG)
3063 int offset;
3064 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3065 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3068 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3070 /* custom data */
3071 if(tlbHeader.CustomDataOffset >= 0)
3073 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3076 /* fill in type descriptions */
3077 if(tlbSegDir.pTypdescTab.length > 0)
3079 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3080 INT16 td[4];
3081 pTypeLibImpl->ctTypeDesc = cTD;
3082 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3083 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3084 for(i=0; i<cTD; )
3086 /* FIXME: add several sanity checks here */
3087 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3088 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3090 /* FIXME: check safearray */
3091 if(td[3] < 0)
3092 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3093 else
3094 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3096 else if(td[0] == VT_CARRAY)
3098 /* array descr table here */
3099 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3101 else if(td[0] == VT_USERDEFINED)
3103 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3105 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3108 /* second time around to fill the array subscript info */
3109 for(i=0;i<cTD;i++)
3111 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3112 if(tlbSegDir.pArrayDescriptions.offset>0)
3114 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3115 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3117 if(td[1]<0)
3118 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3119 else
3120 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3122 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3124 for(j = 0; j<td[2]; j++)
3126 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3127 sizeof(INT), &cx, DO_NOT_SEEK);
3128 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3129 sizeof(INT), &cx, DO_NOT_SEEK);
3132 else
3134 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3135 ERR("didn't find array description data\n");
3140 /* imported type libs */
3141 if(tlbSegDir.pImpFiles.offset>0)
3143 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
3144 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3145 UINT16 size;
3147 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3149 char *name;
3151 *ppImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3152 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
3153 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3155 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3156 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3157 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3158 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3160 size >>= 2;
3161 name = heap_alloc_zero(size+1);
3162 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3163 (*ppImpLib)->name = TLB_MultiByteToBSTR(name);
3164 heap_free(name);
3166 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
3167 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3169 ppImpLib = &(*ppImpLib)->next;
3173 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3174 if(pTypeLibImpl->dispatch_href != -1)
3175 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
3177 /* type infos */
3178 if(tlbHeader.nrtypeinfos >= 0 )
3180 ITypeInfoImpl **ppTI;
3181 int i;
3183 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3185 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3187 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3189 ++ppTI;
3190 (pTypeLibImpl->TypeInfoCount)++;
3194 TRACE("(%p)\n", pTypeLibImpl);
3195 return (ITypeLib2*) pTypeLibImpl;
3199 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3201 char b[3];
3202 int i;
3203 short s;
3205 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3206 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3207 return FALSE;
3210 guid->Data4[0] = s >> 8;
3211 guid->Data4[1] = s & 0xff;
3213 b[2] = '\0';
3214 for(i = 0; i < 6; i++) {
3215 memcpy(b, str + 24 + 2 * i, 2);
3216 guid->Data4[i + 2] = strtol(b, NULL, 16);
3218 return TRUE;
3221 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
3223 WORD bytelen;
3224 DWORD len;
3226 *pBstr = NULL;
3227 bytelen = *(const WORD*)ptr;
3228 if(bytelen == 0xffff) return 2;
3229 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3230 *pBstr = SysAllocStringLen(NULL, len);
3231 if (*pBstr)
3232 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
3233 return bytelen + 2;
3236 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3238 WORD bytelen;
3240 *str = NULL;
3241 bytelen = *(const WORD*)ptr;
3242 if(bytelen == 0xffff) return 2;
3243 *str = heap_alloc(bytelen + 1);
3244 memcpy(*str, ptr + 2, bytelen);
3245 (*str)[bytelen] = '\0';
3246 return bytelen + 2;
3249 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3251 char *ptr = pLibBlk;
3252 WORD w;
3254 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3255 FIXME("libblk magic = %04x\n", w);
3256 return 0;
3259 ptr += 6;
3260 if((w = *(WORD*)ptr) != 0xffff) {
3261 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3262 ptr += w;
3264 ptr += 2;
3266 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
3268 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
3270 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3271 ptr += 4;
3273 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
3274 ptr += 2;
3276 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3277 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3278 else
3279 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = 0;
3280 ptr += 2;
3282 ptr += 4; /* skip res12 */
3284 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
3285 ptr += 2;
3287 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
3288 ptr += 2;
3290 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
3291 ptr += 2;
3293 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
3294 ptr += sizeof(GUID);
3296 return ptr - (char*)pLibBlk;
3299 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3300 typedef struct
3302 unsigned int num;
3303 HREFTYPE refs[1];
3304 } sltg_ref_lookup_t;
3306 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3307 HREFTYPE *typelib_ref)
3309 if(table && typeinfo_ref < table->num)
3311 *typelib_ref = table->refs[typeinfo_ref];
3312 return S_OK;
3315 ERR_(typelib)("Unable to find reference\n");
3316 *typelib_ref = -1;
3317 return E_FAIL;
3320 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3322 BOOL done = FALSE;
3324 while(!done) {
3325 if((*pType & 0xe00) == 0xe00) {
3326 pTD->vt = VT_PTR;
3327 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3328 pTD = pTD->u.lptdesc;
3330 switch(*pType & 0x3f) {
3331 case VT_PTR:
3332 pTD->vt = VT_PTR;
3333 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3334 pTD = pTD->u.lptdesc;
3335 break;
3337 case VT_USERDEFINED:
3338 pTD->vt = VT_USERDEFINED;
3339 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3340 done = TRUE;
3341 break;
3343 case VT_CARRAY:
3345 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3346 array */
3348 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3350 pTD->vt = VT_CARRAY;
3351 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3352 pTD->u.lpadesc->cDims = pSA->cDims;
3353 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3354 pSA->cDims * sizeof(SAFEARRAYBOUND));
3356 pTD = &pTD->u.lpadesc->tdescElem;
3357 break;
3360 case VT_SAFEARRAY:
3362 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3363 useful? */
3365 pType++;
3366 pTD->vt = VT_SAFEARRAY;
3367 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3368 pTD = pTD->u.lptdesc;
3369 break;
3371 default:
3372 pTD->vt = *pType & 0x3f;
3373 done = TRUE;
3374 break;
3376 pType++;
3378 return pType;
3381 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3382 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3384 /* Handle [in/out] first */
3385 if((*pType & 0xc000) == 0xc000)
3386 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3387 else if(*pType & 0x8000)
3388 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3389 else if(*pType & 0x4000)
3390 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3391 else
3392 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3394 if(*pType & 0x2000)
3395 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3397 if(*pType & 0x80)
3398 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3400 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3404 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3405 char *pNameTable)
3407 unsigned int ref;
3408 char *name;
3409 TLBRefType *ref_type;
3410 sltg_ref_lookup_t *table;
3411 HREFTYPE typelib_ref;
3413 if(pRef->magic != SLTG_REF_MAGIC) {
3414 FIXME("Ref magic = %x\n", pRef->magic);
3415 return NULL;
3417 name = ( (char*)pRef->names + pRef->number);
3419 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3420 table->num = pRef->number >> 3;
3422 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3424 /* We don't want the first href to be 0 */
3425 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3427 for(ref = 0; ref < pRef->number >> 3; ref++) {
3428 char *refname;
3429 unsigned int lib_offs, type_num;
3431 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3433 name += SLTG_ReadStringA(name, &refname);
3434 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3435 FIXME_(typelib)("Can't sscanf ref\n");
3436 if(lib_offs != 0xffff) {
3437 TLBImpLib **import = &pTL->pImpLibs;
3439 while(*import) {
3440 if((*import)->offset == lib_offs)
3441 break;
3442 import = &(*import)->next;
3444 if(!*import) {
3445 char fname[MAX_PATH+1];
3446 int len;
3448 *import = heap_alloc_zero(sizeof(**import));
3449 (*import)->offset = lib_offs;
3450 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3451 &(*import)->guid);
3452 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3453 &(*import)->wVersionMajor,
3454 &(*import)->wVersionMinor,
3455 &(*import)->lcid, fname) != 4) {
3456 FIXME_(typelib)("can't sscanf ref %s\n",
3457 pNameTable + lib_offs + 40);
3459 len = strlen(fname);
3460 if(fname[len-1] != '#')
3461 FIXME("fname = %s\n", fname);
3462 fname[len-1] = '\0';
3463 (*import)->name = TLB_MultiByteToBSTR(fname);
3465 ref_type->pImpTLInfo = *import;
3467 /* Store a reference to IDispatch */
3468 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
3469 pTL->dispatch_href = typelib_ref;
3471 } else { /* internal ref */
3472 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3474 ref_type->reference = typelib_ref;
3475 ref_type->index = type_num;
3477 heap_free(refname);
3478 list_add_tail(&pTL->ref_list, &ref_type->entry);
3480 table->refs[ref] = typelib_ref;
3481 typelib_ref += 4;
3483 if((BYTE)*name != SLTG_REF_MAGIC)
3484 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3485 dump_TLBRefType(pTL);
3486 return table;
3489 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3490 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3492 SLTG_ImplInfo *info;
3493 TLBImplType *pImplType;
3494 /* I don't really get this structure, usually it's 0x16 bytes
3495 long, but iuser.tlb contains some that are 0x18 bytes long.
3496 That's ok because we can use the next ptr to jump to the next
3497 one. But how do we know the length of the last one? The WORD
3498 at offs 0x8 might be the clue. For now I'm just assuming that
3499 the last one is the regular 0x16 bytes. */
3501 info = (SLTG_ImplInfo*)pBlk;
3502 while(1){
3503 pTI->TypeAttr.cImplTypes++;
3504 if(info->next == 0xffff)
3505 break;
3506 info = (SLTG_ImplInfo*)(pBlk + info->next);
3509 info = (SLTG_ImplInfo*)pBlk;
3510 pTI->impltypes = TLBImplType_Constructor(pTI->TypeAttr.cImplTypes);
3511 pImplType = pTI->impltypes;
3512 while(1) {
3513 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
3514 pImplType->implflags = info->impltypeflags;
3515 ++pImplType;
3517 if(info->next == 0xffff)
3518 break;
3519 if(OneOnly)
3520 FIXME_(typelib)("Interface inheriting more than one interface\n");
3521 info = (SLTG_ImplInfo*)(pBlk + info->next);
3523 info++; /* see comment at top of function */
3524 return (char*)info;
3527 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3528 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3530 TLBVarDesc *pVarDesc;
3531 BSTR bstrPrevName = NULL;
3532 SLTG_Variable *pItem;
3533 unsigned short i;
3534 WORD *pType;
3536 pVarDesc = pTI->vardescs = TLBVarDesc_Constructor(cVars);
3538 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3539 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
3541 pVarDesc->vardesc.memid = pItem->memid;
3543 if (pItem->magic != SLTG_VAR_MAGIC &&
3544 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3545 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3546 return;
3549 if (pItem->name == 0xfffe)
3550 pVarDesc->Name = SysAllocString(bstrPrevName);
3551 else
3552 pVarDesc->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3554 TRACE_(typelib)("name: %s\n", debugstr_w(pVarDesc->Name));
3555 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3556 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3558 if(pItem->flags & 0x02)
3559 pType = &pItem->type;
3560 else
3561 pType = (WORD*)(pBlk + pItem->type);
3563 if (pItem->flags & ~0xda)
3564 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3566 SLTG_DoElem(pType, pBlk,
3567 &pVarDesc->vardesc.elemdescVar, ref_lookup);
3569 if (TRACE_ON(typelib)) {
3570 char buf[300];
3571 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
3572 TRACE_(typelib)("elemdescVar: %s\n", buf);
3575 if (pItem->flags & 0x40) {
3576 TRACE_(typelib)("VAR_DISPATCH\n");
3577 pVarDesc->vardesc.varkind = VAR_DISPATCH;
3579 else if (pItem->flags & 0x10) {
3580 TRACE_(typelib)("VAR_CONST\n");
3581 pVarDesc->vardesc.varkind = VAR_CONST;
3582 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
3583 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
3584 if (pItem->flags & 0x08)
3585 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
3586 else {
3587 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
3589 case VT_LPSTR:
3590 case VT_LPWSTR:
3591 case VT_BSTR:
3593 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3594 BSTR str;
3595 TRACE_(typelib)("len = %u\n", len);
3596 if (len == 0xffff) {
3597 str = NULL;
3598 } else {
3599 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3600 str = SysAllocStringLen(NULL, alloc_len);
3601 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3603 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
3604 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
3605 break;
3607 case VT_I2:
3608 case VT_UI2:
3609 case VT_I4:
3610 case VT_UI4:
3611 case VT_INT:
3612 case VT_UINT:
3613 V_INT(pVarDesc->vardesc.u.lpvarValue) =
3614 *(INT*)(pBlk + pItem->byte_offs);
3615 break;
3616 default:
3617 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
3621 else {
3622 TRACE_(typelib)("VAR_PERINSTANCE\n");
3623 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
3624 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
3627 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3628 pVarDesc->vardesc.wVarFlags = pItem->varflags;
3630 if (pItem->flags & 0x80)
3631 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3633 bstrPrevName = pVarDesc->Name;
3635 pTI->TypeAttr.cVars = cVars;
3638 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3639 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3641 SLTG_Function *pFunc;
3642 unsigned short i;
3643 TLBFuncDesc *pFuncDesc;
3645 pTI->funcdescs = TLBFuncDesc_Constructor(cFuncs);
3647 pFuncDesc = pTI->funcdescs;
3648 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
3649 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
3651 int param;
3652 WORD *pType, *pArg;
3654 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3655 case SLTG_FUNCTION_MAGIC:
3656 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
3657 break;
3658 case SLTG_DISPATCH_FUNCTION_MAGIC:
3659 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
3660 break;
3661 case SLTG_STATIC_FUNCTION_MAGIC:
3662 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
3663 break;
3664 default:
3665 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3666 continue;
3668 pFuncDesc->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3670 pFuncDesc->funcdesc.memid = pFunc->dispid;
3671 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
3672 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
3673 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
3674 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3675 pFuncDesc->funcdesc.oVft = pFunc->vtblpos & ~1;
3677 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3678 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
3680 if(pFunc->retnextopt & 0x80)
3681 pType = &pFunc->rettype;
3682 else
3683 pType = (WORD*)(pBlk + pFunc->rettype);
3685 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
3687 pFuncDesc->funcdesc.lprgelemdescParam =
3688 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
3689 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
3691 pArg = (WORD*)(pBlk + pFunc->arg_off);
3693 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
3694 char *paramName = pNameTable + *pArg;
3695 BOOL HaveOffs;
3696 /* If arg type follows then paramName points to the 2nd
3697 letter of the name, else the next WORD is an offset to
3698 the arg type and paramName points to the first letter.
3699 So let's take one char off paramName and see if we're
3700 pointing at an alpha-numeric char. However if *pArg is
3701 0xffff or 0xfffe then the param has no name, the former
3702 meaning that the next WORD is the type, the latter
3703 meaning that the next WORD is an offset to the type. */
3705 HaveOffs = FALSE;
3706 if(*pArg == 0xffff)
3707 paramName = NULL;
3708 else if(*pArg == 0xfffe) {
3709 paramName = NULL;
3710 HaveOffs = TRUE;
3712 else if(paramName[-1] && !isalnum(paramName[-1]))
3713 HaveOffs = TRUE;
3715 pArg++;
3717 if(HaveOffs) { /* the next word is an offset to type */
3718 pType = (WORD*)(pBlk + *pArg);
3719 SLTG_DoElem(pType, pBlk,
3720 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
3721 pArg++;
3722 } else {
3723 if(paramName)
3724 paramName--;
3725 pArg = SLTG_DoElem(pArg, pBlk,
3726 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
3729 /* Are we an optional param ? */
3730 if(pFuncDesc->funcdesc.cParams - param <=
3731 pFuncDesc->funcdesc.cParamsOpt)
3732 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3734 if(paramName) {
3735 pFuncDesc->pParamDesc[param].Name =
3736 TLB_MultiByteToBSTR(paramName);
3737 } else {
3738 pFuncDesc->pParamDesc[param].Name =
3739 SysAllocString(pFuncDesc->Name);
3743 pTI->TypeAttr.cFuncs = cFuncs;
3746 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3747 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3748 SLTG_TypeInfoTail *pTITail)
3750 char *pFirstItem;
3751 sltg_ref_lookup_t *ref_lookup = NULL;
3753 if(pTIHeader->href_table != 0xffffffff) {
3754 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3755 pNameTable);
3758 pFirstItem = pBlk;
3760 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3761 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3763 heap_free(ref_lookup);
3767 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3768 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3769 const SLTG_TypeInfoTail *pTITail)
3771 char *pFirstItem;
3772 sltg_ref_lookup_t *ref_lookup = NULL;
3774 if(pTIHeader->href_table != 0xffffffff) {
3775 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3776 pNameTable);
3779 pFirstItem = pBlk;
3781 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3782 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3785 if (pTITail->funcs_off != 0xffff)
3786 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3788 heap_free(ref_lookup);
3790 if (TRACE_ON(typelib))
3791 dump_TLBFuncDesc(pTI->funcdescs, pTI->TypeAttr.cFuncs);
3794 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3795 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3796 const SLTG_TypeInfoTail *pTITail)
3798 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3801 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3802 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3803 const SLTG_TypeInfoTail *pTITail)
3805 WORD *pType;
3806 sltg_ref_lookup_t *ref_lookup = NULL;
3808 if (pTITail->simple_alias) {
3809 /* if simple alias, no more processing required */
3810 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3811 return;
3814 if(pTIHeader->href_table != 0xffffffff) {
3815 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3816 pNameTable);
3819 /* otherwise it is an offset to a type */
3820 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3822 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3824 heap_free(ref_lookup);
3827 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3828 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3829 const SLTG_TypeInfoTail *pTITail)
3831 sltg_ref_lookup_t *ref_lookup = NULL;
3832 if (pTIHeader->href_table != 0xffffffff)
3833 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3834 pNameTable);
3836 if (pTITail->vars_off != 0xffff)
3837 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3839 if (pTITail->funcs_off != 0xffff)
3840 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3842 if (pTITail->impls_off != 0xffff)
3843 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
3845 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3846 * of dispinterface functions including the IDispatch ones, so
3847 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3848 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3850 heap_free(ref_lookup);
3851 if (TRACE_ON(typelib))
3852 dump_TLBFuncDesc(pTI->funcdescs, pTI->TypeAttr.cFuncs);
3855 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3856 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3857 const SLTG_TypeInfoTail *pTITail)
3859 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3862 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3863 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3864 const SLTG_TypeInfoTail *pTITail)
3866 sltg_ref_lookup_t *ref_lookup = NULL;
3867 if (pTIHeader->href_table != 0xffffffff)
3868 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3869 pNameTable);
3871 if (pTITail->vars_off != 0xffff)
3872 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3874 if (pTITail->funcs_off != 0xffff)
3875 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3876 heap_free(ref_lookup);
3877 if (TRACE_ON(typelib))
3878 dump_TypeInfo(pTI);
3881 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3882 managable copy of it into this */
3883 typedef struct {
3884 WORD small_no;
3885 char *index_name;
3886 char *other_name;
3887 WORD res1a;
3888 WORD name_offs;
3889 WORD more_bytes;
3890 char *extra;
3891 WORD res20;
3892 DWORD helpcontext;
3893 WORD res26;
3894 GUID uuid;
3895 } SLTG_InternalOtherTypeInfo;
3897 /****************************************************************************
3898 * ITypeLib2_Constructor_SLTG
3900 * loading a SLTG typelib from an in-memory image
3902 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3904 ITypeLibImpl *pTypeLibImpl;
3905 SLTG_Header *pHeader;
3906 SLTG_BlkEntry *pBlkEntry;
3907 SLTG_Magic *pMagic;
3908 SLTG_Index *pIndex;
3909 SLTG_Pad9 *pPad9;
3910 LPVOID pBlk, pFirstBlk;
3911 SLTG_LibBlk *pLibBlk;
3912 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3913 char *pAfterOTIBlks = NULL;
3914 char *pNameTable, *ptr;
3915 int i;
3916 DWORD len, order;
3917 ITypeInfoImpl **ppTypeInfoImpl;
3919 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3922 pTypeLibImpl = TypeLibImpl_Constructor();
3923 if (!pTypeLibImpl) return NULL;
3925 pHeader = pLib;
3927 TRACE_(typelib)("header:\n");
3928 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3929 pHeader->nrOfFileBlks );
3930 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3931 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3932 pHeader->SLTG_magic);
3933 return NULL;
3936 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3937 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3939 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3940 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3942 /* Next we have a magic block */
3943 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3945 /* Let's see if we're still in sync */
3946 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3947 sizeof(SLTG_COMPOBJ_MAGIC))) {
3948 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3949 return NULL;
3951 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3952 sizeof(SLTG_DIR_MAGIC))) {
3953 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
3954 return NULL;
3957 pIndex = (SLTG_Index*)(pMagic+1);
3959 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3961 pFirstBlk = pPad9 + 1;
3963 /* We'll set up a ptr to the main library block, which is the last one. */
3965 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3966 pBlkEntry[order].next != 0;
3967 order = pBlkEntry[order].next - 1, i++) {
3968 pBlk = (char*)pBlk + pBlkEntry[order].len;
3970 pLibBlk = pBlk;
3972 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3974 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3975 interspersed */
3977 len += 0x40;
3979 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3981 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
3984 ptr = (char*)pLibBlk + len;
3986 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3987 WORD w, extra;
3988 len = 0;
3990 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3992 w = *(WORD*)(ptr + 2);
3993 if(w != 0xffff) {
3994 len += w;
3995 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
3996 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3997 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3999 w = *(WORD*)(ptr + 4 + len);
4000 if(w != 0xffff) {
4001 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4002 len += w;
4003 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4004 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4005 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4007 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4008 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4009 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4010 if(extra) {
4011 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4012 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4013 len += extra;
4015 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4016 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4017 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4018 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4019 len += sizeof(SLTG_OtherTypeInfo);
4020 ptr += len;
4023 pAfterOTIBlks = ptr;
4025 /* Skip this WORD and get the next DWORD */
4026 len = *(DWORD*)(pAfterOTIBlks + 2);
4028 /* Now add this to pLibBLk look at what we're pointing at and
4029 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4030 dust and we should be pointing at the beginning of the name
4031 table */
4033 pNameTable = (char*)pLibBlk + len;
4035 switch(*(WORD*)pNameTable) {
4036 case 0xffff:
4037 break;
4038 case 0x0200:
4039 pNameTable += 0x20;
4040 break;
4041 default:
4042 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4043 break;
4046 pNameTable += 0x216;
4048 pNameTable += 2;
4050 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4052 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
4055 /* Hopefully we now have enough ptrs set up to actually read in
4056 some TypeInfos. It's not clear which order to do them in, so
4057 I'll just follow the links along the BlkEntry chain and read
4058 them in the order in which they are in the file */
4060 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4061 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4063 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4064 pBlkEntry[order].next != 0;
4065 order = pBlkEntry[order].next - 1, i++) {
4067 SLTG_TypeInfoHeader *pTIHeader;
4068 SLTG_TypeInfoTail *pTITail;
4069 SLTG_MemberHeader *pMemHeader;
4071 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
4072 pOtherTypeInfoBlks[i].index_name)) {
4073 FIXME_(typelib)("Index strings don't match\n");
4074 return NULL;
4077 pTIHeader = pBlk;
4078 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4079 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4080 return NULL;
4082 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4083 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4084 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4086 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4087 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4088 (*ppTypeInfoImpl)->index = i;
4089 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
4090 pOtherTypeInfoBlks[i].name_offs +
4091 pNameTable);
4092 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4093 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
4094 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
4095 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
4096 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
4097 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
4098 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4100 if((*ppTypeInfoImpl)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
4101 (*ppTypeInfoImpl)->TypeAttr.typekind = TKIND_DISPATCH;
4103 if((pTIHeader->typeflags1 & 7) != 2)
4104 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4105 if(pTIHeader->typeflags3 != 2)
4106 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4108 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4109 debugstr_w((*ppTypeInfoImpl)->Name),
4110 typekind_desc[pTIHeader->typekind],
4111 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
4112 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
4114 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4116 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4118 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
4119 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
4120 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
4122 switch(pTIHeader->typekind) {
4123 case TKIND_ENUM:
4124 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4125 pTIHeader, pTITail);
4126 break;
4128 case TKIND_RECORD:
4129 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4130 pTIHeader, pTITail);
4131 break;
4133 case TKIND_INTERFACE:
4134 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4135 pTIHeader, pTITail);
4136 break;
4138 case TKIND_COCLASS:
4139 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4140 pTIHeader, pTITail);
4141 break;
4143 case TKIND_ALIAS:
4144 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4145 pTIHeader, pTITail);
4146 break;
4148 case TKIND_DISPATCH:
4149 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4150 pTIHeader, pTITail);
4151 break;
4153 case TKIND_MODULE:
4154 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4155 pTIHeader, pTITail);
4156 break;
4158 default:
4159 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4160 break;
4164 /* could get cFuncs, cVars and cImplTypes from here
4165 but we've already set those */
4166 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4167 X(06);
4168 X(16);
4169 X(18);
4170 X(1a);
4171 X(1e);
4172 X(24);
4173 X(26);
4174 X(2a);
4175 X(2c);
4176 X(2e);
4177 X(30);
4178 X(32);
4179 X(34);
4180 #undef X
4181 ++ppTypeInfoImpl;
4182 pBlk = (char*)pBlk + pBlkEntry[order].len;
4185 if(i != pTypeLibImpl->TypeInfoCount) {
4186 FIXME("Somehow processed %d TypeInfos\n", i);
4187 return NULL;
4190 heap_free(pOtherTypeInfoBlks);
4191 return (ITypeLib2*)pTypeLibImpl;
4194 /* ITypeLib::QueryInterface
4196 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
4197 ITypeLib2 * iface,
4198 REFIID riid,
4199 VOID **ppvObject)
4201 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4203 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4205 *ppvObject=NULL;
4206 if(IsEqualIID(riid, &IID_IUnknown) ||
4207 IsEqualIID(riid,&IID_ITypeLib)||
4208 IsEqualIID(riid,&IID_ITypeLib2))
4210 *ppvObject = This;
4213 if(*ppvObject)
4215 ITypeLib2_AddRef(iface);
4216 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4217 return S_OK;
4219 TRACE("-- Interface: E_NOINTERFACE\n");
4220 return E_NOINTERFACE;
4223 /* ITypeLib::AddRef
4225 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4227 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4228 ULONG ref = InterlockedIncrement(&This->ref);
4230 TRACE("(%p)->ref was %u\n",This, ref - 1);
4232 return ref;
4235 /* ITypeLib::Release
4237 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4239 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4240 ULONG ref = InterlockedDecrement(&This->ref);
4242 TRACE("(%p)->(%u)\n",This, ref);
4244 if (!ref)
4246 TLBImpLib *pImpLib, *pImpLibNext;
4247 TLBRefType *ref_type;
4248 void *cursor2;
4249 int i;
4251 /* remove cache entry */
4252 if(This->path)
4254 TRACE("removing from cache list\n");
4255 EnterCriticalSection(&cache_section);
4256 if (This->next) This->next->prev = This->prev;
4257 if (This->prev) This->prev->next = This->next;
4258 else tlb_cache_first = This->next;
4259 LeaveCriticalSection(&cache_section);
4260 heap_free(This->path);
4262 TRACE(" destroying ITypeLib(%p)\n",This);
4264 SysFreeString(This->Name);
4265 This->Name = NULL;
4267 SysFreeString(This->DocString);
4268 This->DocString = NULL;
4270 SysFreeString(This->HelpFile);
4271 This->HelpFile = NULL;
4273 SysFreeString(This->HelpStringDll);
4274 This->HelpStringDll = NULL;
4276 TLB_FreeCustData(&This->custdata_list);
4278 for (i = 0; i < This->ctTypeDesc; i++)
4279 if (This->pTypeDesc[i].vt == VT_CARRAY)
4280 heap_free(This->pTypeDesc[i].u.lpadesc);
4282 heap_free(This->pTypeDesc);
4284 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
4286 if (pImpLib->pImpTypeLib)
4287 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
4288 SysFreeString(pImpLib->name);
4290 pImpLibNext = pImpLib->next;
4291 heap_free(pImpLib);
4294 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4296 list_remove(&ref_type->entry);
4297 heap_free(ref_type);
4300 for (i = 0; i < This->TypeInfoCount; ++i)
4301 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4302 heap_free(This->typeinfos);
4303 heap_free(This);
4304 return 0;
4307 return ref;
4310 /* ITypeLib::GetTypeInfoCount
4312 * Returns the number of type descriptions in the type library
4314 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4316 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4317 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4318 return This->TypeInfoCount;
4321 /* ITypeLib::GetTypeInfo
4323 * retrieves the specified type description in the library.
4325 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4326 ITypeLib2 *iface,
4327 UINT index,
4328 ITypeInfo **ppTInfo)
4330 ITypeLibImpl *This = (ITypeLibImpl*)iface;
4332 TRACE("%p %u %p\n", This, index, ppTInfo);
4334 if(!ppTInfo)
4335 return E_INVALIDARG;
4337 if(index >= This->TypeInfoCount)
4338 return TYPE_E_ELEMENTNOTFOUND;
4340 *ppTInfo = (ITypeInfo*)This->typeinfos[index];
4341 ITypeInfo_AddRef(*ppTInfo);
4343 return S_OK;
4347 /* ITypeLibs::GetTypeInfoType
4349 * Retrieves the type of a type description.
4351 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4352 ITypeLib2 *iface,
4353 UINT index,
4354 TYPEKIND *pTKind)
4356 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4358 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4360 if(!pTKind)
4361 return E_INVALIDARG;
4363 if(index >= This->TypeInfoCount)
4364 return TYPE_E_ELEMENTNOTFOUND;
4366 *pTKind = This->typeinfos[index]->TypeAttr.typekind;
4368 return S_OK;
4371 /* ITypeLib::GetTypeInfoOfGuid
4373 * Retrieves the type description that corresponds to the specified GUID.
4376 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4377 ITypeLib2 *iface,
4378 REFGUID guid,
4379 ITypeInfo **ppTInfo)
4381 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4382 UINT i;
4384 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4386 for(i = 0; i < This->TypeInfoCount; ++i){
4387 if(IsEqualIID(&This->typeinfos[i]->TypeAttr.guid, guid)){
4388 *ppTInfo = (ITypeInfo*)This->typeinfos[i];
4389 ITypeInfo_AddRef(*ppTInfo);
4390 return S_OK;
4394 return TYPE_E_ELEMENTNOTFOUND;
4397 /* ITypeLib::GetLibAttr
4399 * Retrieves the structure that contains the library's attributes.
4402 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4403 ITypeLib2 *iface,
4404 LPTLIBATTR *attr)
4406 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4408 TRACE("(%p, %p)\n", This, attr);
4410 if (!attr) return E_INVALIDARG;
4412 *attr = heap_alloc(sizeof(**attr));
4413 if (!*attr) return E_OUTOFMEMORY;
4415 **attr = This->LibAttr;
4416 return S_OK;
4419 /* ITypeLib::GetTypeComp
4421 * Enables a client compiler to bind to a library's types, variables,
4422 * constants, and global functions.
4425 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4426 ITypeLib2 *iface,
4427 ITypeComp **ppTComp)
4429 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4431 TRACE("(%p)->(%p)\n",This,ppTComp);
4432 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4433 ITypeComp_AddRef(*ppTComp);
4435 return S_OK;
4438 /* ITypeLib::GetDocumentation
4440 * Retrieves the library's documentation string, the complete Help file name
4441 * and path, and the context identifier for the library Help topic in the Help
4442 * file.
4444 * On a successful return all non-null BSTR pointers will have been set,
4445 * possibly to NULL.
4447 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4448 ITypeLib2 *iface,
4449 INT index,
4450 BSTR *pBstrName,
4451 BSTR *pBstrDocString,
4452 DWORD *pdwHelpContext,
4453 BSTR *pBstrHelpFile)
4455 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4457 HRESULT result = E_INVALIDARG;
4459 ITypeInfo *pTInfo;
4462 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4463 This, index,
4464 pBstrName, pBstrDocString,
4465 pdwHelpContext, pBstrHelpFile);
4467 if(index<0)
4469 /* documentation for the typelib */
4470 if(pBstrName)
4472 if (This->Name)
4474 if(!(*pBstrName = SysAllocString(This->Name)))
4475 goto memerr1;
4477 else
4478 *pBstrName = NULL;
4480 if(pBstrDocString)
4482 if (This->DocString)
4484 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4485 goto memerr2;
4487 else if (This->Name)
4489 if(!(*pBstrDocString = SysAllocString(This->Name)))
4490 goto memerr2;
4492 else
4493 *pBstrDocString = NULL;
4495 if(pdwHelpContext)
4497 *pdwHelpContext = This->dwHelpContext;
4499 if(pBstrHelpFile)
4501 if (This->HelpFile)
4503 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4504 goto memerr3;
4506 else
4507 *pBstrHelpFile = NULL;
4510 result = S_OK;
4512 else
4514 /* for a typeinfo */
4515 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4517 if(SUCCEEDED(result))
4519 result = ITypeInfo_GetDocumentation(pTInfo,
4520 MEMBERID_NIL,
4521 pBstrName,
4522 pBstrDocString,
4523 pdwHelpContext, pBstrHelpFile);
4525 ITypeInfo_Release(pTInfo);
4528 return result;
4529 memerr3:
4530 if (pBstrDocString) SysFreeString (*pBstrDocString);
4531 memerr2:
4532 if (pBstrName) SysFreeString (*pBstrName);
4533 memerr1:
4534 return STG_E_INSUFFICIENTMEMORY;
4537 /* ITypeLib::IsName
4539 * Indicates whether a passed-in string contains the name of a type or member
4540 * described in the library.
4543 static HRESULT WINAPI ITypeLib2_fnIsName(
4544 ITypeLib2 *iface,
4545 LPOLESTR szNameBuf,
4546 ULONG lHashVal,
4547 BOOL *pfName)
4549 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4550 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), tic, fdc, vrc, pc;
4552 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4553 pfName);
4555 *pfName=TRUE;
4556 for(tic = 0; tic < This->TypeInfoCount; ++tic){
4557 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
4558 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4559 for(fdc = 0; fdc < pTInfo->TypeAttr.cFuncs; ++fdc) {
4560 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
4561 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4562 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++)
4563 if(!memcmp(szNameBuf,pFInfo->pParamDesc[pc].Name, nNameBufLen))
4564 goto ITypeLib2_fnIsName_exit;
4566 for(vrc = 0; vrc < pTInfo->TypeAttr.cVars; ++vrc){
4567 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
4568 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4572 *pfName=FALSE;
4574 ITypeLib2_fnIsName_exit:
4575 TRACE("(%p)slow! search for %s: %s found!\n", This,
4576 debugstr_w(szNameBuf), *pfName?"NOT":"");
4578 return S_OK;
4581 /* ITypeLib::FindName
4583 * Finds occurrences of a type description in a type library. This may be used
4584 * to quickly verify that a name exists in a type library.
4587 static HRESULT WINAPI ITypeLib2_fnFindName(
4588 ITypeLib2 *iface,
4589 LPOLESTR szNameBuf,
4590 ULONG lHashVal,
4591 ITypeInfo **ppTInfo,
4592 MEMBERID *rgMemId,
4593 UINT16 *pcFound)
4595 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4596 TLBVarDesc *pVInfo;
4597 UINT tic, fdc, pc, count = 0;
4598 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4600 for(tic = 0; tic < This->TypeInfoCount; ++tic){
4601 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
4602 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4603 for(fdc = 0; fdc < pTInfo->TypeAttr.cFuncs; ++fdc) {
4604 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
4605 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4606 for(pc = 0;pc < pFInfo->funcdesc.cParams; pc++) {
4607 if(!memcmp(szNameBuf,pFInfo->pParamDesc[pc].Name,nNameBufLen))
4608 goto ITypeLib2_fnFindName_exit;
4612 pVInfo = TLB_get_vardesc_by_name(pTInfo->vardescs, pTInfo->TypeAttr.cVars, szNameBuf);
4613 if(pVInfo)
4614 goto ITypeLib2_fnFindName_exit;
4616 continue;
4617 ITypeLib2_fnFindName_exit:
4618 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4619 ppTInfo[count]=(LPTYPEINFO)pTInfo;
4620 count++;
4622 TRACE("(%p)slow! search for %d with %s: found %d TypeInfos!\n",
4623 This, *pcFound, debugstr_w(szNameBuf), count);
4625 *pcFound = count;
4627 return S_OK;
4630 /* ITypeLib::ReleaseTLibAttr
4632 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4635 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4636 ITypeLib2 *iface,
4637 TLIBATTR *pTLibAttr)
4639 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4640 TRACE("freeing (%p)\n",This);
4641 heap_free(pTLibAttr);
4645 /* ITypeLib2::GetCustData
4647 * gets the custom data
4649 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4650 ITypeLib2 * iface,
4651 REFGUID guid,
4652 VARIANT *pVarVal)
4654 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4655 TLBCustData *pCData;
4657 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
4659 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
4660 if(!pCData)
4661 return TYPE_E_ELEMENTNOTFOUND;
4663 VariantInit(pVarVal);
4664 VariantCopy(pVarVal, &pCData->data);
4666 return S_OK;
4669 /* ITypeLib2::GetLibStatistics
4671 * Returns statistics about a type library that are required for efficient
4672 * sizing of hash tables.
4675 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4676 ITypeLib2 * iface,
4677 ULONG *pcUniqueNames,
4678 ULONG *pcchUniqueNames)
4680 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4682 FIXME("(%p): stub!\n", This);
4684 if(pcUniqueNames) *pcUniqueNames=1;
4685 if(pcchUniqueNames) *pcchUniqueNames=1;
4686 return S_OK;
4689 /* ITypeLib2::GetDocumentation2
4691 * Retrieves the library's documentation string, the complete Help file name
4692 * and path, the localization context to use, and the context ID for the
4693 * library Help topic in the Help file.
4696 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4697 ITypeLib2 * iface,
4698 INT index,
4699 LCID lcid,
4700 BSTR *pbstrHelpString,
4701 DWORD *pdwHelpStringContext,
4702 BSTR *pbstrHelpStringDll)
4704 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4705 HRESULT result;
4706 ITypeInfo *pTInfo;
4708 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4710 /* the help string should be obtained from the helpstringdll,
4711 * using the _DLLGetDocumentation function, based on the supplied
4712 * lcid. Nice to do sometime...
4714 if(index<0)
4716 /* documentation for the typelib */
4717 if(pbstrHelpString)
4718 *pbstrHelpString=SysAllocString(This->DocString);
4719 if(pdwHelpStringContext)
4720 *pdwHelpStringContext=This->dwHelpContext;
4721 if(pbstrHelpStringDll)
4722 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4724 result = S_OK;
4726 else
4728 /* for a typeinfo */
4729 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4731 if(SUCCEEDED(result))
4733 ITypeInfo2 * pTInfo2;
4734 result = ITypeInfo_QueryInterface(pTInfo,
4735 &IID_ITypeInfo2,
4736 (LPVOID*) &pTInfo2);
4738 if(SUCCEEDED(result))
4740 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4741 MEMBERID_NIL,
4742 lcid,
4743 pbstrHelpString,
4744 pdwHelpStringContext,
4745 pbstrHelpStringDll);
4747 ITypeInfo2_Release(pTInfo2);
4750 ITypeInfo_Release(pTInfo);
4753 return result;
4756 static HRESULT TLB_copy_all_custdata(struct list *custdata_list, CUSTDATA *pCustData)
4758 TLBCustData *pCData;
4759 unsigned int ct;
4760 CUSTDATAITEM *cdi;
4762 ct = list_count(custdata_list);
4764 pCustData->prgCustData = heap_alloc_zero(ct * sizeof(CUSTDATAITEM));
4765 if(!pCustData->prgCustData)
4766 return E_OUTOFMEMORY;
4768 pCustData->cCustData = ct;
4770 cdi = pCustData->prgCustData;
4771 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
4772 cdi->guid = pCData->guid;
4773 VariantCopy(&cdi->varValue, &pCData->data);
4774 ++cdi;
4777 return S_OK;
4781 /* ITypeLib2::GetAllCustData
4783 * Gets all custom data items for the library.
4786 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4787 ITypeLib2 * iface,
4788 CUSTDATA *pCustData)
4790 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4791 TRACE("%p %p\n", iface, pCustData);
4792 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
4795 static const ITypeLib2Vtbl tlbvt = {
4796 ITypeLib2_fnQueryInterface,
4797 ITypeLib2_fnAddRef,
4798 ITypeLib2_fnRelease,
4799 ITypeLib2_fnGetTypeInfoCount,
4800 ITypeLib2_fnGetTypeInfo,
4801 ITypeLib2_fnGetTypeInfoType,
4802 ITypeLib2_fnGetTypeInfoOfGuid,
4803 ITypeLib2_fnGetLibAttr,
4804 ITypeLib2_fnGetTypeComp,
4805 ITypeLib2_fnGetDocumentation,
4806 ITypeLib2_fnIsName,
4807 ITypeLib2_fnFindName,
4808 ITypeLib2_fnReleaseTLibAttr,
4810 ITypeLib2_fnGetCustData,
4811 ITypeLib2_fnGetLibStatistics,
4812 ITypeLib2_fnGetDocumentation2,
4813 ITypeLib2_fnGetAllCustData
4817 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4819 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4821 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4824 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4826 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4828 return ITypeLib2_AddRef((ITypeLib2 *)This);
4831 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4833 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4835 return ITypeLib2_Release((ITypeLib2 *)This);
4838 static HRESULT WINAPI ITypeLibComp_fnBind(
4839 ITypeComp * iface,
4840 OLECHAR * szName,
4841 ULONG lHash,
4842 WORD wFlags,
4843 ITypeInfo ** ppTInfo,
4844 DESCKIND * pDescKind,
4845 BINDPTR * pBindPtr)
4847 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4848 int typemismatch=0, i;
4850 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4852 *pDescKind = DESCKIND_NONE;
4853 pBindPtr->lptcomp = NULL;
4854 *ppTInfo = NULL;
4856 for(i = 0; i < This->TypeInfoCount; ++i){
4857 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
4858 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4860 /* FIXME: check wFlags here? */
4861 /* FIXME: we should use a hash table to look this info up using lHash
4862 * instead of an O(n) search */
4863 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4864 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4866 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4868 *pDescKind = DESCKIND_TYPECOMP;
4869 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4870 ITypeComp_AddRef(pBindPtr->lptcomp);
4871 TRACE("module or enum: %s\n", debugstr_w(szName));
4872 return S_OK;
4876 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4877 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4879 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4880 HRESULT hr;
4882 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4883 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4885 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4886 return S_OK;
4888 else if (hr == TYPE_E_TYPEMISMATCH)
4889 typemismatch = 1;
4892 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4893 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4895 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4896 HRESULT hr;
4897 ITypeInfo *subtypeinfo;
4898 BINDPTR subbindptr;
4899 DESCKIND subdesckind;
4901 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4902 &subtypeinfo, &subdesckind, &subbindptr);
4903 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4905 TYPEDESC tdesc_appobject;
4906 const VARDESC vardesc_appobject =
4908 -2, /* memid */
4909 NULL, /* lpstrSchema */
4911 0 /* oInst */
4914 /* ELEMDESC */
4916 /* TYPEDESC */
4918 &tdesc_appobject
4920 VT_PTR
4923 0, /* wVarFlags */
4924 VAR_STATIC /* varkind */
4927 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
4928 tdesc_appobject.vt = VT_USERDEFINED;
4930 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4932 /* cleanup things filled in by Bind call so we can put our
4933 * application object data in there instead */
4934 switch (subdesckind)
4936 case DESCKIND_FUNCDESC:
4937 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4938 break;
4939 case DESCKIND_VARDESC:
4940 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4941 break;
4942 default:
4943 break;
4945 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4947 if (pTypeInfo->hreftype == -1)
4948 FIXME("no hreftype for interface %p\n", pTypeInfo);
4950 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4951 if (FAILED(hr))
4952 return hr;
4954 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4955 *ppTInfo = (ITypeInfo *)pTypeInfo;
4956 ITypeInfo_AddRef(*ppTInfo);
4957 return S_OK;
4959 else if (hr == TYPE_E_TYPEMISMATCH)
4960 typemismatch = 1;
4964 if (typemismatch)
4966 TRACE("type mismatch %s\n", debugstr_w(szName));
4967 return TYPE_E_TYPEMISMATCH;
4969 else
4971 TRACE("name not found %s\n", debugstr_w(szName));
4972 return S_OK;
4976 static HRESULT WINAPI ITypeLibComp_fnBindType(
4977 ITypeComp * iface,
4978 OLECHAR * szName,
4979 ULONG lHash,
4980 ITypeInfo ** ppTInfo,
4981 ITypeComp ** ppTComp)
4983 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4984 UINT i;
4986 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4988 if(!szName || !ppTInfo || !ppTComp)
4989 return E_INVALIDARG;
4991 for(i = 0; i < This->TypeInfoCount; ++i)
4993 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
4994 /* FIXME: should use lHash to do the search */
4995 if (pTypeInfo->Name && !strcmpiW(pTypeInfo->Name, szName))
4997 TRACE("returning %p\n", pTypeInfo);
4998 *ppTInfo = (ITypeInfo *)&pTypeInfo->lpVtbl;
4999 ITypeInfo_AddRef(*ppTInfo);
5000 *ppTComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
5001 ITypeComp_AddRef(*ppTComp);
5002 return S_OK;
5006 TRACE("not found\n");
5007 *ppTInfo = NULL;
5008 *ppTComp = NULL;
5009 return S_OK;
5012 static const ITypeCompVtbl tlbtcvt =
5015 ITypeLibComp_fnQueryInterface,
5016 ITypeLibComp_fnAddRef,
5017 ITypeLibComp_fnRelease,
5019 ITypeLibComp_fnBind,
5020 ITypeLibComp_fnBindType
5023 /*================== ITypeInfo(2) Methods ===================================*/
5024 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5026 ITypeInfoImpl *pTypeInfoImpl;
5028 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5029 if (pTypeInfoImpl)
5031 pTypeInfoImpl->lpVtbl = &tinfvt;
5032 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
5033 pTypeInfoImpl->ref = 0;
5034 pTypeInfoImpl->hreftype = -1;
5035 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
5036 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
5037 list_init(&pTypeInfoImpl->custdata_list);
5039 TRACE("(%p)\n", pTypeInfoImpl);
5040 return pTypeInfoImpl;
5043 /* ITypeInfo::QueryInterface
5045 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5046 ITypeInfo2 *iface,
5047 REFIID riid,
5048 VOID **ppvObject)
5050 ITypeLibImpl *This = (ITypeLibImpl *)iface;
5052 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5054 *ppvObject=NULL;
5055 if(IsEqualIID(riid, &IID_IUnknown) ||
5056 IsEqualIID(riid,&IID_ITypeInfo)||
5057 IsEqualIID(riid,&IID_ITypeInfo2))
5058 *ppvObject = This;
5060 if(*ppvObject){
5061 ITypeInfo_AddRef(iface);
5062 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5063 return S_OK;
5065 TRACE("-- Interface: E_NOINTERFACE\n");
5066 return E_NOINTERFACE;
5069 /* ITypeInfo::AddRef
5071 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5073 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5074 ULONG ref = InterlockedIncrement(&This->ref);
5076 TRACE("(%p)->ref is %u\n",This, ref);
5078 if (ref == 1 /* incremented from 0 */)
5079 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
5081 return ref;
5084 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5086 UINT i, j;
5088 TRACE("destroying ITypeInfo(%p)\n",This);
5090 SysFreeString(This->Name);
5091 This->Name = NULL;
5093 SysFreeString(This->DocString);
5094 This->DocString = NULL;
5096 SysFreeString(This->DllName);
5097 This->DllName = NULL;
5099 for (i = 0; i < This->TypeAttr.cFuncs; ++i)
5101 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5102 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5104 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5105 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5107 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5108 heap_free(elemdesc->u.paramdesc.pparamdescex);
5110 TLB_FreeCustData(&pFInfo->pParamDesc[j].custdata_list);
5111 SysFreeString(pFInfo->pParamDesc[j].Name);
5113 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5114 heap_free(pFInfo->pParamDesc);
5115 TLB_FreeCustData(&pFInfo->custdata_list);
5116 if (!IS_INTRESOURCE(pFInfo->Entry) && pFInfo->Entry != (BSTR)-1)
5117 SysFreeString(pFInfo->Entry);
5118 SysFreeString(pFInfo->HelpString);
5119 SysFreeString(pFInfo->Name);
5121 heap_free(This->funcdescs);
5123 for(i = 0; i < This->TypeAttr.cVars; ++i)
5125 TLBVarDesc *pVInfo = &This->vardescs[i];
5126 if (pVInfo->vardesc.varkind == VAR_CONST)
5128 VariantClear(pVInfo->vardesc.u.lpvarValue);
5129 heap_free(pVInfo->vardesc.u.lpvarValue);
5131 TLB_FreeCustData(&pVInfo->custdata_list);
5132 SysFreeString(pVInfo->Name);
5133 SysFreeString(pVInfo->HelpString);
5135 heap_free(This->vardescs);
5137 if(This->impltypes){
5138 for (i = 0; i < This->TypeAttr.cImplTypes; ++i){
5139 TLBImplType *pImpl = &This->impltypes[i];
5140 TLB_FreeCustData(&pImpl->custdata_list);
5142 heap_free(This->impltypes);
5145 TLB_FreeCustData(&This->custdata_list);
5147 heap_free(This);
5150 /* ITypeInfo::Release
5152 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5154 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5155 ULONG ref = InterlockedDecrement(&This->ref);
5157 TRACE("(%p)->(%u)\n",This, ref);
5159 if (!ref)
5161 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5162 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
5163 if (not_attached_to_typelib)
5164 heap_free(This);
5165 /* otherwise This will be freed when typelib is freed */
5168 return ref;
5171 /* ITypeInfo::GetTypeAttr
5173 * Retrieves a TYPEATTR structure that contains the attributes of the type
5174 * description.
5177 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5178 LPTYPEATTR *ppTypeAttr)
5180 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5181 SIZE_T size;
5183 TRACE("(%p)\n",This);
5185 size = sizeof(**ppTypeAttr);
5186 if (This->TypeAttr.typekind == TKIND_ALIAS)
5187 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
5189 *ppTypeAttr = heap_alloc(size);
5190 if (!*ppTypeAttr)
5191 return E_OUTOFMEMORY;
5193 **ppTypeAttr = This->TypeAttr;
5195 if (This->TypeAttr.typekind == TKIND_ALIAS)
5196 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5197 &This->TypeAttr.tdescAlias, *ppTypeAttr + 1);
5199 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5200 /* This should include all the inherited funcs */
5201 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
5202 /* This is always the size of IDispatch's vtbl */
5203 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5204 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5206 return S_OK;
5209 /* ITypeInfo::GetTypeComp
5211 * Retrieves the ITypeComp interface for the type description, which enables a
5212 * client compiler to bind to the type description's members.
5215 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5216 ITypeComp * *ppTComp)
5218 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5220 TRACE("(%p)->(%p)\n", This, ppTComp);
5222 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
5223 ITypeComp_AddRef(*ppTComp);
5224 return S_OK;
5227 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5229 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5230 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5231 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5232 return size;
5235 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5237 *dest = *src;
5238 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5239 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5241 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5242 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5243 *buffer += sizeof(PARAMDESCEX);
5244 *pparamdescex_dest = *pparamdescex_src;
5245 VariantInit(&pparamdescex_dest->varDefaultValue);
5246 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5247 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5249 else
5250 dest->u.paramdesc.pparamdescex = NULL;
5251 return S_OK;
5254 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5256 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5257 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5260 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5262 FUNCDESC *dest;
5263 char *buffer;
5264 SIZE_T size = sizeof(*src);
5265 SHORT i;
5266 HRESULT hr;
5268 size += sizeof(*src->lprgscode) * src->cScodes;
5269 size += TLB_SizeElemDesc(&src->elemdescFunc);
5270 for (i = 0; i < src->cParams; i++)
5272 size += sizeof(ELEMDESC);
5273 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5276 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5277 if (!dest) return E_OUTOFMEMORY;
5279 *dest = *src;
5280 if (dispinterface) /* overwrite funckind */
5281 dest->funckind = FUNC_DISPATCH;
5282 buffer = (char *)(dest + 1);
5284 dest->lprgscode = (SCODE *)buffer;
5285 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5286 buffer += sizeof(*src->lprgscode) * src->cScodes;
5288 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5289 if (FAILED(hr))
5291 SysFreeString((BSTR)dest);
5292 return hr;
5295 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5296 buffer += sizeof(ELEMDESC) * src->cParams;
5297 for (i = 0; i < src->cParams; i++)
5299 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5300 if (FAILED(hr))
5301 break;
5303 if (FAILED(hr))
5305 /* undo the above actions */
5306 for (i = i - 1; i >= 0; i--)
5307 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5308 TLB_FreeElemDesc(&dest->elemdescFunc);
5309 SysFreeString((BSTR)dest);
5310 return hr;
5313 /* special treatment for dispinterfaces: this makes functions appear
5314 * to return their [retval] value when it is really returning an
5315 * HRESULT */
5316 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5318 if (dest->cParams &&
5319 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5321 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5322 if (elemdesc->tdesc.vt != VT_PTR)
5324 ERR("elemdesc should have started with VT_PTR instead of:\n");
5325 if (ERR_ON(ole))
5326 dump_ELEMDESC(elemdesc);
5327 return E_UNEXPECTED;
5330 /* copy last parameter to the return value. we are using a flat
5331 * buffer so there is no danger of leaking memory in
5332 * elemdescFunc */
5333 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5335 /* remove the last parameter */
5336 dest->cParams--;
5338 else
5339 /* otherwise this function is made to appear to have no return
5340 * value */
5341 dest->elemdescFunc.tdesc.vt = VT_VOID;
5345 *dest_ptr = dest;
5346 return S_OK;
5349 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5351 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5353 if (index >= This->TypeAttr.cFuncs)
5354 return TYPE_E_ELEMENTNOTFOUND;
5356 *ppFuncDesc = &This->funcdescs[index].funcdesc;
5357 return S_OK;
5360 /* internal function to make the inherited interfaces' methods appear
5361 * part of the interface */
5362 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5363 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5365 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5366 HRESULT hr;
5367 UINT implemented_funcs = 0;
5369 if (funcs)
5370 *funcs = 0;
5371 else
5372 *hrefoffset = DISPATCH_HREF_OFFSET;
5374 if(This->impltypes)
5376 ITypeInfo *pSubTypeInfo;
5377 UINT sub_funcs;
5379 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5380 if (FAILED(hr))
5381 return hr;
5383 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5384 index,
5385 ppFuncDesc,
5386 &sub_funcs, hrefoffset);
5387 implemented_funcs += sub_funcs;
5388 ITypeInfo_Release(pSubTypeInfo);
5389 if (SUCCEEDED(hr))
5390 return hr;
5391 *hrefoffset += DISPATCH_HREF_OFFSET;
5394 if (funcs)
5395 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
5396 else
5397 *hrefoffset = 0;
5399 if (index < implemented_funcs)
5400 return E_INVALIDARG;
5401 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5402 ppFuncDesc);
5405 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5407 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5408 while (TRUE)
5410 switch (pTypeDesc->vt)
5412 case VT_USERDEFINED:
5413 pTypeDesc->u.hreftype += hrefoffset;
5414 return;
5415 case VT_PTR:
5416 case VT_SAFEARRAY:
5417 pTypeDesc = pTypeDesc->u.lptdesc;
5418 break;
5419 case VT_CARRAY:
5420 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5421 break;
5422 default:
5423 return;
5428 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5430 SHORT i;
5431 for (i = 0; i < pFuncDesc->cParams; i++)
5432 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5433 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5436 /* ITypeInfo::GetFuncDesc
5438 * Retrieves the FUNCDESC structure that contains information about a
5439 * specified function.
5442 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5443 LPFUNCDESC *ppFuncDesc)
5445 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5446 const FUNCDESC *internal_funcdesc;
5447 HRESULT hr;
5448 UINT hrefoffset = 0;
5450 TRACE("(%p) index %d\n", This, index);
5452 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5453 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5454 &internal_funcdesc, NULL,
5455 &hrefoffset);
5456 else
5457 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5458 &internal_funcdesc);
5459 if (FAILED(hr))
5461 WARN("description for function %d not found\n", index);
5462 return hr;
5465 hr = TLB_AllocAndInitFuncDesc(
5466 internal_funcdesc,
5467 ppFuncDesc,
5468 This->TypeAttr.typekind == TKIND_DISPATCH);
5470 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5471 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5473 TRACE("-- 0x%08x\n", hr);
5474 return hr;
5477 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5479 VARDESC *dest;
5480 char *buffer;
5481 SIZE_T size = sizeof(*src);
5482 HRESULT hr;
5484 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5485 if (src->varkind == VAR_CONST)
5486 size += sizeof(VARIANT);
5487 size += TLB_SizeElemDesc(&src->elemdescVar);
5489 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5490 if (!dest) return E_OUTOFMEMORY;
5492 *dest = *src;
5493 buffer = (char *)(dest + 1);
5494 if (src->lpstrSchema)
5496 int len;
5497 dest->lpstrSchema = (LPOLESTR)buffer;
5498 len = strlenW(src->lpstrSchema);
5499 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5500 buffer += (len + 1) * sizeof(WCHAR);
5503 if (src->varkind == VAR_CONST)
5505 HRESULT hr;
5507 dest->u.lpvarValue = (VARIANT *)buffer;
5508 *dest->u.lpvarValue = *src->u.lpvarValue;
5509 buffer += sizeof(VARIANT);
5510 VariantInit(dest->u.lpvarValue);
5511 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5512 if (FAILED(hr))
5514 SysFreeString((BSTR)dest);
5515 return hr;
5518 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5519 if (FAILED(hr))
5521 if (src->varkind == VAR_CONST)
5522 VariantClear(dest->u.lpvarValue);
5523 SysFreeString((BSTR)dest);
5524 return hr;
5526 *dest_ptr = dest;
5527 return S_OK;
5530 /* ITypeInfo::GetVarDesc
5532 * Retrieves a VARDESC structure that describes the specified variable.
5535 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5536 LPVARDESC *ppVarDesc)
5538 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5539 const TLBVarDesc *pVDesc = &This->vardescs[index];
5541 TRACE("(%p) index %d\n", This, index);
5543 if(index >= This->TypeAttr.cVars)
5544 return TYPE_E_ELEMENTNOTFOUND;
5546 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5549 /* ITypeInfo_GetNames
5551 * Retrieves the variable with the specified member ID (or the name of the
5552 * property or method and its parameters) that correspond to the specified
5553 * function ID.
5555 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5556 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5558 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5559 const TLBFuncDesc *pFDesc;
5560 const TLBVarDesc *pVDesc;
5561 int i;
5562 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5563 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
5564 if(pFDesc)
5566 /* function found, now return function and parameter names */
5567 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5569 if(!i)
5570 *rgBstrNames=SysAllocString(pFDesc->Name);
5571 else
5572 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5574 *pcNames=i;
5576 else
5578 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
5579 if(pVDesc)
5581 *rgBstrNames=SysAllocString(pVDesc->Name);
5582 *pcNames=1;
5584 else
5586 if(This->impltypes &&
5587 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5588 /* recursive search */
5589 ITypeInfo *pTInfo;
5590 HRESULT result;
5591 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef,
5592 &pTInfo);
5593 if(SUCCEEDED(result))
5595 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5596 ITypeInfo_Release(pTInfo);
5597 return result;
5599 WARN("Could not search inherited interface!\n");
5601 else
5603 WARN("no names found\n");
5605 *pcNames=0;
5606 return TYPE_E_ELEMENTNOTFOUND;
5609 return S_OK;
5613 /* ITypeInfo::GetRefTypeOfImplType
5615 * If a type description describes a COM class, it retrieves the type
5616 * description of the implemented interface types. For an interface,
5617 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5618 * if any exist.
5621 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5622 ITypeInfo2 *iface,
5623 UINT index,
5624 HREFTYPE *pRefType)
5626 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5627 HRESULT hr = S_OK;
5629 TRACE("(%p) index %d\n", This, index);
5630 if (TRACE_ON(ole)) dump_TypeInfo(This);
5632 if(index==(UINT)-1)
5634 /* only valid on dual interfaces;
5635 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5637 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5639 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
5641 *pRefType = -1;
5643 else
5645 hr = TYPE_E_ELEMENTNOTFOUND;
5648 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5650 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5651 *pRefType = This->pTypeLib->dispatch_href;
5653 else
5655 if(index >= This->TypeAttr.cImplTypes)
5656 hr = TYPE_E_ELEMENTNOTFOUND;
5657 else
5658 *pRefType = This->impltypes[index].hRef;
5661 if(TRACE_ON(ole))
5663 if(SUCCEEDED(hr))
5664 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5665 else
5666 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5669 return hr;
5672 /* ITypeInfo::GetImplTypeFlags
5674 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5675 * or base interface in a type description.
5677 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5678 UINT index, INT *pImplTypeFlags)
5680 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5682 TRACE("(%p) index %d\n", This, index);
5684 if(This->TypeAttr.typekind == TKIND_DISPATCH && index == 0){
5685 *pImplTypeFlags = 0;
5686 return S_OK;
5689 if(index >= This->TypeAttr.cImplTypes)
5690 return TYPE_E_ELEMENTNOTFOUND;
5692 *pImplTypeFlags = This->impltypes[index].implflags;
5694 return S_OK;
5697 /* GetIDsOfNames
5698 * Maps between member names and member IDs, and parameter names and
5699 * parameter IDs.
5701 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5702 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5704 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5705 const TLBVarDesc *pVDesc;
5706 HRESULT ret=S_OK;
5707 UINT i, fdc;
5709 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5710 cNames);
5712 /* init out parameters in case of failure */
5713 for (i = 0; i < cNames; i++)
5714 pMemId[i] = MEMBERID_NIL;
5716 for (fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc) {
5717 int j;
5718 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
5719 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5720 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5721 for(i=1; i < cNames; i++){
5722 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5723 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5724 break;
5725 if( j<pFDesc->funcdesc.cParams)
5726 pMemId[i]=j;
5727 else
5728 ret=DISP_E_UNKNOWNNAME;
5730 TRACE("-- 0x%08x\n", ret);
5731 return ret;
5734 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->TypeAttr.cVars, *rgszNames);
5735 if(pVDesc){
5736 if(cNames)
5737 *pMemId = pVDesc->vardesc.memid;
5738 return ret;
5740 /* not found, see if it can be found in an inherited interface */
5741 if(This->impltypes) {
5742 /* recursive search */
5743 ITypeInfo *pTInfo;
5744 ret=ITypeInfo_GetRefTypeInfo(iface,
5745 This->impltypes[0].hRef, &pTInfo);
5746 if(SUCCEEDED(ret)){
5747 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5748 ITypeInfo_Release(pTInfo);
5749 return ret;
5751 WARN("Could not search inherited interface!\n");
5752 } else
5753 WARN("no names found\n");
5754 return DISP_E_UNKNOWNNAME;
5758 #ifdef __i386__
5760 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
5761 __ASM_GLOBAL_FUNC( call_method,
5762 "pushl %ebp\n\t"
5763 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
5764 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
5765 "movl %esp,%ebp\n\t"
5766 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
5767 "pushl %esi\n\t"
5768 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
5769 "pushl %edi\n\t"
5770 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
5771 "movl 12(%ebp),%edx\n\t"
5772 "movl %esp,%edi\n\t"
5773 "shll $2,%edx\n\t"
5774 "jz 1f\n\t"
5775 "subl %edx,%edi\n\t"
5776 "andl $~15,%edi\n\t"
5777 "movl %edi,%esp\n\t"
5778 "movl 12(%ebp),%ecx\n\t"
5779 "movl 16(%ebp),%esi\n\t"
5780 "cld\n\t"
5781 "rep; movsl\n"
5782 "1:\tcall *8(%ebp)\n\t"
5783 "subl %esp,%edi\n\t"
5784 "movl 20(%ebp),%ecx\n\t"
5785 "movl %edi,(%ecx)\n\t"
5786 "leal -8(%ebp),%esp\n\t"
5787 "popl %edi\n\t"
5788 __ASM_CFI(".cfi_same_value %edi\n\t")
5789 "popl %esi\n\t"
5790 __ASM_CFI(".cfi_same_value %esi\n\t")
5791 "popl %ebp\n\t"
5792 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
5793 __ASM_CFI(".cfi_same_value %ebp\n\t")
5794 "ret" )
5796 /* same function but returning floating point */
5797 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
5799 /* ITypeInfo::Invoke
5801 * Invokes a method, or accesses a property of an object, that implements the
5802 * interface described by the type description.
5804 DWORD
5805 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5806 DWORD res;
5807 int stack_offset;
5809 if (TRACE_ON(ole)) {
5810 int i;
5811 TRACE("Calling %p(",func);
5812 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
5813 if (nrargs > 30) TRACE("...");
5814 TRACE(")\n");
5817 switch (callconv) {
5818 case CC_STDCALL:
5819 case CC_CDECL:
5820 res = call_method( func, nrargs, args, &stack_offset );
5821 break;
5822 default:
5823 FIXME("unsupported calling convention %d\n",callconv);
5824 res = -1;
5825 break;
5827 TRACE("returns %08x\n",res);
5828 return res;
5831 #elif defined(__x86_64__)
5833 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
5834 __ASM_GLOBAL_FUNC( call_method,
5835 "pushq %rbp\n\t"
5836 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
5837 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
5838 "movq %rsp,%rbp\n\t"
5839 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
5840 "pushq %rsi\n\t"
5841 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
5842 "pushq %rdi\n\t"
5843 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
5844 "movq %rcx,%rax\n\t"
5845 "movq $4,%rcx\n\t"
5846 "cmp %rcx,%rdx\n\t"
5847 "cmovgq %rdx,%rcx\n\t"
5848 "leaq 0(,%rcx,8),%rdx\n\t"
5849 "subq %rdx,%rsp\n\t"
5850 "andq $~15,%rsp\n\t"
5851 "movq %rsp,%rdi\n\t"
5852 "movq %r8,%rsi\n\t"
5853 "rep; movsq\n\t"
5854 "movq 0(%rsp),%rcx\n\t"
5855 "movq 8(%rsp),%rdx\n\t"
5856 "movq 16(%rsp),%r8\n\t"
5857 "movq 24(%rsp),%r9\n\t"
5858 "movq %rcx,%xmm0\n\t"
5859 "movq %rdx,%xmm1\n\t"
5860 "movq %r8,%xmm2\n\t"
5861 "movq %r9,%xmm3\n\t"
5862 "callq *%rax\n\t"
5863 "leaq -16(%rbp),%rsp\n\t"
5864 "popq %rdi\n\t"
5865 __ASM_CFI(".cfi_same_value %rdi\n\t")
5866 "popq %rsi\n\t"
5867 __ASM_CFI(".cfi_same_value %rsi\n\t")
5868 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
5869 "popq %rbp\n\t"
5870 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
5871 __ASM_CFI(".cfi_same_value %rbp\n\t")
5872 "ret")
5874 /* same function but returning floating point */
5875 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
5877 #endif /* __x86_64__ */
5879 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5881 HRESULT hr = S_OK;
5882 ITypeInfo *tinfo2 = NULL;
5883 TYPEATTR *tattr = NULL;
5885 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5886 if (hr)
5888 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5889 "hr = 0x%08x\n",
5890 tdesc->u.hreftype, hr);
5891 return hr;
5893 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5894 if (hr)
5896 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5897 ITypeInfo_Release(tinfo2);
5898 return hr;
5901 switch (tattr->typekind)
5903 case TKIND_ENUM:
5904 *vt |= VT_I4;
5905 break;
5907 case TKIND_ALIAS:
5908 tdesc = &tattr->tdescAlias;
5909 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5910 break;
5912 case TKIND_INTERFACE:
5913 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5914 *vt |= VT_DISPATCH;
5915 else
5916 *vt |= VT_UNKNOWN;
5917 break;
5919 case TKIND_DISPATCH:
5920 *vt |= VT_DISPATCH;
5921 break;
5923 case TKIND_COCLASS:
5924 *vt |= VT_DISPATCH;
5925 break;
5927 case TKIND_RECORD:
5928 FIXME("TKIND_RECORD unhandled.\n");
5929 hr = E_NOTIMPL;
5930 break;
5932 case TKIND_UNION:
5933 FIXME("TKIND_UNION unhandled.\n");
5934 hr = E_NOTIMPL;
5935 break;
5937 default:
5938 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5939 hr = E_NOTIMPL;
5940 break;
5942 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5943 ITypeInfo_Release(tinfo2);
5944 return hr;
5947 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5949 HRESULT hr = S_OK;
5951 /* enforce only one level of pointer indirection */
5952 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5954 tdesc = tdesc->u.lptdesc;
5956 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5957 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5958 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5959 if ((tdesc->vt == VT_USERDEFINED) ||
5960 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5962 VARTYPE vt_userdefined = 0;
5963 const TYPEDESC *tdesc_userdefined = tdesc;
5964 if (tdesc->vt == VT_PTR)
5966 vt_userdefined = VT_BYREF;
5967 tdesc_userdefined = tdesc->u.lptdesc;
5969 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5970 if ((hr == S_OK) &&
5971 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5972 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5974 *vt |= vt_userdefined;
5975 return S_OK;
5978 *vt = VT_BYREF;
5981 switch (tdesc->vt)
5983 case VT_HRESULT:
5984 *vt |= VT_ERROR;
5985 break;
5986 case VT_USERDEFINED:
5987 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5988 break;
5989 case VT_VOID:
5990 case VT_CARRAY:
5991 case VT_PTR:
5992 case VT_LPSTR:
5993 case VT_LPWSTR:
5994 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5995 hr = DISP_E_BADVARTYPE;
5996 break;
5997 case VT_SAFEARRAY:
5998 *vt |= VT_ARRAY;
5999 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
6000 break;
6001 case VT_INT:
6002 *vt |= VT_I4;
6003 break;
6004 case VT_UINT:
6005 *vt |= VT_UI4;
6006 break;
6007 default:
6008 *vt |= tdesc->vt;
6009 break;
6011 return hr;
6014 /***********************************************************************
6015 * DispCallFunc (OLEAUT32.@)
6017 * Invokes a function of the specified calling convention, passing the
6018 * specified arguments and returns the result.
6020 * PARAMS
6021 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6022 * oVft [I] The offset in the vtable. See notes.
6023 * cc [I] Calling convention of the function to call.
6024 * vtReturn [I] The return type of the function.
6025 * cActuals [I] Number of parameters.
6026 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6027 * prgpvarg [I] The arguments to pass.
6028 * pvargResult [O] The return value of the function. Can be NULL.
6030 * RETURNS
6031 * Success: S_OK.
6032 * Failure: HRESULT code.
6034 * NOTES
6035 * The HRESULT return value of this function is not affected by the return
6036 * value of the user supplied function, which is returned in pvargResult.
6038 * If pvInstance is NULL then a non-object function is to be called and oVft
6039 * is the address of the function to call.
6041 * The cc parameter can be one of the following values:
6042 *|CC_FASTCALL
6043 *|CC_CDECL
6044 *|CC_PASCAL
6045 *|CC_STDCALL
6046 *|CC_FPFASTCALL
6047 *|CC_SYSCALL
6048 *|CC_MPWCDECL
6049 *|CC_MPWPASCAL
6052 HRESULT WINAPI
6053 DispCallFunc(
6054 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
6055 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
6057 #ifdef __i386__
6058 int argspos, stack_offset;
6059 void *func;
6060 UINT i;
6061 DWORD *args;
6063 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6064 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6065 pvargResult, V_VT(pvargResult));
6067 if (cc != CC_STDCALL && cc != CC_CDECL)
6069 FIXME("unsupported calling convention %d\n",cc);
6070 return E_INVALIDARG;
6073 /* maximum size for an argument is sizeof(VARIANT) */
6074 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6076 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6077 argspos = 1;
6078 if (pvInstance)
6080 const FARPROC *vtable = *(FARPROC **)pvInstance;
6081 func = vtable[oVft/sizeof(void *)];
6082 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6084 else func = (void *)oVft;
6086 for (i = 0; i < cActuals; i++)
6088 VARIANT *arg = prgpvarg[i];
6090 switch (prgvt[i])
6092 case VT_EMPTY:
6093 break;
6094 case VT_I8:
6095 case VT_UI8:
6096 case VT_R8:
6097 case VT_DATE:
6098 case VT_CY:
6099 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6100 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6101 break;
6102 case VT_DECIMAL:
6103 case VT_VARIANT:
6104 memcpy( &args[argspos], arg, sizeof(*arg) );
6105 argspos += sizeof(*arg) / sizeof(DWORD);
6106 break;
6107 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6108 args[argspos++] = V_BOOL(arg);
6109 break;
6110 default:
6111 args[argspos++] = V_UI4(arg);
6112 break;
6114 TRACE("arg %u: type %d\n",i,prgvt[i]);
6115 dump_Variant(arg);
6118 switch (vtReturn)
6120 case VT_EMPTY:
6121 call_method( func, argspos - 1, args + 1, &stack_offset );
6122 break;
6123 case VT_R4:
6124 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6125 break;
6126 case VT_R8:
6127 case VT_DATE:
6128 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6129 break;
6130 case VT_DECIMAL:
6131 case VT_VARIANT:
6132 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6133 call_method( func, argspos, args, &stack_offset );
6134 break;
6135 case VT_I8:
6136 case VT_UI8:
6137 case VT_CY:
6138 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6139 break;
6140 default:
6141 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6142 break;
6144 heap_free( args );
6145 if (stack_offset && cc == CC_STDCALL)
6147 WARN( "stack pointer off by %d\n", stack_offset );
6148 return DISP_E_BADCALLEE;
6150 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6151 TRACE("retval: "); dump_Variant(pvargResult);
6152 return S_OK;
6154 #elif defined(__x86_64__)
6155 int argspos;
6156 UINT i;
6157 DWORD_PTR *args;
6158 void *func;
6160 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6161 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6162 pvargResult, V_VT(pvargResult));
6164 if (cc != CC_STDCALL && cc != CC_CDECL)
6166 FIXME("unsupported calling convention %d\n",cc);
6167 return E_INVALIDARG;
6170 /* maximum size for an argument is sizeof(DWORD_PTR) */
6171 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6173 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6174 argspos = 1;
6175 if (pvInstance)
6177 const FARPROC *vtable = *(FARPROC **)pvInstance;
6178 func = vtable[oVft/sizeof(void *)];
6179 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6181 else func = (void *)oVft;
6183 for (i = 0; i < cActuals; i++)
6185 VARIANT *arg = prgpvarg[i];
6187 switch (prgvt[i])
6189 case VT_DECIMAL:
6190 case VT_VARIANT:
6191 args[argspos++] = (ULONG_PTR)arg;
6192 break;
6193 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6194 args[argspos++] = V_BOOL(arg);
6195 break;
6196 default:
6197 args[argspos++] = V_UI8(arg);
6198 break;
6200 TRACE("arg %u: type %d\n",i,prgvt[i]);
6201 dump_Variant(arg);
6204 switch (vtReturn)
6206 case VT_R4:
6207 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6208 break;
6209 case VT_R8:
6210 case VT_DATE:
6211 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6212 break;
6213 case VT_DECIMAL:
6214 case VT_VARIANT:
6215 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6216 call_method( func, argspos, args );
6217 break;
6218 default:
6219 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6220 break;
6222 heap_free( args );
6223 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6224 TRACE("retval: "); dump_Variant(pvargResult);
6225 return S_OK;
6227 #else
6228 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6229 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6230 return E_NOTIMPL;
6231 #endif
6234 #define INVBUF_ELEMENT_SIZE \
6235 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6236 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6237 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6238 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6239 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6240 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6241 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6242 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6244 static HRESULT WINAPI ITypeInfo_fnInvoke(
6245 ITypeInfo2 *iface,
6246 VOID *pIUnk,
6247 MEMBERID memid,
6248 UINT16 wFlags,
6249 DISPPARAMS *pDispParams,
6250 VARIANT *pVarResult,
6251 EXCEPINFO *pExcepInfo,
6252 UINT *pArgErr)
6254 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6255 int i;
6256 unsigned int var_index;
6257 TYPEKIND type_kind;
6258 HRESULT hres;
6259 const TLBFuncDesc *pFuncInfo;
6260 UINT fdc;
6262 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6263 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6266 if( This->TypeAttr.wTypeFlags & TYPEFLAG_FRESTRICTED )
6267 return DISP_E_MEMBERNOTFOUND;
6269 if (!pDispParams)
6271 ERR("NULL pDispParams not allowed\n");
6272 return E_INVALIDARG;
6275 dump_DispParms(pDispParams);
6277 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6279 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6280 pDispParams->cNamedArgs, pDispParams->cArgs);
6281 return E_INVALIDARG;
6284 /* we do this instead of using GetFuncDesc since it will return a fake
6285 * FUNCDESC for dispinterfaces and we want the real function description */
6286 for (fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc){
6287 pFuncInfo = &This->funcdescs[fdc];
6288 if ((memid == pFuncInfo->funcdesc.memid) &&
6289 (wFlags & pFuncInfo->funcdesc.invkind) &&
6290 (pFuncInfo->funcdesc.wFuncFlags & FUNCFLAG_FRESTRICTED) == 0)
6291 break;
6294 if (fdc < This->TypeAttr.cFuncs) {
6295 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6297 if (TRACE_ON(ole))
6299 TRACE("invoking:\n");
6300 dump_TLBFuncDescOne(pFuncInfo);
6303 switch (func_desc->funckind) {
6304 case FUNC_PUREVIRTUAL:
6305 case FUNC_VIRTUAL: {
6306 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
6307 VARIANT varresult;
6308 VARIANT retval; /* pointer for storing byref retvals in */
6309 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6310 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6311 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6312 UINT cNamedArgs = pDispParams->cNamedArgs;
6313 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6314 UINT vargs_converted=0;
6316 hres = S_OK;
6318 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6320 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6322 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6323 hres = DISP_E_PARAMNOTFOUND;
6324 goto func_fail;
6328 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6330 ERR("functions with the vararg attribute do not support named arguments\n");
6331 hres = DISP_E_NONAMEDARGS;
6332 goto func_fail;
6335 for (i = 0; i < func_desc->cParams; i++)
6337 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6338 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6339 if (FAILED(hres))
6340 goto func_fail;
6343 TRACE("changing args\n");
6344 for (i = 0; i < func_desc->cParams; i++)
6346 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6347 VARIANTARG *src_arg;
6349 if (wParamFlags & PARAMFLAG_FLCID)
6351 VARIANTARG *arg;
6352 arg = prgpvarg[i] = &rgvarg[i];
6353 V_VT(arg) = VT_I4;
6354 V_I4(arg) = This->pTypeLib->lcid;
6355 continue;
6358 src_arg = NULL;
6360 if (cNamedArgs)
6362 USHORT j;
6363 for (j = 0; j < cNamedArgs; j++)
6364 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
6366 src_arg = &pDispParams->rgvarg[j];
6367 break;
6371 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
6373 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6374 vargs_converted++;
6377 if (wParamFlags & PARAMFLAG_FRETVAL)
6379 /* under most conditions the caller is not allowed to
6380 * pass in a dispparam arg in the index of what would be
6381 * the retval parameter. however, there is an exception
6382 * where the extra parameter is used in an extra
6383 * IDispatch::Invoke below */
6384 if ((i < pDispParams->cArgs) &&
6385 ((func_desc->cParams != 1) || !pVarResult ||
6386 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6388 hres = DISP_E_BADPARAMCOUNT;
6389 break;
6392 /* note: this check is placed so that if the caller passes
6393 * in a VARIANTARG for the retval we just ignore it, like
6394 * native does */
6395 if (i == func_desc->cParams - 1)
6397 VARIANTARG *arg;
6398 arg = prgpvarg[i] = &rgvarg[i];
6399 memset(arg, 0, sizeof(*arg));
6400 V_VT(arg) = rgvt[i];
6401 memset(&retval, 0, sizeof(retval));
6402 V_BYREF(arg) = &retval;
6404 else
6406 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6407 hres = E_UNEXPECTED;
6408 break;
6411 else if (src_arg)
6413 dump_Variant(src_arg);
6415 if (rgvt[i] == VT_VARIANT)
6416 hres = VariantCopy(&rgvarg[i], src_arg);
6417 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6419 if (rgvt[i] == V_VT(src_arg))
6420 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6421 else
6423 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6424 if (wParamFlags & PARAMFLAG_FIN)
6425 hres = VariantCopy(&missing_arg[i], src_arg);
6426 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6428 V_VT(&rgvarg[i]) = rgvt[i];
6430 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6432 SAFEARRAY *a;
6433 SAFEARRAYBOUND bound;
6434 VARIANT *v;
6435 LONG j;
6436 bound.lLbound = 0;
6437 bound.cElements = pDispParams->cArgs-i;
6438 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6440 ERR("SafeArrayCreate failed\n");
6441 break;
6443 hres = SafeArrayAccessData(a, (LPVOID)&v);
6444 if (hres != S_OK)
6446 ERR("SafeArrayAccessData failed with %x\n", hres);
6447 break;
6449 for (j = 0; j < bound.cElements; j++)
6450 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6451 hres = SafeArrayUnaccessData(a);
6452 if (hres != S_OK)
6454 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6455 break;
6457 V_ARRAY(&rgvarg[i]) = a;
6458 V_VT(&rgvarg[i]) = rgvt[i];
6460 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6462 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6463 if (wParamFlags & PARAMFLAG_FIN)
6464 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6465 else
6466 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
6467 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6468 V_VT(&rgvarg[i]) = rgvt[i];
6470 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6472 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6473 V_VT(&rgvarg[i]) = rgvt[i];
6475 else
6477 /* FIXME: this doesn't work for VT_BYREF arguments if
6478 * they are not the same type as in the paramdesc */
6479 V_VT(&rgvarg[i]) = V_VT(src_arg);
6480 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6481 V_VT(&rgvarg[i]) = rgvt[i];
6484 if (FAILED(hres))
6486 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6487 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6488 debugstr_VT(src_arg), debugstr_VF(src_arg));
6489 break;
6491 prgpvarg[i] = &rgvarg[i];
6493 else if (wParamFlags & PARAMFLAG_FOPT)
6495 VARIANTARG *arg;
6496 arg = prgpvarg[i] = &rgvarg[i];
6497 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6499 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6500 if (FAILED(hres))
6501 break;
6503 else
6505 VARIANTARG *missing_arg;
6506 /* if the function wants a pointer to a variant then
6507 * set that up, otherwise just pass the VT_ERROR in
6508 * the argument by value */
6509 if (rgvt[i] & VT_BYREF)
6511 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6512 V_VT(arg) = VT_VARIANT | VT_BYREF;
6513 V_VARIANTREF(arg) = missing_arg;
6515 else
6516 missing_arg = arg;
6517 V_VT(missing_arg) = VT_ERROR;
6518 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6521 else
6523 hres = DISP_E_BADPARAMCOUNT;
6524 break;
6527 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6529 /* VT_VOID is a special case for return types, so it is not
6530 * handled in the general function */
6531 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6532 V_VT(&varresult) = VT_EMPTY;
6533 else
6535 V_VT(&varresult) = 0;
6536 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6537 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6540 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6541 V_VT(&varresult), func_desc->cParams, rgvt,
6542 prgpvarg, &varresult);
6544 vargs_converted = 0;
6546 for (i = 0; i < func_desc->cParams; i++)
6548 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6549 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6551 if (wParamFlags & PARAMFLAG_FLCID)
6552 continue;
6553 else if (wParamFlags & PARAMFLAG_FRETVAL)
6555 if (TRACE_ON(ole))
6557 TRACE("[retval] value: ");
6558 dump_Variant(prgpvarg[i]);
6561 if (pVarResult)
6563 VariantInit(pVarResult);
6564 /* deref return value */
6565 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6568 VARIANT_ClearInd(prgpvarg[i]);
6570 else if (vargs_converted < pDispParams->cArgs)
6572 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6573 if (wParamFlags & PARAMFLAG_FOUT)
6575 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
6577 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6579 if (FAILED(hres))
6581 ERR("failed to convert param %d to vt %d\n", i,
6582 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
6583 break;
6587 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6588 func_desc->cParamsOpt < 0 &&
6589 i == func_desc->cParams-1)
6591 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6592 LONG j, ubound;
6593 VARIANT *v;
6594 hres = SafeArrayGetUBound(a, 1, &ubound);
6595 if (hres != S_OK)
6597 ERR("SafeArrayGetUBound failed with %x\n", hres);
6598 break;
6600 hres = SafeArrayAccessData(a, (LPVOID)&v);
6601 if (hres != S_OK)
6603 ERR("SafeArrayAccessData failed with %x\n", hres);
6604 break;
6606 for (j = 0; j <= ubound; j++)
6607 VariantClear(&v[j]);
6608 hres = SafeArrayUnaccessData(a);
6609 if (hres != S_OK)
6611 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6612 break;
6615 VariantClear(&rgvarg[i]);
6616 vargs_converted++;
6618 else if (wParamFlags & PARAMFLAG_FOPT)
6620 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6621 VariantClear(&rgvarg[i]);
6624 VariantClear(&missing_arg[i]);
6627 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6629 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6630 hres = DISP_E_EXCEPTION;
6631 if (pExcepInfo)
6633 IErrorInfo *pErrorInfo;
6634 pExcepInfo->scode = V_ERROR(&varresult);
6635 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6637 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6638 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6639 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6640 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6642 IErrorInfo_Release(pErrorInfo);
6646 if (V_VT(&varresult) != VT_ERROR)
6648 TRACE("varresult value: ");
6649 dump_Variant(&varresult);
6651 if (pVarResult)
6653 VariantClear(pVarResult);
6654 *pVarResult = varresult;
6656 else
6657 VariantClear(&varresult);
6660 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6661 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6662 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6663 (pDispParams->cArgs != 0))
6665 if (V_VT(pVarResult) == VT_DISPATCH)
6667 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6668 /* Note: not VariantClear; we still need the dispatch
6669 * pointer to be valid */
6670 VariantInit(pVarResult);
6671 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6672 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6673 pDispParams, pVarResult, pExcepInfo, pArgErr);
6674 IDispatch_Release(pDispatch);
6676 else
6678 VariantClear(pVarResult);
6679 hres = DISP_E_NOTACOLLECTION;
6683 func_fail:
6684 heap_free(buffer);
6685 break;
6687 case FUNC_DISPATCH: {
6688 IDispatch *disp;
6690 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6691 if (SUCCEEDED(hres)) {
6692 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6693 hres = IDispatch_Invoke(
6694 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6695 pVarResult,pExcepInfo,pArgErr
6697 if (FAILED(hres))
6698 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6699 IDispatch_Release(disp);
6700 } else
6701 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6702 break;
6704 default:
6705 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6706 hres = E_FAIL;
6707 break;
6710 TRACE("-- 0x%08x\n", hres);
6711 return hres;
6713 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6714 VARDESC *var_desc;
6716 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6717 if(FAILED(hres)) return hres;
6719 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6720 dump_VARDESC(var_desc);
6721 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6722 return E_NOTIMPL;
6725 /* not found, look for it in inherited interfaces */
6726 ITypeInfo2_GetTypeKind(iface, &type_kind);
6727 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6728 if(This->impltypes) {
6729 /* recursive search */
6730 ITypeInfo *pTInfo;
6731 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6732 if(SUCCEEDED(hres)){
6733 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6734 ITypeInfo_Release(pTInfo);
6735 return hres;
6737 WARN("Could not search inherited interface!\n");
6740 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6741 return DISP_E_MEMBERNOTFOUND;
6744 /* ITypeInfo::GetDocumentation
6746 * Retrieves the documentation string, the complete Help file name and path,
6747 * and the context ID for the Help topic for a specified type description.
6749 * (Can be tested by the Visual Basic Editor in Word for instance.)
6751 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6752 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6753 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6755 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6756 const TLBFuncDesc *pFDesc;
6757 const TLBVarDesc *pVDesc;
6758 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6759 " HelpContext(%p) HelpFile(%p)\n",
6760 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6761 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6762 if(pBstrName)
6763 *pBstrName=SysAllocString(This->Name);
6764 if(pBstrDocString)
6765 *pBstrDocString=SysAllocString(This->DocString);
6766 if(pdwHelpContext)
6767 *pdwHelpContext=This->dwHelpContext;
6768 if(pBstrHelpFile)
6769 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6770 return S_OK;
6771 }else {/* for a member */
6772 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
6773 if(pFDesc){
6774 if(pBstrName)
6775 *pBstrName = SysAllocString(pFDesc->Name);
6776 if(pBstrDocString)
6777 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6778 if(pdwHelpContext)
6779 *pdwHelpContext=pFDesc->helpcontext;
6780 return S_OK;
6782 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
6783 if(pVDesc){
6784 if(pBstrName)
6785 *pBstrName = SysAllocString(pVDesc->Name);
6786 if(pBstrDocString)
6787 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6788 if(pdwHelpContext)
6789 *pdwHelpContext=pVDesc->HelpContext;
6790 return S_OK;
6794 if(This->impltypes &&
6795 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6796 /* recursive search */
6797 ITypeInfo *pTInfo;
6798 HRESULT result;
6799 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef,
6800 &pTInfo);
6801 if(SUCCEEDED(result)) {
6802 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6803 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6804 ITypeInfo_Release(pTInfo);
6805 return result;
6807 WARN("Could not search inherited interface!\n");
6810 WARN("member %d not found\n", memid);
6811 return TYPE_E_ELEMENTNOTFOUND;
6814 /* ITypeInfo::GetDllEntry
6816 * Retrieves a description or specification of an entry point for a function
6817 * in a DLL.
6819 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6820 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6821 WORD *pwOrdinal)
6823 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6824 const TLBFuncDesc *pFDesc;
6826 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6828 if (pBstrDllName) *pBstrDllName = NULL;
6829 if (pBstrName) *pBstrName = NULL;
6830 if (pwOrdinal) *pwOrdinal = 0;
6832 if (This->TypeAttr.typekind != TKIND_MODULE)
6833 return TYPE_E_BADMODULEKIND;
6835 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
6836 if(pFDesc){
6837 dump_TypeInfo(This);
6838 if (TRACE_ON(ole))
6839 dump_TLBFuncDescOne(pFDesc);
6841 if (pBstrDllName)
6842 *pBstrDllName = SysAllocString(This->DllName);
6844 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6845 if (pBstrName)
6846 *pBstrName = SysAllocString(pFDesc->Entry);
6847 if (pwOrdinal)
6848 *pwOrdinal = -1;
6849 return S_OK;
6851 if (pBstrName)
6852 *pBstrName = NULL;
6853 if (pwOrdinal)
6854 *pwOrdinal = LOWORD(pFDesc->Entry);
6855 return S_OK;
6857 return TYPE_E_ELEMENTNOTFOUND;
6860 /* internal function to make the inherited interfaces' methods appear
6861 * part of the interface */
6862 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6863 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6865 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6866 HRESULT hr;
6868 TRACE("%p, 0x%x\n", iface, *hRefType);
6870 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
6872 ITypeInfo *pSubTypeInfo;
6874 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
6875 if (FAILED(hr))
6876 return hr;
6878 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6879 hRefType, ppTInfo);
6880 ITypeInfo_Release(pSubTypeInfo);
6881 if (SUCCEEDED(hr))
6882 return hr;
6884 *hRefType -= DISPATCH_HREF_OFFSET;
6886 if (!(*hRefType & DISPATCH_HREF_MASK))
6887 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6888 else
6889 return E_FAIL;
6892 /* ITypeInfo::GetRefTypeInfo
6894 * If a type description references other type descriptions, it retrieves
6895 * the referenced type descriptions.
6897 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6898 ITypeInfo2 *iface,
6899 HREFTYPE hRefType,
6900 ITypeInfo **ppTInfo)
6902 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6903 HRESULT result = E_FAIL;
6905 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6907 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6908 ITypeInfo_AddRef(*ppTInfo);
6909 result = S_OK;
6911 else if (hRefType == -1 &&
6912 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6913 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6915 /* when we meet a DUAL dispinterface, we must create the interface
6916 * version of it.
6918 ITypeInfoImpl *pTypeInfoImpl = ITypeInfoImpl_Constructor();
6921 /* the interface version contains the same information as the dispinterface
6922 * copy the contents of the structs.
6924 *pTypeInfoImpl = *This;
6925 pTypeInfoImpl->ref = 0;
6927 /* change the type to interface */
6928 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6930 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6932 /* the AddRef implicitly adds a reference to the parent typelib, which
6933 * stops the copied data from being destroyed until the new typeinfo's
6934 * refcount goes to zero, but we need to signal to the new instance to
6935 * not free its data structures when it is destroyed */
6936 pTypeInfoImpl->not_attached_to_typelib = TRUE;
6938 ITypeInfo_AddRef(*ppTInfo);
6940 result = S_OK;
6942 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6943 (This->TypeAttr.typekind == TKIND_DISPATCH))
6945 HREFTYPE href_dispatch = hRefType;
6946 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6947 } else {
6948 TLBRefType *ref_type;
6949 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6951 if(ref_type->reference == hRefType)
6952 break;
6954 if(&ref_type->entry == &This->pTypeLib->ref_list)
6956 FIXME("Can't find pRefType for ref %x\n", hRefType);
6957 goto end;
6959 if(hRefType != -1) {
6960 ITypeLib *pTLib = NULL;
6962 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6963 UINT Index;
6964 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6965 } else {
6966 if(ref_type->pImpTLInfo->pImpTypeLib) {
6967 TRACE("typeinfo in imported typelib that is already loaded\n");
6968 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6969 ITypeLib2_AddRef(pTLib);
6970 result = S_OK;
6971 } else {
6972 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6973 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6974 ref_type->pImpTLInfo->wVersionMajor,
6975 ref_type->pImpTLInfo->wVersionMinor,
6976 ref_type->pImpTLInfo->lcid,
6977 &pTLib);
6979 if(FAILED(result)) {
6980 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6981 result=LoadTypeLib(libnam, &pTLib);
6982 SysFreeString(libnam);
6984 if(SUCCEEDED(result)) {
6985 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6986 ITypeLib2_AddRef(pTLib);
6990 if(SUCCEEDED(result)) {
6991 if(ref_type->index == TLB_REF_USE_GUID)
6992 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6993 &ref_type->guid,
6994 ppTInfo);
6995 else
6996 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6997 ppTInfo);
6999 if (pTLib != NULL)
7000 ITypeLib2_Release(pTLib);
7004 end:
7005 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
7006 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
7007 return result;
7010 /* ITypeInfo::AddressOfMember
7012 * Retrieves the addresses of static functions or variables, such as those
7013 * defined in a DLL.
7015 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
7016 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
7018 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7019 HRESULT hr;
7020 BSTR dll, entry;
7021 WORD ordinal;
7022 HMODULE module;
7024 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
7026 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
7027 if (FAILED(hr))
7028 return hr;
7030 module = LoadLibraryW(dll);
7031 if (!module)
7033 ERR("couldn't load %s\n", debugstr_w(dll));
7034 SysFreeString(dll);
7035 SysFreeString(entry);
7036 return STG_E_FILENOTFOUND;
7038 /* FIXME: store library somewhere where we can free it */
7040 if (entry)
7042 LPSTR entryA;
7043 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
7044 entryA = heap_alloc(len);
7045 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
7047 *ppv = GetProcAddress(module, entryA);
7048 if (!*ppv)
7049 ERR("function not found %s\n", debugstr_a(entryA));
7051 heap_free(entryA);
7053 else
7055 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7056 if (!*ppv)
7057 ERR("function not found %d\n", ordinal);
7060 SysFreeString(dll);
7061 SysFreeString(entry);
7063 if (!*ppv)
7064 return TYPE_E_DLLFUNCTIONNOTFOUND;
7066 return S_OK;
7069 /* ITypeInfo::CreateInstance
7071 * Creates a new instance of a type that describes a component object class
7072 * (coclass).
7074 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7075 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7077 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7078 HRESULT hr;
7079 TYPEATTR *pTA;
7081 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7083 *ppvObj = NULL;
7085 if(pOuterUnk)
7087 WARN("Not able to aggregate\n");
7088 return CLASS_E_NOAGGREGATION;
7091 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
7092 if(FAILED(hr)) return hr;
7094 if(pTA->typekind != TKIND_COCLASS)
7096 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7097 hr = E_INVALIDARG;
7098 goto end;
7101 hr = S_FALSE;
7102 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7104 IUnknown *pUnk;
7105 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7106 TRACE("GetActiveObject rets %08x\n", hr);
7107 if(hr == S_OK)
7109 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7110 IUnknown_Release(pUnk);
7114 if(hr != S_OK)
7115 hr = CoCreateInstance(&pTA->guid, NULL,
7116 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7117 riid, ppvObj);
7119 end:
7120 ITypeInfo_ReleaseTypeAttr(iface, pTA);
7121 return hr;
7124 /* ITypeInfo::GetMops
7126 * Retrieves marshalling information.
7128 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7129 BSTR *pBstrMops)
7131 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7132 FIXME("(%p %d) stub!\n", This, memid);
7133 *pBstrMops = NULL;
7134 return S_OK;
7137 /* ITypeInfo::GetContainingTypeLib
7139 * Retrieves the containing type library and the index of the type description
7140 * within that type library.
7142 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7143 ITypeLib * *ppTLib, UINT *pIndex)
7145 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7147 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7148 if (pIndex) {
7149 *pIndex=This->index;
7150 TRACE("returning pIndex=%d\n", *pIndex);
7153 if (ppTLib) {
7154 *ppTLib=(LPTYPELIB )(This->pTypeLib);
7155 ITypeLib2_AddRef(*ppTLib);
7156 TRACE("returning ppTLib=%p\n", *ppTLib);
7159 return S_OK;
7162 /* ITypeInfo::ReleaseTypeAttr
7164 * Releases a TYPEATTR previously returned by GetTypeAttr.
7167 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7168 TYPEATTR* pTypeAttr)
7170 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7171 TRACE("(%p)->(%p)\n", This, pTypeAttr);
7172 heap_free(pTypeAttr);
7175 /* ITypeInfo::ReleaseFuncDesc
7177 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7179 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7180 ITypeInfo2 *iface,
7181 FUNCDESC *pFuncDesc)
7183 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7184 SHORT i;
7186 TRACE("(%p)->(%p)\n", This, pFuncDesc);
7188 for (i = 0; i < pFuncDesc->cParams; i++)
7189 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7190 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7192 SysFreeString((BSTR)pFuncDesc);
7195 /* ITypeInfo::ReleaseVarDesc
7197 * Releases a VARDESC previously returned by GetVarDesc.
7199 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7200 VARDESC *pVarDesc)
7202 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7203 TRACE("(%p)->(%p)\n", This, pVarDesc);
7205 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
7206 if (pVarDesc->varkind == VAR_CONST)
7207 VariantClear(pVarDesc->u.lpvarValue);
7208 SysFreeString((BSTR)pVarDesc);
7211 /* ITypeInfo2::GetTypeKind
7213 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7216 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7217 TYPEKIND *pTypeKind)
7219 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7220 *pTypeKind=This->TypeAttr.typekind;
7221 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7222 return S_OK;
7225 /* ITypeInfo2::GetTypeFlags
7227 * Returns the type flags without any allocations. This returns a DWORD type
7228 * flag, which expands the type flags without growing the TYPEATTR (type
7229 * attribute).
7232 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7234 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7235 *pTypeFlags=This->TypeAttr.wTypeFlags;
7236 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7237 return S_OK;
7240 /* ITypeInfo2::GetFuncIndexOfMemId
7241 * Binds to a specific member based on a known DISPID, where the member name
7242 * is not known (for example, when binding to a default member).
7245 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7246 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7248 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7249 UINT fdc;
7250 HRESULT result;
7252 for (fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc){
7253 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
7254 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7255 break;
7257 if(fdc < This->TypeAttr.cFuncs) {
7258 *pFuncIndex = fdc;
7259 result = S_OK;
7260 } else
7261 result = TYPE_E_ELEMENTNOTFOUND;
7263 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7264 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7265 return result;
7268 /* TypeInfo2::GetVarIndexOfMemId
7270 * Binds to a specific member based on a known DISPID, where the member name
7271 * is not known (for example, when binding to a default member).
7274 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7275 MEMBERID memid, UINT *pVarIndex)
7277 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7278 TLBVarDesc *pVarInfo;
7280 TRACE("%p %d %p\n", iface, memid, pVarIndex);
7282 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
7283 if(!pVarInfo)
7284 return TYPE_E_ELEMENTNOTFOUND;
7286 *pVarIndex = (pVarInfo - This->vardescs);
7288 return S_OK;
7291 /* ITypeInfo2::GetCustData
7293 * Gets the custom data
7295 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7296 ITypeInfo2 * iface,
7297 REFGUID guid,
7298 VARIANT *pVarVal)
7300 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7301 TLBCustData *pCData;
7303 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7305 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
7307 VariantInit( pVarVal);
7308 if (pCData)
7309 VariantCopy( pVarVal, &pCData->data);
7310 else
7311 VariantClear( pVarVal );
7312 return S_OK;
7315 /* ITypeInfo2::GetFuncCustData
7317 * Gets the custom data
7319 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7320 ITypeInfo2 * iface,
7321 UINT index,
7322 REFGUID guid,
7323 VARIANT *pVarVal)
7325 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7326 TLBCustData *pCData;
7327 TLBFuncDesc *pFDesc = &This->funcdescs[index];
7329 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
7331 if(index >= This->TypeAttr.cFuncs)
7332 return TYPE_E_ELEMENTNOTFOUND;
7334 pCData = TLB_get_custdata_by_guid(&pFDesc->custdata_list, guid);
7335 if(!pCData)
7336 return TYPE_E_ELEMENTNOTFOUND;
7338 VariantInit(pVarVal);
7339 VariantCopy(pVarVal, &pCData->data);
7341 return S_OK;
7344 /* ITypeInfo2::GetParamCustData
7346 * Gets the custom data
7348 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7349 ITypeInfo2 * iface,
7350 UINT indexFunc,
7351 UINT indexParam,
7352 REFGUID guid,
7353 VARIANT *pVarVal)
7355 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7356 TLBCustData *pCData;
7357 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
7359 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
7360 debugstr_guid(guid), pVarVal);
7362 if(indexFunc >= This->TypeAttr.cFuncs)
7363 return TYPE_E_ELEMENTNOTFOUND;
7365 if(indexParam >= pFDesc->funcdesc.cParams)
7366 return TYPE_E_ELEMENTNOTFOUND;
7368 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
7369 if(!pCData)
7370 return TYPE_E_ELEMENTNOTFOUND;
7372 VariantInit(pVarVal);
7373 VariantCopy(pVarVal, &pCData->data);
7375 return S_OK;
7378 /* ITypeInfo2::GetVarCustData
7380 * Gets the custom data
7382 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7383 ITypeInfo2 * iface,
7384 UINT index,
7385 REFGUID guid,
7386 VARIANT *pVarVal)
7388 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7389 TLBCustData *pCData;
7390 TLBVarDesc *pVDesc = &This->vardescs[index];
7392 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7394 if(index >= This->TypeAttr.cVars)
7395 return TYPE_E_ELEMENTNOTFOUND;
7397 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
7398 if(!pCData)
7399 return TYPE_E_ELEMENTNOTFOUND;
7401 VariantInit(pVarVal);
7402 VariantCopy(pVarVal, &pCData->data);
7404 return S_OK;
7407 /* ITypeInfo2::GetImplCustData
7409 * Gets the custom data
7411 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7412 ITypeInfo2 * iface,
7413 UINT index,
7414 REFGUID guid,
7415 VARIANT *pVarVal)
7417 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7418 TLBCustData *pCData;
7419 TLBImplType *pRDesc = &This->impltypes[index];
7421 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
7423 if(index >= This->TypeAttr.cImplTypes)
7424 return TYPE_E_ELEMENTNOTFOUND;
7426 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
7427 if(!pCData)
7428 return TYPE_E_ELEMENTNOTFOUND;
7430 VariantInit(pVarVal);
7431 VariantCopy(pVarVal, &pCData->data);
7433 return S_OK;
7436 /* ITypeInfo2::GetDocumentation2
7438 * Retrieves the documentation string, the complete Help file name and path,
7439 * the localization context to use, and the context ID for the library Help
7440 * topic in the Help file.
7443 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7444 ITypeInfo2 * iface,
7445 MEMBERID memid,
7446 LCID lcid,
7447 BSTR *pbstrHelpString,
7448 DWORD *pdwHelpStringContext,
7449 BSTR *pbstrHelpStringDll)
7451 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7452 const TLBFuncDesc *pFDesc;
7453 const TLBVarDesc *pVDesc;
7454 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7455 "HelpStringContext(%p) HelpStringDll(%p)\n",
7456 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7457 pbstrHelpStringDll );
7458 /* the help string should be obtained from the helpstringdll,
7459 * using the _DLLGetDocumentation function, based on the supplied
7460 * lcid. Nice to do sometime...
7462 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7463 if(pbstrHelpString)
7464 *pbstrHelpString=SysAllocString(This->Name);
7465 if(pdwHelpStringContext)
7466 *pdwHelpStringContext=This->dwHelpStringContext;
7467 if(pbstrHelpStringDll)
7468 *pbstrHelpStringDll=
7469 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7470 return S_OK;
7471 }else {/* for a member */
7472 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
7473 if(pFDesc){
7474 if(pbstrHelpString)
7475 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
7476 if(pdwHelpStringContext)
7477 *pdwHelpStringContext=pFDesc->HelpStringContext;
7478 if(pbstrHelpStringDll)
7479 *pbstrHelpStringDll=
7480 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7481 return S_OK;
7483 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
7484 if(pVDesc){
7485 if(pbstrHelpString)
7486 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
7487 if(pdwHelpStringContext)
7488 *pdwHelpStringContext=pVDesc->HelpStringContext;
7489 if(pbstrHelpStringDll)
7490 *pbstrHelpStringDll=
7491 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7492 return S_OK;
7495 return TYPE_E_ELEMENTNOTFOUND;
7498 /* ITypeInfo2::GetAllCustData
7500 * Gets all custom data items for the Type info.
7503 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7504 ITypeInfo2 * iface,
7505 CUSTDATA *pCustData)
7507 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7509 TRACE("%p %p\n", This, pCustData);
7511 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
7514 /* ITypeInfo2::GetAllFuncCustData
7516 * Gets all custom data items for the specified Function
7519 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7520 ITypeInfo2 * iface,
7521 UINT index,
7522 CUSTDATA *pCustData)
7524 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7525 TLBFuncDesc *pFDesc = &This->funcdescs[index];
7527 TRACE("%p %u %p\n", This, index, pCustData);
7529 if(index >= This->TypeAttr.cFuncs)
7530 return TYPE_E_ELEMENTNOTFOUND;
7532 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
7535 /* ITypeInfo2::GetAllParamCustData
7537 * Gets all custom data items for the Functions
7540 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7541 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7543 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7544 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
7546 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
7548 if(indexFunc >= This->TypeAttr.cFuncs)
7549 return TYPE_E_ELEMENTNOTFOUND;
7551 if(indexParam >= pFDesc->funcdesc.cParams)
7552 return TYPE_E_ELEMENTNOTFOUND;
7554 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
7557 /* ITypeInfo2::GetAllVarCustData
7559 * Gets all custom data items for the specified Variable
7562 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7563 UINT index, CUSTDATA *pCustData)
7565 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7566 TLBVarDesc * pVDesc = &This->vardescs[index];
7568 TRACE("%p %u %p\n", This, index, pCustData);
7570 if(index >= This->TypeAttr.cVars)
7571 return TYPE_E_ELEMENTNOTFOUND;
7573 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
7576 /* ITypeInfo2::GetAllImplCustData
7578 * Gets all custom data items for the specified implementation type
7581 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7582 ITypeInfo2 * iface,
7583 UINT index,
7584 CUSTDATA *pCustData)
7586 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7587 TLBImplType *pRDesc = &This->impltypes[index];
7589 TRACE("%p %u %p\n", This, index, pCustData);
7591 if(index >= This->TypeAttr.cImplTypes)
7592 return TYPE_E_ELEMENTNOTFOUND;
7594 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
7597 static const ITypeInfo2Vtbl tinfvt =
7600 ITypeInfo_fnQueryInterface,
7601 ITypeInfo_fnAddRef,
7602 ITypeInfo_fnRelease,
7604 ITypeInfo_fnGetTypeAttr,
7605 ITypeInfo_fnGetTypeComp,
7606 ITypeInfo_fnGetFuncDesc,
7607 ITypeInfo_fnGetVarDesc,
7608 ITypeInfo_fnGetNames,
7609 ITypeInfo_fnGetRefTypeOfImplType,
7610 ITypeInfo_fnGetImplTypeFlags,
7611 ITypeInfo_fnGetIDsOfNames,
7612 ITypeInfo_fnInvoke,
7613 ITypeInfo_fnGetDocumentation,
7614 ITypeInfo_fnGetDllEntry,
7615 ITypeInfo_fnGetRefTypeInfo,
7616 ITypeInfo_fnAddressOfMember,
7617 ITypeInfo_fnCreateInstance,
7618 ITypeInfo_fnGetMops,
7619 ITypeInfo_fnGetContainingTypeLib,
7620 ITypeInfo_fnReleaseTypeAttr,
7621 ITypeInfo_fnReleaseFuncDesc,
7622 ITypeInfo_fnReleaseVarDesc,
7624 ITypeInfo2_fnGetTypeKind,
7625 ITypeInfo2_fnGetTypeFlags,
7626 ITypeInfo2_fnGetFuncIndexOfMemId,
7627 ITypeInfo2_fnGetVarIndexOfMemId,
7628 ITypeInfo2_fnGetCustData,
7629 ITypeInfo2_fnGetFuncCustData,
7630 ITypeInfo2_fnGetParamCustData,
7631 ITypeInfo2_fnGetVarCustData,
7632 ITypeInfo2_fnGetImplTypeCustData,
7633 ITypeInfo2_fnGetDocumentation2,
7634 ITypeInfo2_fnGetAllCustData,
7635 ITypeInfo2_fnGetAllFuncCustData,
7636 ITypeInfo2_fnGetAllParamCustData,
7637 ITypeInfo2_fnGetAllVarCustData,
7638 ITypeInfo2_fnGetAllImplTypeCustData,
7641 /******************************************************************************
7642 * CreateDispTypeInfo [OLEAUT32.31]
7644 * Build type information for an object so it can be called through an
7645 * IDispatch interface.
7647 * RETURNS
7648 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7649 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7651 * NOTES
7652 * This call allows an objects methods to be accessed through IDispatch, by
7653 * building an ITypeInfo object that IDispatch can use to call through.
7655 HRESULT WINAPI CreateDispTypeInfo(
7656 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7657 LCID lcid, /* [I] Locale Id */
7658 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7660 ITypeInfoImpl *pTIClass, *pTIIface;
7661 ITypeLibImpl *pTypeLibImpl;
7662 unsigned int param, func;
7663 TLBFuncDesc *pFuncDesc;
7664 TLBRefType *ref;
7666 TRACE("\n");
7667 pTypeLibImpl = TypeLibImpl_Constructor();
7668 if (!pTypeLibImpl) return E_FAIL;
7670 pTypeLibImpl->TypeInfoCount = 2;
7671 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
7673 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
7674 pTIIface->pTypeLib = pTypeLibImpl;
7675 pTIIface->index = 0;
7676 pTIIface->Name = NULL;
7677 pTIIface->dwHelpContext = -1;
7678 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7679 pTIIface->TypeAttr.lcid = lcid;
7680 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7681 pTIIface->TypeAttr.wMajorVerNum = 0;
7682 pTIIface->TypeAttr.wMinorVerNum = 0;
7683 pTIIface->TypeAttr.cbAlignment = 2;
7684 pTIIface->TypeAttr.cbSizeInstance = -1;
7685 pTIIface->TypeAttr.cbSizeVft = -1;
7686 pTIIface->TypeAttr.cFuncs = 0;
7687 pTIIface->TypeAttr.cImplTypes = 0;
7688 pTIIface->TypeAttr.cVars = 0;
7689 pTIIface->TypeAttr.wTypeFlags = 0;
7691 pTIIface->funcdescs = TLBFuncDesc_Constructor(pidata->cMembers);
7692 pFuncDesc = pTIIface->funcdescs;
7693 for(func = 0; func < pidata->cMembers; func++) {
7694 METHODDATA *md = pidata->pmethdata + func;
7695 pFuncDesc->Name = SysAllocString(md->szName);
7696 pFuncDesc->funcdesc.memid = md->dispid;
7697 pFuncDesc->funcdesc.lprgscode = NULL;
7698 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
7699 pFuncDesc->funcdesc.invkind = md->wFlags;
7700 pFuncDesc->funcdesc.callconv = md->cc;
7701 pFuncDesc->funcdesc.cParams = md->cArgs;
7702 pFuncDesc->funcdesc.cParamsOpt = 0;
7703 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
7704 pFuncDesc->funcdesc.cScodes = 0;
7705 pFuncDesc->funcdesc.wFuncFlags = 0;
7706 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7707 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7708 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7709 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7710 md->cArgs * sizeof(ELEMDESC));
7711 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
7712 for(param = 0; param < md->cArgs; param++) {
7713 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7714 pFuncDesc->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7716 pFuncDesc->helpcontext = 0;
7717 pFuncDesc->HelpStringContext = 0;
7718 pFuncDesc->HelpString = NULL;
7719 pFuncDesc->Entry = NULL;
7720 list_init(&pFuncDesc->custdata_list);
7721 pTIIface->TypeAttr.cFuncs++;
7722 ++pFuncDesc;
7725 dump_TypeInfo(pTIIface);
7727 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
7728 pTIClass->pTypeLib = pTypeLibImpl;
7729 pTIClass->index = 1;
7730 pTIClass->Name = NULL;
7731 pTIClass->dwHelpContext = -1;
7732 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7733 pTIClass->TypeAttr.lcid = lcid;
7734 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7735 pTIClass->TypeAttr.wMajorVerNum = 0;
7736 pTIClass->TypeAttr.wMinorVerNum = 0;
7737 pTIClass->TypeAttr.cbAlignment = 2;
7738 pTIClass->TypeAttr.cbSizeInstance = -1;
7739 pTIClass->TypeAttr.cbSizeVft = -1;
7740 pTIClass->TypeAttr.cFuncs = 0;
7741 pTIClass->TypeAttr.cImplTypes = 1;
7742 pTIClass->TypeAttr.cVars = 0;
7743 pTIClass->TypeAttr.wTypeFlags = 0;
7745 pTIClass->impltypes = TLBImplType_Constructor(1);
7747 ref = heap_alloc_zero(sizeof(*ref));
7748 ref->pImpTLInfo = TLB_REF_INTERNAL;
7749 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7751 dump_TypeInfo(pTIClass);
7753 *pptinfo = (ITypeInfo*)pTIClass;
7755 ITypeInfo_AddRef(*pptinfo);
7756 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7758 return S_OK;
7762 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7764 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7766 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7769 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7771 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7773 return ITypeInfo_AddRef((ITypeInfo *)This);
7776 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7778 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7780 return ITypeInfo_Release((ITypeInfo *)This);
7783 static HRESULT WINAPI ITypeComp_fnBind(
7784 ITypeComp * iface,
7785 OLECHAR * szName,
7786 ULONG lHash,
7787 WORD wFlags,
7788 ITypeInfo ** ppTInfo,
7789 DESCKIND * pDescKind,
7790 BINDPTR * pBindPtr)
7792 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7793 const TLBFuncDesc *pFDesc;
7794 const TLBVarDesc *pVDesc;
7795 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7796 UINT fdc;
7798 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7800 *pDescKind = DESCKIND_NONE;
7801 pBindPtr->lpfuncdesc = NULL;
7802 *ppTInfo = NULL;
7804 for(fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc){
7805 pFDesc = &This->funcdescs[fdc];
7806 if (!strcmpiW(pFDesc->Name, szName)) {
7807 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7808 break;
7809 else
7810 /* name found, but wrong flags */
7811 hr = TYPE_E_TYPEMISMATCH;
7815 if (fdc < This->TypeAttr.cFuncs)
7817 HRESULT hr = TLB_AllocAndInitFuncDesc(
7818 &pFDesc->funcdesc,
7819 &pBindPtr->lpfuncdesc,
7820 This->TypeAttr.typekind == TKIND_DISPATCH);
7821 if (FAILED(hr))
7822 return hr;
7823 *pDescKind = DESCKIND_FUNCDESC;
7824 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7825 ITypeInfo_AddRef(*ppTInfo);
7826 return S_OK;
7827 } else {
7828 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->TypeAttr.cVars, szName);
7829 if(pVDesc){
7830 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7831 if (FAILED(hr))
7832 return hr;
7833 *pDescKind = DESCKIND_VARDESC;
7834 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7835 ITypeInfo_AddRef(*ppTInfo);
7836 return S_OK;
7839 /* FIXME: search each inherited interface, not just the first */
7840 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
7841 /* recursive search */
7842 ITypeInfo *pTInfo;
7843 ITypeComp *pTComp;
7844 HRESULT hr;
7845 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypes[0].hRef, &pTInfo);
7846 if (SUCCEEDED(hr))
7848 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7849 ITypeInfo_Release(pTInfo);
7851 if (SUCCEEDED(hr))
7853 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7854 ITypeComp_Release(pTComp);
7855 return hr;
7857 WARN("Could not search inherited interface!\n");
7859 if (hr == DISP_E_MEMBERNOTFOUND)
7860 hr = S_OK;
7861 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
7862 return hr;
7865 static HRESULT WINAPI ITypeComp_fnBindType(
7866 ITypeComp * iface,
7867 OLECHAR * szName,
7868 ULONG lHash,
7869 ITypeInfo ** ppTInfo,
7870 ITypeComp ** ppTComp)
7872 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7874 /* strange behaviour (does nothing) but like the
7875 * original */
7877 if (!ppTInfo || !ppTComp)
7878 return E_POINTER;
7880 *ppTInfo = NULL;
7881 *ppTComp = NULL;
7883 return S_OK;
7886 static const ITypeCompVtbl tcompvt =
7889 ITypeComp_fnQueryInterface,
7890 ITypeComp_fnAddRef,
7891 ITypeComp_fnRelease,
7893 ITypeComp_fnBind,
7894 ITypeComp_fnBindType