oleaut32: COM cleanup for internal loading structures.
[wine/wine-gecko.git] / dlls / oleaut32 / typelib.c
blobf13024ef041aa52cd81740ecb1e4381a277d9954
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 ITypeLib_Release(*pptLib);
450 *pptLib = 0;
452 break;
453 case REGKIND_NONE:
454 break;
457 TRACE(" returns %08x\n",res);
458 return res;
461 /******************************************************************************
462 * LoadRegTypeLib [OLEAUT32.162]
464 * Loads a registered type library.
466 * PARAMS
467 * rguid [I] GUID of the registered type library.
468 * wVerMajor [I] major version.
469 * wVerMinor [I] minor version.
470 * lcid [I] locale ID.
471 * ppTLib [O] pointer that receives an ITypeLib object on success.
473 * RETURNS
474 * Success: S_OK.
475 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
476 * LoadTypeLib.
478 HRESULT WINAPI LoadRegTypeLib(
479 REFGUID rguid,
480 WORD wVerMajor,
481 WORD wVerMinor,
482 LCID lcid,
483 ITypeLib **ppTLib)
485 BSTR bstr=NULL;
486 HRESULT res;
488 *ppTLib = NULL;
490 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
492 if(SUCCEEDED(res))
494 res= LoadTypeLib(bstr, ppTLib);
495 SysFreeString(bstr);
498 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
500 return res;
504 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
505 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
506 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
507 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
508 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
509 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
511 /******************************************************************************
512 * RegisterTypeLib [OLEAUT32.163]
513 * Adds information about a type library to the System Registry
514 * NOTES
515 * Docs: ITypeLib FAR * ptlib
516 * Docs: OLECHAR FAR* szFullPath
517 * Docs: OLECHAR FAR* szHelpDir
519 * RETURNS
520 * Success: S_OK
521 * Failure: Status
523 HRESULT WINAPI RegisterTypeLib(
524 ITypeLib * ptlib, /* [in] Pointer to the library*/
525 OLECHAR * szFullPath, /* [in] full Path of the library*/
526 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
527 may be NULL*/
529 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
530 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
531 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
532 HRESULT res;
533 TLIBATTR *attr;
534 WCHAR keyName[60];
535 WCHAR tmp[16];
536 HKEY key, subKey;
537 UINT types, tidx;
538 TYPEKIND kind;
539 DWORD disposition;
541 if (ptlib == NULL || szFullPath == NULL)
542 return E_INVALIDARG;
544 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
545 return E_FAIL;
547 #ifdef _WIN64
548 if (attr->syskind != SYS_WIN64) return TYPE_E_BADMODULEKIND;
549 #else
550 if (attr->syskind != SYS_WIN32 && attr->syskind != SYS_WIN16) return TYPE_E_BADMODULEKIND;
551 #endif
553 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
555 res = S_OK;
556 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
557 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
559 LPOLESTR doc;
561 /* Set the human-readable name of the typelib */
562 if (FAILED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
563 res = E_FAIL;
564 else if (doc)
566 if (RegSetValueExW(key, NULL, 0, REG_SZ,
567 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
568 res = E_FAIL;
570 SysFreeString(doc);
573 /* Make up the name of the typelib path subkey */
574 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
576 /* Create the typelib path subkey */
577 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
578 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
580 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
581 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
582 res = E_FAIL;
584 RegCloseKey(subKey);
586 else
587 res = E_FAIL;
589 /* Create the flags subkey */
590 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
591 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
593 /* FIXME: is %u correct? */
594 static const WCHAR formatW[] = {'%','u',0};
595 WCHAR buf[20];
596 sprintfW(buf, formatW, attr->wLibFlags);
597 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
598 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
599 res = E_FAIL;
601 RegCloseKey(subKey);
603 else
604 res = E_FAIL;
606 /* create the helpdir subkey */
607 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
608 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
610 BOOL freeHelpDir = FALSE;
611 OLECHAR* pIndexStr;
613 /* if we created a new key, and helpDir was null, set the helpdir
614 to the directory which contains the typelib. However,
615 if we just opened an existing key, we leave the helpdir alone */
616 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
617 szHelpDir = SysAllocString(szFullPath);
618 pIndexStr = strrchrW(szHelpDir, '\\');
619 if (pIndexStr) {
620 *pIndexStr = 0;
622 freeHelpDir = TRUE;
625 /* if we have an szHelpDir, set it! */
626 if (szHelpDir != NULL) {
627 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
628 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
629 res = E_FAIL;
633 /* tidy up */
634 if (freeHelpDir) SysFreeString(szHelpDir);
635 RegCloseKey(subKey);
637 } else {
638 res = E_FAIL;
641 RegCloseKey(key);
643 else
644 res = E_FAIL;
646 /* register OLE Automation-compatible interfaces for this typelib */
647 types = ITypeLib_GetTypeInfoCount(ptlib);
648 for (tidx=0; tidx<types; tidx++) {
649 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
650 LPOLESTR name = NULL;
651 ITypeInfo *tinfo = NULL;
653 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
655 switch (kind) {
656 case TKIND_INTERFACE:
657 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
658 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
659 break;
661 case TKIND_DISPATCH:
662 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
663 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
664 break;
666 default:
667 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
668 break;
671 if (tinfo) {
672 TYPEATTR *tattr = NULL;
673 ITypeInfo_GetTypeAttr(tinfo, &tattr);
675 if (tattr) {
676 TRACE_(typelib)("guid=%s, flags=%04x (",
677 debugstr_guid(&tattr->guid),
678 tattr->wTypeFlags);
680 if (TRACE_ON(typelib)) {
681 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
682 XX(FAPPOBJECT);
683 XX(FCANCREATE);
684 XX(FLICENSED);
685 XX(FPREDECLID);
686 XX(FHIDDEN);
687 XX(FCONTROL);
688 XX(FDUAL);
689 XX(FNONEXTENSIBLE);
690 XX(FOLEAUTOMATION);
691 XX(FRESTRICTED);
692 XX(FAGGREGATABLE);
693 XX(FREPLACEABLE);
694 XX(FDISPATCHABLE);
695 XX(FREVERSEBIND);
696 XX(FPROXY);
697 #undef XX
698 MESSAGE("\n");
701 /* Register all dispinterfaces (which includes dual interfaces) and
702 oleautomation interfaces */
703 if ((kind == TKIND_INTERFACE && (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
704 kind == TKIND_DISPATCH)
706 /* register interface<->typelib coupling */
707 get_interface_key( &tattr->guid, keyName );
708 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
709 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
711 if (name)
712 RegSetValueExW(key, NULL, 0, REG_SZ,
713 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
715 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
716 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
717 RegSetValueExW(subKey, NULL, 0, REG_SZ,
718 (const BYTE *)PSOA, sizeof PSOA);
719 RegCloseKey(subKey);
722 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
723 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
724 RegSetValueExW(subKey, NULL, 0, REG_SZ,
725 (const BYTE *)PSOA, sizeof PSOA);
726 RegCloseKey(subKey);
729 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
730 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
732 WCHAR buffer[40];
733 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
734 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
736 StringFromGUID2(&attr->guid, buffer, 40);
737 RegSetValueExW(subKey, NULL, 0, REG_SZ,
738 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
739 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
740 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
741 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
742 RegCloseKey(subKey);
745 RegCloseKey(key);
749 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
752 ITypeInfo_Release(tinfo);
755 SysFreeString(name);
759 ITypeLib_ReleaseTLibAttr(ptlib, attr);
761 return res;
765 /******************************************************************************
766 * UnRegisterTypeLib [OLEAUT32.186]
767 * Removes information about a type library from the System Registry
768 * NOTES
770 * RETURNS
771 * Success: S_OK
772 * Failure: Status
774 HRESULT WINAPI UnRegisterTypeLib(
775 REFGUID libid, /* [in] Guid of the library */
776 WORD wVerMajor, /* [in] major version */
777 WORD wVerMinor, /* [in] minor version */
778 LCID lcid, /* [in] locale id */
779 SYSKIND syskind)
781 BSTR tlibPath = NULL;
782 DWORD tmpLength;
783 WCHAR keyName[60];
784 WCHAR subKeyName[50];
785 int result = S_OK;
786 DWORD i = 0;
787 BOOL deleteOtherStuff;
788 HKEY key = NULL;
789 HKEY subKey = NULL;
790 TYPEATTR* typeAttr = NULL;
791 TYPEKIND kind;
792 ITypeInfo* typeInfo = NULL;
793 ITypeLib* typeLib = NULL;
794 int numTypes;
796 TRACE("(IID: %s)\n",debugstr_guid(libid));
798 /* Create the path to the key */
799 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
801 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
803 TRACE("Unsupported syskind %i\n", syskind);
804 result = E_INVALIDARG;
805 goto end;
808 /* get the path to the typelib on disk */
809 if (query_typelib_path(libid, wVerMajor, wVerMinor, syskind, lcid, &tlibPath) != S_OK) {
810 result = E_INVALIDARG;
811 goto end;
814 /* Try and open the key to the type library. */
815 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
816 result = E_INVALIDARG;
817 goto end;
820 /* Try and load the type library */
821 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib) != S_OK) {
822 result = TYPE_E_INVALIDSTATE;
823 goto end;
826 /* remove any types registered with this typelib */
827 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
828 for (i=0; i<numTypes; i++) {
829 /* get the kind of type */
830 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
831 goto enddeleteloop;
834 /* skip non-interfaces, and get type info for the type */
835 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
836 goto enddeleteloop;
838 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
839 goto enddeleteloop;
841 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
842 goto enddeleteloop;
845 if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
846 kind == TKIND_DISPATCH)
848 /* the path to the type */
849 get_interface_key( &typeAttr->guid, subKeyName );
851 /* Delete its bits */
852 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS)
853 goto enddeleteloop;
855 RegDeleteKeyW(subKey, ProxyStubClsidW);
856 RegDeleteKeyW(subKey, ProxyStubClsid32W);
857 RegDeleteKeyW(subKey, TypeLibW);
858 RegCloseKey(subKey);
859 subKey = NULL;
860 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
863 enddeleteloop:
864 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
865 typeAttr = NULL;
866 if (typeInfo) ITypeInfo_Release(typeInfo);
867 typeInfo = NULL;
870 /* Now, delete the type library path subkey */
871 get_lcid_subkey( lcid, syskind, subKeyName );
872 RegDeleteKeyW(key, subKeyName);
873 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
874 RegDeleteKeyW(key, subKeyName);
876 /* check if there is anything besides the FLAGS/HELPDIR keys.
877 If there is, we don't delete them */
878 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
879 deleteOtherStuff = TRUE;
880 i = 0;
881 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
882 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
884 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
885 if (!strcmpW(subKeyName, FLAGSW)) continue;
886 if (!strcmpW(subKeyName, HELPDIRW)) continue;
887 deleteOtherStuff = FALSE;
888 break;
891 /* only delete the other parts of the key if we're absolutely sure */
892 if (deleteOtherStuff) {
893 RegDeleteKeyW(key, FLAGSW);
894 RegDeleteKeyW(key, HELPDIRW);
895 RegCloseKey(key);
896 key = NULL;
898 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
899 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
900 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
903 end:
904 SysFreeString(tlibPath);
905 if (typeLib) ITypeLib_Release(typeLib);
906 if (subKey) RegCloseKey(subKey);
907 if (key) RegCloseKey(key);
908 return result;
911 /******************************************************************************
912 * RegisterTypeLibForUser [OLEAUT32.442]
913 * Adds information about a type library to the user registry
914 * NOTES
915 * Docs: ITypeLib FAR * ptlib
916 * Docs: OLECHAR FAR* szFullPath
917 * Docs: OLECHAR FAR* szHelpDir
919 * RETURNS
920 * Success: S_OK
921 * Failure: Status
923 HRESULT WINAPI RegisterTypeLibForUser(
924 ITypeLib * ptlib, /* [in] Pointer to the library*/
925 OLECHAR * szFullPath, /* [in] full Path of the library*/
926 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
927 may be NULL*/
929 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib,
930 debugstr_w(szFullPath), debugstr_w(szHelpDir));
931 return RegisterTypeLib(ptlib, szFullPath, szHelpDir);
934 /******************************************************************************
935 * UnRegisterTypeLibForUser [OLEAUT32.443]
936 * Removes information about a type library from the user registry
938 * RETURNS
939 * Success: S_OK
940 * Failure: Status
942 HRESULT WINAPI UnRegisterTypeLibForUser(
943 REFGUID libid, /* [in] GUID of the library */
944 WORD wVerMajor, /* [in] major version */
945 WORD wVerMinor, /* [in] minor version */
946 LCID lcid, /* [in] locale id */
947 SYSKIND syskind)
949 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
950 debugstr_guid(libid), wVerMajor, wVerMinor, lcid, syskind);
951 return UnRegisterTypeLib(libid, wVerMajor, wVerMinor, lcid, syskind);
954 /*======================= ITypeLib implementation =======================*/
956 typedef struct tagTLBCustData
958 GUID guid;
959 VARIANT data;
960 struct list entry;
961 } TLBCustData;
963 /* data structure for import typelibs */
964 typedef struct tagTLBImpLib
966 int offset; /* offset in the file (MSFT)
967 offset in nametable (SLTG)
968 just used to identify library while reading
969 data from file */
970 GUID guid; /* libid */
971 BSTR name; /* name */
973 LCID lcid; /* lcid of imported typelib */
975 WORD wVersionMajor; /* major version number */
976 WORD wVersionMinor; /* minor version number */
978 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
979 NULL if not yet loaded */
980 struct list entry;
981 } TLBImpLib;
983 /* internal ITypeLib data */
984 typedef struct tagITypeLibImpl
986 ITypeLib2 ITypeLib2_iface;
987 ITypeComp ITypeComp_iface;
988 LONG ref;
989 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
990 LCID lcid;
992 /* strings can be stored in tlb as multibyte strings BUT they are *always*
993 * exported to the application as a UNICODE string.
995 BSTR Name;
996 BSTR DocString;
997 BSTR HelpFile;
998 BSTR HelpStringDll;
999 DWORD dwHelpContext;
1000 int TypeInfoCount; /* nr of typeinfo's in librarry */
1001 struct tagITypeInfoImpl **typeinfos;
1002 struct list custdata_list;
1003 struct list implib_list;
1004 int ctTypeDesc; /* number of items in type desc array */
1005 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1006 library. Only used while reading MSFT
1007 typelibs */
1008 struct list ref_list; /* list of ref types in this typelib */
1009 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1012 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1013 struct list entry;
1014 WCHAR *path;
1015 INT index;
1016 } ITypeLibImpl;
1018 static const ITypeLib2Vtbl tlbvt;
1019 static const ITypeCompVtbl tlbtcvt;
1021 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1023 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeComp_iface);
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 ITypeInfo2 ITypeInfo2_iface;
1098 ITypeComp ITypeComp_iface;
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 CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeComp_iface);
1131 static const ITypeInfo2Vtbl tinfvt;
1132 static const ITypeCompVtbl tcompvt;
1134 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1135 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1137 typedef struct tagTLBContext
1139 unsigned int oStart; /* start of TLB in file */
1140 unsigned int pos; /* current pos */
1141 unsigned int length; /* total length */
1142 void *mapping; /* memory mapping */
1143 MSFT_SegDir * pTblDir;
1144 ITypeLibImpl* pLibInfo;
1145 } TLBContext;
1148 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1151 debug
1153 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1154 if (pTD->vt & VT_RESERVED)
1155 szVarType += strlen(strcpy(szVarType, "reserved | "));
1156 if (pTD->vt & VT_BYREF)
1157 szVarType += strlen(strcpy(szVarType, "ref to "));
1158 if (pTD->vt & VT_ARRAY)
1159 szVarType += strlen(strcpy(szVarType, "array of "));
1160 if (pTD->vt & VT_VECTOR)
1161 szVarType += strlen(strcpy(szVarType, "vector of "));
1162 switch(pTD->vt & VT_TYPEMASK) {
1163 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1164 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1165 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1166 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1167 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1168 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1169 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1170 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1171 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1172 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1173 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1174 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1175 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1176 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1177 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1178 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1179 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1180 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1181 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1182 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1183 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1184 pTD->u.hreftype); break;
1185 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1186 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1187 case VT_PTR: sprintf(szVarType, "ptr to ");
1188 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1189 break;
1190 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1191 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1192 break;
1193 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1194 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1195 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1196 break;
1198 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1202 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1203 char buf[200];
1204 USHORT flags = edesc->u.paramdesc.wParamFlags;
1205 dump_TypeDesc(&edesc->tdesc,buf);
1206 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1207 MESSAGE("\t\tu.paramdesc.wParamFlags");
1208 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1209 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1210 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1211 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1212 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1213 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1214 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1215 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1216 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1218 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1219 int i;
1220 MESSAGE("memid is %08x\n",funcdesc->memid);
1221 for (i=0;i<funcdesc->cParams;i++) {
1222 MESSAGE("Param %d:\n",i);
1223 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1225 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1226 switch (funcdesc->funckind) {
1227 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1228 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1229 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1230 case FUNC_STATIC: MESSAGE("static");break;
1231 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1232 default: MESSAGE("unknown");break;
1234 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1235 switch (funcdesc->invkind) {
1236 case INVOKE_FUNC: MESSAGE("func");break;
1237 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1238 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1239 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1241 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1242 switch (funcdesc->callconv) {
1243 case CC_CDECL: MESSAGE("cdecl");break;
1244 case CC_PASCAL: MESSAGE("pascal");break;
1245 case CC_STDCALL: MESSAGE("stdcall");break;
1246 case CC_SYSCALL: MESSAGE("syscall");break;
1247 default:break;
1249 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1250 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1251 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1253 MESSAGE("\telemdescFunc (return value type):\n");
1254 dump_ELEMDESC(&funcdesc->elemdescFunc);
1257 static const char * const typekind_desc[] =
1259 "TKIND_ENUM",
1260 "TKIND_RECORD",
1261 "TKIND_MODULE",
1262 "TKIND_INTERFACE",
1263 "TKIND_DISPATCH",
1264 "TKIND_COCLASS",
1265 "TKIND_ALIAS",
1266 "TKIND_UNION",
1267 "TKIND_MAX"
1270 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1272 int i;
1273 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1274 for (i=0;i<pfd->funcdesc.cParams;i++)
1275 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1278 dump_FUNCDESC(&(pfd->funcdesc));
1280 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1281 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1283 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1285 while (n)
1287 dump_TLBFuncDescOne(pfd);
1288 ++pfd;
1289 --n;
1292 static void dump_TLBVarDesc(const TLBVarDesc * pvd, UINT n)
1294 while (n)
1296 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1297 ++pvd;
1298 --n;
1302 static void dump_TLBImpLib(const TLBImpLib *import)
1304 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1305 debugstr_w(import->name));
1306 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1307 import->wVersionMinor, import->lcid, import->offset);
1310 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1312 TLBRefType *ref;
1314 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1316 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1317 if(ref->index == -1)
1318 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1319 else
1320 TRACE_(typelib)("type no: %d\n", ref->index);
1322 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1324 TRACE_(typelib)("in lib\n");
1325 dump_TLBImpLib(ref->pImpTLInfo);
1330 static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1332 if(!impl)
1333 return;
1334 while (n) {
1335 TRACE_(typelib)("implementing/inheriting interface hRef = %x implflags %x\n",
1336 impl->hRef, impl->implflags);
1337 ++impl;
1338 --n;
1342 static void dump_Variant(const VARIANT * pvar)
1344 SYSTEMTIME st;
1346 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1348 if (pvar)
1350 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1351 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1353 TRACE(",%p", V_BYREF(pvar));
1355 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1357 TRACE(",%p", V_ARRAY(pvar));
1359 else switch (V_TYPE(pvar))
1361 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1362 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1363 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1364 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1365 case VT_INT:
1366 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1367 case VT_UINT:
1368 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1369 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1370 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1371 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1372 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1373 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1374 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1375 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1376 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1377 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1378 V_CY(pvar).s.Lo); break;
1379 case VT_DATE:
1380 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1381 TRACE(",<invalid>");
1382 else
1383 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1384 st.wHour, st.wMinute, st.wSecond);
1385 break;
1386 case VT_ERROR:
1387 case VT_VOID:
1388 case VT_USERDEFINED:
1389 case VT_EMPTY:
1390 case VT_NULL: break;
1391 default: TRACE(",?"); break;
1394 TRACE("}\n");
1397 static void dump_DispParms(const DISPPARAMS * pdp)
1399 unsigned int index;
1401 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1403 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1405 TRACE("named args:\n");
1406 for (index = 0; index < pdp->cNamedArgs; index++)
1407 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1410 if (pdp->cArgs && pdp->rgvarg)
1412 TRACE("args:\n");
1413 for (index = 0; index < pdp->cArgs; index++)
1414 dump_Variant( &pdp->rgvarg[index] );
1418 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1420 TRACE("%p ref=%u\n", pty, pty->ref);
1421 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1422 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1423 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1424 TRACE("fct:%u var:%u impl:%u\n",
1425 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1426 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1427 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1428 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1429 if (TRACE_ON(ole))
1430 dump_TLBFuncDesc(pty->funcdescs, pty->TypeAttr.cFuncs);
1431 dump_TLBVarDesc(pty->vardescs, pty->TypeAttr.cVars);
1432 dump_TLBImplType(pty->impltypes, pty->TypeAttr.cImplTypes);
1435 static void dump_VARDESC(const VARDESC *v)
1437 MESSAGE("memid %d\n",v->memid);
1438 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1439 MESSAGE("oInst %d\n",v->u.oInst);
1440 dump_ELEMDESC(&(v->elemdescVar));
1441 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1442 MESSAGE("varkind %d\n",v->varkind);
1445 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1447 /* VT_LPWSTR is largest type that, may appear in type description */
1448 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1449 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1450 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1451 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1452 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1453 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1454 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1455 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1458 static void TLB_abort(void)
1460 DebugBreak();
1463 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size)
1465 void *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
1466 if (!ret) ERR("cannot allocate memory\n");
1467 return ret;
1470 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size)
1472 void *ret = HeapAlloc(GetProcessHeap(), 0, size);
1473 if (!ret) ERR("cannot allocate memory\n");
1474 return ret;
1477 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr, unsigned size)
1479 return HeapReAlloc(GetProcessHeap(), 0, ptr, size);
1482 void heap_free(void *ptr)
1484 HeapFree(GetProcessHeap(), 0, ptr);
1487 /* returns the size required for a deep copy of a typedesc into a
1488 * flat buffer */
1489 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1491 SIZE_T size = 0;
1493 if (alloc_initial_space)
1494 size += sizeof(TYPEDESC);
1496 switch (tdesc->vt)
1498 case VT_PTR:
1499 case VT_SAFEARRAY:
1500 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1501 break;
1502 case VT_CARRAY:
1503 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1504 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1505 break;
1507 return size;
1510 /* deep copy a typedesc into a flat buffer */
1511 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1513 if (!dest)
1515 dest = buffer;
1516 buffer = (char *)buffer + sizeof(TYPEDESC);
1519 *dest = *src;
1521 switch (src->vt)
1523 case VT_PTR:
1524 case VT_SAFEARRAY:
1525 dest->u.lptdesc = buffer;
1526 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1527 break;
1528 case VT_CARRAY:
1529 dest->u.lpadesc = buffer;
1530 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1531 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1532 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1533 break;
1535 return buffer;
1538 /* free custom data allocated by MSFT_CustData */
1539 static inline void TLB_FreeCustData(struct list *custdata_list)
1541 TLBCustData *cd, *cdn;
1542 LIST_FOR_EACH_ENTRY_SAFE(cd, cdn, custdata_list, TLBCustData, entry)
1544 list_remove(&cd->entry);
1545 VariantClear(&cd->data);
1546 heap_free(cd);
1550 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1552 DWORD len;
1553 BSTR ret;
1555 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1556 ret = SysAllocStringLen(NULL, len - 1);
1557 if (!ret) return ret;
1558 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1559 return ret;
1562 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(TLBFuncDesc *funcdescs,
1563 UINT n, MEMBERID memid)
1565 while(n){
1566 if(funcdescs->funcdesc.memid == memid)
1567 return funcdescs;
1568 ++funcdescs;
1569 --n;
1571 return NULL;
1574 static inline TLBFuncDesc *TLB_get_funcdesc_by_name(TLBFuncDesc *funcdescs,
1575 UINT n, const OLECHAR *name)
1577 while(n){
1578 if(!lstrcmpiW(funcdescs->Name, name))
1579 return funcdescs;
1580 ++funcdescs;
1581 --n;
1583 return NULL;
1586 static inline TLBVarDesc *TLB_get_vardesc_by_memberid(TLBVarDesc *vardescs,
1587 UINT n, MEMBERID memid)
1589 while(n){
1590 if(vardescs->vardesc.memid == memid)
1591 return vardescs;
1592 ++vardescs;
1593 --n;
1595 return NULL;
1598 static inline TLBVarDesc *TLB_get_vardesc_by_name(TLBVarDesc *vardescs,
1599 UINT n, const OLECHAR *name)
1601 while(n){
1602 if(!lstrcmpiW(vardescs->Name, name))
1603 return vardescs;
1604 ++vardescs;
1605 --n;
1607 return NULL;
1610 static inline TLBCustData *TLB_get_custdata_by_guid(struct list *custdata_list, REFGUID guid)
1612 TLBCustData *cust_data;
1613 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1614 if(IsEqualIID(&cust_data->guid, guid))
1615 return cust_data;
1616 return NULL;
1619 static TLBVarDesc *TLBVarDesc_Constructor(UINT n)
1621 TLBVarDesc *ret;
1623 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1624 if(!ret)
1625 return NULL;
1627 while(n){
1628 list_init(&ret[n-1].custdata_list);
1629 --n;
1632 return ret;
1635 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1637 TLBParDesc *ret;
1639 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1640 if(!ret)
1641 return NULL;
1643 while(n){
1644 list_init(&ret[n-1].custdata_list);
1645 --n;
1648 return ret;
1651 static TLBFuncDesc *TLBFuncDesc_Constructor(UINT n)
1653 TLBFuncDesc *ret;
1655 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1656 if(!ret)
1657 return NULL;
1659 while(n){
1660 list_init(&ret[n-1].custdata_list);
1661 --n;
1664 return ret;
1667 static TLBImplType *TLBImplType_Constructor(UINT n)
1669 TLBImplType *ret;
1671 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1672 if(!ret)
1673 return NULL;
1675 while(n){
1676 list_init(&ret[n-1].custdata_list);
1677 --n;
1680 return ret;
1683 /**********************************************************************
1685 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1687 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1689 return pcx->pos;
1692 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
1694 if (where != DO_NOT_SEEK)
1696 where += pcx->oStart;
1697 if (where > pcx->length)
1699 /* FIXME */
1700 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
1701 TLB_abort();
1703 pcx->pos = where;
1707 /* read function */
1708 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
1710 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
1711 pcx->pos, count, pcx->oStart, pcx->length, where);
1713 MSFT_Seek(pcx, where);
1714 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1715 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1716 pcx->pos += count;
1717 return count;
1720 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1721 LONG where )
1723 DWORD ret;
1725 ret = MSFT_Read(buffer, count, pcx, where);
1726 FromLEDWords(buffer, ret);
1728 return ret;
1731 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1732 LONG where )
1734 DWORD ret;
1736 ret = MSFT_Read(buffer, count, pcx, where);
1737 FromLEWords(buffer, ret);
1739 return ret;
1742 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1744 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1745 memset(pGuid,0, sizeof(GUID));
1746 return;
1748 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1749 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1750 pGuid->Data2 = FromLEWord(pGuid->Data2);
1751 pGuid->Data3 = FromLEWord(pGuid->Data3);
1752 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1755 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1757 MSFT_NameIntro niName;
1759 if (offset < 0)
1761 ERR_(typelib)("bad offset %d\n", offset);
1762 return -1;
1765 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1766 pcx->pTblDir->pNametab.offset+offset);
1768 return niName.hreftype;
1771 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1773 char * name;
1774 MSFT_NameIntro niName;
1775 int lengthInChars;
1776 BSTR bstrName = NULL;
1778 if (offset < 0)
1780 ERR_(typelib)("bad offset %d\n", offset);
1781 return NULL;
1783 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1784 pcx->pTblDir->pNametab.offset+offset);
1785 niName.namelen &= 0xFF; /* FIXME: correct ? */
1786 name = heap_alloc_zero((niName.namelen & 0xff) +1);
1787 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1788 name[niName.namelen & 0xff]='\0';
1790 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1791 name, -1, NULL, 0);
1793 /* no invalid characters in string */
1794 if (lengthInChars)
1796 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1798 /* don't check for invalid character since this has been done previously */
1799 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1801 heap_free(name);
1803 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1804 return bstrName;
1807 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1809 char * string;
1810 INT16 length;
1811 int lengthInChars;
1812 BSTR bstr = NULL;
1814 if(offset<0) return NULL;
1815 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1816 if(length <= 0) return 0;
1817 string = heap_alloc_zero(length +1);
1818 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1819 string[length]='\0';
1821 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1822 string, -1, NULL, 0);
1824 /* no invalid characters in string */
1825 if (lengthInChars)
1827 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1829 /* don't check for invalid character since this has been done previously */
1830 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1832 heap_free(string);
1834 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1835 return bstr;
1838 * read a value and fill a VARIANT structure
1840 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1842 int size;
1844 TRACE_(typelib)("\n");
1846 if(offset <0) { /* data are packed in here */
1847 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1848 V_I4(pVar) = offset & 0x3ffffff;
1849 return;
1851 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1852 pcx->pTblDir->pCustData.offset + offset );
1853 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1854 switch (V_VT(pVar)){
1855 case VT_EMPTY: /* FIXME: is this right? */
1856 case VT_NULL: /* FIXME: is this right? */
1857 case VT_I2 : /* this should not happen */
1858 case VT_I4 :
1859 case VT_R4 :
1860 case VT_ERROR :
1861 case VT_BOOL :
1862 case VT_I1 :
1863 case VT_UI1 :
1864 case VT_UI2 :
1865 case VT_UI4 :
1866 case VT_INT :
1867 case VT_UINT :
1868 case VT_VOID : /* FIXME: is this right? */
1869 case VT_HRESULT :
1870 size=4; break;
1871 case VT_R8 :
1872 case VT_CY :
1873 case VT_DATE :
1874 case VT_I8 :
1875 case VT_UI8 :
1876 case VT_DECIMAL : /* FIXME: is this right? */
1877 case VT_FILETIME :
1878 size=8;break;
1879 /* pointer types with known behaviour */
1880 case VT_BSTR :{
1881 char * ptr;
1882 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1883 if(size < 0) {
1884 char next;
1885 DWORD origPos = MSFT_Tell(pcx), nullPos;
1887 do {
1888 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1889 } while (next);
1890 nullPos = MSFT_Tell(pcx);
1891 size = nullPos - origPos;
1892 MSFT_Seek(pcx, origPos);
1894 ptr = heap_alloc_zero(size);/* allocate temp buffer */
1895 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1896 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1897 /* FIXME: do we need a AtoW conversion here? */
1898 V_UNION(pVar, bstrVal[size])='\0';
1899 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1900 heap_free(ptr);
1902 size=-4; break;
1903 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1904 case VT_DISPATCH :
1905 case VT_VARIANT :
1906 case VT_UNKNOWN :
1907 case VT_PTR :
1908 case VT_SAFEARRAY :
1909 case VT_CARRAY :
1910 case VT_USERDEFINED :
1911 case VT_LPSTR :
1912 case VT_LPWSTR :
1913 case VT_BLOB :
1914 case VT_STREAM :
1915 case VT_STORAGE :
1916 case VT_STREAMED_OBJECT :
1917 case VT_STORED_OBJECT :
1918 case VT_BLOB_OBJECT :
1919 case VT_CF :
1920 case VT_CLSID :
1921 default:
1922 size=0;
1923 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1924 V_VT(pVar));
1927 if(size>0) /* (big|small) endian correct? */
1928 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1929 return;
1932 * create a linked list with custom data
1934 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
1936 MSFT_CDGuid entry;
1937 TLBCustData* pNew;
1938 int count=0;
1940 TRACE_(typelib)("\n");
1942 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
1944 while(offset >=0){
1945 count++;
1946 pNew=heap_alloc_zero(sizeof(TLBCustData));
1947 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1948 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1949 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1950 list_add_head(custdata_list, &pNew->entry);
1951 offset = entry.next;
1953 return count;
1956 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1957 ITypeInfoImpl *pTI)
1959 if(type <0)
1960 pTd->vt=type & VT_TYPEMASK;
1961 else
1962 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1964 if(pTd->vt == VT_USERDEFINED)
1965 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1967 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1970 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1972 /* resolve referenced type if any */
1973 while (lpTypeDesc)
1975 switch (lpTypeDesc->vt)
1977 case VT_PTR:
1978 lpTypeDesc = lpTypeDesc->u.lptdesc;
1979 break;
1981 case VT_CARRAY:
1982 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1983 break;
1985 case VT_USERDEFINED:
1986 MSFT_DoRefType(pcx, pTI->pTypeLib,
1987 lpTypeDesc->u.hreftype);
1989 lpTypeDesc = NULL;
1990 break;
1992 default:
1993 lpTypeDesc = NULL;
1998 static void
1999 MSFT_DoFuncs(TLBContext* pcx,
2000 ITypeInfoImpl* pTI,
2001 int cFuncs,
2002 int cVars,
2003 int offset,
2004 TLBFuncDesc** pptfd)
2007 * member information is stored in a data structure at offset
2008 * indicated by the memoffset field of the typeinfo structure
2009 * There are several distinctive parts.
2010 * The first part starts with a field that holds the total length
2011 * of this (first) part excluding this field. Then follow the records,
2012 * for each member there is one record.
2014 * The first entry is always the length of the record (including this
2015 * length word).
2016 * The rest of the record depends on the type of the member. If there is
2017 * a field indicating the member type (function, variable, interface, etc)
2018 * I have not found it yet. At this time we depend on the information
2019 * in the type info and the usual order how things are stored.
2021 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2022 * for each member;
2024 * Third is an equal sized array with file offsets to the name entry
2025 * of each member.
2027 * The fourth and last (?) part is an array with offsets to the records
2028 * in the first part of this file segment.
2031 int infolen, nameoffset, reclength, i;
2032 int recoffset = offset + sizeof(INT);
2034 char *recbuf = heap_alloc(0xffff);
2035 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2036 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2038 TRACE_(typelib)("\n");
2040 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2042 *pptfd = TLBFuncDesc_Constructor(cFuncs);
2043 ptfd = *pptfd;
2044 for ( i = 0; i < cFuncs ; i++ )
2046 int optional;
2048 /* name, eventually add to a hash table */
2049 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2050 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2052 /* nameoffset is sometimes -1 on the second half of a propget/propput
2053 * pair of functions */
2054 if ((nameoffset == -1) && (i > 0))
2055 ptfd->Name = SysAllocString(ptfd_prev->Name);
2056 else
2057 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2059 /* read the function information record */
2060 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2062 reclength &= 0xffff;
2064 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2066 /* size without argument data */
2067 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2069 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2070 ptfd->helpcontext = pFuncRec->HelpContext;
2072 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2073 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2075 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2077 if (pFuncRec->FKCCIC & 0x2000 )
2079 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2080 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2081 ptfd->Entry = (BSTR)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2083 else
2084 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2086 else
2087 ptfd->Entry = (BSTR)-1;
2089 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2090 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2092 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2093 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2095 /* fill the FuncDesc Structure */
2096 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2097 offset + infolen + ( i + 1) * sizeof(INT));
2099 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2100 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2101 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2102 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2103 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2104 ptfd->funcdesc.oVft = pFuncRec->VtableOffset & ~1;
2105 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2107 MSFT_GetTdesc(pcx,
2108 pFuncRec->DataType,
2109 &ptfd->funcdesc.elemdescFunc.tdesc,
2110 pTI);
2111 MSFT_ResolveReferencedTypes(pcx, pTI, &ptfd->funcdesc.elemdescFunc.tdesc);
2113 /* do the parameters/arguments */
2114 if(pFuncRec->nrargs)
2116 int j = 0;
2117 MSFT_ParameterInfo paraminfo;
2119 ptfd->funcdesc.lprgelemdescParam =
2120 heap_alloc_zero(pFuncRec->nrargs * sizeof(ELEMDESC));
2122 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2124 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2125 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2127 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2129 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2131 MSFT_GetTdesc(pcx,
2132 paraminfo.DataType,
2133 &elemdesc->tdesc,
2134 pTI);
2136 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2138 /* name */
2139 if (paraminfo.oName == -1)
2140 /* this occurs for [propput] or [propget] methods, so
2141 * we should just set the name of the parameter to the
2142 * name of the method. */
2143 ptfd->pParamDesc[j].Name = SysAllocString(ptfd->Name);
2144 else
2145 ptfd->pParamDesc[j].Name =
2146 MSFT_ReadName( pcx, paraminfo.oName );
2147 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(ptfd->pParamDesc[j].Name));
2149 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
2151 /* default value */
2152 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2153 (pFuncRec->FKCCIC & 0x1000) )
2155 INT* pInt = (INT *)((char *)pFuncRec +
2156 reclength -
2157 (pFuncRec->nrargs * 4) * sizeof(INT) );
2159 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2161 pParamDesc->pparamdescex = heap_alloc_zero(sizeof(PARAMDESCEX));
2162 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2164 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2165 pInt[j], pcx);
2167 else
2168 elemdesc->u.paramdesc.pparamdescex = NULL;
2170 /* custom info */
2171 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2172 j*sizeof(pFuncRec->oArgCustData[0])) &&
2173 pFuncRec->FKCCIC & 0x80 )
2175 MSFT_CustData(pcx,
2176 pFuncRec->oArgCustData[j],
2177 &ptfd->pParamDesc[j].custdata_list);
2180 /* SEEK value = jump to offset,
2181 * from there jump to the end of record,
2182 * go back by (j-1) arguments
2184 MSFT_ReadLEDWords( &paraminfo ,
2185 sizeof(MSFT_ParameterInfo), pcx,
2186 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2187 * sizeof(MSFT_ParameterInfo)));
2191 /* scode is not used: archaic win16 stuff FIXME: right? */
2192 ptfd->funcdesc.cScodes = 0 ;
2193 ptfd->funcdesc.lprgscode = NULL ;
2195 ptfd_prev = ptfd;
2196 ++ptfd;
2197 recoffset += reclength;
2199 heap_free(recbuf);
2202 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2203 int cVars, int offset, TLBVarDesc ** pptvd)
2205 int infolen, nameoffset, reclength;
2206 char recbuf[256];
2207 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2208 TLBVarDesc *ptvd;
2209 int i;
2210 int recoffset;
2212 TRACE_(typelib)("\n");
2214 ptvd = *pptvd = TLBVarDesc_Constructor(cVars);
2215 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2216 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2217 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2218 recoffset += offset+sizeof(INT);
2219 for(i=0;i<cVars;i++, ++ptvd){
2220 /* name, eventually add to a hash table */
2221 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2222 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2223 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2224 /* read the variable information record */
2225 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2226 reclength &= 0xff;
2227 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2229 /* optional data */
2230 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2231 ptvd->HelpContext = pVarRec->HelpContext;
2233 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2234 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2236 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2237 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2239 /* fill the VarDesc Structure */
2240 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2241 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2242 ptvd->vardesc.varkind = pVarRec->VarKind;
2243 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2244 MSFT_GetTdesc(pcx, pVarRec->DataType,
2245 &ptvd->vardesc.elemdescVar.tdesc, pTI);
2246 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2247 if(pVarRec->VarKind == VAR_CONST ){
2248 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2249 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2250 pVarRec->OffsValue, pcx);
2251 } else
2252 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2253 MSFT_ResolveReferencedTypes(pcx, pTI, &ptvd->vardesc.elemdescVar.tdesc);
2254 recoffset += reclength;
2258 /* fill in data for a hreftype (offset). When the referenced type is contained
2259 * in the typelib, it's just an (file) offset in the type info base dir.
2260 * If comes from import, it's an offset+1 in the ImpInfo table
2261 * */
2262 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2263 int offset)
2265 TLBRefType *ref;
2267 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2269 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2271 if(ref->reference == offset) return;
2274 ref = heap_alloc_zero(sizeof(TLBRefType));
2275 list_add_tail(&pTL->ref_list, &ref->entry);
2277 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2278 /* external typelib */
2279 MSFT_ImpInfo impinfo;
2280 TLBImpLib *pImpLib;
2282 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2284 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2285 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2287 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2288 if(pImpLib->offset==impinfo.oImpFile)
2289 break;
2291 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2292 ref->reference = offset;
2293 ref->pImpTLInfo = pImpLib;
2294 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2295 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2296 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2297 ref->index = TLB_REF_USE_GUID;
2298 } else
2299 ref->index = impinfo.oGuid;
2300 }else{
2301 ERR("Cannot find a reference\n");
2302 ref->reference = -1;
2303 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2305 }else{
2306 /* in this typelib */
2307 ref->index = MSFT_HREFTYPE_INDEX(offset);
2308 ref->reference = offset;
2309 ref->pImpTLInfo = TLB_REF_INTERNAL;
2313 /* process Implemented Interfaces of a com class */
2314 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2315 int offset)
2317 int i;
2318 MSFT_RefRecord refrec;
2319 TLBImplType *pImpl;
2321 TRACE_(typelib)("\n");
2323 pTI->impltypes = TLBImplType_Constructor(count);
2324 pImpl = pTI->impltypes;
2325 for(i=0;i<count;i++){
2326 if(offset<0) break; /* paranoia */
2327 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2328 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2329 pImpl->hRef = refrec.reftype;
2330 pImpl->implflags=refrec.flags;
2331 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2332 offset=refrec.onext;
2333 ++pImpl;
2337 * process a typeinfo record
2339 static ITypeInfoImpl * MSFT_DoTypeInfo(
2340 TLBContext *pcx,
2341 int count,
2342 ITypeLibImpl * pLibInfo)
2344 MSFT_TypeInfoBase tiBase;
2345 ITypeInfoImpl *ptiRet;
2347 TRACE_(typelib)("count=%u\n", count);
2349 ptiRet = ITypeInfoImpl_Constructor();
2350 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2351 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2353 /* this is where we are coming from */
2354 ptiRet->pTypeLib = pLibInfo;
2355 ptiRet->index=count;
2356 /* fill in the typeattr fields */
2358 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2359 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2360 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2361 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2362 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2363 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2364 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2365 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2366 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2367 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2368 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2369 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2370 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2371 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2372 MSFT_GetTdesc(pcx, tiBase.datatype1,
2373 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2375 /* FIXME: */
2376 /* IDLDESC idldescType; *//* never saw this one != zero */
2378 /* name, eventually add to a hash table */
2379 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2380 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2381 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2382 /* help info */
2383 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2384 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2385 ptiRet->dwHelpContext=tiBase.helpcontext;
2387 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2388 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2390 /* note: InfoType's Help file and HelpStringDll come from the containing
2391 * library. Further HelpString and Docstring appear to be the same thing :(
2393 /* functions */
2394 if(ptiRet->TypeAttr.cFuncs >0 )
2395 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2396 ptiRet->TypeAttr.cVars,
2397 tiBase.memoffset, &ptiRet->funcdescs);
2398 /* variables */
2399 if(ptiRet->TypeAttr.cVars >0 )
2400 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2401 ptiRet->TypeAttr.cVars,
2402 tiBase.memoffset, &ptiRet->vardescs);
2403 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2404 switch(ptiRet->TypeAttr.typekind)
2406 case TKIND_COCLASS:
2407 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2408 tiBase.datatype1);
2409 break;
2410 case TKIND_DISPATCH:
2411 /* This is not -1 when the interface is a non-base dual interface or
2412 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2413 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2414 not this interface.
2417 if (tiBase.datatype1 != -1)
2419 ptiRet->impltypes = TLBImplType_Constructor(1);
2420 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2421 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2423 break;
2424 default:
2425 ptiRet->impltypes = TLBImplType_Constructor(1);
2426 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2427 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2428 break;
2431 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->custdata_list);
2433 TRACE_(typelib)("%s guid: %s kind:%s\n",
2434 debugstr_w(ptiRet->Name),
2435 debugstr_guid(&ptiRet->TypeAttr.guid),
2436 typekind_desc[ptiRet->TypeAttr.typekind]);
2437 if (TRACE_ON(typelib))
2438 dump_TypeInfo(ptiRet);
2440 return ptiRet;
2443 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2444 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2445 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2446 * tradeoff here.
2448 static struct list tlb_cache = LIST_INIT(tlb_cache);
2449 static CRITICAL_SECTION cache_section;
2450 static CRITICAL_SECTION_DEBUG cache_section_debug =
2452 0, 0, &cache_section,
2453 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2454 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2456 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2459 typedef struct TLB_PEFile
2461 IUnknown IUnknown_iface;
2462 LONG refs;
2463 HMODULE dll;
2464 HRSRC typelib_resource;
2465 HGLOBAL typelib_global;
2466 LPVOID typelib_base;
2467 } TLB_PEFile;
2469 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2471 if (IsEqualIID(riid, &IID_IUnknown))
2473 *ppv = iface;
2474 IUnknown_AddRef(iface);
2475 return S_OK;
2477 *ppv = NULL;
2478 return E_NOINTERFACE;
2481 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2483 TLB_PEFile *This = (TLB_PEFile *)iface;
2484 return InterlockedIncrement(&This->refs);
2487 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2489 TLB_PEFile *This = (TLB_PEFile *)iface;
2490 ULONG refs = InterlockedDecrement(&This->refs);
2491 if (!refs)
2493 if (This->typelib_global)
2494 FreeResource(This->typelib_global);
2495 if (This->dll)
2496 FreeLibrary(This->dll);
2497 heap_free(This);
2499 return refs;
2502 static const IUnknownVtbl TLB_PEFile_Vtable =
2504 TLB_PEFile_QueryInterface,
2505 TLB_PEFile_AddRef,
2506 TLB_PEFile_Release
2509 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2511 TLB_PEFile *This;
2512 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2514 This = heap_alloc(sizeof(TLB_PEFile));
2515 if (!This)
2516 return E_OUTOFMEMORY;
2518 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
2519 This->refs = 1;
2520 This->dll = NULL;
2521 This->typelib_resource = NULL;
2522 This->typelib_global = NULL;
2523 This->typelib_base = NULL;
2525 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2526 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2528 if (This->dll)
2530 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2531 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2532 if (This->typelib_resource)
2534 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2535 if (This->typelib_global)
2537 This->typelib_base = LockResource(This->typelib_global);
2539 if (This->typelib_base)
2541 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2542 *ppBase = This->typelib_base;
2543 *ppFile = &This->IUnknown_iface;
2544 return S_OK;
2549 TRACE("No TYPELIB resource found\n");
2550 hr = E_FAIL;
2553 TLB_PEFile_Release(&This->IUnknown_iface);
2554 return hr;
2557 typedef struct TLB_NEFile
2559 IUnknown IUnknown_iface;
2560 LONG refs;
2561 LPVOID typelib_base;
2562 } TLB_NEFile;
2564 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2566 if (IsEqualIID(riid, &IID_IUnknown))
2568 *ppv = iface;
2569 IUnknown_AddRef(iface);
2570 return S_OK;
2572 *ppv = NULL;
2573 return E_NOINTERFACE;
2576 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2578 TLB_NEFile *This = (TLB_NEFile *)iface;
2579 return InterlockedIncrement(&This->refs);
2582 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2584 TLB_NEFile *This = (TLB_NEFile *)iface;
2585 ULONG refs = InterlockedDecrement(&This->refs);
2586 if (!refs)
2588 heap_free(This->typelib_base);
2589 heap_free(This);
2591 return refs;
2594 static const IUnknownVtbl TLB_NEFile_Vtable =
2596 TLB_NEFile_QueryInterface,
2597 TLB_NEFile_AddRef,
2598 TLB_NEFile_Release
2601 /***********************************************************************
2602 * read_xx_header [internal]
2604 static int read_xx_header( HFILE lzfd )
2606 IMAGE_DOS_HEADER mzh;
2607 char magic[3];
2609 LZSeek( lzfd, 0, SEEK_SET );
2610 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2611 return 0;
2612 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2613 return 0;
2615 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2616 if ( 2 != LZRead( lzfd, magic, 2 ) )
2617 return 0;
2619 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2621 if ( magic[0] == 'N' && magic[1] == 'E' )
2622 return IMAGE_OS2_SIGNATURE;
2623 if ( magic[0] == 'P' && magic[1] == 'E' )
2624 return IMAGE_NT_SIGNATURE;
2626 magic[2] = '\0';
2627 WARN("Can't handle %s files.\n", magic );
2628 return 0;
2632 /***********************************************************************
2633 * find_ne_resource [internal]
2635 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2636 DWORD *resLen, DWORD *resOff )
2638 IMAGE_OS2_HEADER nehd;
2639 NE_TYPEINFO *typeInfo;
2640 NE_NAMEINFO *nameInfo;
2641 DWORD nehdoffset;
2642 LPBYTE resTab;
2643 DWORD resTabSize;
2644 int count;
2646 /* Read in NE header */
2647 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2648 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2650 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2651 if ( !resTabSize )
2653 TRACE("No resources in NE dll\n" );
2654 return FALSE;
2657 /* Read in resource table */
2658 resTab = heap_alloc( resTabSize );
2659 if ( !resTab ) return FALSE;
2661 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2662 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2664 heap_free( resTab );
2665 return FALSE;
2668 /* Find resource */
2669 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2671 if (!IS_INTRESOURCE(typeid)) /* named type */
2673 BYTE len = strlen( typeid );
2674 while (typeInfo->type_id)
2676 if (!(typeInfo->type_id & 0x8000))
2678 BYTE *p = resTab + typeInfo->type_id;
2679 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2681 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2682 typeInfo->count * sizeof(NE_NAMEINFO));
2685 else /* numeric type id */
2687 WORD id = LOWORD(typeid) | 0x8000;
2688 while (typeInfo->type_id)
2690 if (typeInfo->type_id == id) goto found_type;
2691 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2692 typeInfo->count * sizeof(NE_NAMEINFO));
2695 TRACE("No typeid entry found for %p\n", typeid );
2696 heap_free( resTab );
2697 return FALSE;
2699 found_type:
2700 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2702 if (!IS_INTRESOURCE(resid)) /* named resource */
2704 BYTE len = strlen( resid );
2705 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2707 BYTE *p = resTab + nameInfo->id;
2708 if (nameInfo->id & 0x8000) continue;
2709 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2712 else /* numeric resource id */
2714 WORD id = LOWORD(resid) | 0x8000;
2715 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2716 if (nameInfo->id == id) goto found_name;
2718 TRACE("No resid entry found for %p\n", typeid );
2719 heap_free( resTab );
2720 return FALSE;
2722 found_name:
2723 /* Return resource data */
2724 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2725 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2727 heap_free( resTab );
2728 return TRUE;
2731 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
2733 HFILE lzfd = -1;
2734 OFSTRUCT ofs;
2735 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2736 TLB_NEFile *This;
2738 This = heap_alloc(sizeof(TLB_NEFile));
2739 if (!This) return E_OUTOFMEMORY;
2741 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
2742 This->refs = 1;
2743 This->typelib_base = NULL;
2745 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
2746 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
2748 DWORD reslen, offset;
2749 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
2751 This->typelib_base = heap_alloc(reslen);
2752 if( !This->typelib_base )
2753 hr = E_OUTOFMEMORY;
2754 else
2756 LZSeek( lzfd, offset, SEEK_SET );
2757 reslen = LZRead( lzfd, This->typelib_base, reslen );
2758 LZClose( lzfd );
2759 *ppBase = This->typelib_base;
2760 *pdwTLBLength = reslen;
2761 *ppFile = &This->IUnknown_iface;
2762 return S_OK;
2767 if( lzfd >= 0) LZClose( lzfd );
2768 TLB_NEFile_Release(&This->IUnknown_iface);
2769 return hr;
2772 typedef struct TLB_Mapping
2774 IUnknown IUnknown_iface;
2775 LONG refs;
2776 HANDLE file;
2777 HANDLE mapping;
2778 LPVOID typelib_base;
2779 } TLB_Mapping;
2781 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2783 if (IsEqualIID(riid, &IID_IUnknown))
2785 *ppv = iface;
2786 IUnknown_AddRef(iface);
2787 return S_OK;
2789 *ppv = NULL;
2790 return E_NOINTERFACE;
2793 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2795 TLB_Mapping *This = (TLB_Mapping *)iface;
2796 return InterlockedIncrement(&This->refs);
2799 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2801 TLB_Mapping *This = (TLB_Mapping *)iface;
2802 ULONG refs = InterlockedDecrement(&This->refs);
2803 if (!refs)
2805 if (This->typelib_base)
2806 UnmapViewOfFile(This->typelib_base);
2807 if (This->mapping)
2808 CloseHandle(This->mapping);
2809 if (This->file != INVALID_HANDLE_VALUE)
2810 CloseHandle(This->file);
2811 heap_free(This);
2813 return refs;
2816 static const IUnknownVtbl TLB_Mapping_Vtable =
2818 TLB_Mapping_QueryInterface,
2819 TLB_Mapping_AddRef,
2820 TLB_Mapping_Release
2823 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2825 TLB_Mapping *This;
2827 This = heap_alloc(sizeof(TLB_Mapping));
2828 if (!This)
2829 return E_OUTOFMEMORY;
2831 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
2832 This->refs = 1;
2833 This->file = INVALID_HANDLE_VALUE;
2834 This->mapping = NULL;
2835 This->typelib_base = NULL;
2837 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2838 if (INVALID_HANDLE_VALUE != This->file)
2840 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2841 if (This->mapping)
2843 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2844 if(This->typelib_base)
2846 /* retrieve file size */
2847 *pdwTLBLength = GetFileSize(This->file, NULL);
2848 *ppBase = This->typelib_base;
2849 *ppFile = &This->IUnknown_iface;
2850 return S_OK;
2855 IUnknown_Release(&This->IUnknown_iface);
2856 return TYPE_E_CANTLOADLIBRARY;
2859 /****************************************************************************
2860 * TLB_ReadTypeLib
2862 * find the type of the typelib file and map the typelib resource into
2863 * the memory
2866 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2867 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2869 ITypeLibImpl *entry;
2870 HRESULT ret;
2871 INT index = 1;
2872 LPWSTR index_str, file = (LPWSTR)pszFileName;
2873 LPVOID pBase = NULL;
2874 DWORD dwTLBLength = 0;
2875 IUnknown *pFile = NULL;
2877 *ppTypeLib = NULL;
2879 index_str = strrchrW(pszFileName, '\\');
2880 if(index_str && *++index_str != '\0')
2882 LPWSTR end_ptr;
2883 LONG idx = strtolW(index_str, &end_ptr, 10);
2884 if(*end_ptr == '\0')
2886 int str_len = index_str - pszFileName - 1;
2887 index = idx;
2888 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
2889 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2890 file[str_len] = 0;
2894 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2896 if(strchrW(file, '\\'))
2898 lstrcpyW(pszPath, file);
2900 else
2902 int len = GetSystemDirectoryW(pszPath, cchPath);
2903 pszPath[len] = '\\';
2904 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2908 if(file != pszFileName) heap_free(file);
2910 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2912 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2913 EnterCriticalSection(&cache_section);
2914 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
2916 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2918 TRACE("cache hit\n");
2919 *ppTypeLib = &entry->ITypeLib2_iface;
2920 ITypeLib2_AddRef(*ppTypeLib);
2921 LeaveCriticalSection(&cache_section);
2922 return S_OK;
2925 LeaveCriticalSection(&cache_section);
2927 /* now actually load and parse the typelib */
2929 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2930 if (ret == TYPE_E_CANTLOADLIBRARY)
2931 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2932 if (ret == TYPE_E_CANTLOADLIBRARY)
2933 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2934 if (SUCCEEDED(ret))
2936 if (dwTLBLength >= 4)
2938 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2939 if (dwSignature == MSFT_SIGNATURE)
2940 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2941 else if (dwSignature == SLTG_SIGNATURE)
2942 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2943 else
2945 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2946 ret = TYPE_E_CANTLOADLIBRARY;
2949 else
2950 ret = TYPE_E_CANTLOADLIBRARY;
2951 IUnknown_Release(pFile);
2954 if(*ppTypeLib) {
2955 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2957 TRACE("adding to cache\n");
2958 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
2959 lstrcpyW(impl->path, pszPath);
2960 /* We should really canonicalise the path here. */
2961 impl->index = index;
2963 /* FIXME: check if it has added already in the meantime */
2964 EnterCriticalSection(&cache_section);
2965 list_add_head(&tlb_cache, &impl->entry);
2966 LeaveCriticalSection(&cache_section);
2967 ret = S_OK;
2969 else
2971 if(ret != E_FAIL)
2972 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2974 ret = TYPE_E_CANTLOADLIBRARY;
2978 return ret;
2981 /*================== ITypeLib(2) Methods ===================================*/
2983 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2985 ITypeLibImpl* pTypeLibImpl;
2987 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
2988 if (!pTypeLibImpl) return NULL;
2990 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
2991 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
2992 pTypeLibImpl->ref = 1;
2994 list_init(&pTypeLibImpl->implib_list);
2995 list_init(&pTypeLibImpl->custdata_list);
2996 list_init(&pTypeLibImpl->ref_list);
2997 pTypeLibImpl->dispatch_href = -1;
2999 return pTypeLibImpl;
3002 /****************************************************************************
3003 * ITypeLib2_Constructor_MSFT
3005 * loading an MSFT typelib from an in-memory image
3007 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3009 TLBContext cx;
3010 LONG lPSegDir;
3011 MSFT_Header tlbHeader;
3012 MSFT_SegDir tlbSegDir;
3013 ITypeLibImpl * pTypeLibImpl;
3015 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3017 pTypeLibImpl = TypeLibImpl_Constructor();
3018 if (!pTypeLibImpl) return NULL;
3020 /* get pointer to beginning of typelib data */
3021 cx.pos = 0;
3022 cx.oStart=0;
3023 cx.mapping = pLib;
3024 cx.pLibInfo = pTypeLibImpl;
3025 cx.length = dwTLBLength;
3027 /* read header */
3028 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
3029 TRACE_(typelib)("header:\n");
3030 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3031 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3032 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3033 return NULL;
3035 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3037 /* there is a small amount of information here until the next important
3038 * part:
3039 * the segment directory . Try to calculate the amount of data */
3040 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3042 /* now read the segment directory */
3043 TRACE("read segment directory (at %d)\n",lPSegDir);
3044 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3045 cx.pTblDir = &tlbSegDir;
3047 /* just check two entries */
3048 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3050 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3051 heap_free(pTypeLibImpl);
3052 return NULL;
3055 /* now fill our internal data */
3056 /* TLIBATTR fields */
3057 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
3059 pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid2;
3060 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3061 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
3062 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
3063 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
3065 pTypeLibImpl->lcid = tlbHeader.lcid;
3067 /* name, eventually add to a hash table */
3068 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3070 /* help info */
3071 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3072 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3074 if( tlbHeader.varflags & HELPDLLFLAG)
3076 int offset;
3077 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3078 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3081 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3083 /* custom data */
3084 if(tlbHeader.CustomDataOffset >= 0)
3086 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3089 /* fill in type descriptions */
3090 if(tlbSegDir.pTypdescTab.length > 0)
3092 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3093 INT16 td[4];
3094 pTypeLibImpl->ctTypeDesc = cTD;
3095 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3096 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3097 for(i=0; i<cTD; )
3099 /* FIXME: add several sanity checks here */
3100 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3101 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3103 /* FIXME: check safearray */
3104 if(td[3] < 0)
3105 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3106 else
3107 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3109 else if(td[0] == VT_CARRAY)
3111 /* array descr table here */
3112 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3114 else if(td[0] == VT_USERDEFINED)
3116 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3118 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3121 /* second time around to fill the array subscript info */
3122 for(i=0;i<cTD;i++)
3124 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3125 if(tlbSegDir.pArrayDescriptions.offset>0)
3127 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3128 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3130 if(td[1]<0)
3131 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3132 else
3133 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3135 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3137 for(j = 0; j<td[2]; j++)
3139 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3140 sizeof(INT), &cx, DO_NOT_SEEK);
3141 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3142 sizeof(INT), &cx, DO_NOT_SEEK);
3145 else
3147 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3148 ERR("didn't find array description data\n");
3153 /* imported type libs */
3154 if(tlbSegDir.pImpFiles.offset>0)
3156 TLBImpLib *pImpLib;
3157 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3158 UINT16 size;
3160 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3162 char *name;
3164 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3165 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3166 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3168 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3169 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3170 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3171 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3173 size >>= 2;
3174 name = heap_alloc_zero(size+1);
3175 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3176 pImpLib->name = TLB_MultiByteToBSTR(name);
3177 heap_free(name);
3179 MSFT_ReadGuid(&pImpLib->guid, oGuid, &cx);
3180 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3182 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3186 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3187 if(pTypeLibImpl->dispatch_href != -1)
3188 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
3190 /* type infos */
3191 if(tlbHeader.nrtypeinfos >= 0 )
3193 ITypeInfoImpl **ppTI;
3194 int i;
3196 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3198 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3200 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3202 ++ppTI;
3203 (pTypeLibImpl->TypeInfoCount)++;
3207 TRACE("(%p)\n", pTypeLibImpl);
3208 return &pTypeLibImpl->ITypeLib2_iface;
3212 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3214 char b[3];
3215 int i;
3216 short s;
3218 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3219 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3220 return FALSE;
3223 guid->Data4[0] = s >> 8;
3224 guid->Data4[1] = s & 0xff;
3226 b[2] = '\0';
3227 for(i = 0; i < 6; i++) {
3228 memcpy(b, str + 24 + 2 * i, 2);
3229 guid->Data4[i + 2] = strtol(b, NULL, 16);
3231 return TRUE;
3234 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
3236 WORD bytelen;
3237 DWORD len;
3239 *pBstr = NULL;
3240 bytelen = *(const WORD*)ptr;
3241 if(bytelen == 0xffff) return 2;
3242 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3243 *pBstr = SysAllocStringLen(NULL, len);
3244 if (*pBstr)
3245 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
3246 return bytelen + 2;
3249 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3251 WORD bytelen;
3253 *str = NULL;
3254 bytelen = *(const WORD*)ptr;
3255 if(bytelen == 0xffff) return 2;
3256 *str = heap_alloc(bytelen + 1);
3257 memcpy(*str, ptr + 2, bytelen);
3258 (*str)[bytelen] = '\0';
3259 return bytelen + 2;
3262 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3264 char *ptr = pLibBlk;
3265 WORD w;
3267 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3268 FIXME("libblk magic = %04x\n", w);
3269 return 0;
3272 ptr += 6;
3273 if((w = *(WORD*)ptr) != 0xffff) {
3274 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3275 ptr += w;
3277 ptr += 2;
3279 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
3281 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
3283 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3284 ptr += 4;
3286 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
3287 ptr += 2;
3289 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3290 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3291 else
3292 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = 0;
3293 ptr += 2;
3295 ptr += 4; /* skip res12 */
3297 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
3298 ptr += 2;
3300 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
3301 ptr += 2;
3303 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
3304 ptr += 2;
3306 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
3307 ptr += sizeof(GUID);
3309 return ptr - (char*)pLibBlk;
3312 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3313 typedef struct
3315 unsigned int num;
3316 HREFTYPE refs[1];
3317 } sltg_ref_lookup_t;
3319 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3320 HREFTYPE *typelib_ref)
3322 if(table && typeinfo_ref < table->num)
3324 *typelib_ref = table->refs[typeinfo_ref];
3325 return S_OK;
3328 ERR_(typelib)("Unable to find reference\n");
3329 *typelib_ref = -1;
3330 return E_FAIL;
3333 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3335 BOOL done = FALSE;
3337 while(!done) {
3338 if((*pType & 0xe00) == 0xe00) {
3339 pTD->vt = VT_PTR;
3340 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3341 pTD = pTD->u.lptdesc;
3343 switch(*pType & 0x3f) {
3344 case VT_PTR:
3345 pTD->vt = VT_PTR;
3346 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3347 pTD = pTD->u.lptdesc;
3348 break;
3350 case VT_USERDEFINED:
3351 pTD->vt = VT_USERDEFINED;
3352 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3353 done = TRUE;
3354 break;
3356 case VT_CARRAY:
3358 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3359 array */
3361 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3363 pTD->vt = VT_CARRAY;
3364 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3365 pTD->u.lpadesc->cDims = pSA->cDims;
3366 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3367 pSA->cDims * sizeof(SAFEARRAYBOUND));
3369 pTD = &pTD->u.lpadesc->tdescElem;
3370 break;
3373 case VT_SAFEARRAY:
3375 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3376 useful? */
3378 pType++;
3379 pTD->vt = VT_SAFEARRAY;
3380 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3381 pTD = pTD->u.lptdesc;
3382 break;
3384 default:
3385 pTD->vt = *pType & 0x3f;
3386 done = TRUE;
3387 break;
3389 pType++;
3391 return pType;
3394 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3395 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3397 /* Handle [in/out] first */
3398 if((*pType & 0xc000) == 0xc000)
3399 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3400 else if(*pType & 0x8000)
3401 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3402 else if(*pType & 0x4000)
3403 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3404 else
3405 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3407 if(*pType & 0x2000)
3408 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3410 if(*pType & 0x80)
3411 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3413 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3417 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3418 char *pNameTable)
3420 unsigned int ref;
3421 char *name;
3422 TLBRefType *ref_type;
3423 sltg_ref_lookup_t *table;
3424 HREFTYPE typelib_ref;
3426 if(pRef->magic != SLTG_REF_MAGIC) {
3427 FIXME("Ref magic = %x\n", pRef->magic);
3428 return NULL;
3430 name = ( (char*)pRef->names + pRef->number);
3432 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3433 table->num = pRef->number >> 3;
3435 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3437 /* We don't want the first href to be 0 */
3438 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3440 for(ref = 0; ref < pRef->number >> 3; ref++) {
3441 char *refname;
3442 unsigned int lib_offs, type_num;
3444 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3446 name += SLTG_ReadStringA(name, &refname);
3447 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3448 FIXME_(typelib)("Can't sscanf ref\n");
3449 if(lib_offs != 0xffff) {
3450 TLBImpLib *import;
3452 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
3453 if(import->offset == lib_offs)
3454 break;
3456 if(&import->entry == &pTL->implib_list) {
3457 char fname[MAX_PATH+1];
3458 int len;
3460 import = heap_alloc_zero(sizeof(*import));
3461 import->offset = lib_offs;
3462 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3463 &import->guid);
3464 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3465 &import->wVersionMajor,
3466 &import->wVersionMinor,
3467 &import->lcid, fname) != 4) {
3468 FIXME_(typelib)("can't sscanf ref %s\n",
3469 pNameTable + lib_offs + 40);
3471 len = strlen(fname);
3472 if(fname[len-1] != '#')
3473 FIXME("fname = %s\n", fname);
3474 fname[len-1] = '\0';
3475 import->name = TLB_MultiByteToBSTR(fname);
3476 list_add_tail(&pTL->implib_list, &import->entry);
3478 ref_type->pImpTLInfo = import;
3480 /* Store a reference to IDispatch */
3481 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid, &IID_StdOle) && type_num == 4)
3482 pTL->dispatch_href = typelib_ref;
3484 } else { /* internal ref */
3485 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3487 ref_type->reference = typelib_ref;
3488 ref_type->index = type_num;
3490 heap_free(refname);
3491 list_add_tail(&pTL->ref_list, &ref_type->entry);
3493 table->refs[ref] = typelib_ref;
3494 typelib_ref += 4;
3496 if((BYTE)*name != SLTG_REF_MAGIC)
3497 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3498 dump_TLBRefType(pTL);
3499 return table;
3502 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3503 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3505 SLTG_ImplInfo *info;
3506 TLBImplType *pImplType;
3507 /* I don't really get this structure, usually it's 0x16 bytes
3508 long, but iuser.tlb contains some that are 0x18 bytes long.
3509 That's ok because we can use the next ptr to jump to the next
3510 one. But how do we know the length of the last one? The WORD
3511 at offs 0x8 might be the clue. For now I'm just assuming that
3512 the last one is the regular 0x16 bytes. */
3514 info = (SLTG_ImplInfo*)pBlk;
3515 while(1){
3516 pTI->TypeAttr.cImplTypes++;
3517 if(info->next == 0xffff)
3518 break;
3519 info = (SLTG_ImplInfo*)(pBlk + info->next);
3522 info = (SLTG_ImplInfo*)pBlk;
3523 pTI->impltypes = TLBImplType_Constructor(pTI->TypeAttr.cImplTypes);
3524 pImplType = pTI->impltypes;
3525 while(1) {
3526 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
3527 pImplType->implflags = info->impltypeflags;
3528 ++pImplType;
3530 if(info->next == 0xffff)
3531 break;
3532 if(OneOnly)
3533 FIXME_(typelib)("Interface inheriting more than one interface\n");
3534 info = (SLTG_ImplInfo*)(pBlk + info->next);
3536 info++; /* see comment at top of function */
3537 return (char*)info;
3540 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3541 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3543 TLBVarDesc *pVarDesc;
3544 BSTR bstrPrevName = NULL;
3545 SLTG_Variable *pItem;
3546 unsigned short i;
3547 WORD *pType;
3549 pVarDesc = pTI->vardescs = TLBVarDesc_Constructor(cVars);
3551 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3552 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
3554 pVarDesc->vardesc.memid = pItem->memid;
3556 if (pItem->magic != SLTG_VAR_MAGIC &&
3557 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3558 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3559 return;
3562 if (pItem->name == 0xfffe)
3563 pVarDesc->Name = SysAllocString(bstrPrevName);
3564 else
3565 pVarDesc->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3567 TRACE_(typelib)("name: %s\n", debugstr_w(pVarDesc->Name));
3568 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3569 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3571 if(pItem->flags & 0x02)
3572 pType = &pItem->type;
3573 else
3574 pType = (WORD*)(pBlk + pItem->type);
3576 if (pItem->flags & ~0xda)
3577 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3579 SLTG_DoElem(pType, pBlk,
3580 &pVarDesc->vardesc.elemdescVar, ref_lookup);
3582 if (TRACE_ON(typelib)) {
3583 char buf[300];
3584 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
3585 TRACE_(typelib)("elemdescVar: %s\n", buf);
3588 if (pItem->flags & 0x40) {
3589 TRACE_(typelib)("VAR_DISPATCH\n");
3590 pVarDesc->vardesc.varkind = VAR_DISPATCH;
3592 else if (pItem->flags & 0x10) {
3593 TRACE_(typelib)("VAR_CONST\n");
3594 pVarDesc->vardesc.varkind = VAR_CONST;
3595 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
3596 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
3597 if (pItem->flags & 0x08)
3598 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
3599 else {
3600 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
3602 case VT_LPSTR:
3603 case VT_LPWSTR:
3604 case VT_BSTR:
3606 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3607 BSTR str;
3608 TRACE_(typelib)("len = %u\n", len);
3609 if (len == 0xffff) {
3610 str = NULL;
3611 } else {
3612 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3613 str = SysAllocStringLen(NULL, alloc_len);
3614 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3616 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
3617 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
3618 break;
3620 case VT_I2:
3621 case VT_UI2:
3622 case VT_I4:
3623 case VT_UI4:
3624 case VT_INT:
3625 case VT_UINT:
3626 V_INT(pVarDesc->vardesc.u.lpvarValue) =
3627 *(INT*)(pBlk + pItem->byte_offs);
3628 break;
3629 default:
3630 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
3634 else {
3635 TRACE_(typelib)("VAR_PERINSTANCE\n");
3636 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
3637 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
3640 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3641 pVarDesc->vardesc.wVarFlags = pItem->varflags;
3643 if (pItem->flags & 0x80)
3644 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3646 bstrPrevName = pVarDesc->Name;
3648 pTI->TypeAttr.cVars = cVars;
3651 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3652 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3654 SLTG_Function *pFunc;
3655 unsigned short i;
3656 TLBFuncDesc *pFuncDesc;
3658 pTI->funcdescs = TLBFuncDesc_Constructor(cFuncs);
3660 pFuncDesc = pTI->funcdescs;
3661 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
3662 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
3664 int param;
3665 WORD *pType, *pArg;
3667 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3668 case SLTG_FUNCTION_MAGIC:
3669 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
3670 break;
3671 case SLTG_DISPATCH_FUNCTION_MAGIC:
3672 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
3673 break;
3674 case SLTG_STATIC_FUNCTION_MAGIC:
3675 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
3676 break;
3677 default:
3678 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3679 continue;
3681 pFuncDesc->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3683 pFuncDesc->funcdesc.memid = pFunc->dispid;
3684 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
3685 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
3686 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
3687 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3688 pFuncDesc->funcdesc.oVft = pFunc->vtblpos & ~1;
3690 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3691 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
3693 if(pFunc->retnextopt & 0x80)
3694 pType = &pFunc->rettype;
3695 else
3696 pType = (WORD*)(pBlk + pFunc->rettype);
3698 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
3700 pFuncDesc->funcdesc.lprgelemdescParam =
3701 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
3702 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
3704 pArg = (WORD*)(pBlk + pFunc->arg_off);
3706 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
3707 char *paramName = pNameTable + *pArg;
3708 BOOL HaveOffs;
3709 /* If arg type follows then paramName points to the 2nd
3710 letter of the name, else the next WORD is an offset to
3711 the arg type and paramName points to the first letter.
3712 So let's take one char off paramName and see if we're
3713 pointing at an alpha-numeric char. However if *pArg is
3714 0xffff or 0xfffe then the param has no name, the former
3715 meaning that the next WORD is the type, the latter
3716 meaning that the next WORD is an offset to the type. */
3718 HaveOffs = FALSE;
3719 if(*pArg == 0xffff)
3720 paramName = NULL;
3721 else if(*pArg == 0xfffe) {
3722 paramName = NULL;
3723 HaveOffs = TRUE;
3725 else if(paramName[-1] && !isalnum(paramName[-1]))
3726 HaveOffs = TRUE;
3728 pArg++;
3730 if(HaveOffs) { /* the next word is an offset to type */
3731 pType = (WORD*)(pBlk + *pArg);
3732 SLTG_DoElem(pType, pBlk,
3733 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
3734 pArg++;
3735 } else {
3736 if(paramName)
3737 paramName--;
3738 pArg = SLTG_DoElem(pArg, pBlk,
3739 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
3742 /* Are we an optional param ? */
3743 if(pFuncDesc->funcdesc.cParams - param <=
3744 pFuncDesc->funcdesc.cParamsOpt)
3745 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3747 if(paramName) {
3748 pFuncDesc->pParamDesc[param].Name =
3749 TLB_MultiByteToBSTR(paramName);
3750 } else {
3751 pFuncDesc->pParamDesc[param].Name =
3752 SysAllocString(pFuncDesc->Name);
3756 pTI->TypeAttr.cFuncs = cFuncs;
3759 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3760 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3761 SLTG_TypeInfoTail *pTITail)
3763 char *pFirstItem;
3764 sltg_ref_lookup_t *ref_lookup = NULL;
3766 if(pTIHeader->href_table != 0xffffffff) {
3767 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3768 pNameTable);
3771 pFirstItem = pBlk;
3773 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3774 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3776 heap_free(ref_lookup);
3780 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3781 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3782 const SLTG_TypeInfoTail *pTITail)
3784 char *pFirstItem;
3785 sltg_ref_lookup_t *ref_lookup = NULL;
3787 if(pTIHeader->href_table != 0xffffffff) {
3788 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3789 pNameTable);
3792 pFirstItem = pBlk;
3794 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3795 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3798 if (pTITail->funcs_off != 0xffff)
3799 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3801 heap_free(ref_lookup);
3803 if (TRACE_ON(typelib))
3804 dump_TLBFuncDesc(pTI->funcdescs, pTI->TypeAttr.cFuncs);
3807 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3808 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3809 const SLTG_TypeInfoTail *pTITail)
3811 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3814 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3815 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3816 const SLTG_TypeInfoTail *pTITail)
3818 WORD *pType;
3819 sltg_ref_lookup_t *ref_lookup = NULL;
3821 if (pTITail->simple_alias) {
3822 /* if simple alias, no more processing required */
3823 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3824 return;
3827 if(pTIHeader->href_table != 0xffffffff) {
3828 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3829 pNameTable);
3832 /* otherwise it is an offset to a type */
3833 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3835 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3837 heap_free(ref_lookup);
3840 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3841 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3842 const SLTG_TypeInfoTail *pTITail)
3844 sltg_ref_lookup_t *ref_lookup = NULL;
3845 if (pTIHeader->href_table != 0xffffffff)
3846 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3847 pNameTable);
3849 if (pTITail->vars_off != 0xffff)
3850 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3852 if (pTITail->funcs_off != 0xffff)
3853 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3855 if (pTITail->impls_off != 0xffff)
3856 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
3858 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3859 * of dispinterface functions including the IDispatch ones, so
3860 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3861 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3863 heap_free(ref_lookup);
3864 if (TRACE_ON(typelib))
3865 dump_TLBFuncDesc(pTI->funcdescs, pTI->TypeAttr.cFuncs);
3868 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3869 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3870 const SLTG_TypeInfoTail *pTITail)
3872 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3875 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3876 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3877 const SLTG_TypeInfoTail *pTITail)
3879 sltg_ref_lookup_t *ref_lookup = NULL;
3880 if (pTIHeader->href_table != 0xffffffff)
3881 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3882 pNameTable);
3884 if (pTITail->vars_off != 0xffff)
3885 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3887 if (pTITail->funcs_off != 0xffff)
3888 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3889 heap_free(ref_lookup);
3890 if (TRACE_ON(typelib))
3891 dump_TypeInfo(pTI);
3894 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3895 manageable copy of it into this */
3896 typedef struct {
3897 WORD small_no;
3898 char *index_name;
3899 char *other_name;
3900 WORD res1a;
3901 WORD name_offs;
3902 WORD more_bytes;
3903 char *extra;
3904 WORD res20;
3905 DWORD helpcontext;
3906 WORD res26;
3907 GUID uuid;
3908 } SLTG_InternalOtherTypeInfo;
3910 /****************************************************************************
3911 * ITypeLib2_Constructor_SLTG
3913 * loading a SLTG typelib from an in-memory image
3915 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3917 ITypeLibImpl *pTypeLibImpl;
3918 SLTG_Header *pHeader;
3919 SLTG_BlkEntry *pBlkEntry;
3920 SLTG_Magic *pMagic;
3921 SLTG_Index *pIndex;
3922 SLTG_Pad9 *pPad9;
3923 LPVOID pBlk, pFirstBlk;
3924 SLTG_LibBlk *pLibBlk;
3925 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3926 char *pAfterOTIBlks = NULL;
3927 char *pNameTable, *ptr;
3928 int i;
3929 DWORD len, order;
3930 ITypeInfoImpl **ppTypeInfoImpl;
3932 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3935 pTypeLibImpl = TypeLibImpl_Constructor();
3936 if (!pTypeLibImpl) return NULL;
3938 pHeader = pLib;
3940 TRACE_(typelib)("header:\n");
3941 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3942 pHeader->nrOfFileBlks );
3943 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3944 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3945 pHeader->SLTG_magic);
3946 return NULL;
3949 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3950 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3952 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3953 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3955 /* Next we have a magic block */
3956 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3958 /* Let's see if we're still in sync */
3959 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3960 sizeof(SLTG_COMPOBJ_MAGIC))) {
3961 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3962 return NULL;
3964 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3965 sizeof(SLTG_DIR_MAGIC))) {
3966 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
3967 return NULL;
3970 pIndex = (SLTG_Index*)(pMagic+1);
3972 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3974 pFirstBlk = pPad9 + 1;
3976 /* We'll set up a ptr to the main library block, which is the last one. */
3978 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3979 pBlkEntry[order].next != 0;
3980 order = pBlkEntry[order].next - 1, i++) {
3981 pBlk = (char*)pBlk + pBlkEntry[order].len;
3983 pLibBlk = pBlk;
3985 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3987 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3988 interspersed */
3990 len += 0x40;
3992 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3994 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
3997 ptr = (char*)pLibBlk + len;
3999 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4000 WORD w, extra;
4001 len = 0;
4003 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
4005 w = *(WORD*)(ptr + 2);
4006 if(w != 0xffff) {
4007 len += w;
4008 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
4009 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4010 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4012 w = *(WORD*)(ptr + 4 + len);
4013 if(w != 0xffff) {
4014 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4015 len += w;
4016 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4017 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4018 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4020 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4021 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4022 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4023 if(extra) {
4024 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4025 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4026 len += extra;
4028 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4029 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4030 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4031 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4032 len += sizeof(SLTG_OtherTypeInfo);
4033 ptr += len;
4036 pAfterOTIBlks = ptr;
4038 /* Skip this WORD and get the next DWORD */
4039 len = *(DWORD*)(pAfterOTIBlks + 2);
4041 /* Now add this to pLibBLk look at what we're pointing at and
4042 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4043 dust and we should be pointing at the beginning of the name
4044 table */
4046 pNameTable = (char*)pLibBlk + len;
4048 switch(*(WORD*)pNameTable) {
4049 case 0xffff:
4050 break;
4051 case 0x0200:
4052 pNameTable += 0x20;
4053 break;
4054 default:
4055 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4056 break;
4059 pNameTable += 0x216;
4061 pNameTable += 2;
4063 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4065 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
4068 /* Hopefully we now have enough ptrs set up to actually read in
4069 some TypeInfos. It's not clear which order to do them in, so
4070 I'll just follow the links along the BlkEntry chain and read
4071 them in the order in which they are in the file */
4073 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4074 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4076 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4077 pBlkEntry[order].next != 0;
4078 order = pBlkEntry[order].next - 1, i++) {
4080 SLTG_TypeInfoHeader *pTIHeader;
4081 SLTG_TypeInfoTail *pTITail;
4082 SLTG_MemberHeader *pMemHeader;
4084 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4085 FIXME_(typelib)("Index strings don't match\n");
4086 heap_free(pOtherTypeInfoBlks);
4087 return NULL;
4090 pTIHeader = pBlk;
4091 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4092 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4093 heap_free(pOtherTypeInfoBlks);
4094 return NULL;
4096 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4097 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4098 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4100 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4101 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4102 (*ppTypeInfoImpl)->index = i;
4103 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
4104 pOtherTypeInfoBlks[i].name_offs +
4105 pNameTable);
4106 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4107 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
4108 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
4109 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
4110 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
4111 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
4112 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4114 if((*ppTypeInfoImpl)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
4115 (*ppTypeInfoImpl)->TypeAttr.typekind = TKIND_DISPATCH;
4117 if((pTIHeader->typeflags1 & 7) != 2)
4118 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4119 if(pTIHeader->typeflags3 != 2)
4120 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4122 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4123 debugstr_w((*ppTypeInfoImpl)->Name),
4124 typekind_desc[pTIHeader->typekind],
4125 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
4126 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
4128 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4130 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4132 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
4133 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
4134 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
4136 switch(pTIHeader->typekind) {
4137 case TKIND_ENUM:
4138 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4139 pTIHeader, pTITail);
4140 break;
4142 case TKIND_RECORD:
4143 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4144 pTIHeader, pTITail);
4145 break;
4147 case TKIND_INTERFACE:
4148 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4149 pTIHeader, pTITail);
4150 break;
4152 case TKIND_COCLASS:
4153 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4154 pTIHeader, pTITail);
4155 break;
4157 case TKIND_ALIAS:
4158 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4159 pTIHeader, pTITail);
4160 break;
4162 case TKIND_DISPATCH:
4163 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4164 pTIHeader, pTITail);
4165 break;
4167 case TKIND_MODULE:
4168 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4169 pTIHeader, pTITail);
4170 break;
4172 default:
4173 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4174 break;
4178 /* could get cFuncs, cVars and cImplTypes from here
4179 but we've already set those */
4180 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4181 X(06);
4182 X(16);
4183 X(18);
4184 X(1a);
4185 X(1e);
4186 X(24);
4187 X(26);
4188 X(2a);
4189 X(2c);
4190 X(2e);
4191 X(30);
4192 X(32);
4193 X(34);
4194 #undef X
4195 ++ppTypeInfoImpl;
4196 pBlk = (char*)pBlk + pBlkEntry[order].len;
4199 if(i != pTypeLibImpl->TypeInfoCount) {
4200 FIXME("Somehow processed %d TypeInfos\n", i);
4201 heap_free(pOtherTypeInfoBlks);
4202 return NULL;
4205 heap_free(pOtherTypeInfoBlks);
4206 return &pTypeLibImpl->ITypeLib2_iface;
4209 static inline ITypeLibImpl *impl_from_ITypeLib2(ITypeLib2 *iface)
4211 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeLib2_iface);
4214 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4216 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4218 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4220 if(IsEqualIID(riid, &IID_IUnknown) ||
4221 IsEqualIID(riid,&IID_ITypeLib)||
4222 IsEqualIID(riid,&IID_ITypeLib2))
4224 *ppv = &This->ITypeLib2_iface;
4226 else
4228 *ppv = NULL;
4229 TRACE("-- Interface: E_NOINTERFACE\n");
4230 return E_NOINTERFACE;
4233 IUnknown_AddRef((IUnknown*)*ppv);
4234 return S_OK;
4237 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4239 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4240 ULONG ref = InterlockedIncrement(&This->ref);
4242 TRACE("(%p) ref=%u\n", This, ref);
4244 return ref;
4247 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4249 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4250 ULONG ref = InterlockedDecrement(&This->ref);
4252 TRACE("(%p) ref=%u\n",This, ref);
4254 if (!ref)
4256 TLBImpLib *pImpLib, *pImpLibNext;
4257 TLBRefType *ref_type;
4258 void *cursor2;
4259 int i;
4261 /* remove cache entry */
4262 if(This->path)
4264 TRACE("removing from cache list\n");
4265 EnterCriticalSection(&cache_section);
4266 if(This->entry.next)
4267 list_remove(&This->entry);
4268 LeaveCriticalSection(&cache_section);
4269 heap_free(This->path);
4271 TRACE(" destroying ITypeLib(%p)\n",This);
4273 SysFreeString(This->Name);
4274 This->Name = NULL;
4276 SysFreeString(This->DocString);
4277 This->DocString = NULL;
4279 SysFreeString(This->HelpFile);
4280 This->HelpFile = NULL;
4282 SysFreeString(This->HelpStringDll);
4283 This->HelpStringDll = NULL;
4285 TLB_FreeCustData(&This->custdata_list);
4287 for (i = 0; i < This->ctTypeDesc; i++)
4288 if (This->pTypeDesc[i].vt == VT_CARRAY)
4289 heap_free(This->pTypeDesc[i].u.lpadesc);
4291 heap_free(This->pTypeDesc);
4293 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4295 if (pImpLib->pImpTypeLib)
4296 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4297 SysFreeString(pImpLib->name);
4299 list_remove(&pImpLib->entry);
4300 heap_free(pImpLib);
4303 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4305 list_remove(&ref_type->entry);
4306 heap_free(ref_type);
4309 for (i = 0; i < This->TypeInfoCount; ++i)
4310 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4311 heap_free(This->typeinfos);
4312 heap_free(This);
4313 return 0;
4316 return ref;
4319 /* ITypeLib::GetTypeInfoCount
4321 * Returns the number of type descriptions in the type library
4323 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4325 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4326 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4327 return This->TypeInfoCount;
4330 /* ITypeLib::GetTypeInfo
4332 * retrieves the specified type description in the library.
4334 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4335 ITypeLib2 *iface,
4336 UINT index,
4337 ITypeInfo **ppTInfo)
4339 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4341 TRACE("%p %u %p\n", This, index, ppTInfo);
4343 if(!ppTInfo)
4344 return E_INVALIDARG;
4346 if(index >= This->TypeInfoCount)
4347 return TYPE_E_ELEMENTNOTFOUND;
4349 *ppTInfo = (ITypeInfo*)This->typeinfos[index];
4350 ITypeInfo_AddRef(*ppTInfo);
4352 return S_OK;
4356 /* ITypeLibs::GetTypeInfoType
4358 * Retrieves the type of a type description.
4360 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4361 ITypeLib2 *iface,
4362 UINT index,
4363 TYPEKIND *pTKind)
4365 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4367 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4369 if(!pTKind)
4370 return E_INVALIDARG;
4372 if(index >= This->TypeInfoCount)
4373 return TYPE_E_ELEMENTNOTFOUND;
4375 *pTKind = This->typeinfos[index]->TypeAttr.typekind;
4377 return S_OK;
4380 /* ITypeLib::GetTypeInfoOfGuid
4382 * Retrieves the type description that corresponds to the specified GUID.
4385 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4386 ITypeLib2 *iface,
4387 REFGUID guid,
4388 ITypeInfo **ppTInfo)
4390 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4391 int i;
4393 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4395 for(i = 0; i < This->TypeInfoCount; ++i){
4396 if(IsEqualIID(&This->typeinfos[i]->TypeAttr.guid, guid)){
4397 *ppTInfo = (ITypeInfo*)This->typeinfos[i];
4398 ITypeInfo_AddRef(*ppTInfo);
4399 return S_OK;
4403 return TYPE_E_ELEMENTNOTFOUND;
4406 /* ITypeLib::GetLibAttr
4408 * Retrieves the structure that contains the library's attributes.
4411 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4412 ITypeLib2 *iface,
4413 LPTLIBATTR *attr)
4415 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4417 TRACE("(%p, %p)\n", This, attr);
4419 if (!attr) return E_INVALIDARG;
4421 *attr = heap_alloc(sizeof(**attr));
4422 if (!*attr) return E_OUTOFMEMORY;
4424 **attr = This->LibAttr;
4425 return S_OK;
4428 /* ITypeLib::GetTypeComp
4430 * Enables a client compiler to bind to a library's types, variables,
4431 * constants, and global functions.
4434 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4435 ITypeLib2 *iface,
4436 ITypeComp **ppTComp)
4438 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4440 TRACE("(%p)->(%p)\n",This,ppTComp);
4441 *ppTComp = &This->ITypeComp_iface;
4442 ITypeComp_AddRef(*ppTComp);
4444 return S_OK;
4447 /* ITypeLib::GetDocumentation
4449 * Retrieves the library's documentation string, the complete Help file name
4450 * and path, and the context identifier for the library Help topic in the Help
4451 * file.
4453 * On a successful return all non-null BSTR pointers will have been set,
4454 * possibly to NULL.
4456 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4457 ITypeLib2 *iface,
4458 INT index,
4459 BSTR *pBstrName,
4460 BSTR *pBstrDocString,
4461 DWORD *pdwHelpContext,
4462 BSTR *pBstrHelpFile)
4464 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4465 HRESULT result = E_INVALIDARG;
4466 ITypeInfo *pTInfo;
4468 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4469 This, index,
4470 pBstrName, pBstrDocString,
4471 pdwHelpContext, pBstrHelpFile);
4473 if(index<0)
4475 /* documentation for the typelib */
4476 if(pBstrName)
4478 if (This->Name)
4480 if(!(*pBstrName = SysAllocString(This->Name)))
4481 goto memerr1;
4483 else
4484 *pBstrName = NULL;
4486 if(pBstrDocString)
4488 if (This->DocString)
4490 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4491 goto memerr2;
4493 else if (This->Name)
4495 if(!(*pBstrDocString = SysAllocString(This->Name)))
4496 goto memerr2;
4498 else
4499 *pBstrDocString = NULL;
4501 if(pdwHelpContext)
4503 *pdwHelpContext = This->dwHelpContext;
4505 if(pBstrHelpFile)
4507 if (This->HelpFile)
4509 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4510 goto memerr3;
4512 else
4513 *pBstrHelpFile = NULL;
4516 result = S_OK;
4518 else
4520 /* for a typeinfo */
4521 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4523 if(SUCCEEDED(result))
4525 result = ITypeInfo_GetDocumentation(pTInfo,
4526 MEMBERID_NIL,
4527 pBstrName,
4528 pBstrDocString,
4529 pdwHelpContext, pBstrHelpFile);
4531 ITypeInfo_Release(pTInfo);
4534 return result;
4535 memerr3:
4536 if (pBstrDocString) SysFreeString (*pBstrDocString);
4537 memerr2:
4538 if (pBstrName) SysFreeString (*pBstrName);
4539 memerr1:
4540 return STG_E_INSUFFICIENTMEMORY;
4543 /* ITypeLib::IsName
4545 * Indicates whether a passed-in string contains the name of a type or member
4546 * described in the library.
4549 static HRESULT WINAPI ITypeLib2_fnIsName(
4550 ITypeLib2 *iface,
4551 LPOLESTR szNameBuf,
4552 ULONG lHashVal,
4553 BOOL *pfName)
4555 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4556 int tic;
4557 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
4559 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4560 pfName);
4562 *pfName=TRUE;
4563 for(tic = 0; tic < This->TypeInfoCount; ++tic){
4564 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
4565 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4566 for(fdc = 0; fdc < pTInfo->TypeAttr.cFuncs; ++fdc) {
4567 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
4568 int pc;
4570 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4571 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++)
4572 if(!memcmp(szNameBuf,pFInfo->pParamDesc[pc].Name, nNameBufLen))
4573 goto ITypeLib2_fnIsName_exit;
4575 for(vrc = 0; vrc < pTInfo->TypeAttr.cVars; ++vrc){
4576 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
4577 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4581 *pfName=FALSE;
4583 ITypeLib2_fnIsName_exit:
4584 TRACE("(%p)slow! search for %s: %s found!\n", This,
4585 debugstr_w(szNameBuf), *pfName?"NOT":"");
4587 return S_OK;
4590 /* ITypeLib::FindName
4592 * Finds occurrences of a type description in a type library. This may be used
4593 * to quickly verify that a name exists in a type library.
4596 static HRESULT WINAPI ITypeLib2_fnFindName(
4597 ITypeLib2 *iface,
4598 LPOLESTR name,
4599 ULONG hash,
4600 ITypeInfo **ppTInfo,
4601 MEMBERID *memid,
4602 UINT16 *found)
4604 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4605 int tic;
4606 UINT count = 0;
4607 UINT len;
4609 TRACE("(%p)->(%s %u %p %p %p)\n", This, debugstr_w(name), hash, ppTInfo, memid, found);
4611 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
4612 return E_INVALIDARG;
4614 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
4615 for(tic = 0; tic < This->TypeInfoCount; ++tic) {
4616 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
4617 TLBVarDesc *var;
4618 UINT fdc;
4620 if(!memcmp(name, pTInfo->Name, len)) goto ITypeLib2_fnFindName_exit;
4621 for(fdc = 0; fdc < pTInfo->TypeAttr.cFuncs; ++fdc) {
4622 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
4623 int pc;
4625 if(!memcmp(name, func->Name, len)) goto ITypeLib2_fnFindName_exit;
4626 for(pc = 0; pc < func->funcdesc.cParams; pc++) {
4627 if(!memcmp(name, func->pParamDesc[pc].Name, len))
4628 goto ITypeLib2_fnFindName_exit;
4632 var = TLB_get_vardesc_by_name(pTInfo->vardescs, pTInfo->TypeAttr.cVars, name);
4633 if (var)
4634 goto ITypeLib2_fnFindName_exit;
4636 continue;
4637 ITypeLib2_fnFindName_exit:
4638 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4639 ppTInfo[count]=(LPTYPEINFO)pTInfo;
4640 count++;
4642 TRACE("found %d typeinfos\n", count);
4644 *found = count;
4646 return S_OK;
4649 /* ITypeLib::ReleaseTLibAttr
4651 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4654 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4655 ITypeLib2 *iface,
4656 TLIBATTR *pTLibAttr)
4658 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4659 TRACE("(%p)->(%p)\n", This, pTLibAttr);
4660 heap_free(pTLibAttr);
4663 /* ITypeLib2::GetCustData
4665 * gets the custom data
4667 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4668 ITypeLib2 * iface,
4669 REFGUID guid,
4670 VARIANT *pVarVal)
4672 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4673 TLBCustData *pCData;
4675 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
4677 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
4678 if(!pCData)
4679 return TYPE_E_ELEMENTNOTFOUND;
4681 VariantInit(pVarVal);
4682 VariantCopy(pVarVal, &pCData->data);
4684 return S_OK;
4687 /* ITypeLib2::GetLibStatistics
4689 * Returns statistics about a type library that are required for efficient
4690 * sizing of hash tables.
4693 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4694 ITypeLib2 * iface,
4695 ULONG *pcUniqueNames,
4696 ULONG *pcchUniqueNames)
4698 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4700 FIXME("(%p): stub!\n", This);
4702 if(pcUniqueNames) *pcUniqueNames=1;
4703 if(pcchUniqueNames) *pcchUniqueNames=1;
4704 return S_OK;
4707 /* ITypeLib2::GetDocumentation2
4709 * Retrieves the library's documentation string, the complete Help file name
4710 * and path, the localization context to use, and the context ID for the
4711 * library Help topic in the Help file.
4714 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4715 ITypeLib2 * iface,
4716 INT index,
4717 LCID lcid,
4718 BSTR *pbstrHelpString,
4719 DWORD *pdwHelpStringContext,
4720 BSTR *pbstrHelpStringDll)
4722 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4723 HRESULT result;
4724 ITypeInfo *pTInfo;
4726 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4728 /* the help string should be obtained from the helpstringdll,
4729 * using the _DLLGetDocumentation function, based on the supplied
4730 * lcid. Nice to do sometime...
4732 if(index<0)
4734 /* documentation for the typelib */
4735 if(pbstrHelpString)
4736 *pbstrHelpString=SysAllocString(This->DocString);
4737 if(pdwHelpStringContext)
4738 *pdwHelpStringContext=This->dwHelpContext;
4739 if(pbstrHelpStringDll)
4740 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4742 result = S_OK;
4744 else
4746 /* for a typeinfo */
4747 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4749 if(SUCCEEDED(result))
4751 ITypeInfo2 * pTInfo2;
4752 result = ITypeInfo_QueryInterface(pTInfo,
4753 &IID_ITypeInfo2,
4754 (LPVOID*) &pTInfo2);
4756 if(SUCCEEDED(result))
4758 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4759 MEMBERID_NIL,
4760 lcid,
4761 pbstrHelpString,
4762 pdwHelpStringContext,
4763 pbstrHelpStringDll);
4765 ITypeInfo2_Release(pTInfo2);
4768 ITypeInfo_Release(pTInfo);
4771 return result;
4774 static HRESULT TLB_copy_all_custdata(struct list *custdata_list, CUSTDATA *pCustData)
4776 TLBCustData *pCData;
4777 unsigned int ct;
4778 CUSTDATAITEM *cdi;
4780 ct = list_count(custdata_list);
4782 pCustData->prgCustData = heap_alloc_zero(ct * sizeof(CUSTDATAITEM));
4783 if(!pCustData->prgCustData)
4784 return E_OUTOFMEMORY;
4786 pCustData->cCustData = ct;
4788 cdi = pCustData->prgCustData;
4789 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
4790 cdi->guid = pCData->guid;
4791 VariantCopy(&cdi->varValue, &pCData->data);
4792 ++cdi;
4795 return S_OK;
4799 /* ITypeLib2::GetAllCustData
4801 * Gets all custom data items for the library.
4804 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4805 ITypeLib2 * iface,
4806 CUSTDATA *pCustData)
4808 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4809 TRACE("(%p)->(%p)\n", This, pCustData);
4810 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
4813 static const ITypeLib2Vtbl tlbvt = {
4814 ITypeLib2_fnQueryInterface,
4815 ITypeLib2_fnAddRef,
4816 ITypeLib2_fnRelease,
4817 ITypeLib2_fnGetTypeInfoCount,
4818 ITypeLib2_fnGetTypeInfo,
4819 ITypeLib2_fnGetTypeInfoType,
4820 ITypeLib2_fnGetTypeInfoOfGuid,
4821 ITypeLib2_fnGetLibAttr,
4822 ITypeLib2_fnGetTypeComp,
4823 ITypeLib2_fnGetDocumentation,
4824 ITypeLib2_fnIsName,
4825 ITypeLib2_fnFindName,
4826 ITypeLib2_fnReleaseTLibAttr,
4828 ITypeLib2_fnGetCustData,
4829 ITypeLib2_fnGetLibStatistics,
4830 ITypeLib2_fnGetDocumentation2,
4831 ITypeLib2_fnGetAllCustData
4835 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4837 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4839 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
4842 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4844 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4846 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
4849 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4851 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4853 return ITypeLib2_Release(&This->ITypeLib2_iface);
4856 static HRESULT WINAPI ITypeLibComp_fnBind(
4857 ITypeComp * iface,
4858 OLECHAR * szName,
4859 ULONG lHash,
4860 WORD wFlags,
4861 ITypeInfo ** ppTInfo,
4862 DESCKIND * pDescKind,
4863 BINDPTR * pBindPtr)
4865 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4866 int typemismatch=0, i;
4868 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4870 *pDescKind = DESCKIND_NONE;
4871 pBindPtr->lptcomp = NULL;
4872 *ppTInfo = NULL;
4874 for(i = 0; i < This->TypeInfoCount; ++i){
4875 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
4876 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4878 /* FIXME: check wFlags here? */
4879 /* FIXME: we should use a hash table to look this info up using lHash
4880 * instead of an O(n) search */
4881 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4882 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4884 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4886 *pDescKind = DESCKIND_TYPECOMP;
4887 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
4888 ITypeComp_AddRef(pBindPtr->lptcomp);
4889 TRACE("module or enum: %s\n", debugstr_w(szName));
4890 return S_OK;
4894 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4895 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4897 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
4898 HRESULT hr;
4900 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4901 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4903 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4904 return S_OK;
4906 else if (hr == TYPE_E_TYPEMISMATCH)
4907 typemismatch = 1;
4910 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4911 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4913 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
4914 HRESULT hr;
4915 ITypeInfo *subtypeinfo;
4916 BINDPTR subbindptr;
4917 DESCKIND subdesckind;
4919 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4920 &subtypeinfo, &subdesckind, &subbindptr);
4921 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4923 TYPEDESC tdesc_appobject;
4924 const VARDESC vardesc_appobject =
4926 -2, /* memid */
4927 NULL, /* lpstrSchema */
4929 0 /* oInst */
4932 /* ELEMDESC */
4934 /* TYPEDESC */
4936 &tdesc_appobject
4938 VT_PTR
4941 0, /* wVarFlags */
4942 VAR_STATIC /* varkind */
4945 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
4946 tdesc_appobject.vt = VT_USERDEFINED;
4948 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4950 /* cleanup things filled in by Bind call so we can put our
4951 * application object data in there instead */
4952 switch (subdesckind)
4954 case DESCKIND_FUNCDESC:
4955 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4956 break;
4957 case DESCKIND_VARDESC:
4958 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4959 break;
4960 default:
4961 break;
4963 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4965 if (pTypeInfo->hreftype == -1)
4966 FIXME("no hreftype for interface %p\n", pTypeInfo);
4968 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4969 if (FAILED(hr))
4970 return hr;
4972 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4973 *ppTInfo = (ITypeInfo *)pTypeInfo;
4974 ITypeInfo_AddRef(*ppTInfo);
4975 return S_OK;
4977 else if (hr == TYPE_E_TYPEMISMATCH)
4978 typemismatch = 1;
4982 if (typemismatch)
4984 TRACE("type mismatch %s\n", debugstr_w(szName));
4985 return TYPE_E_TYPEMISMATCH;
4987 else
4989 TRACE("name not found %s\n", debugstr_w(szName));
4990 return S_OK;
4994 static HRESULT WINAPI ITypeLibComp_fnBindType(
4995 ITypeComp * iface,
4996 OLECHAR * szName,
4997 ULONG lHash,
4998 ITypeInfo ** ppTInfo,
4999 ITypeComp ** ppTComp)
5001 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5002 int i;
5004 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5006 if(!szName || !ppTInfo || !ppTComp)
5007 return E_INVALIDARG;
5009 for(i = 0; i < This->TypeInfoCount; ++i)
5011 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5012 /* FIXME: should use lHash to do the search */
5013 if (pTypeInfo->Name && !strcmpiW(pTypeInfo->Name, szName))
5015 TRACE("returning %p\n", pTypeInfo);
5016 *ppTInfo = (ITypeInfo *)&pTypeInfo->ITypeInfo2_iface;
5017 ITypeInfo_AddRef(*ppTInfo);
5018 *ppTComp = &pTypeInfo->ITypeComp_iface;
5019 ITypeComp_AddRef(*ppTComp);
5020 return S_OK;
5024 TRACE("not found\n");
5025 *ppTInfo = NULL;
5026 *ppTComp = NULL;
5027 return S_OK;
5030 static const ITypeCompVtbl tlbtcvt =
5033 ITypeLibComp_fnQueryInterface,
5034 ITypeLibComp_fnAddRef,
5035 ITypeLibComp_fnRelease,
5037 ITypeLibComp_fnBind,
5038 ITypeLibComp_fnBindType
5041 /*================== ITypeInfo(2) Methods ===================================*/
5042 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5044 ITypeInfoImpl *pTypeInfoImpl;
5046 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5047 if (pTypeInfoImpl)
5049 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5050 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5051 pTypeInfoImpl->ref = 0;
5052 pTypeInfoImpl->hreftype = -1;
5053 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
5054 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
5055 list_init(&pTypeInfoImpl->custdata_list);
5057 TRACE("(%p)\n", pTypeInfoImpl);
5058 return pTypeInfoImpl;
5061 /* ITypeInfo::QueryInterface
5063 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5064 ITypeInfo2 *iface,
5065 REFIID riid,
5066 VOID **ppvObject)
5068 ITypeLibImpl *This = (ITypeLibImpl *)iface;
5070 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5072 *ppvObject=NULL;
5073 if(IsEqualIID(riid, &IID_IUnknown) ||
5074 IsEqualIID(riid,&IID_ITypeInfo)||
5075 IsEqualIID(riid,&IID_ITypeInfo2))
5076 *ppvObject = This;
5078 if(*ppvObject){
5079 ITypeInfo2_AddRef(iface);
5080 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5081 return S_OK;
5083 TRACE("-- Interface: E_NOINTERFACE\n");
5084 return E_NOINTERFACE;
5087 /* ITypeInfo::AddRef
5089 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5091 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5092 ULONG ref = InterlockedIncrement(&This->ref);
5094 TRACE("(%p)->ref is %u\n",This, ref);
5096 if (ref == 1 /* incremented from 0 */)
5097 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5099 return ref;
5102 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5104 UINT i;
5106 TRACE("destroying ITypeInfo(%p)\n",This);
5108 SysFreeString(This->Name);
5109 This->Name = NULL;
5111 SysFreeString(This->DocString);
5112 This->DocString = NULL;
5114 SysFreeString(This->DllName);
5115 This->DllName = NULL;
5117 for (i = 0; i < This->TypeAttr.cFuncs; ++i)
5119 int j;
5120 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5121 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5123 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5124 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5126 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5127 heap_free(elemdesc->u.paramdesc.pparamdescex);
5129 TLB_FreeCustData(&pFInfo->pParamDesc[j].custdata_list);
5130 SysFreeString(pFInfo->pParamDesc[j].Name);
5132 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5133 heap_free(pFInfo->pParamDesc);
5134 TLB_FreeCustData(&pFInfo->custdata_list);
5135 if (!IS_INTRESOURCE(pFInfo->Entry) && pFInfo->Entry != (BSTR)-1)
5136 SysFreeString(pFInfo->Entry);
5137 SysFreeString(pFInfo->HelpString);
5138 SysFreeString(pFInfo->Name);
5140 heap_free(This->funcdescs);
5142 for(i = 0; i < This->TypeAttr.cVars; ++i)
5144 TLBVarDesc *pVInfo = &This->vardescs[i];
5145 if (pVInfo->vardesc.varkind == VAR_CONST)
5147 VariantClear(pVInfo->vardesc.u.lpvarValue);
5148 heap_free(pVInfo->vardesc.u.lpvarValue);
5150 TLB_FreeCustData(&pVInfo->custdata_list);
5151 SysFreeString(pVInfo->Name);
5152 SysFreeString(pVInfo->HelpString);
5154 heap_free(This->vardescs);
5156 if(This->impltypes){
5157 for (i = 0; i < This->TypeAttr.cImplTypes; ++i){
5158 TLBImplType *pImpl = &This->impltypes[i];
5159 TLB_FreeCustData(&pImpl->custdata_list);
5161 heap_free(This->impltypes);
5164 TLB_FreeCustData(&This->custdata_list);
5166 heap_free(This);
5169 /* ITypeInfo::Release
5171 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5173 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5174 ULONG ref = InterlockedDecrement(&This->ref);
5176 TRACE("(%p)->(%u)\n",This, ref);
5178 if (!ref)
5180 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5181 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5182 if (not_attached_to_typelib)
5183 heap_free(This);
5184 /* otherwise This will be freed when typelib is freed */
5187 return ref;
5190 /* ITypeInfo::GetTypeAttr
5192 * Retrieves a TYPEATTR structure that contains the attributes of the type
5193 * description.
5196 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5197 LPTYPEATTR *ppTypeAttr)
5199 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5200 SIZE_T size;
5202 TRACE("(%p)\n",This);
5204 size = sizeof(**ppTypeAttr);
5205 if (This->TypeAttr.typekind == TKIND_ALIAS)
5206 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
5208 *ppTypeAttr = heap_alloc(size);
5209 if (!*ppTypeAttr)
5210 return E_OUTOFMEMORY;
5212 **ppTypeAttr = This->TypeAttr;
5214 if (This->TypeAttr.typekind == TKIND_ALIAS)
5215 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5216 &This->TypeAttr.tdescAlias, *ppTypeAttr + 1);
5218 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5219 /* This should include all the inherited funcs */
5220 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
5221 /* This is always the size of IDispatch's vtbl */
5222 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5223 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5225 return S_OK;
5228 /* ITypeInfo::GetTypeComp
5230 * Retrieves the ITypeComp interface for the type description, which enables a
5231 * client compiler to bind to the type description's members.
5234 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5235 ITypeComp * *ppTComp)
5237 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5239 TRACE("(%p)->(%p)\n", This, ppTComp);
5241 *ppTComp = &This->ITypeComp_iface;
5242 ITypeComp_AddRef(*ppTComp);
5243 return S_OK;
5246 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5248 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5249 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5250 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5251 return size;
5254 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5256 *dest = *src;
5257 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5258 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5260 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5261 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5262 *buffer += sizeof(PARAMDESCEX);
5263 *pparamdescex_dest = *pparamdescex_src;
5264 VariantInit(&pparamdescex_dest->varDefaultValue);
5265 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5266 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5268 else
5269 dest->u.paramdesc.pparamdescex = NULL;
5270 return S_OK;
5273 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5275 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5276 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5279 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5281 FUNCDESC *dest;
5282 char *buffer;
5283 SIZE_T size = sizeof(*src);
5284 SHORT i;
5285 HRESULT hr;
5287 size += sizeof(*src->lprgscode) * src->cScodes;
5288 size += TLB_SizeElemDesc(&src->elemdescFunc);
5289 for (i = 0; i < src->cParams; i++)
5291 size += sizeof(ELEMDESC);
5292 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5295 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5296 if (!dest) return E_OUTOFMEMORY;
5298 *dest = *src;
5299 if (dispinterface) /* overwrite funckind */
5300 dest->funckind = FUNC_DISPATCH;
5301 buffer = (char *)(dest + 1);
5303 dest->lprgscode = (SCODE *)buffer;
5304 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5305 buffer += sizeof(*src->lprgscode) * src->cScodes;
5307 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5308 if (FAILED(hr))
5310 SysFreeString((BSTR)dest);
5311 return hr;
5314 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5315 buffer += sizeof(ELEMDESC) * src->cParams;
5316 for (i = 0; i < src->cParams; i++)
5318 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5319 if (FAILED(hr))
5320 break;
5322 if (FAILED(hr))
5324 /* undo the above actions */
5325 for (i = i - 1; i >= 0; i--)
5326 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5327 TLB_FreeElemDesc(&dest->elemdescFunc);
5328 SysFreeString((BSTR)dest);
5329 return hr;
5332 /* special treatment for dispinterfaces: this makes functions appear
5333 * to return their [retval] value when it is really returning an
5334 * HRESULT */
5335 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5337 if (dest->cParams &&
5338 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5340 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5341 if (elemdesc->tdesc.vt != VT_PTR)
5343 ERR("elemdesc should have started with VT_PTR instead of:\n");
5344 if (ERR_ON(ole))
5345 dump_ELEMDESC(elemdesc);
5346 return E_UNEXPECTED;
5349 /* copy last parameter to the return value. we are using a flat
5350 * buffer so there is no danger of leaking memory in
5351 * elemdescFunc */
5352 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5354 /* remove the last parameter */
5355 dest->cParams--;
5357 else
5358 /* otherwise this function is made to appear to have no return
5359 * value */
5360 dest->elemdescFunc.tdesc.vt = VT_VOID;
5364 *dest_ptr = dest;
5365 return S_OK;
5368 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5370 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5372 if (index >= This->TypeAttr.cFuncs)
5373 return TYPE_E_ELEMENTNOTFOUND;
5375 *ppFuncDesc = &This->funcdescs[index].funcdesc;
5376 return S_OK;
5379 /* internal function to make the inherited interfaces' methods appear
5380 * part of the interface */
5381 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5382 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5384 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5385 HRESULT hr;
5386 UINT implemented_funcs = 0;
5388 if (funcs)
5389 *funcs = 0;
5390 else
5391 *hrefoffset = DISPATCH_HREF_OFFSET;
5393 if(This->impltypes)
5395 ITypeInfo *pSubTypeInfo;
5396 UINT sub_funcs;
5398 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5399 if (FAILED(hr))
5400 return hr;
5402 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5403 index,
5404 ppFuncDesc,
5405 &sub_funcs, hrefoffset);
5406 implemented_funcs += sub_funcs;
5407 ITypeInfo_Release(pSubTypeInfo);
5408 if (SUCCEEDED(hr))
5409 return hr;
5410 *hrefoffset += DISPATCH_HREF_OFFSET;
5413 if (funcs)
5414 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
5415 else
5416 *hrefoffset = 0;
5418 if (index < implemented_funcs)
5419 return E_INVALIDARG;
5420 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5421 ppFuncDesc);
5424 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5426 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5427 while (TRUE)
5429 switch (pTypeDesc->vt)
5431 case VT_USERDEFINED:
5432 pTypeDesc->u.hreftype += hrefoffset;
5433 return;
5434 case VT_PTR:
5435 case VT_SAFEARRAY:
5436 pTypeDesc = pTypeDesc->u.lptdesc;
5437 break;
5438 case VT_CARRAY:
5439 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5440 break;
5441 default:
5442 return;
5447 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5449 SHORT i;
5450 for (i = 0; i < pFuncDesc->cParams; i++)
5451 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5452 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5455 /* ITypeInfo::GetFuncDesc
5457 * Retrieves the FUNCDESC structure that contains information about a
5458 * specified function.
5461 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5462 LPFUNCDESC *ppFuncDesc)
5464 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5465 const FUNCDESC *internal_funcdesc;
5466 HRESULT hr;
5467 UINT hrefoffset = 0;
5469 TRACE("(%p) index %d\n", This, index);
5471 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5472 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5473 &internal_funcdesc, NULL,
5474 &hrefoffset);
5475 else
5476 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5477 &internal_funcdesc);
5478 if (FAILED(hr))
5480 WARN("description for function %d not found\n", index);
5481 return hr;
5484 hr = TLB_AllocAndInitFuncDesc(
5485 internal_funcdesc,
5486 ppFuncDesc,
5487 This->TypeAttr.typekind == TKIND_DISPATCH);
5489 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5490 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5492 TRACE("-- 0x%08x\n", hr);
5493 return hr;
5496 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5498 VARDESC *dest;
5499 char *buffer;
5500 SIZE_T size = sizeof(*src);
5501 HRESULT hr;
5503 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5504 if (src->varkind == VAR_CONST)
5505 size += sizeof(VARIANT);
5506 size += TLB_SizeElemDesc(&src->elemdescVar);
5508 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5509 if (!dest) return E_OUTOFMEMORY;
5511 *dest = *src;
5512 buffer = (char *)(dest + 1);
5513 if (src->lpstrSchema)
5515 int len;
5516 dest->lpstrSchema = (LPOLESTR)buffer;
5517 len = strlenW(src->lpstrSchema);
5518 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5519 buffer += (len + 1) * sizeof(WCHAR);
5522 if (src->varkind == VAR_CONST)
5524 HRESULT hr;
5526 dest->u.lpvarValue = (VARIANT *)buffer;
5527 *dest->u.lpvarValue = *src->u.lpvarValue;
5528 buffer += sizeof(VARIANT);
5529 VariantInit(dest->u.lpvarValue);
5530 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5531 if (FAILED(hr))
5533 SysFreeString((BSTR)dest);
5534 return hr;
5537 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5538 if (FAILED(hr))
5540 if (src->varkind == VAR_CONST)
5541 VariantClear(dest->u.lpvarValue);
5542 SysFreeString((BSTR)dest);
5543 return hr;
5545 *dest_ptr = dest;
5546 return S_OK;
5549 /* ITypeInfo::GetVarDesc
5551 * Retrieves a VARDESC structure that describes the specified variable.
5554 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5555 LPVARDESC *ppVarDesc)
5557 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5558 const TLBVarDesc *pVDesc = &This->vardescs[index];
5560 TRACE("(%p) index %d\n", This, index);
5562 if(index >= This->TypeAttr.cVars)
5563 return TYPE_E_ELEMENTNOTFOUND;
5565 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5568 /* ITypeInfo_GetNames
5570 * Retrieves the variable with the specified member ID (or the name of the
5571 * property or method and its parameters) that correspond to the specified
5572 * function ID.
5574 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5575 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5577 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5578 const TLBFuncDesc *pFDesc;
5579 const TLBVarDesc *pVDesc;
5580 int i;
5581 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5582 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
5583 if(pFDesc)
5585 /* function found, now return function and parameter names */
5586 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5588 if(!i)
5589 *rgBstrNames=SysAllocString(pFDesc->Name);
5590 else
5591 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5593 *pcNames=i;
5595 else
5597 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
5598 if(pVDesc)
5600 *rgBstrNames=SysAllocString(pVDesc->Name);
5601 *pcNames=1;
5603 else
5605 if(This->impltypes &&
5606 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5607 /* recursive search */
5608 ITypeInfo *pTInfo;
5609 HRESULT result;
5610 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
5611 if(SUCCEEDED(result))
5613 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5614 ITypeInfo_Release(pTInfo);
5615 return result;
5617 WARN("Could not search inherited interface!\n");
5619 else
5621 WARN("no names found\n");
5623 *pcNames=0;
5624 return TYPE_E_ELEMENTNOTFOUND;
5627 return S_OK;
5631 /* ITypeInfo::GetRefTypeOfImplType
5633 * If a type description describes a COM class, it retrieves the type
5634 * description of the implemented interface types. For an interface,
5635 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5636 * if any exist.
5639 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5640 ITypeInfo2 *iface,
5641 UINT index,
5642 HREFTYPE *pRefType)
5644 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5645 HRESULT hr = S_OK;
5647 TRACE("(%p) index %d\n", This, index);
5648 if (TRACE_ON(ole)) dump_TypeInfo(This);
5650 if(index==(UINT)-1)
5652 /* only valid on dual interfaces;
5653 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5655 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5657 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
5659 *pRefType = -1;
5661 else
5663 hr = TYPE_E_ELEMENTNOTFOUND;
5666 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5668 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5669 *pRefType = This->pTypeLib->dispatch_href;
5671 else
5673 if(index >= This->TypeAttr.cImplTypes)
5674 hr = TYPE_E_ELEMENTNOTFOUND;
5675 else
5676 *pRefType = This->impltypes[index].hRef;
5679 if(TRACE_ON(ole))
5681 if(SUCCEEDED(hr))
5682 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5683 else
5684 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5687 return hr;
5690 /* ITypeInfo::GetImplTypeFlags
5692 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5693 * or base interface in a type description.
5695 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5696 UINT index, INT *pImplTypeFlags)
5698 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5700 TRACE("(%p) index %d\n", This, index);
5702 if(This->TypeAttr.typekind == TKIND_DISPATCH && index == 0){
5703 *pImplTypeFlags = 0;
5704 return S_OK;
5707 if(index >= This->TypeAttr.cImplTypes)
5708 return TYPE_E_ELEMENTNOTFOUND;
5710 *pImplTypeFlags = This->impltypes[index].implflags;
5712 return S_OK;
5715 /* GetIDsOfNames
5716 * Maps between member names and member IDs, and parameter names and
5717 * parameter IDs.
5719 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5720 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5722 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5723 const TLBVarDesc *pVDesc;
5724 HRESULT ret=S_OK;
5725 UINT i, fdc;
5727 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5728 cNames);
5730 /* init out parameters in case of failure */
5731 for (i = 0; i < cNames; i++)
5732 pMemId[i] = MEMBERID_NIL;
5734 for (fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc) {
5735 int j;
5736 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
5737 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5738 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5739 for(i=1; i < cNames; i++){
5740 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5741 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5742 break;
5743 if( j<pFDesc->funcdesc.cParams)
5744 pMemId[i]=j;
5745 else
5746 ret=DISP_E_UNKNOWNNAME;
5748 TRACE("-- 0x%08x\n", ret);
5749 return ret;
5752 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->TypeAttr.cVars, *rgszNames);
5753 if(pVDesc){
5754 if(cNames)
5755 *pMemId = pVDesc->vardesc.memid;
5756 return ret;
5758 /* not found, see if it can be found in an inherited interface */
5759 if(This->impltypes) {
5760 /* recursive search */
5761 ITypeInfo *pTInfo;
5762 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
5763 if(SUCCEEDED(ret)){
5764 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5765 ITypeInfo_Release(pTInfo);
5766 return ret;
5768 WARN("Could not search inherited interface!\n");
5769 } else
5770 WARN("no names found\n");
5771 return DISP_E_UNKNOWNNAME;
5775 #ifdef __i386__
5777 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
5778 __ASM_GLOBAL_FUNC( call_method,
5779 "pushl %ebp\n\t"
5780 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
5781 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
5782 "movl %esp,%ebp\n\t"
5783 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
5784 "pushl %esi\n\t"
5785 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
5786 "pushl %edi\n\t"
5787 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
5788 "movl 12(%ebp),%edx\n\t"
5789 "movl %esp,%edi\n\t"
5790 "shll $2,%edx\n\t"
5791 "jz 1f\n\t"
5792 "subl %edx,%edi\n\t"
5793 "andl $~15,%edi\n\t"
5794 "movl %edi,%esp\n\t"
5795 "movl 12(%ebp),%ecx\n\t"
5796 "movl 16(%ebp),%esi\n\t"
5797 "cld\n\t"
5798 "rep; movsl\n"
5799 "1:\tcall *8(%ebp)\n\t"
5800 "subl %esp,%edi\n\t"
5801 "movl 20(%ebp),%ecx\n\t"
5802 "movl %edi,(%ecx)\n\t"
5803 "leal -8(%ebp),%esp\n\t"
5804 "popl %edi\n\t"
5805 __ASM_CFI(".cfi_same_value %edi\n\t")
5806 "popl %esi\n\t"
5807 __ASM_CFI(".cfi_same_value %esi\n\t")
5808 "popl %ebp\n\t"
5809 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
5810 __ASM_CFI(".cfi_same_value %ebp\n\t")
5811 "ret" )
5813 /* same function but returning floating point */
5814 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
5816 /* ITypeInfo::Invoke
5818 * Invokes a method, or accesses a property of an object, that implements the
5819 * interface described by the type description.
5821 DWORD
5822 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5823 DWORD res;
5824 int stack_offset;
5826 if (TRACE_ON(ole)) {
5827 int i;
5828 TRACE("Calling %p(",func);
5829 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
5830 if (nrargs > 30) TRACE("...");
5831 TRACE(")\n");
5834 switch (callconv) {
5835 case CC_STDCALL:
5836 case CC_CDECL:
5837 res = call_method( func, nrargs, args, &stack_offset );
5838 break;
5839 default:
5840 FIXME("unsupported calling convention %d\n",callconv);
5841 res = -1;
5842 break;
5844 TRACE("returns %08x\n",res);
5845 return res;
5848 #elif defined(__x86_64__)
5850 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
5851 __ASM_GLOBAL_FUNC( call_method,
5852 "pushq %rbp\n\t"
5853 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
5854 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
5855 "movq %rsp,%rbp\n\t"
5856 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
5857 "pushq %rsi\n\t"
5858 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
5859 "pushq %rdi\n\t"
5860 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
5861 "movq %rcx,%rax\n\t"
5862 "movq $4,%rcx\n\t"
5863 "cmp %rcx,%rdx\n\t"
5864 "cmovgq %rdx,%rcx\n\t"
5865 "leaq 0(,%rcx,8),%rdx\n\t"
5866 "subq %rdx,%rsp\n\t"
5867 "andq $~15,%rsp\n\t"
5868 "movq %rsp,%rdi\n\t"
5869 "movq %r8,%rsi\n\t"
5870 "rep; movsq\n\t"
5871 "movq 0(%rsp),%rcx\n\t"
5872 "movq 8(%rsp),%rdx\n\t"
5873 "movq 16(%rsp),%r8\n\t"
5874 "movq 24(%rsp),%r9\n\t"
5875 "movq %rcx,%xmm0\n\t"
5876 "movq %rdx,%xmm1\n\t"
5877 "movq %r8,%xmm2\n\t"
5878 "movq %r9,%xmm3\n\t"
5879 "callq *%rax\n\t"
5880 "leaq -16(%rbp),%rsp\n\t"
5881 "popq %rdi\n\t"
5882 __ASM_CFI(".cfi_same_value %rdi\n\t")
5883 "popq %rsi\n\t"
5884 __ASM_CFI(".cfi_same_value %rsi\n\t")
5885 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
5886 "popq %rbp\n\t"
5887 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
5888 __ASM_CFI(".cfi_same_value %rbp\n\t")
5889 "ret")
5891 /* same function but returning floating point */
5892 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
5894 #endif /* __x86_64__ */
5896 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5898 HRESULT hr = S_OK;
5899 ITypeInfo *tinfo2 = NULL;
5900 TYPEATTR *tattr = NULL;
5902 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5903 if (hr)
5905 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5906 "hr = 0x%08x\n",
5907 tdesc->u.hreftype, hr);
5908 return hr;
5910 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5911 if (hr)
5913 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5914 ITypeInfo_Release(tinfo2);
5915 return hr;
5918 switch (tattr->typekind)
5920 case TKIND_ENUM:
5921 *vt |= VT_I4;
5922 break;
5924 case TKIND_ALIAS:
5925 tdesc = &tattr->tdescAlias;
5926 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5927 break;
5929 case TKIND_INTERFACE:
5930 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5931 *vt |= VT_DISPATCH;
5932 else
5933 *vt |= VT_UNKNOWN;
5934 break;
5936 case TKIND_DISPATCH:
5937 *vt |= VT_DISPATCH;
5938 break;
5940 case TKIND_COCLASS:
5941 *vt |= VT_DISPATCH;
5942 break;
5944 case TKIND_RECORD:
5945 FIXME("TKIND_RECORD unhandled.\n");
5946 hr = E_NOTIMPL;
5947 break;
5949 case TKIND_UNION:
5950 FIXME("TKIND_UNION unhandled.\n");
5951 hr = E_NOTIMPL;
5952 break;
5954 default:
5955 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5956 hr = E_NOTIMPL;
5957 break;
5959 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5960 ITypeInfo_Release(tinfo2);
5961 return hr;
5964 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5966 HRESULT hr = S_OK;
5968 /* enforce only one level of pointer indirection */
5969 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5971 tdesc = tdesc->u.lptdesc;
5973 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5974 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5975 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5976 if ((tdesc->vt == VT_USERDEFINED) ||
5977 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5979 VARTYPE vt_userdefined = 0;
5980 const TYPEDESC *tdesc_userdefined = tdesc;
5981 if (tdesc->vt == VT_PTR)
5983 vt_userdefined = VT_BYREF;
5984 tdesc_userdefined = tdesc->u.lptdesc;
5986 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5987 if ((hr == S_OK) &&
5988 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5989 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5991 *vt |= vt_userdefined;
5992 return S_OK;
5995 *vt = VT_BYREF;
5998 switch (tdesc->vt)
6000 case VT_HRESULT:
6001 *vt |= VT_ERROR;
6002 break;
6003 case VT_USERDEFINED:
6004 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
6005 break;
6006 case VT_VOID:
6007 case VT_CARRAY:
6008 case VT_PTR:
6009 case VT_LPSTR:
6010 case VT_LPWSTR:
6011 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
6012 hr = DISP_E_BADVARTYPE;
6013 break;
6014 case VT_SAFEARRAY:
6015 *vt |= VT_ARRAY;
6016 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
6017 break;
6018 case VT_INT:
6019 *vt |= VT_I4;
6020 break;
6021 case VT_UINT:
6022 *vt |= VT_UI4;
6023 break;
6024 default:
6025 *vt |= tdesc->vt;
6026 break;
6028 return hr;
6031 static HRESULT get_iface_guid(ITypeInfo *tinfo, const TYPEDESC *tdesc, GUID *guid)
6033 ITypeInfo *tinfo2;
6034 TYPEATTR *tattr;
6035 HRESULT hres;
6037 hres = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6038 if(FAILED(hres))
6039 return hres;
6041 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6042 if(FAILED(hres)) {
6043 ITypeInfo_Release(tinfo2);
6044 return hres;
6047 switch(tattr->typekind) {
6048 case TKIND_ALIAS:
6049 hres = get_iface_guid(tinfo2, &tattr->tdescAlias, guid);
6050 break;
6052 case TKIND_INTERFACE:
6053 case TKIND_DISPATCH:
6054 *guid = tattr->guid;
6055 break;
6057 default:
6058 ERR("Unexpected typekind %d\n", tattr->typekind);
6059 hres = E_UNEXPECTED;
6062 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6063 ITypeInfo_Release(tinfo2);
6064 return hres;
6067 /***********************************************************************
6068 * DispCallFunc (OLEAUT32.@)
6070 * Invokes a function of the specified calling convention, passing the
6071 * specified arguments and returns the result.
6073 * PARAMS
6074 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6075 * oVft [I] The offset in the vtable. See notes.
6076 * cc [I] Calling convention of the function to call.
6077 * vtReturn [I] The return type of the function.
6078 * cActuals [I] Number of parameters.
6079 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6080 * prgpvarg [I] The arguments to pass.
6081 * pvargResult [O] The return value of the function. Can be NULL.
6083 * RETURNS
6084 * Success: S_OK.
6085 * Failure: HRESULT code.
6087 * NOTES
6088 * The HRESULT return value of this function is not affected by the return
6089 * value of the user supplied function, which is returned in pvargResult.
6091 * If pvInstance is NULL then a non-object function is to be called and oVft
6092 * is the address of the function to call.
6094 * The cc parameter can be one of the following values:
6095 *|CC_FASTCALL
6096 *|CC_CDECL
6097 *|CC_PASCAL
6098 *|CC_STDCALL
6099 *|CC_FPFASTCALL
6100 *|CC_SYSCALL
6101 *|CC_MPWCDECL
6102 *|CC_MPWPASCAL
6105 HRESULT WINAPI
6106 DispCallFunc(
6107 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
6108 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
6110 #ifdef __i386__
6111 int argspos, stack_offset;
6112 void *func;
6113 UINT i;
6114 DWORD *args;
6116 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6117 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6118 pvargResult, V_VT(pvargResult));
6120 if (cc != CC_STDCALL && cc != CC_CDECL)
6122 FIXME("unsupported calling convention %d\n",cc);
6123 return E_INVALIDARG;
6126 /* maximum size for an argument is sizeof(VARIANT) */
6127 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6129 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6130 argspos = 1;
6131 if (pvInstance)
6133 const FARPROC *vtable = *(FARPROC **)pvInstance;
6134 func = vtable[oVft/sizeof(void *)];
6135 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6137 else func = (void *)oVft;
6139 for (i = 0; i < cActuals; i++)
6141 VARIANT *arg = prgpvarg[i];
6143 switch (prgvt[i])
6145 case VT_EMPTY:
6146 break;
6147 case VT_I8:
6148 case VT_UI8:
6149 case VT_R8:
6150 case VT_DATE:
6151 case VT_CY:
6152 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6153 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6154 break;
6155 case VT_DECIMAL:
6156 case VT_VARIANT:
6157 memcpy( &args[argspos], arg, sizeof(*arg) );
6158 argspos += sizeof(*arg) / sizeof(DWORD);
6159 break;
6160 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6161 args[argspos++] = V_BOOL(arg);
6162 break;
6163 default:
6164 args[argspos++] = V_UI4(arg);
6165 break;
6167 TRACE("arg %u: type %d\n",i,prgvt[i]);
6168 dump_Variant(arg);
6171 switch (vtReturn)
6173 case VT_EMPTY:
6174 call_method( func, argspos - 1, args + 1, &stack_offset );
6175 break;
6176 case VT_R4:
6177 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6178 break;
6179 case VT_R8:
6180 case VT_DATE:
6181 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6182 break;
6183 case VT_DECIMAL:
6184 case VT_VARIANT:
6185 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6186 call_method( func, argspos, args, &stack_offset );
6187 break;
6188 case VT_I8:
6189 case VT_UI8:
6190 case VT_CY:
6191 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6192 break;
6193 case VT_HRESULT:
6194 WARN("invalid return type %u\n", vtReturn);
6195 heap_free( args );
6196 return E_INVALIDARG;
6197 default:
6198 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6199 break;
6201 heap_free( args );
6202 if (stack_offset && cc == CC_STDCALL)
6204 WARN( "stack pointer off by %d\n", stack_offset );
6205 return DISP_E_BADCALLEE;
6207 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6208 TRACE("retval: "); dump_Variant(pvargResult);
6209 return S_OK;
6211 #elif defined(__x86_64__)
6212 int argspos;
6213 UINT i;
6214 DWORD_PTR *args;
6215 void *func;
6217 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6218 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6219 pvargResult, V_VT(pvargResult));
6221 if (cc != CC_STDCALL && cc != CC_CDECL)
6223 FIXME("unsupported calling convention %d\n",cc);
6224 return E_INVALIDARG;
6227 /* maximum size for an argument is sizeof(DWORD_PTR) */
6228 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6230 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6231 argspos = 1;
6232 if (pvInstance)
6234 const FARPROC *vtable = *(FARPROC **)pvInstance;
6235 func = vtable[oVft/sizeof(void *)];
6236 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6238 else func = (void *)oVft;
6240 for (i = 0; i < cActuals; i++)
6242 VARIANT *arg = prgpvarg[i];
6244 switch (prgvt[i])
6246 case VT_DECIMAL:
6247 case VT_VARIANT:
6248 args[argspos++] = (ULONG_PTR)arg;
6249 break;
6250 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6251 args[argspos++] = V_BOOL(arg);
6252 break;
6253 default:
6254 args[argspos++] = V_UI8(arg);
6255 break;
6257 TRACE("arg %u: type %d\n",i,prgvt[i]);
6258 dump_Variant(arg);
6261 switch (vtReturn)
6263 case VT_R4:
6264 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6265 break;
6266 case VT_R8:
6267 case VT_DATE:
6268 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6269 break;
6270 case VT_DECIMAL:
6271 case VT_VARIANT:
6272 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6273 call_method( func, argspos, args );
6274 break;
6275 case VT_HRESULT:
6276 WARN("invalid return type %u\n", vtReturn);
6277 heap_free( args );
6278 return E_INVALIDARG;
6279 default:
6280 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6281 break;
6283 heap_free( args );
6284 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6285 TRACE("retval: "); dump_Variant(pvargResult);
6286 return S_OK;
6288 #else
6289 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6290 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6291 return E_NOTIMPL;
6292 #endif
6295 static inline BOOL func_restricted( const FUNCDESC *desc )
6297 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
6300 #define INVBUF_ELEMENT_SIZE \
6301 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6302 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6303 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6304 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6305 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6306 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6307 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6308 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6310 static HRESULT WINAPI ITypeInfo_fnInvoke(
6311 ITypeInfo2 *iface,
6312 VOID *pIUnk,
6313 MEMBERID memid,
6314 UINT16 wFlags,
6315 DISPPARAMS *pDispParams,
6316 VARIANT *pVarResult,
6317 EXCEPINFO *pExcepInfo,
6318 UINT *pArgErr)
6320 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6321 int i;
6322 unsigned int var_index;
6323 TYPEKIND type_kind;
6324 HRESULT hres;
6325 const TLBFuncDesc *pFuncInfo;
6326 UINT fdc;
6328 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6329 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6332 if( This->TypeAttr.wTypeFlags & TYPEFLAG_FRESTRICTED )
6333 return DISP_E_MEMBERNOTFOUND;
6335 if (!pDispParams)
6337 ERR("NULL pDispParams not allowed\n");
6338 return E_INVALIDARG;
6341 dump_DispParms(pDispParams);
6343 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6345 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6346 pDispParams->cNamedArgs, pDispParams->cArgs);
6347 return E_INVALIDARG;
6350 /* we do this instead of using GetFuncDesc since it will return a fake
6351 * FUNCDESC for dispinterfaces and we want the real function description */
6352 for (fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc){
6353 pFuncInfo = &This->funcdescs[fdc];
6354 if ((memid == pFuncInfo->funcdesc.memid) &&
6355 (wFlags & pFuncInfo->funcdesc.invkind) &&
6356 !func_restricted( &pFuncInfo->funcdesc ))
6357 break;
6360 if (fdc < This->TypeAttr.cFuncs) {
6361 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6363 if (TRACE_ON(ole))
6365 TRACE("invoking:\n");
6366 dump_TLBFuncDescOne(pFuncInfo);
6369 switch (func_desc->funckind) {
6370 case FUNC_PUREVIRTUAL:
6371 case FUNC_VIRTUAL: {
6372 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
6373 VARIANT varresult;
6374 VARIANT retval; /* pointer for storing byref retvals in */
6375 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6376 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6377 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6378 UINT cNamedArgs = pDispParams->cNamedArgs;
6379 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6380 UINT vargs_converted=0;
6382 hres = S_OK;
6384 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6386 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6388 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6389 hres = DISP_E_PARAMNOTFOUND;
6390 goto func_fail;
6394 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6396 ERR("functions with the vararg attribute do not support named arguments\n");
6397 hres = DISP_E_NONAMEDARGS;
6398 goto func_fail;
6401 for (i = 0; i < func_desc->cParams; i++)
6403 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6404 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6405 if (FAILED(hres))
6406 goto func_fail;
6409 TRACE("changing args\n");
6410 for (i = 0; i < func_desc->cParams; i++)
6412 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6413 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6414 VARIANTARG *src_arg;
6416 if (wParamFlags & PARAMFLAG_FLCID)
6418 VARIANTARG *arg;
6419 arg = prgpvarg[i] = &rgvarg[i];
6420 V_VT(arg) = VT_I4;
6421 V_I4(arg) = This->pTypeLib->lcid;
6422 continue;
6425 src_arg = NULL;
6427 if (cNamedArgs)
6429 USHORT j;
6430 for (j = 0; j < cNamedArgs; j++)
6431 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
6433 src_arg = &pDispParams->rgvarg[j];
6434 break;
6438 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
6440 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6441 vargs_converted++;
6444 if (wParamFlags & PARAMFLAG_FRETVAL)
6446 /* under most conditions the caller is not allowed to
6447 * pass in a dispparam arg in the index of what would be
6448 * the retval parameter. however, there is an exception
6449 * where the extra parameter is used in an extra
6450 * IDispatch::Invoke below */
6451 if ((i < pDispParams->cArgs) &&
6452 ((func_desc->cParams != 1) || !pVarResult ||
6453 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6455 hres = DISP_E_BADPARAMCOUNT;
6456 break;
6459 /* note: this check is placed so that if the caller passes
6460 * in a VARIANTARG for the retval we just ignore it, like
6461 * native does */
6462 if (i == func_desc->cParams - 1)
6464 VARIANTARG *arg;
6465 arg = prgpvarg[i] = &rgvarg[i];
6466 memset(arg, 0, sizeof(*arg));
6467 V_VT(arg) = rgvt[i];
6468 memset(&retval, 0, sizeof(retval));
6469 V_BYREF(arg) = &retval;
6471 else
6473 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6474 hres = E_UNEXPECTED;
6475 break;
6478 else if (src_arg)
6480 dump_Variant(src_arg);
6482 if(rgvt[i]!=V_VT(src_arg))
6484 if (rgvt[i] == VT_VARIANT)
6485 hres = VariantCopy(&rgvarg[i], src_arg);
6486 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6488 if (rgvt[i] == V_VT(src_arg))
6489 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6490 else
6492 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6493 if (wParamFlags & PARAMFLAG_FIN)
6494 hres = VariantCopy(&missing_arg[i], src_arg);
6495 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6497 V_VT(&rgvarg[i]) = rgvt[i];
6499 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6501 SAFEARRAY *a;
6502 SAFEARRAYBOUND bound;
6503 VARIANT *v;
6504 LONG j;
6505 bound.lLbound = 0;
6506 bound.cElements = pDispParams->cArgs-i;
6507 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6509 ERR("SafeArrayCreate failed\n");
6510 break;
6512 hres = SafeArrayAccessData(a, (LPVOID)&v);
6513 if (hres != S_OK)
6515 ERR("SafeArrayAccessData failed with %x\n", hres);
6516 SafeArrayDestroy(a);
6517 break;
6519 for (j = 0; j < bound.cElements; j++)
6520 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6521 hres = SafeArrayUnaccessData(a);
6522 if (hres != S_OK)
6524 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6525 SafeArrayDestroy(a);
6526 break;
6528 V_ARRAY(&rgvarg[i]) = a;
6529 V_VT(&rgvarg[i]) = rgvt[i];
6531 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6533 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6534 if (wParamFlags & PARAMFLAG_FIN)
6535 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6536 else
6537 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
6538 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6539 V_VT(&rgvarg[i]) = rgvt[i];
6541 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6543 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6544 V_VT(&rgvarg[i]) = rgvt[i];
6546 else
6548 /* FIXME: this doesn't work for VT_BYREF arguments if
6549 * they are not the same type as in the paramdesc */
6550 V_VT(&rgvarg[i]) = V_VT(src_arg);
6551 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6552 V_VT(&rgvarg[i]) = rgvt[i];
6555 if (FAILED(hres))
6557 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6558 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6559 debugstr_VT(src_arg), debugstr_VF(src_arg));
6560 break;
6562 prgpvarg[i] = &rgvarg[i];
6564 else
6566 prgpvarg[i] = src_arg;
6569 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
6570 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
6571 && V_UNKNOWN(prgpvarg[i])) {
6572 IUnknown *userdefined_iface;
6573 GUID guid;
6575 hres = get_iface_guid((ITypeInfo*)iface, tdesc->vt == VT_PTR ? tdesc->u.lptdesc : tdesc, &guid);
6576 if(FAILED(hres))
6577 break;
6579 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
6580 if(FAILED(hres)) {
6581 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
6582 break;
6585 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
6586 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
6589 else if (wParamFlags & PARAMFLAG_FOPT)
6591 VARIANTARG *arg;
6592 arg = prgpvarg[i] = &rgvarg[i];
6593 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6595 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6596 if (FAILED(hres))
6597 break;
6599 else
6601 VARIANTARG *missing_arg;
6602 /* if the function wants a pointer to a variant then
6603 * set that up, otherwise just pass the VT_ERROR in
6604 * the argument by value */
6605 if (rgvt[i] & VT_BYREF)
6607 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6608 V_VT(arg) = VT_VARIANT | VT_BYREF;
6609 V_VARIANTREF(arg) = missing_arg;
6611 else
6612 missing_arg = arg;
6613 V_VT(missing_arg) = VT_ERROR;
6614 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6617 else
6619 hres = DISP_E_BADPARAMCOUNT;
6620 break;
6623 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6625 /* VT_VOID is a special case for return types, so it is not
6626 * handled in the general function */
6627 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6628 V_VT(&varresult) = VT_EMPTY;
6629 else
6631 V_VT(&varresult) = 0;
6632 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6633 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6636 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6637 V_VT(&varresult), func_desc->cParams, rgvt,
6638 prgpvarg, &varresult);
6640 vargs_converted = 0;
6642 for (i = 0; i < func_desc->cParams; i++)
6644 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6645 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6647 if (wParamFlags & PARAMFLAG_FLCID)
6648 continue;
6649 else if (wParamFlags & PARAMFLAG_FRETVAL)
6651 if (TRACE_ON(ole))
6653 TRACE("[retval] value: ");
6654 dump_Variant(prgpvarg[i]);
6657 if (pVarResult)
6659 VariantInit(pVarResult);
6660 /* deref return value */
6661 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6664 VARIANT_ClearInd(prgpvarg[i]);
6666 else if (vargs_converted < pDispParams->cArgs)
6668 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6669 if (wParamFlags & PARAMFLAG_FOUT)
6671 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
6673 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6675 if (FAILED(hres))
6677 ERR("failed to convert param %d to vt %d\n", i,
6678 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
6679 break;
6683 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6684 func_desc->cParamsOpt < 0 &&
6685 i == func_desc->cParams-1)
6687 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6688 LONG j, ubound;
6689 VARIANT *v;
6690 hres = SafeArrayGetUBound(a, 1, &ubound);
6691 if (hres != S_OK)
6693 ERR("SafeArrayGetUBound failed with %x\n", hres);
6694 break;
6696 hres = SafeArrayAccessData(a, (LPVOID)&v);
6697 if (hres != S_OK)
6699 ERR("SafeArrayAccessData failed with %x\n", hres);
6700 break;
6702 for (j = 0; j <= ubound; j++)
6703 VariantClear(&v[j]);
6704 hres = SafeArrayUnaccessData(a);
6705 if (hres != S_OK)
6707 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6708 break;
6711 VariantClear(&rgvarg[i]);
6712 vargs_converted++;
6714 else if (wParamFlags & PARAMFLAG_FOPT)
6716 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6717 VariantClear(&rgvarg[i]);
6720 VariantClear(&missing_arg[i]);
6723 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6725 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6726 hres = DISP_E_EXCEPTION;
6727 if (pExcepInfo)
6729 IErrorInfo *pErrorInfo;
6730 pExcepInfo->scode = V_ERROR(&varresult);
6731 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6733 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6734 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6735 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6736 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6738 IErrorInfo_Release(pErrorInfo);
6742 if (V_VT(&varresult) != VT_ERROR)
6744 TRACE("varresult value: ");
6745 dump_Variant(&varresult);
6747 if (pVarResult)
6749 VariantClear(pVarResult);
6750 *pVarResult = varresult;
6752 else
6753 VariantClear(&varresult);
6756 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6757 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6758 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6759 (pDispParams->cArgs != 0))
6761 if (V_VT(pVarResult) == VT_DISPATCH)
6763 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6764 /* Note: not VariantClear; we still need the dispatch
6765 * pointer to be valid */
6766 VariantInit(pVarResult);
6767 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6768 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6769 pDispParams, pVarResult, pExcepInfo, pArgErr);
6770 IDispatch_Release(pDispatch);
6772 else
6774 VariantClear(pVarResult);
6775 hres = DISP_E_NOTACOLLECTION;
6779 func_fail:
6780 heap_free(buffer);
6781 break;
6783 case FUNC_DISPATCH: {
6784 IDispatch *disp;
6786 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6787 if (SUCCEEDED(hres)) {
6788 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6789 hres = IDispatch_Invoke(
6790 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6791 pVarResult,pExcepInfo,pArgErr
6793 if (FAILED(hres))
6794 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6795 IDispatch_Release(disp);
6796 } else
6797 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6798 break;
6800 default:
6801 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6802 hres = E_FAIL;
6803 break;
6806 TRACE("-- 0x%08x\n", hres);
6807 return hres;
6809 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6810 VARDESC *var_desc;
6812 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6813 if(FAILED(hres)) return hres;
6815 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6816 dump_VARDESC(var_desc);
6817 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6818 return E_NOTIMPL;
6821 /* not found, look for it in inherited interfaces */
6822 ITypeInfo2_GetTypeKind(iface, &type_kind);
6823 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6824 if(This->impltypes) {
6825 /* recursive search */
6826 ITypeInfo *pTInfo;
6827 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6828 if(SUCCEEDED(hres)){
6829 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6830 ITypeInfo_Release(pTInfo);
6831 return hres;
6833 WARN("Could not search inherited interface!\n");
6836 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6837 return DISP_E_MEMBERNOTFOUND;
6840 /* ITypeInfo::GetDocumentation
6842 * Retrieves the documentation string, the complete Help file name and path,
6843 * and the context ID for the Help topic for a specified type description.
6845 * (Can be tested by the Visual Basic Editor in Word for instance.)
6847 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6848 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6849 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6851 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6852 const TLBFuncDesc *pFDesc;
6853 const TLBVarDesc *pVDesc;
6854 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6855 " HelpContext(%p) HelpFile(%p)\n",
6856 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6857 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6858 if(pBstrName)
6859 *pBstrName=SysAllocString(This->Name);
6860 if(pBstrDocString)
6861 *pBstrDocString=SysAllocString(This->DocString);
6862 if(pdwHelpContext)
6863 *pdwHelpContext=This->dwHelpContext;
6864 if(pBstrHelpFile)
6865 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6866 return S_OK;
6867 }else {/* for a member */
6868 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
6869 if(pFDesc){
6870 if(pBstrName)
6871 *pBstrName = SysAllocString(pFDesc->Name);
6872 if(pBstrDocString)
6873 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6874 if(pdwHelpContext)
6875 *pdwHelpContext=pFDesc->helpcontext;
6876 return S_OK;
6878 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
6879 if(pVDesc){
6880 if(pBstrName)
6881 *pBstrName = SysAllocString(pVDesc->Name);
6882 if(pBstrDocString)
6883 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6884 if(pdwHelpContext)
6885 *pdwHelpContext=pVDesc->HelpContext;
6886 return S_OK;
6890 if(This->impltypes &&
6891 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6892 /* recursive search */
6893 ITypeInfo *pTInfo;
6894 HRESULT result;
6895 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6896 if(SUCCEEDED(result)) {
6897 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6898 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6899 ITypeInfo_Release(pTInfo);
6900 return result;
6902 WARN("Could not search inherited interface!\n");
6905 WARN("member %d not found\n", memid);
6906 return TYPE_E_ELEMENTNOTFOUND;
6909 /* ITypeInfo::GetDllEntry
6911 * Retrieves a description or specification of an entry point for a function
6912 * in a DLL.
6914 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6915 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6916 WORD *pwOrdinal)
6918 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6919 const TLBFuncDesc *pFDesc;
6921 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6923 if (pBstrDllName) *pBstrDllName = NULL;
6924 if (pBstrName) *pBstrName = NULL;
6925 if (pwOrdinal) *pwOrdinal = 0;
6927 if (This->TypeAttr.typekind != TKIND_MODULE)
6928 return TYPE_E_BADMODULEKIND;
6930 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
6931 if(pFDesc){
6932 dump_TypeInfo(This);
6933 if (TRACE_ON(ole))
6934 dump_TLBFuncDescOne(pFDesc);
6936 if (pBstrDllName)
6937 *pBstrDllName = SysAllocString(This->DllName);
6939 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6940 if (pBstrName)
6941 *pBstrName = SysAllocString(pFDesc->Entry);
6942 if (pwOrdinal)
6943 *pwOrdinal = -1;
6944 return S_OK;
6946 if (pBstrName)
6947 *pBstrName = NULL;
6948 if (pwOrdinal)
6949 *pwOrdinal = LOWORD(pFDesc->Entry);
6950 return S_OK;
6952 return TYPE_E_ELEMENTNOTFOUND;
6955 /* internal function to make the inherited interfaces' methods appear
6956 * part of the interface */
6957 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6958 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6960 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6961 HRESULT hr;
6963 TRACE("%p, 0x%x\n", iface, *hRefType);
6965 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
6967 ITypeInfo *pSubTypeInfo;
6969 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
6970 if (FAILED(hr))
6971 return hr;
6973 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6974 hRefType, ppTInfo);
6975 ITypeInfo_Release(pSubTypeInfo);
6976 if (SUCCEEDED(hr))
6977 return hr;
6979 *hRefType -= DISPATCH_HREF_OFFSET;
6981 if (!(*hRefType & DISPATCH_HREF_MASK))
6982 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6983 else
6984 return E_FAIL;
6987 /* ITypeInfo::GetRefTypeInfo
6989 * If a type description references other type descriptions, it retrieves
6990 * the referenced type descriptions.
6992 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6993 ITypeInfo2 *iface,
6994 HREFTYPE hRefType,
6995 ITypeInfo **ppTInfo)
6997 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6998 HRESULT result = E_FAIL;
7000 if ((This->hreftype != -1) && (This->hreftype == hRefType))
7002 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
7003 ITypeInfo_AddRef(*ppTInfo);
7004 result = S_OK;
7006 else if (hRefType == -1 &&
7007 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
7008 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
7010 /* when we meet a DUAL dispinterface, we must create the interface
7011 * version of it.
7013 ITypeInfoImpl *pTypeInfoImpl = ITypeInfoImpl_Constructor();
7016 /* the interface version contains the same information as the dispinterface
7017 * copy the contents of the structs.
7019 *pTypeInfoImpl = *This;
7020 pTypeInfoImpl->ref = 0;
7022 /* change the type to interface */
7023 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
7025 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
7027 /* the AddRef implicitly adds a reference to the parent typelib, which
7028 * stops the copied data from being destroyed until the new typeinfo's
7029 * refcount goes to zero, but we need to signal to the new instance to
7030 * not free its data structures when it is destroyed */
7031 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7033 ITypeInfo_AddRef(*ppTInfo);
7035 result = S_OK;
7037 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
7038 (This->TypeAttr.typekind == TKIND_DISPATCH))
7040 HREFTYPE href_dispatch = hRefType;
7041 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
7042 } else {
7043 TLBRefType *ref_type;
7044 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7046 if(ref_type->reference == hRefType)
7047 break;
7049 if(&ref_type->entry == &This->pTypeLib->ref_list)
7051 FIXME("Can't find pRefType for ref %x\n", hRefType);
7052 goto end;
7054 if(hRefType != -1) {
7055 ITypeLib *pTLib = NULL;
7057 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7058 UINT Index;
7059 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7060 } else {
7061 if(ref_type->pImpTLInfo->pImpTypeLib) {
7062 TRACE("typeinfo in imported typelib that is already loaded\n");
7063 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
7064 ITypeLib_AddRef(pTLib);
7065 result = S_OK;
7066 } else {
7067 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7068 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
7069 ref_type->pImpTLInfo->wVersionMajor,
7070 ref_type->pImpTLInfo->wVersionMinor,
7071 ref_type->pImpTLInfo->lcid,
7072 &pTLib);
7074 if(FAILED(result)) {
7075 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
7076 result=LoadTypeLib(libnam, &pTLib);
7077 SysFreeString(libnam);
7079 if(SUCCEEDED(result)) {
7080 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
7081 ITypeLib_AddRef(pTLib);
7085 if(SUCCEEDED(result)) {
7086 if(ref_type->index == TLB_REF_USE_GUID)
7087 result = ITypeLib_GetTypeInfoOfGuid(pTLib, &ref_type->guid, ppTInfo);
7088 else
7089 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, ppTInfo);
7091 if (pTLib != NULL)
7092 ITypeLib_Release(pTLib);
7096 end:
7097 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
7098 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
7099 return result;
7102 /* ITypeInfo::AddressOfMember
7104 * Retrieves the addresses of static functions or variables, such as those
7105 * defined in a DLL.
7107 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
7108 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
7110 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7111 HRESULT hr;
7112 BSTR dll, entry;
7113 WORD ordinal;
7114 HMODULE module;
7116 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
7118 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
7119 if (FAILED(hr))
7120 return hr;
7122 module = LoadLibraryW(dll);
7123 if (!module)
7125 ERR("couldn't load %s\n", debugstr_w(dll));
7126 SysFreeString(dll);
7127 SysFreeString(entry);
7128 return STG_E_FILENOTFOUND;
7130 /* FIXME: store library somewhere where we can free it */
7132 if (entry)
7134 LPSTR entryA;
7135 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
7136 entryA = heap_alloc(len);
7137 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
7139 *ppv = GetProcAddress(module, entryA);
7140 if (!*ppv)
7141 ERR("function not found %s\n", debugstr_a(entryA));
7143 heap_free(entryA);
7145 else
7147 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7148 if (!*ppv)
7149 ERR("function not found %d\n", ordinal);
7152 SysFreeString(dll);
7153 SysFreeString(entry);
7155 if (!*ppv)
7156 return TYPE_E_DLLFUNCTIONNOTFOUND;
7158 return S_OK;
7161 /* ITypeInfo::CreateInstance
7163 * Creates a new instance of a type that describes a component object class
7164 * (coclass).
7166 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7167 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7169 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7170 HRESULT hr;
7171 TYPEATTR *pTA;
7173 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7175 *ppvObj = NULL;
7177 if(pOuterUnk)
7179 WARN("Not able to aggregate\n");
7180 return CLASS_E_NOAGGREGATION;
7183 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
7184 if(FAILED(hr)) return hr;
7186 if(pTA->typekind != TKIND_COCLASS)
7188 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7189 hr = E_INVALIDARG;
7190 goto end;
7193 hr = S_FALSE;
7194 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7196 IUnknown *pUnk;
7197 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7198 TRACE("GetActiveObject rets %08x\n", hr);
7199 if(hr == S_OK)
7201 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7202 IUnknown_Release(pUnk);
7206 if(hr != S_OK)
7207 hr = CoCreateInstance(&pTA->guid, NULL,
7208 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7209 riid, ppvObj);
7211 end:
7212 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
7213 return hr;
7216 /* ITypeInfo::GetMops
7218 * Retrieves marshalling information.
7220 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7221 BSTR *pBstrMops)
7223 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7224 FIXME("(%p %d) stub!\n", This, memid);
7225 *pBstrMops = NULL;
7226 return S_OK;
7229 /* ITypeInfo::GetContainingTypeLib
7231 * Retrieves the containing type library and the index of the type description
7232 * within that type library.
7234 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7235 ITypeLib * *ppTLib, UINT *pIndex)
7237 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7239 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7240 if (pIndex) {
7241 *pIndex=This->index;
7242 TRACE("returning pIndex=%d\n", *pIndex);
7245 if (ppTLib) {
7246 *ppTLib=(LPTYPELIB )(This->pTypeLib);
7247 ITypeLib_AddRef(*ppTLib);
7248 TRACE("returning ppTLib=%p\n", *ppTLib);
7251 return S_OK;
7254 /* ITypeInfo::ReleaseTypeAttr
7256 * Releases a TYPEATTR previously returned by GetTypeAttr.
7259 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7260 TYPEATTR* pTypeAttr)
7262 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7263 TRACE("(%p)->(%p)\n", This, pTypeAttr);
7264 heap_free(pTypeAttr);
7267 /* ITypeInfo::ReleaseFuncDesc
7269 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7271 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7272 ITypeInfo2 *iface,
7273 FUNCDESC *pFuncDesc)
7275 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7276 SHORT i;
7278 TRACE("(%p)->(%p)\n", This, pFuncDesc);
7280 for (i = 0; i < pFuncDesc->cParams; i++)
7281 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7282 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7284 SysFreeString((BSTR)pFuncDesc);
7287 /* ITypeInfo::ReleaseVarDesc
7289 * Releases a VARDESC previously returned by GetVarDesc.
7291 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7292 VARDESC *pVarDesc)
7294 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7295 TRACE("(%p)->(%p)\n", This, pVarDesc);
7297 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
7298 if (pVarDesc->varkind == VAR_CONST)
7299 VariantClear(pVarDesc->u.lpvarValue);
7300 SysFreeString((BSTR)pVarDesc);
7303 /* ITypeInfo2::GetTypeKind
7305 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7308 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7309 TYPEKIND *pTypeKind)
7311 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7312 *pTypeKind=This->TypeAttr.typekind;
7313 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7314 return S_OK;
7317 /* ITypeInfo2::GetTypeFlags
7319 * Returns the type flags without any allocations. This returns a DWORD type
7320 * flag, which expands the type flags without growing the TYPEATTR (type
7321 * attribute).
7324 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7326 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7327 *pTypeFlags=This->TypeAttr.wTypeFlags;
7328 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7329 return S_OK;
7332 /* ITypeInfo2::GetFuncIndexOfMemId
7333 * Binds to a specific member based on a known DISPID, where the member name
7334 * is not known (for example, when binding to a default member).
7337 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7338 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7340 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7341 UINT fdc;
7342 HRESULT result;
7344 for (fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc){
7345 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
7346 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7347 break;
7349 if(fdc < This->TypeAttr.cFuncs) {
7350 *pFuncIndex = fdc;
7351 result = S_OK;
7352 } else
7353 result = TYPE_E_ELEMENTNOTFOUND;
7355 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7356 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7357 return result;
7360 /* TypeInfo2::GetVarIndexOfMemId
7362 * Binds to a specific member based on a known DISPID, where the member name
7363 * is not known (for example, when binding to a default member).
7366 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7367 MEMBERID memid, UINT *pVarIndex)
7369 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7370 TLBVarDesc *pVarInfo;
7372 TRACE("%p %d %p\n", iface, memid, pVarIndex);
7374 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
7375 if(!pVarInfo)
7376 return TYPE_E_ELEMENTNOTFOUND;
7378 *pVarIndex = (pVarInfo - This->vardescs);
7380 return S_OK;
7383 /* ITypeInfo2::GetCustData
7385 * Gets the custom data
7387 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7388 ITypeInfo2 * iface,
7389 REFGUID guid,
7390 VARIANT *pVarVal)
7392 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7393 TLBCustData *pCData;
7395 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7397 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
7399 VariantInit( pVarVal);
7400 if (pCData)
7401 VariantCopy( pVarVal, &pCData->data);
7402 else
7403 VariantClear( pVarVal );
7404 return S_OK;
7407 /* ITypeInfo2::GetFuncCustData
7409 * Gets the custom data
7411 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7412 ITypeInfo2 * iface,
7413 UINT index,
7414 REFGUID guid,
7415 VARIANT *pVarVal)
7417 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7418 TLBCustData *pCData;
7419 TLBFuncDesc *pFDesc = &This->funcdescs[index];
7421 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
7423 if(index >= This->TypeAttr.cFuncs)
7424 return TYPE_E_ELEMENTNOTFOUND;
7426 pCData = TLB_get_custdata_by_guid(&pFDesc->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::GetParamCustData
7438 * Gets the custom data
7440 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7441 ITypeInfo2 * iface,
7442 UINT indexFunc,
7443 UINT indexParam,
7444 REFGUID guid,
7445 VARIANT *pVarVal)
7447 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7448 TLBCustData *pCData;
7449 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
7451 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
7452 debugstr_guid(guid), pVarVal);
7454 if(indexFunc >= This->TypeAttr.cFuncs)
7455 return TYPE_E_ELEMENTNOTFOUND;
7457 if(indexParam >= pFDesc->funcdesc.cParams)
7458 return TYPE_E_ELEMENTNOTFOUND;
7460 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
7461 if(!pCData)
7462 return TYPE_E_ELEMENTNOTFOUND;
7464 VariantInit(pVarVal);
7465 VariantCopy(pVarVal, &pCData->data);
7467 return S_OK;
7470 /* ITypeInfo2::GetVarCustData
7472 * Gets the custom data
7474 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7475 ITypeInfo2 * iface,
7476 UINT index,
7477 REFGUID guid,
7478 VARIANT *pVarVal)
7480 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7481 TLBCustData *pCData;
7482 TLBVarDesc *pVDesc = &This->vardescs[index];
7484 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7486 if(index >= This->TypeAttr.cVars)
7487 return TYPE_E_ELEMENTNOTFOUND;
7489 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
7490 if(!pCData)
7491 return TYPE_E_ELEMENTNOTFOUND;
7493 VariantInit(pVarVal);
7494 VariantCopy(pVarVal, &pCData->data);
7496 return S_OK;
7499 /* ITypeInfo2::GetImplCustData
7501 * Gets the custom data
7503 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7504 ITypeInfo2 * iface,
7505 UINT index,
7506 REFGUID guid,
7507 VARIANT *pVarVal)
7509 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7510 TLBCustData *pCData;
7511 TLBImplType *pRDesc = &This->impltypes[index];
7513 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
7515 if(index >= This->TypeAttr.cImplTypes)
7516 return TYPE_E_ELEMENTNOTFOUND;
7518 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
7519 if(!pCData)
7520 return TYPE_E_ELEMENTNOTFOUND;
7522 VariantInit(pVarVal);
7523 VariantCopy(pVarVal, &pCData->data);
7525 return S_OK;
7528 /* ITypeInfo2::GetDocumentation2
7530 * Retrieves the documentation string, the complete Help file name and path,
7531 * the localization context to use, and the context ID for the library Help
7532 * topic in the Help file.
7535 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7536 ITypeInfo2 * iface,
7537 MEMBERID memid,
7538 LCID lcid,
7539 BSTR *pbstrHelpString,
7540 DWORD *pdwHelpStringContext,
7541 BSTR *pbstrHelpStringDll)
7543 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7544 const TLBFuncDesc *pFDesc;
7545 const TLBVarDesc *pVDesc;
7546 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7547 "HelpStringContext(%p) HelpStringDll(%p)\n",
7548 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7549 pbstrHelpStringDll );
7550 /* the help string should be obtained from the helpstringdll,
7551 * using the _DLLGetDocumentation function, based on the supplied
7552 * lcid. Nice to do sometime...
7554 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7555 if(pbstrHelpString)
7556 *pbstrHelpString=SysAllocString(This->Name);
7557 if(pdwHelpStringContext)
7558 *pdwHelpStringContext=This->dwHelpStringContext;
7559 if(pbstrHelpStringDll)
7560 *pbstrHelpStringDll=
7561 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7562 return S_OK;
7563 }else {/* for a member */
7564 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
7565 if(pFDesc){
7566 if(pbstrHelpString)
7567 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
7568 if(pdwHelpStringContext)
7569 *pdwHelpStringContext=pFDesc->HelpStringContext;
7570 if(pbstrHelpStringDll)
7571 *pbstrHelpStringDll=
7572 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7573 return S_OK;
7575 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
7576 if(pVDesc){
7577 if(pbstrHelpString)
7578 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
7579 if(pdwHelpStringContext)
7580 *pdwHelpStringContext=pVDesc->HelpStringContext;
7581 if(pbstrHelpStringDll)
7582 *pbstrHelpStringDll=
7583 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7584 return S_OK;
7587 return TYPE_E_ELEMENTNOTFOUND;
7590 /* ITypeInfo2::GetAllCustData
7592 * Gets all custom data items for the Type info.
7595 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7596 ITypeInfo2 * iface,
7597 CUSTDATA *pCustData)
7599 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7601 TRACE("%p %p\n", This, pCustData);
7603 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
7606 /* ITypeInfo2::GetAllFuncCustData
7608 * Gets all custom data items for the specified Function
7611 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7612 ITypeInfo2 * iface,
7613 UINT index,
7614 CUSTDATA *pCustData)
7616 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7617 TLBFuncDesc *pFDesc = &This->funcdescs[index];
7619 TRACE("%p %u %p\n", This, index, pCustData);
7621 if(index >= This->TypeAttr.cFuncs)
7622 return TYPE_E_ELEMENTNOTFOUND;
7624 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
7627 /* ITypeInfo2::GetAllParamCustData
7629 * Gets all custom data items for the Functions
7632 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7633 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7635 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7636 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
7638 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
7640 if(indexFunc >= This->TypeAttr.cFuncs)
7641 return TYPE_E_ELEMENTNOTFOUND;
7643 if(indexParam >= pFDesc->funcdesc.cParams)
7644 return TYPE_E_ELEMENTNOTFOUND;
7646 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
7649 /* ITypeInfo2::GetAllVarCustData
7651 * Gets all custom data items for the specified Variable
7654 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7655 UINT index, CUSTDATA *pCustData)
7657 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7658 TLBVarDesc * pVDesc = &This->vardescs[index];
7660 TRACE("%p %u %p\n", This, index, pCustData);
7662 if(index >= This->TypeAttr.cVars)
7663 return TYPE_E_ELEMENTNOTFOUND;
7665 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
7668 /* ITypeInfo2::GetAllImplCustData
7670 * Gets all custom data items for the specified implementation type
7673 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7674 ITypeInfo2 * iface,
7675 UINT index,
7676 CUSTDATA *pCustData)
7678 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7679 TLBImplType *pRDesc = &This->impltypes[index];
7681 TRACE("%p %u %p\n", This, index, pCustData);
7683 if(index >= This->TypeAttr.cImplTypes)
7684 return TYPE_E_ELEMENTNOTFOUND;
7686 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
7689 static const ITypeInfo2Vtbl tinfvt =
7692 ITypeInfo_fnQueryInterface,
7693 ITypeInfo_fnAddRef,
7694 ITypeInfo_fnRelease,
7696 ITypeInfo_fnGetTypeAttr,
7697 ITypeInfo_fnGetTypeComp,
7698 ITypeInfo_fnGetFuncDesc,
7699 ITypeInfo_fnGetVarDesc,
7700 ITypeInfo_fnGetNames,
7701 ITypeInfo_fnGetRefTypeOfImplType,
7702 ITypeInfo_fnGetImplTypeFlags,
7703 ITypeInfo_fnGetIDsOfNames,
7704 ITypeInfo_fnInvoke,
7705 ITypeInfo_fnGetDocumentation,
7706 ITypeInfo_fnGetDllEntry,
7707 ITypeInfo_fnGetRefTypeInfo,
7708 ITypeInfo_fnAddressOfMember,
7709 ITypeInfo_fnCreateInstance,
7710 ITypeInfo_fnGetMops,
7711 ITypeInfo_fnGetContainingTypeLib,
7712 ITypeInfo_fnReleaseTypeAttr,
7713 ITypeInfo_fnReleaseFuncDesc,
7714 ITypeInfo_fnReleaseVarDesc,
7716 ITypeInfo2_fnGetTypeKind,
7717 ITypeInfo2_fnGetTypeFlags,
7718 ITypeInfo2_fnGetFuncIndexOfMemId,
7719 ITypeInfo2_fnGetVarIndexOfMemId,
7720 ITypeInfo2_fnGetCustData,
7721 ITypeInfo2_fnGetFuncCustData,
7722 ITypeInfo2_fnGetParamCustData,
7723 ITypeInfo2_fnGetVarCustData,
7724 ITypeInfo2_fnGetImplTypeCustData,
7725 ITypeInfo2_fnGetDocumentation2,
7726 ITypeInfo2_fnGetAllCustData,
7727 ITypeInfo2_fnGetAllFuncCustData,
7728 ITypeInfo2_fnGetAllParamCustData,
7729 ITypeInfo2_fnGetAllVarCustData,
7730 ITypeInfo2_fnGetAllImplTypeCustData,
7733 /******************************************************************************
7734 * CreateDispTypeInfo [OLEAUT32.31]
7736 * Build type information for an object so it can be called through an
7737 * IDispatch interface.
7739 * RETURNS
7740 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7741 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7743 * NOTES
7744 * This call allows an objects methods to be accessed through IDispatch, by
7745 * building an ITypeInfo object that IDispatch can use to call through.
7747 HRESULT WINAPI CreateDispTypeInfo(
7748 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7749 LCID lcid, /* [I] Locale Id */
7750 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7752 ITypeInfoImpl *pTIClass, *pTIIface;
7753 ITypeLibImpl *pTypeLibImpl;
7754 unsigned int param, func;
7755 TLBFuncDesc *pFuncDesc;
7756 TLBRefType *ref;
7758 TRACE("\n");
7759 pTypeLibImpl = TypeLibImpl_Constructor();
7760 if (!pTypeLibImpl) return E_FAIL;
7762 pTypeLibImpl->TypeInfoCount = 2;
7763 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
7765 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
7766 pTIIface->pTypeLib = pTypeLibImpl;
7767 pTIIface->index = 0;
7768 pTIIface->Name = NULL;
7769 pTIIface->dwHelpContext = -1;
7770 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7771 pTIIface->TypeAttr.lcid = lcid;
7772 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7773 pTIIface->TypeAttr.wMajorVerNum = 0;
7774 pTIIface->TypeAttr.wMinorVerNum = 0;
7775 pTIIface->TypeAttr.cbAlignment = 2;
7776 pTIIface->TypeAttr.cbSizeInstance = -1;
7777 pTIIface->TypeAttr.cbSizeVft = -1;
7778 pTIIface->TypeAttr.cFuncs = 0;
7779 pTIIface->TypeAttr.cImplTypes = 0;
7780 pTIIface->TypeAttr.cVars = 0;
7781 pTIIface->TypeAttr.wTypeFlags = 0;
7783 pTIIface->funcdescs = TLBFuncDesc_Constructor(pidata->cMembers);
7784 pFuncDesc = pTIIface->funcdescs;
7785 for(func = 0; func < pidata->cMembers; func++) {
7786 METHODDATA *md = pidata->pmethdata + func;
7787 pFuncDesc->Name = SysAllocString(md->szName);
7788 pFuncDesc->funcdesc.memid = md->dispid;
7789 pFuncDesc->funcdesc.lprgscode = NULL;
7790 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
7791 pFuncDesc->funcdesc.invkind = md->wFlags;
7792 pFuncDesc->funcdesc.callconv = md->cc;
7793 pFuncDesc->funcdesc.cParams = md->cArgs;
7794 pFuncDesc->funcdesc.cParamsOpt = 0;
7795 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
7796 pFuncDesc->funcdesc.cScodes = 0;
7797 pFuncDesc->funcdesc.wFuncFlags = 0;
7798 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7799 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7800 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7801 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7802 md->cArgs * sizeof(ELEMDESC));
7803 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
7804 for(param = 0; param < md->cArgs; param++) {
7805 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7806 pFuncDesc->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7808 pFuncDesc->helpcontext = 0;
7809 pFuncDesc->HelpStringContext = 0;
7810 pFuncDesc->HelpString = NULL;
7811 pFuncDesc->Entry = NULL;
7812 list_init(&pFuncDesc->custdata_list);
7813 pTIIface->TypeAttr.cFuncs++;
7814 ++pFuncDesc;
7817 dump_TypeInfo(pTIIface);
7819 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
7820 pTIClass->pTypeLib = pTypeLibImpl;
7821 pTIClass->index = 1;
7822 pTIClass->Name = NULL;
7823 pTIClass->dwHelpContext = -1;
7824 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7825 pTIClass->TypeAttr.lcid = lcid;
7826 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7827 pTIClass->TypeAttr.wMajorVerNum = 0;
7828 pTIClass->TypeAttr.wMinorVerNum = 0;
7829 pTIClass->TypeAttr.cbAlignment = 2;
7830 pTIClass->TypeAttr.cbSizeInstance = -1;
7831 pTIClass->TypeAttr.cbSizeVft = -1;
7832 pTIClass->TypeAttr.cFuncs = 0;
7833 pTIClass->TypeAttr.cImplTypes = 1;
7834 pTIClass->TypeAttr.cVars = 0;
7835 pTIClass->TypeAttr.wTypeFlags = 0;
7837 pTIClass->impltypes = TLBImplType_Constructor(1);
7839 ref = heap_alloc_zero(sizeof(*ref));
7840 ref->pImpTLInfo = TLB_REF_INTERNAL;
7841 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7843 dump_TypeInfo(pTIClass);
7845 *pptinfo = (ITypeInfo*)pTIClass;
7847 ITypeInfo_AddRef(*pptinfo);
7848 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
7850 return S_OK;
7854 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7856 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7858 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7861 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7863 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7865 return ITypeInfo_AddRef((ITypeInfo *)This);
7868 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7870 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7872 return ITypeInfo_Release((ITypeInfo *)This);
7875 static HRESULT WINAPI ITypeComp_fnBind(
7876 ITypeComp * iface,
7877 OLECHAR * szName,
7878 ULONG lHash,
7879 WORD wFlags,
7880 ITypeInfo ** ppTInfo,
7881 DESCKIND * pDescKind,
7882 BINDPTR * pBindPtr)
7884 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7885 const TLBFuncDesc *pFDesc;
7886 const TLBVarDesc *pVDesc;
7887 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7888 UINT fdc;
7890 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7892 *pDescKind = DESCKIND_NONE;
7893 pBindPtr->lpfuncdesc = NULL;
7894 *ppTInfo = NULL;
7896 for(fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc){
7897 pFDesc = &This->funcdescs[fdc];
7898 if (!strcmpiW(pFDesc->Name, szName)) {
7899 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7900 break;
7901 else
7902 /* name found, but wrong flags */
7903 hr = TYPE_E_TYPEMISMATCH;
7907 if (fdc < This->TypeAttr.cFuncs)
7909 HRESULT hr = TLB_AllocAndInitFuncDesc(
7910 &pFDesc->funcdesc,
7911 &pBindPtr->lpfuncdesc,
7912 This->TypeAttr.typekind == TKIND_DISPATCH);
7913 if (FAILED(hr))
7914 return hr;
7915 *pDescKind = DESCKIND_FUNCDESC;
7916 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
7917 ITypeInfo_AddRef(*ppTInfo);
7918 return S_OK;
7919 } else {
7920 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->TypeAttr.cVars, szName);
7921 if(pVDesc){
7922 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7923 if (FAILED(hr))
7924 return hr;
7925 *pDescKind = DESCKIND_VARDESC;
7926 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
7927 ITypeInfo_AddRef(*ppTInfo);
7928 return S_OK;
7931 /* FIXME: search each inherited interface, not just the first */
7932 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
7933 /* recursive search */
7934 ITypeInfo *pTInfo;
7935 ITypeComp *pTComp;
7936 HRESULT hr;
7937 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
7938 if (SUCCEEDED(hr))
7940 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7941 ITypeInfo_Release(pTInfo);
7943 if (SUCCEEDED(hr))
7945 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7946 ITypeComp_Release(pTComp);
7947 return hr;
7949 WARN("Could not search inherited interface!\n");
7951 if (hr == DISP_E_MEMBERNOTFOUND)
7952 hr = S_OK;
7953 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
7954 return hr;
7957 static HRESULT WINAPI ITypeComp_fnBindType(
7958 ITypeComp * iface,
7959 OLECHAR * szName,
7960 ULONG lHash,
7961 ITypeInfo ** ppTInfo,
7962 ITypeComp ** ppTComp)
7964 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7966 /* strange behaviour (does nothing) but like the
7967 * original */
7969 if (!ppTInfo || !ppTComp)
7970 return E_POINTER;
7972 *ppTInfo = NULL;
7973 *ppTComp = NULL;
7975 return S_OK;
7978 static const ITypeCompVtbl tcompvt =
7981 ITypeComp_fnQueryInterface,
7982 ITypeComp_fnAddRef,
7983 ITypeComp_fnRelease,
7985 ITypeComp_fnBind,
7986 ITypeComp_fnBindType