oleaut32: Recurse through the impltype list so that dispinterfaces get the correct...
[wine/winequartzdrv.git] / dlls / oleaut32 / typelib.c
bloba1b28ece5454c874242870916ef43170dfe66767
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"
68 #include "wine/unicode.h"
69 #include "objbase.h"
70 #include "typelib.h"
71 #include "wine/debug.h"
72 #include "variant.h"
73 #include "wine/list.h"
75 WINE_DEFAULT_DEBUG_CHANNEL(ole);
76 WINE_DECLARE_DEBUG_CHANNEL(typelib);
78 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
79 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
81 /****************************************************************************
82 * FromLExxx
84 * Takes p_iVal (which is in little endian) and returns it
85 * in the host machine's byte order.
87 #ifdef WORDS_BIGENDIAN
88 static WORD FromLEWord(WORD p_iVal)
90 return (((p_iVal & 0x00FF) << 8) |
91 ((p_iVal & 0xFF00) >> 8));
95 static DWORD FromLEDWord(DWORD p_iVal)
97 return (((p_iVal & 0x000000FF) << 24) |
98 ((p_iVal & 0x0000FF00) << 8) |
99 ((p_iVal & 0x00FF0000) >> 8) |
100 ((p_iVal & 0xFF000000) >> 24));
102 #else
103 #define FromLEWord(X) (X)
104 #define FromLEDWord(X) (X)
105 #endif
108 /****************************************************************************
109 * FromLExxx
111 * Fix byte order in any structure if necessary
113 #ifdef WORDS_BIGENDIAN
114 static void FromLEWords(void *p_Val, int p_iSize)
116 WORD *Val = p_Val;
118 p_iSize /= sizeof(WORD);
120 while (p_iSize) {
121 *Val = FromLEWord(*Val);
122 Val++;
123 p_iSize--;
128 static void FromLEDWords(void *p_Val, int p_iSize)
130 DWORD *Val = p_Val;
132 p_iSize /= sizeof(DWORD);
134 while (p_iSize) {
135 *Val = FromLEDWord(*Val);
136 Val++;
137 p_iSize--;
140 #else
141 #define FromLEWords(X,Y) /*nothing*/
142 #define FromLEDWords(X,Y) /*nothing*/
143 #endif
146 * Find a typelib key which matches a requested maj.min version.
148 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
150 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
151 WCHAR buffer[60];
152 char key_name[16];
153 DWORD len, i;
154 INT best_min = -1;
155 HKEY hkey;
157 memcpy( buffer, typelibW, sizeof(typelibW) );
158 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
160 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
161 return FALSE;
163 len = sizeof(key_name);
164 i = 0;
165 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
167 INT v_maj, v_min;
169 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
171 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
173 if (*wMaj == v_maj)
175 if (*wMin == v_min)
177 best_min = v_min;
178 break; /* exact match */
180 if (v_min > best_min) best_min = v_min;
183 len = sizeof(key_name);
185 RegCloseKey( hkey );
186 if (best_min >= 0)
188 *wMin = best_min;
189 return TRUE;
191 return FALSE;
194 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
195 /* buffer must be at least 60 characters long */
196 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
198 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
199 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
201 memcpy( buffer, TypelibW, sizeof(TypelibW) );
202 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
203 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
204 return buffer;
207 /* get the path of an interface key, in the form "Interface\\<guid>" */
208 /* buffer must be at least 50 characters long */
209 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
211 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
213 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
214 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
215 return buffer;
218 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
219 /* buffer must be at least 16 characters long */
220 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
222 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
223 static const WCHAR win16W[] = {'w','i','n','1','6',0};
224 static const WCHAR win32W[] = {'w','i','n','3','2',0};
226 sprintfW( buffer, LcidFormatW, lcid );
227 switch(syskind)
229 case SYS_WIN16: strcatW( buffer, win16W ); break;
230 case SYS_WIN32: strcatW( buffer, win32W ); break;
231 default:
232 TRACE("Typelib is for unsupported syskind %i\n", syskind);
233 return NULL;
235 return buffer;
238 static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
241 /****************************************************************************
242 * QueryPathOfRegTypeLib [OLEAUT32.164]
244 * Gets the path to a registered type library.
246 * PARAMS
247 * guid [I] referenced guid
248 * wMaj [I] major version
249 * wMin [I] minor version
250 * lcid [I] locale id
251 * path [O] path of typelib
253 * RETURNS
254 * Success: S_OK.
255 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
256 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
257 * opened.
259 HRESULT WINAPI QueryPathOfRegTypeLib(
260 REFGUID guid,
261 WORD wMaj,
262 WORD wMin,
263 LCID lcid,
264 LPBSTR path )
266 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
267 LCID myLCID = lcid;
268 HKEY hkey;
269 WCHAR buffer[60];
270 WCHAR Path[MAX_PATH];
271 LONG res;
273 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
275 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
276 get_typelib_key( guid, wMaj, wMin, buffer );
278 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
279 if (res == ERROR_FILE_NOT_FOUND)
281 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
282 return TYPE_E_LIBNOTREGISTERED;
284 else if (res != ERROR_SUCCESS)
286 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
287 return TYPE_E_REGISTRYACCESS;
290 while (hr != S_OK)
292 LONG dwPathLen = sizeof(Path);
294 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
296 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
298 if (!lcid)
299 break;
300 else if (myLCID == lcid)
302 /* try with sub-langid */
303 myLCID = SUBLANGID(lcid);
305 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
307 /* try with system langid */
308 myLCID = 0;
310 else
312 break;
315 else
317 *path = SysAllocString( Path );
318 hr = S_OK;
321 RegCloseKey( hkey );
322 TRACE_(typelib)("-- 0x%08x\n", hr);
323 return hr;
326 /******************************************************************************
327 * CreateTypeLib [OLEAUT32.160] creates a typelib
329 * RETURNS
330 * Success: S_OK
331 * Failure: Status
333 HRESULT WINAPI CreateTypeLib(
334 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
336 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
337 return E_FAIL;
340 /******************************************************************************
341 * LoadTypeLib [OLEAUT32.161]
343 * Loads a type library
345 * PARAMS
346 * szFile [I] Name of file to load from.
347 * pptLib [O] Pointer that receives ITypeLib object on success.
349 * RETURNS
350 * Success: S_OK
351 * Failure: Status
353 * SEE
354 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
356 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
358 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
359 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
362 /******************************************************************************
363 * LoadTypeLibEx [OLEAUT32.183]
365 * Loads and optionally registers a type library
367 * RETURNS
368 * Success: S_OK
369 * Failure: Status
371 HRESULT WINAPI LoadTypeLibEx(
372 LPCOLESTR szFile, /* [in] Name of file to load from */
373 REGKIND regkind, /* [in] Specify kind of registration */
374 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
376 WCHAR szPath[MAX_PATH+1];
377 HRESULT res;
379 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
381 *pptLib = NULL;
383 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
385 if (SUCCEEDED(res))
386 switch(regkind)
388 case REGKIND_DEFAULT:
389 /* don't register typelibs supplied with full path. Experimentation confirms the following */
390 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
391 (szFile[0] && (szFile[1] == ':'))) break;
392 /* else fall-through */
394 case REGKIND_REGISTER:
395 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
397 IUnknown_Release(*pptLib);
398 *pptLib = 0;
400 break;
401 case REGKIND_NONE:
402 break;
405 TRACE(" returns %08x\n",res);
406 return res;
409 /******************************************************************************
410 * LoadRegTypeLib [OLEAUT32.162]
412 * Loads a registered type library.
414 * PARAMS
415 * rguid [I] GUID of the registered type library.
416 * wVerMajor [I] major version.
417 * wVerMinor [I] minor version.
418 * lcid [I] locale ID.
419 * ppTLib [O] pointer that receives an ITypeLib object on success.
421 * RETURNS
422 * Success: S_OK.
423 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
424 * LoadTypeLib.
426 HRESULT WINAPI LoadRegTypeLib(
427 REFGUID rguid,
428 WORD wVerMajor,
429 WORD wVerMinor,
430 LCID lcid,
431 ITypeLib **ppTLib)
433 BSTR bstr=NULL;
434 HRESULT res;
436 *ppTLib = NULL;
438 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
440 if(SUCCEEDED(res))
442 res= LoadTypeLib(bstr, ppTLib);
443 SysFreeString(bstr);
446 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
448 return res;
452 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
453 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
454 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
455 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
456 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
457 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
459 /******************************************************************************
460 * RegisterTypeLib [OLEAUT32.163]
461 * Adds information about a type library to the System Registry
462 * NOTES
463 * Docs: ITypeLib FAR * ptlib
464 * Docs: OLECHAR FAR* szFullPath
465 * Docs: OLECHAR FAR* szHelpDir
467 * RETURNS
468 * Success: S_OK
469 * Failure: Status
471 HRESULT WINAPI RegisterTypeLib(
472 ITypeLib * ptlib, /* [in] Pointer to the library*/
473 OLECHAR * szFullPath, /* [in] full Path of the library*/
474 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
475 may be NULL*/
477 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
478 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
479 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
480 HRESULT res;
481 TLIBATTR *attr;
482 WCHAR keyName[60];
483 WCHAR tmp[16];
484 HKEY key, subKey;
485 UINT types, tidx;
486 TYPEKIND kind;
487 DWORD disposition;
489 if (ptlib == NULL || szFullPath == NULL)
490 return E_INVALIDARG;
492 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
493 return E_FAIL;
495 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
497 res = S_OK;
498 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
499 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
501 LPOLESTR doc;
503 /* Set the human-readable name of the typelib */
504 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
506 if (RegSetValueExW(key, NULL, 0, REG_SZ,
507 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
508 res = E_FAIL;
510 SysFreeString(doc);
512 else
513 res = E_FAIL;
515 /* Make up the name of the typelib path subkey */
516 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
518 /* Create the typelib path subkey */
519 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
520 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
522 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
523 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
524 res = E_FAIL;
526 RegCloseKey(subKey);
528 else
529 res = E_FAIL;
531 /* Create the flags subkey */
532 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
533 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
535 /* FIXME: is %u correct? */
536 static const WCHAR formatW[] = {'%','u',0};
537 WCHAR buf[20];
538 sprintfW(buf, formatW, attr->wLibFlags);
539 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
540 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
541 res = E_FAIL;
543 RegCloseKey(subKey);
545 else
546 res = E_FAIL;
548 /* create the helpdir subkey */
549 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
550 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
552 BOOL freeHelpDir = FALSE;
553 OLECHAR* pIndexStr;
555 /* if we created a new key, and helpDir was null, set the helpdir
556 to the directory which contains the typelib. However,
557 if we just opened an existing key, we leave the helpdir alone */
558 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
559 szHelpDir = SysAllocString(szFullPath);
560 pIndexStr = strrchrW(szHelpDir, '\\');
561 if (pIndexStr) {
562 *pIndexStr = 0;
564 freeHelpDir = TRUE;
567 /* if we have an szHelpDir, set it! */
568 if (szHelpDir != NULL) {
569 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
570 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
571 res = E_FAIL;
575 /* tidy up */
576 if (freeHelpDir) SysFreeString(szHelpDir);
577 RegCloseKey(subKey);
579 } else {
580 res = E_FAIL;
583 RegCloseKey(key);
585 else
586 res = E_FAIL;
588 /* register OLE Automation-compatible interfaces for this typelib */
589 types = ITypeLib_GetTypeInfoCount(ptlib);
590 for (tidx=0; tidx<types; tidx++) {
591 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
592 LPOLESTR name = NULL;
593 ITypeInfo *tinfo = NULL;
595 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
597 switch (kind) {
598 case TKIND_INTERFACE:
599 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
600 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
601 break;
603 case TKIND_DISPATCH:
604 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
605 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
606 break;
608 default:
609 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
610 break;
613 if (tinfo) {
614 TYPEATTR *tattr = NULL;
615 ITypeInfo_GetTypeAttr(tinfo, &tattr);
617 if (tattr) {
618 TRACE_(typelib)("guid=%s, flags=%04x (",
619 debugstr_guid(&tattr->guid),
620 tattr->wTypeFlags);
622 if (TRACE_ON(typelib)) {
623 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
624 XX(FAPPOBJECT);
625 XX(FCANCREATE);
626 XX(FLICENSED);
627 XX(FPREDECLID);
628 XX(FHIDDEN);
629 XX(FCONTROL);
630 XX(FDUAL);
631 XX(FNONEXTENSIBLE);
632 XX(FOLEAUTOMATION);
633 XX(FRESTRICTED);
634 XX(FAGGREGATABLE);
635 XX(FREPLACEABLE);
636 XX(FDISPATCHABLE);
637 XX(FREVERSEBIND);
638 XX(FPROXY);
639 #undef XX
640 MESSAGE("\n");
643 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL|TYPEFLAG_FDISPATCHABLE))
645 /* register interface<->typelib coupling */
646 get_interface_key( &tattr->guid, keyName );
647 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
648 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
650 if (name)
651 RegSetValueExW(key, NULL, 0, REG_SZ,
652 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
654 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
655 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
656 RegSetValueExW(subKey, NULL, 0, REG_SZ,
657 (const BYTE *)PSOA, sizeof PSOA);
658 RegCloseKey(subKey);
661 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
662 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
663 RegSetValueExW(subKey, NULL, 0, REG_SZ,
664 (const BYTE *)PSOA, sizeof PSOA);
665 RegCloseKey(subKey);
668 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
669 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
671 WCHAR buffer[40];
672 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
673 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
675 StringFromGUID2(&attr->guid, buffer, 40);
676 RegSetValueExW(subKey, NULL, 0, REG_SZ,
677 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
678 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
679 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
680 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
681 RegCloseKey(subKey);
684 RegCloseKey(key);
688 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
691 ITypeInfo_Release(tinfo);
694 SysFreeString(name);
698 ITypeLib_ReleaseTLibAttr(ptlib, attr);
700 return res;
704 /******************************************************************************
705 * UnRegisterTypeLib [OLEAUT32.186]
706 * Removes information about a type library from the System Registry
707 * NOTES
709 * RETURNS
710 * Success: S_OK
711 * Failure: Status
713 HRESULT WINAPI UnRegisterTypeLib(
714 REFGUID libid, /* [in] Guid of the library */
715 WORD wVerMajor, /* [in] major version */
716 WORD wVerMinor, /* [in] minor version */
717 LCID lcid, /* [in] locale id */
718 SYSKIND syskind)
720 BSTR tlibPath = NULL;
721 DWORD tmpLength;
722 WCHAR keyName[60];
723 WCHAR subKeyName[50];
724 int result = S_OK;
725 DWORD i = 0;
726 BOOL deleteOtherStuff;
727 HKEY key = NULL;
728 HKEY subKey = NULL;
729 TYPEATTR* typeAttr = NULL;
730 TYPEKIND kind;
731 ITypeInfo* typeInfo = NULL;
732 ITypeLib* typeLib = NULL;
733 int numTypes;
735 TRACE("(IID: %s)\n",debugstr_guid(libid));
737 /* Create the path to the key */
738 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
740 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
742 TRACE("Unsupported syskind %i\n", syskind);
743 result = E_INVALIDARG;
744 goto end;
747 /* get the path to the typelib on disk */
748 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
749 result = E_INVALIDARG;
750 goto end;
753 /* Try and open the key to the type library. */
754 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
755 result = E_INVALIDARG;
756 goto end;
759 /* Try and load the type library */
760 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
761 result = TYPE_E_INVALIDSTATE;
762 goto end;
765 /* remove any types registered with this typelib */
766 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
767 for (i=0; i<numTypes; i++) {
768 /* get the kind of type */
769 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
770 goto enddeleteloop;
773 /* skip non-interfaces, and get type info for the type */
774 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
775 goto enddeleteloop;
777 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
778 goto enddeleteloop;
780 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
781 goto enddeleteloop;
784 /* the path to the type */
785 get_interface_key( &typeAttr->guid, subKeyName );
787 /* Delete its bits */
788 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS) {
789 goto enddeleteloop;
791 RegDeleteKeyW(subKey, ProxyStubClsidW);
792 RegDeleteKeyW(subKey, ProxyStubClsid32W);
793 RegDeleteKeyW(subKey, TypeLibW);
794 RegCloseKey(subKey);
795 subKey = NULL;
796 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
798 enddeleteloop:
799 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
800 typeAttr = NULL;
801 if (typeInfo) ITypeInfo_Release(typeInfo);
802 typeInfo = NULL;
805 /* Now, delete the type library path subkey */
806 get_lcid_subkey( lcid, syskind, subKeyName );
807 RegDeleteKeyW(key, subKeyName);
808 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
809 RegDeleteKeyW(key, subKeyName);
811 /* check if there is anything besides the FLAGS/HELPDIR keys.
812 If there is, we don't delete them */
813 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
814 deleteOtherStuff = TRUE;
815 i = 0;
816 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
817 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
819 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
820 if (!strcmpW(subKeyName, FLAGSW)) continue;
821 if (!strcmpW(subKeyName, HELPDIRW)) continue;
822 deleteOtherStuff = FALSE;
823 break;
826 /* only delete the other parts of the key if we're absolutely sure */
827 if (deleteOtherStuff) {
828 RegDeleteKeyW(key, FLAGSW);
829 RegDeleteKeyW(key, HELPDIRW);
830 RegCloseKey(key);
831 key = NULL;
833 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
834 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
835 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
838 end:
839 if (tlibPath) SysFreeString(tlibPath);
840 if (typeLib) ITypeLib_Release(typeLib);
841 if (subKey) RegCloseKey(subKey);
842 if (key) RegCloseKey(key);
843 return result;
846 /*======================= ITypeLib implementation =======================*/
848 typedef struct tagTLBCustData
850 GUID guid;
851 VARIANT data;
852 struct tagTLBCustData* next;
853 } TLBCustData;
855 /* data structure for import typelibs */
856 typedef struct tagTLBImpLib
858 int offset; /* offset in the file (MSFT)
859 offset in nametable (SLTG)
860 just used to identify library while reading
861 data from file */
862 GUID guid; /* libid */
863 BSTR name; /* name */
865 LCID lcid; /* lcid of imported typelib */
867 WORD wVersionMajor; /* major version number */
868 WORD wVersionMinor; /* minor version number */
870 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
871 NULL if not yet loaded */
872 struct tagTLBImpLib * next;
873 } TLBImpLib;
875 /* internal ITypeLib data */
876 typedef struct tagITypeLibImpl
878 const ITypeLib2Vtbl *lpVtbl;
879 const ITypeCompVtbl *lpVtblTypeComp;
880 LONG ref;
881 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
883 /* strings can be stored in tlb as multibyte strings BUT they are *always*
884 * exported to the application as a UNICODE string.
886 BSTR Name;
887 BSTR DocString;
888 BSTR HelpFile;
889 BSTR HelpStringDll;
890 unsigned long dwHelpContext;
891 int TypeInfoCount; /* nr of typeinfo's in librarry */
892 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
893 int ctCustData; /* number of items in cust data list */
894 TLBCustData * pCustData; /* linked list to cust data */
895 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
896 int ctTypeDesc; /* number of items in type desc array */
897 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
898 library. Only used while reading MSFT
899 typelibs */
900 struct list ref_list; /* list of ref types in this typelib */
901 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
904 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
905 struct tagITypeLibImpl *next, *prev;
906 WCHAR *path;
907 INT index;
908 } ITypeLibImpl;
910 static const ITypeLib2Vtbl tlbvt;
911 static const ITypeCompVtbl tlbtcvt;
913 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
915 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
918 /* ITypeLib methods */
919 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
920 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
922 /*======================= ITypeInfo implementation =======================*/
924 /* data for referenced types */
925 typedef struct tagTLBRefType
927 INT index; /* Type index for internal ref or for external ref
928 it the format is SLTG. -2 indicates to
929 use guid */
931 GUID guid; /* guid of the referenced type */
932 /* if index == TLB_REF_USE_GUID */
934 HREFTYPE reference; /* The href of this ref */
935 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
936 TLB_REF_INTERNAL for internal refs
937 TLB_REF_NOT_FOUND for broken refs */
939 struct list entry;
940 } TLBRefType;
942 #define TLB_REF_USE_GUID -2
944 #define TLB_REF_INTERNAL (void*)-2
945 #define TLB_REF_NOT_FOUND (void*)-1
947 /* internal Parameter data */
948 typedef struct tagTLBParDesc
950 BSTR Name;
951 int ctCustData;
952 TLBCustData * pCustData; /* linked list to cust data */
953 } TLBParDesc;
955 /* internal Function data */
956 typedef struct tagTLBFuncDesc
958 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
959 BSTR Name; /* the name of this function */
960 TLBParDesc *pParamDesc; /* array with param names and custom data */
961 int helpcontext;
962 int HelpStringContext;
963 BSTR HelpString;
964 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
965 int ctCustData;
966 TLBCustData * pCustData; /* linked list to cust data; */
967 struct tagTLBFuncDesc * next;
968 } TLBFuncDesc;
970 /* internal Variable data */
971 typedef struct tagTLBVarDesc
973 VARDESC vardesc; /* lots of info on the variable and its attributes. */
974 BSTR Name; /* the name of this variable */
975 int HelpContext;
976 int HelpStringContext; /* FIXME: where? */
977 BSTR HelpString;
978 int ctCustData;
979 TLBCustData * pCustData;/* linked list to cust data; */
980 struct tagTLBVarDesc * next;
981 } TLBVarDesc;
983 /* internal implemented interface data */
984 typedef struct tagTLBImplType
986 HREFTYPE hRef; /* hRef of interface */
987 int implflags; /* IMPLFLAG_*s */
988 int ctCustData;
989 TLBCustData * pCustData;/* linked list to custom data; */
990 struct tagTLBImplType *next;
991 } TLBImplType;
993 /* internal TypeInfo data */
994 typedef struct tagITypeInfoImpl
996 const ITypeInfo2Vtbl *lpVtbl;
997 const ITypeCompVtbl *lpVtblTypeComp;
998 LONG ref;
999 BOOL no_free_data; /* don't free data structurees */
1000 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1001 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1002 int index; /* index in this typelib; */
1003 HREFTYPE hreftype; /* hreftype for app object binding */
1004 /* type libs seem to store the doc strings in ascii
1005 * so why should we do it in unicode?
1007 BSTR Name;
1008 BSTR DocString;
1009 BSTR DllName;
1010 unsigned long dwHelpContext;
1011 unsigned long dwHelpStringContext;
1013 /* functions */
1014 TLBFuncDesc * funclist; /* linked list with function descriptions */
1016 /* variables */
1017 TLBVarDesc * varlist; /* linked list with variable descriptions */
1019 /* Implemented Interfaces */
1020 TLBImplType * impltypelist;
1022 int ctCustData;
1023 TLBCustData * pCustData; /* linked list to cust data; */
1024 struct tagITypeInfoImpl * next;
1025 } ITypeInfoImpl;
1027 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1029 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1032 static const ITypeInfo2Vtbl tinfvt;
1033 static const ITypeCompVtbl tcompvt;
1035 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
1037 typedef struct tagTLBContext
1039 unsigned int oStart; /* start of TLB in file */
1040 unsigned int pos; /* current pos */
1041 unsigned int length; /* total length */
1042 void *mapping; /* memory mapping */
1043 MSFT_SegDir * pTblDir;
1044 ITypeLibImpl* pLibInfo;
1045 } TLBContext;
1048 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1051 debug
1053 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1054 if (pTD->vt & VT_RESERVED)
1055 szVarType += strlen(strcpy(szVarType, "reserved | "));
1056 if (pTD->vt & VT_BYREF)
1057 szVarType += strlen(strcpy(szVarType, "ref to "));
1058 if (pTD->vt & VT_ARRAY)
1059 szVarType += strlen(strcpy(szVarType, "array of "));
1060 if (pTD->vt & VT_VECTOR)
1061 szVarType += strlen(strcpy(szVarType, "vector of "));
1062 switch(pTD->vt & VT_TYPEMASK) {
1063 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1064 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1065 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1066 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1067 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1068 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1069 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1070 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1071 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1072 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1073 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1074 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1075 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1076 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1077 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1078 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1079 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1080 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1081 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1082 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1083 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1084 pTD->u.hreftype); break;
1085 case VT_PTR: sprintf(szVarType, "ptr to ");
1086 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1087 break;
1088 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1089 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1090 break;
1091 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1092 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1093 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1094 break;
1096 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1100 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1101 char buf[200];
1102 USHORT flags = edesc->u.paramdesc.wParamFlags;
1103 dump_TypeDesc(&edesc->tdesc,buf);
1104 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1105 MESSAGE("\t\tu.paramdesc.wParamFlags");
1106 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1107 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1108 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1109 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1110 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1111 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1112 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1113 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1114 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1116 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1117 int i;
1118 MESSAGE("memid is %08x\n",funcdesc->memid);
1119 for (i=0;i<funcdesc->cParams;i++) {
1120 MESSAGE("Param %d:\n",i);
1121 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1123 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1124 switch (funcdesc->funckind) {
1125 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1126 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1127 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1128 case FUNC_STATIC: MESSAGE("static");break;
1129 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1130 default: MESSAGE("unknown");break;
1132 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1133 switch (funcdesc->invkind) {
1134 case INVOKE_FUNC: MESSAGE("func");break;
1135 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1136 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1137 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1139 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1140 switch (funcdesc->callconv) {
1141 case CC_CDECL: MESSAGE("cdecl");break;
1142 case CC_PASCAL: MESSAGE("pascal");break;
1143 case CC_STDCALL: MESSAGE("stdcall");break;
1144 case CC_SYSCALL: MESSAGE("syscall");break;
1145 default:break;
1147 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1148 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1149 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1151 MESSAGE("\telemdescFunc (return value type):\n");
1152 dump_ELEMDESC(&funcdesc->elemdescFunc);
1155 static const char * const typekind_desc[] =
1157 "TKIND_ENUM",
1158 "TKIND_RECORD",
1159 "TKIND_MODULE",
1160 "TKIND_INTERFACE",
1161 "TKIND_DISPATCH",
1162 "TKIND_COCLASS",
1163 "TKIND_ALIAS",
1164 "TKIND_UNION",
1165 "TKIND_MAX"
1168 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1170 int i;
1171 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1172 for (i=0;i<pfd->funcdesc.cParams;i++)
1173 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1176 dump_FUNCDESC(&(pfd->funcdesc));
1178 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1179 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1181 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1183 while (pfd)
1185 dump_TLBFuncDescOne(pfd);
1186 pfd = pfd->next;
1189 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1191 while (pvd)
1193 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1194 pvd = pvd->next;
1198 static void dump_TLBImpLib(const TLBImpLib *import)
1200 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1201 debugstr_w(import->name));
1202 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1203 import->wVersionMinor, import->lcid, import->offset);
1206 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1208 TLBRefType *ref;
1210 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1212 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1213 if(ref->index == -1)
1214 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1215 else
1216 TRACE_(typelib)("type no: %d\n", ref->index);
1218 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1220 TRACE_(typelib)("in lib\n");
1221 dump_TLBImpLib(ref->pImpTLInfo);
1226 static void dump_TLBImplType(const TLBImplType * impl)
1228 while (impl) {
1229 TRACE_(typelib)(
1230 "implementing/inheriting interface hRef = %x implflags %x\n",
1231 impl->hRef, impl->implflags);
1232 impl = impl->next;
1236 static void dump_Variant(const VARIANT * pvar)
1238 SYSTEMTIME st;
1240 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1242 if (pvar)
1244 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1245 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1247 TRACE(",%p", V_BYREF(pvar));
1249 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1251 TRACE(",%p", V_ARRAY(pvar));
1253 else switch (V_TYPE(pvar))
1255 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1256 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1257 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1258 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1259 case VT_INT:
1260 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1261 case VT_UINT:
1262 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1263 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1264 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1265 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1266 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1267 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1268 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1269 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1270 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1271 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1272 V_CY(pvar).s.Lo); break;
1273 case VT_DATE:
1274 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1275 TRACE(",<invalid>");
1276 else
1277 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1278 st.wHour, st.wMinute, st.wSecond);
1279 break;
1280 case VT_ERROR:
1281 case VT_VOID:
1282 case VT_USERDEFINED:
1283 case VT_EMPTY:
1284 case VT_NULL: break;
1285 default: TRACE(",?"); break;
1288 TRACE("}\n");
1291 static void dump_DispParms(const DISPPARAMS * pdp)
1293 int index;
1295 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1297 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1299 TRACE("named args:\n");
1300 for (index = 0; index < pdp->cNamedArgs; index++)
1301 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1304 if (pdp->cArgs && pdp->rgvarg)
1306 TRACE("args:\n");
1307 for (index = 0; index < pdp->cArgs; index++)
1308 dump_Variant( &pdp->rgvarg[index] );
1312 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1314 TRACE("%p ref=%u\n", pty, pty->ref);
1315 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1316 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1317 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1318 TRACE("fct:%u var:%u impl:%u\n",
1319 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1320 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1321 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1322 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1323 if (TRACE_ON(ole))
1324 dump_TLBFuncDesc(pty->funclist);
1325 dump_TLBVarDesc(pty->varlist);
1326 dump_TLBImplType(pty->impltypelist);
1329 static void dump_VARDESC(const VARDESC *v)
1331 MESSAGE("memid %d\n",v->memid);
1332 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1333 MESSAGE("oInst %d\n",v->u.oInst);
1334 dump_ELEMDESC(&(v->elemdescVar));
1335 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1336 MESSAGE("varkind %d\n",v->varkind);
1339 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1341 /* VT_LPWSTR is largest type that */
1342 /* may appear in type description*/
1343 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1344 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1345 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1346 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1347 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1348 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1349 {{0},30},{{0},31}
1352 static void TLB_abort(void)
1354 DebugBreak();
1356 static void * TLB_Alloc(unsigned size)
1358 void * ret;
1359 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1360 /* FIXME */
1361 ERR("cannot allocate memory\n");
1363 return ret;
1366 static void TLB_Free(void * ptr)
1368 HeapFree(GetProcessHeap(), 0, ptr);
1371 /* returns the size required for a deep copy of a typedesc into a
1372 * flat buffer */
1373 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1375 SIZE_T size = 0;
1377 if (alloc_initial_space)
1378 size += sizeof(TYPEDESC);
1380 switch (tdesc->vt)
1382 case VT_PTR:
1383 case VT_SAFEARRAY:
1384 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1385 break;
1386 case VT_CARRAY:
1387 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1388 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1389 break;
1391 return size;
1394 /* deep copy a typedesc into a flat buffer */
1395 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1397 if (!dest)
1399 dest = buffer;
1400 buffer = (char *)buffer + sizeof(TYPEDESC);
1403 *dest = *src;
1405 switch (src->vt)
1407 case VT_PTR:
1408 case VT_SAFEARRAY:
1409 dest->u.lptdesc = buffer;
1410 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1411 break;
1412 case VT_CARRAY:
1413 dest->u.lpadesc = buffer;
1414 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1415 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1416 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1417 break;
1419 return buffer;
1422 /**********************************************************************
1424 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1426 static inline unsigned int MSFT_Tell(TLBContext *pcx)
1428 return pcx->pos;
1431 static inline void MSFT_Seek(TLBContext *pcx, long where)
1433 if (where != DO_NOT_SEEK)
1435 where += pcx->oStart;
1436 if (where > pcx->length)
1438 /* FIXME */
1439 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1440 TLB_abort();
1442 pcx->pos = where;
1446 /* read function */
1447 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1449 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1450 pcx->pos, count, pcx->oStart, pcx->length, where);
1452 MSFT_Seek(pcx, where);
1453 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1454 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1455 pcx->pos += count;
1456 return count;
1459 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1460 long where )
1462 DWORD ret;
1464 ret = MSFT_Read(buffer, count, pcx, where);
1465 FromLEDWords(buffer, ret);
1467 return ret;
1470 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1471 long where )
1473 DWORD ret;
1475 ret = MSFT_Read(buffer, count, pcx, where);
1476 FromLEWords(buffer, ret);
1478 return ret;
1481 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1483 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1484 memset(pGuid,0, sizeof(GUID));
1485 return;
1487 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1488 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1489 pGuid->Data2 = FromLEWord(pGuid->Data2);
1490 pGuid->Data3 = FromLEWord(pGuid->Data3);
1491 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1494 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1496 MSFT_NameIntro niName;
1498 if (offset < 0)
1500 ERR_(typelib)("bad offset %d\n", offset);
1501 return -1;
1504 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1505 pcx->pTblDir->pNametab.offset+offset);
1507 return niName.hreftype;
1510 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1512 char * name;
1513 MSFT_NameIntro niName;
1514 int lengthInChars;
1515 BSTR bstrName = NULL;
1517 if (offset < 0)
1519 ERR_(typelib)("bad offset %d\n", offset);
1520 return NULL;
1522 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1523 pcx->pTblDir->pNametab.offset+offset);
1524 niName.namelen &= 0xFF; /* FIXME: correct ? */
1525 name=TLB_Alloc((niName.namelen & 0xff) +1);
1526 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1527 name[niName.namelen & 0xff]='\0';
1529 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1530 name, -1, NULL, 0);
1532 /* no invalid characters in string */
1533 if (lengthInChars)
1535 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1537 /* don't check for invalid character since this has been done previously */
1538 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1540 TLB_Free(name);
1542 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1543 return bstrName;
1546 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1548 char * string;
1549 INT16 length;
1550 int lengthInChars;
1551 BSTR bstr = NULL;
1553 if(offset<0) return NULL;
1554 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1555 if(length <= 0) return 0;
1556 string=TLB_Alloc(length +1);
1557 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1558 string[length]='\0';
1560 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1561 string, -1, NULL, 0);
1563 /* no invalid characters in string */
1564 if (lengthInChars)
1566 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1568 /* don't check for invalid character since this has been done previously */
1569 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1571 TLB_Free(string);
1573 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1574 return bstr;
1577 * read a value and fill a VARIANT structure
1579 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1581 int size;
1583 TRACE_(typelib)("\n");
1585 if(offset <0) { /* data are packed in here */
1586 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1587 V_I4(pVar) = offset & 0x3ffffff;
1588 return;
1590 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1591 pcx->pTblDir->pCustData.offset + offset );
1592 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1593 switch (V_VT(pVar)){
1594 case VT_EMPTY: /* FIXME: is this right? */
1595 case VT_NULL: /* FIXME: is this right? */
1596 case VT_I2 : /* this should not happen */
1597 case VT_I4 :
1598 case VT_R4 :
1599 case VT_ERROR :
1600 case VT_BOOL :
1601 case VT_I1 :
1602 case VT_UI1 :
1603 case VT_UI2 :
1604 case VT_UI4 :
1605 case VT_INT :
1606 case VT_UINT :
1607 case VT_VOID : /* FIXME: is this right? */
1608 case VT_HRESULT :
1609 size=4; break;
1610 case VT_R8 :
1611 case VT_CY :
1612 case VT_DATE :
1613 case VT_I8 :
1614 case VT_UI8 :
1615 case VT_DECIMAL : /* FIXME: is this right? */
1616 case VT_FILETIME :
1617 size=8;break;
1618 /* pointer types with known behaviour */
1619 case VT_BSTR :{
1620 char * ptr;
1621 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1622 if(size < 0) {
1623 char next;
1624 DWORD origPos = MSFT_Tell(pcx), nullPos;
1626 do {
1627 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1628 } while (next);
1629 nullPos = MSFT_Tell(pcx);
1630 size = nullPos - origPos;
1631 MSFT_Seek(pcx, origPos);
1633 ptr=TLB_Alloc(size);/* allocate temp buffer */
1634 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1635 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1636 /* FIXME: do we need a AtoW conversion here? */
1637 V_UNION(pVar, bstrVal[size])=L'\0';
1638 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1639 TLB_Free(ptr);
1641 size=-4; break;
1642 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1643 case VT_DISPATCH :
1644 case VT_VARIANT :
1645 case VT_UNKNOWN :
1646 case VT_PTR :
1647 case VT_SAFEARRAY :
1648 case VT_CARRAY :
1649 case VT_USERDEFINED :
1650 case VT_LPSTR :
1651 case VT_LPWSTR :
1652 case VT_BLOB :
1653 case VT_STREAM :
1654 case VT_STORAGE :
1655 case VT_STREAMED_OBJECT :
1656 case VT_STORED_OBJECT :
1657 case VT_BLOB_OBJECT :
1658 case VT_CF :
1659 case VT_CLSID :
1660 default:
1661 size=0;
1662 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1663 V_VT(pVar));
1666 if(size>0) /* (big|small) endian correct? */
1667 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1668 return;
1671 * create a linked list with custom data
1673 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1675 MSFT_CDGuid entry;
1676 TLBCustData* pNew;
1677 int count=0;
1679 TRACE_(typelib)("\n");
1681 while(offset >=0){
1682 count++;
1683 pNew=TLB_Alloc(sizeof(TLBCustData));
1684 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1685 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1686 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1687 /* add new custom data at head of the list */
1688 pNew->next=*ppCustData;
1689 *ppCustData=pNew;
1690 offset = entry.next;
1692 return count;
1695 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1696 ITypeInfoImpl *pTI)
1698 if(type <0)
1699 pTd->vt=type & VT_TYPEMASK;
1700 else
1701 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1703 if(pTd->vt == VT_USERDEFINED)
1704 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1706 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1709 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1711 /* resolve referenced type if any */
1712 while (lpTypeDesc)
1714 switch (lpTypeDesc->vt)
1716 case VT_PTR:
1717 lpTypeDesc = lpTypeDesc->u.lptdesc;
1718 break;
1720 case VT_CARRAY:
1721 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1722 break;
1724 case VT_USERDEFINED:
1725 MSFT_DoRefType(pcx, pTI->pTypeLib,
1726 lpTypeDesc->u.hreftype);
1728 lpTypeDesc = NULL;
1729 break;
1731 default:
1732 lpTypeDesc = NULL;
1737 static void
1738 MSFT_DoFuncs(TLBContext* pcx,
1739 ITypeInfoImpl* pTI,
1740 int cFuncs,
1741 int cVars,
1742 int offset,
1743 TLBFuncDesc** pptfd)
1746 * member information is stored in a data structure at offset
1747 * indicated by the memoffset field of the typeinfo structure
1748 * There are several distinctive parts.
1749 * The first part starts with a field that holds the total length
1750 * of this (first) part excluding this field. Then follow the records,
1751 * for each member there is one record.
1753 * The first entry is always the length of the record (including this
1754 * length word).
1755 * The rest of the record depends on the type of the member. If there is
1756 * a field indicating the member type (function, variable, interface, etc)
1757 * I have not found it yet. At this time we depend on the information
1758 * in the type info and the usual order how things are stored.
1760 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1761 * for each member;
1763 * Third is an equal sized array with file offsets to the name entry
1764 * of each member.
1766 * The fourth and last (?) part is an array with offsets to the records
1767 * in the first part of this file segment.
1770 int infolen, nameoffset, reclength, nrattributes, i;
1771 int recoffset = offset + sizeof(INT);
1773 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1774 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1775 TLBFuncDesc *ptfd_prev = NULL;
1777 TRACE_(typelib)("\n");
1779 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1781 for ( i = 0; i < cFuncs ; i++ )
1783 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1785 /* name, eventually add to a hash table */
1786 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1787 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1789 /* nameoffset is sometimes -1 on the second half of a propget/propput
1790 * pair of functions */
1791 if ((nameoffset == -1) && (i > 0))
1792 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1793 else
1794 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1796 /* read the function information record */
1797 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1799 reclength &= 0xffff;
1801 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1803 /* do the attributes */
1804 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1805 / sizeof(int);
1807 if ( nrattributes > 0 )
1809 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1811 if ( nrattributes > 1 )
1813 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1814 pFuncRec->OptAttr[1]) ;
1816 if ( nrattributes > 2 )
1818 if ( pFuncRec->FKCCIC & 0x2000 )
1820 if (HIWORD(pFuncRec->OptAttr[2]) != 0)
1821 ERR("ordinal 0x%08x invalid, HIWORD != 0\n", pFuncRec->OptAttr[2]);
1822 (*pptfd)->Entry = (BSTR)pFuncRec->OptAttr[2];
1824 else
1826 (*pptfd)->Entry = MSFT_ReadString(pcx,
1827 pFuncRec->OptAttr[2]);
1829 if( nrattributes > 5 )
1831 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1833 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1835 MSFT_CustData(pcx,
1836 pFuncRec->OptAttr[6],
1837 &(*pptfd)->pCustData);
1841 else
1843 (*pptfd)->Entry = (BSTR)-1;
1848 /* fill the FuncDesc Structure */
1849 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1850 offset + infolen + ( i + 1) * sizeof(INT));
1852 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1853 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1854 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1855 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1856 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1857 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1858 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1860 MSFT_GetTdesc(pcx,
1861 pFuncRec->DataType,
1862 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1863 pTI);
1864 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1866 /* do the parameters/arguments */
1867 if(pFuncRec->nrargs)
1869 int j = 0;
1870 MSFT_ParameterInfo paraminfo;
1872 (*pptfd)->funcdesc.lprgelemdescParam =
1873 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1875 (*pptfd)->pParamDesc =
1876 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1878 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1879 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1881 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1883 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1885 MSFT_GetTdesc(pcx,
1886 paraminfo.DataType,
1887 &elemdesc->tdesc,
1888 pTI);
1890 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1892 /* name */
1893 if (paraminfo.oName == -1)
1894 /* this occurs for [propput] or [propget] methods, so
1895 * we should just set the name of the parameter to the
1896 * name of the method. */
1897 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1898 else
1899 (*pptfd)->pParamDesc[j].Name =
1900 MSFT_ReadName( pcx, paraminfo.oName );
1901 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1903 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1905 /* default value */
1906 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1907 (pFuncRec->FKCCIC & 0x1000) )
1909 INT* pInt = (INT *)((char *)pFuncRec +
1910 reclength -
1911 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1913 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1915 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1916 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1918 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1919 pInt[j], pcx);
1921 else
1922 elemdesc->u.paramdesc.pparamdescex = NULL;
1923 /* custom info */
1924 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1926 MSFT_CustData(pcx,
1927 pFuncRec->OptAttr[7+j],
1928 &(*pptfd)->pParamDesc[j].pCustData);
1931 /* SEEK value = jump to offset,
1932 * from there jump to the end of record,
1933 * go back by (j-1) arguments
1935 MSFT_ReadLEDWords( &paraminfo ,
1936 sizeof(MSFT_ParameterInfo), pcx,
1937 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1938 * sizeof(MSFT_ParameterInfo)));
1942 /* scode is not used: archaic win16 stuff FIXME: right? */
1943 (*pptfd)->funcdesc.cScodes = 0 ;
1944 (*pptfd)->funcdesc.lprgscode = NULL ;
1946 ptfd_prev = *pptfd;
1947 pptfd = & ((*pptfd)->next);
1948 recoffset += reclength;
1950 HeapFree(GetProcessHeap(), 0, recbuf);
1953 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1954 int cVars, int offset, TLBVarDesc ** pptvd)
1956 int infolen, nameoffset, reclength;
1957 char recbuf[256];
1958 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1959 int i;
1960 int recoffset;
1962 TRACE_(typelib)("\n");
1964 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1965 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1966 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1967 recoffset += offset+sizeof(INT);
1968 for(i=0;i<cVars;i++){
1969 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1970 /* name, eventually add to a hash table */
1971 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1972 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
1973 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1974 /* read the variable information record */
1975 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1976 reclength &=0xff;
1977 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1978 /* Optional data */
1979 if(reclength >(6*sizeof(INT)) )
1980 (*pptvd)->HelpContext=pVarRec->HelpContext;
1981 if(reclength >(7*sizeof(INT)) )
1982 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1983 if(reclength >(8*sizeof(INT)) )
1984 if(reclength >(9*sizeof(INT)) )
1985 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1986 /* fill the VarDesc Structure */
1987 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1988 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
1989 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1990 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1991 MSFT_GetTdesc(pcx, pVarRec->DataType,
1992 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1993 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1994 if(pVarRec->VarKind == VAR_CONST ){
1995 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1996 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1997 pVarRec->OffsValue, pcx);
1998 } else
1999 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
2000 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
2001 pptvd=&((*pptvd)->next);
2002 recoffset += reclength;
2005 /* fill in data for a hreftype (offset). When the referenced type is contained
2006 * in the typelib, it's just an (file) offset in the type info base dir.
2007 * If comes from import, it's an offset+1 in the ImpInfo table
2008 * */
2009 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2010 int offset)
2012 int j;
2013 TLBRefType *ref;
2015 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2017 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2019 if(ref->reference == offset) return;
2022 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
2023 list_add_tail(&pTL->ref_list, &ref->entry);
2025 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2026 /* external typelib */
2027 MSFT_ImpInfo impinfo;
2028 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2030 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2032 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2033 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2034 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
2035 if(pImpLib->offset==impinfo.oImpFile) break;
2036 pImpLib=pImpLib->next;
2038 if(pImpLib){
2039 ref->reference = offset;
2040 ref->pImpTLInfo = pImpLib;
2041 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2042 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2043 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2044 ref->index = TLB_REF_USE_GUID;
2045 } else
2046 ref->index = impinfo.oGuid;
2047 }else{
2048 ERR("Cannot find a reference\n");
2049 ref->reference = -1;
2050 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2052 }else{
2053 /* in this typelib */
2054 ref->index = MSFT_HREFTYPE_INDEX(offset);
2055 ref->reference = offset;
2056 ref->pImpTLInfo = TLB_REF_INTERNAL;
2060 /* process Implemented Interfaces of a com class */
2061 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2062 int offset)
2064 int i;
2065 MSFT_RefRecord refrec;
2066 TLBImplType **ppImpl = &pTI->impltypelist;
2068 TRACE_(typelib)("\n");
2070 for(i=0;i<count;i++){
2071 if(offset<0) break; /* paranoia */
2072 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2073 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2074 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2075 (*ppImpl)->hRef = refrec.reftype;
2076 (*ppImpl)->implflags=refrec.flags;
2077 (*ppImpl)->ctCustData=
2078 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2079 offset=refrec.onext;
2080 ppImpl=&((*ppImpl)->next);
2084 * process a typeinfo record
2086 static ITypeInfoImpl * MSFT_DoTypeInfo(
2087 TLBContext *pcx,
2088 int count,
2089 ITypeLibImpl * pLibInfo)
2091 MSFT_TypeInfoBase tiBase;
2092 ITypeInfoImpl *ptiRet;
2094 TRACE_(typelib)("count=%u\n", count);
2096 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2097 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2098 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2100 /* this is where we are coming from */
2101 ptiRet->pTypeLib = pLibInfo;
2102 ptiRet->index=count;
2103 /* fill in the typeattr fields */
2105 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2106 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2107 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2108 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2109 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2110 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2111 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2112 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2113 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2114 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2115 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2116 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2117 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2118 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2119 MSFT_GetTdesc(pcx, tiBase.datatype1,
2120 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2122 /* FIXME: */
2123 /* IDLDESC idldescType; *//* never saw this one != zero */
2125 /* name, eventually add to a hash table */
2126 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2127 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2128 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2129 /* help info */
2130 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2131 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2132 ptiRet->dwHelpContext=tiBase.helpcontext;
2134 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2135 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2137 /* note: InfoType's Help file and HelpStringDll come from the containing
2138 * library. Further HelpString and Docstring appear to be the same thing :(
2140 /* functions */
2141 if(ptiRet->TypeAttr.cFuncs >0 )
2142 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2143 ptiRet->TypeAttr.cVars,
2144 tiBase.memoffset, & ptiRet->funclist);
2145 /* variables */
2146 if(ptiRet->TypeAttr.cVars >0 )
2147 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2148 ptiRet->TypeAttr.cVars,
2149 tiBase.memoffset, & ptiRet->varlist);
2150 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2151 switch(ptiRet->TypeAttr.typekind)
2153 case TKIND_COCLASS:
2154 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2155 tiBase.datatype1);
2156 break;
2157 case TKIND_DISPATCH:
2158 /* This is not -1 when the interface is a non-base dual interface or
2159 when a dispinterface wraps an interface ie the idl 'dispinterface x {interface y;};'.
2160 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2161 not this interface.
2164 if (tiBase.datatype1 != -1)
2166 ptiRet->impltypelist = TLB_Alloc(sizeof(TLBImplType));
2167 ptiRet->impltypelist->hRef = tiBase.datatype1;
2168 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2170 break;
2171 default:
2172 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2173 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2174 ptiRet->impltypelist->hRef = tiBase.datatype1;
2175 break;
2178 ptiRet->ctCustData=
2179 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2181 TRACE_(typelib)("%s guid: %s kind:%s\n",
2182 debugstr_w(ptiRet->Name),
2183 debugstr_guid(&ptiRet->TypeAttr.guid),
2184 typekind_desc[ptiRet->TypeAttr.typekind]);
2186 return ptiRet;
2189 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2190 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2191 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2192 * tradeoff here.
2194 static ITypeLibImpl *tlb_cache_first;
2195 static CRITICAL_SECTION cache_section;
2196 static CRITICAL_SECTION_DEBUG cache_section_debug =
2198 0, 0, &cache_section,
2199 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2200 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2202 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2205 /****************************************************************************
2206 * TLB_ReadTypeLib
2208 * find the type of the typelib file and map the typelib resource into
2209 * the memory
2211 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2212 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2213 static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2215 ITypeLibImpl *entry;
2216 int ret = TYPE_E_CANTLOADLIBRARY;
2217 INT index = 1;
2218 HINSTANCE hinstDLL;
2219 LPWSTR index_str, file = (LPWSTR)pszFileName;
2221 *ppTypeLib = NULL;
2223 index_str = strrchrW(pszFileName, '\\');
2224 if(index_str && *++index_str != '\0')
2226 LPWSTR end_ptr;
2227 long idx = strtolW(index_str, &end_ptr, 10);
2228 if(*end_ptr == '\0')
2230 int str_len = index_str - pszFileName - 1;
2231 index = idx;
2232 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
2233 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2234 file[str_len] = 0;
2238 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2240 if(strchrW(file, '\\'))
2242 lstrcpyW(pszPath, file);
2244 else
2246 int len = GetSystemDirectoryW(pszPath, cchPath);
2247 pszPath[len] = '\\';
2248 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2252 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file);
2254 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2256 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2257 EnterCriticalSection(&cache_section);
2258 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2260 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2262 TRACE("cache hit\n");
2263 *ppTypeLib = (ITypeLib2*)entry;
2264 ITypeLib_AddRef(*ppTypeLib);
2265 LeaveCriticalSection(&cache_section);
2266 return S_OK;
2269 LeaveCriticalSection(&cache_section);
2271 /* now actually load and parse the typelib */
2273 hinstDLL = LoadLibraryExW(pszPath, 0, DONT_RESOLVE_DLL_REFERENCES |
2274 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2276 if (hinstDLL)
2278 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2279 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2280 if (hrsrc)
2282 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2283 if (hGlobal)
2285 LPVOID pBase = LockResource(hGlobal);
2286 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2288 if (pBase)
2290 /* try to load as incore resource */
2291 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2292 if (dwSignature == MSFT_SIGNATURE)
2293 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2294 else if (dwSignature == SLTG_SIGNATURE)
2295 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2296 else
2297 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2299 FreeResource( hGlobal );
2302 FreeLibrary(hinstDLL);
2304 else
2306 HANDLE hFile = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2307 if (INVALID_HANDLE_VALUE != hFile)
2309 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2310 if (hMapping)
2312 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2313 if(pBase)
2315 /* retrieve file size */
2316 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2317 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2319 if (dwSignature == MSFT_SIGNATURE)
2320 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2321 else if (dwSignature == SLTG_SIGNATURE)
2322 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2324 UnmapViewOfFile(pBase);
2326 CloseHandle(hMapping);
2328 CloseHandle(hFile);
2332 if(*ppTypeLib) {
2333 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2335 TRACE("adding to cache\n");
2336 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2337 lstrcpyW(impl->path, pszPath);
2338 /* We should really canonicalise the path here. */
2339 impl->index = index;
2341 /* FIXME: check if it has added already in the meantime */
2342 EnterCriticalSection(&cache_section);
2343 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2344 impl->prev = NULL;
2345 tlb_cache_first = impl;
2346 LeaveCriticalSection(&cache_section);
2347 ret = S_OK;
2348 } else
2349 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2351 return ret;
2354 /*================== ITypeLib(2) Methods ===================================*/
2356 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2358 ITypeLibImpl* pTypeLibImpl;
2360 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2361 if (!pTypeLibImpl) return NULL;
2363 pTypeLibImpl->lpVtbl = &tlbvt;
2364 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2365 pTypeLibImpl->ref = 1;
2367 list_init(&pTypeLibImpl->ref_list);
2368 pTypeLibImpl->dispatch_href = -1;
2370 return pTypeLibImpl;
2373 /****************************************************************************
2374 * ITypeLib2_Constructor_MSFT
2376 * loading an MSFT typelib from an in-memory image
2378 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2380 TLBContext cx;
2381 long lPSegDir;
2382 MSFT_Header tlbHeader;
2383 MSFT_SegDir tlbSegDir;
2384 ITypeLibImpl * pTypeLibImpl;
2386 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2388 pTypeLibImpl = TypeLibImpl_Constructor();
2389 if (!pTypeLibImpl) return NULL;
2391 /* get pointer to beginning of typelib data */
2392 cx.pos = 0;
2393 cx.oStart=0;
2394 cx.mapping = pLib;
2395 cx.pLibInfo = pTypeLibImpl;
2396 cx.length = dwTLBLength;
2398 /* read header */
2399 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2400 TRACE_(typelib)("header:\n");
2401 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2402 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2403 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2404 return NULL;
2406 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2408 /* there is a small amount of information here until the next important
2409 * part:
2410 * the segment directory . Try to calculate the amount of data */
2411 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2413 /* now read the segment directory */
2414 TRACE("read segment directory (at %ld)\n",lPSegDir);
2415 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2416 cx.pTblDir = &tlbSegDir;
2418 /* just check two entries */
2419 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2421 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2422 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2423 return NULL;
2426 /* now fill our internal data */
2427 /* TLIBATTR fields */
2428 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2430 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2431 /* Windows seems to have zero here, is this correct? */
2432 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2433 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2434 else
2435 pTypeLibImpl->LibAttr.lcid = 0;
2437 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2438 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2439 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2440 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2442 /* name, eventually add to a hash table */
2443 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2445 /* help info */
2446 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2447 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2449 if( tlbHeader.varflags & HELPDLLFLAG)
2451 int offset;
2452 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2453 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2456 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2458 /* custom data */
2459 if(tlbHeader.CustomDataOffset >= 0)
2461 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2464 /* fill in typedescriptions */
2465 if(tlbSegDir.pTypdescTab.length > 0)
2467 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2468 INT16 td[4];
2469 pTypeLibImpl->ctTypeDesc = cTD;
2470 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2471 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2472 for(i=0; i<cTD; )
2474 /* FIXME: add several sanity checks here */
2475 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2476 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2478 /* FIXME: check safearray */
2479 if(td[3] < 0)
2480 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2481 else
2482 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2484 else if(td[0] == VT_CARRAY)
2486 /* array descr table here */
2487 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2489 else if(td[0] == VT_USERDEFINED)
2491 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2493 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2496 /* second time around to fill the array subscript info */
2497 for(i=0;i<cTD;i++)
2499 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2500 if(tlbSegDir.pArrayDescriptions.offset>0)
2502 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2503 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2505 if(td[1]<0)
2506 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2507 else
2508 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2510 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2512 for(j = 0; j<td[2]; j++)
2514 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2515 sizeof(INT), &cx, DO_NOT_SEEK);
2516 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2517 sizeof(INT), &cx, DO_NOT_SEEK);
2520 else
2522 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2523 ERR("didn't find array description data\n");
2528 /* imported type libs */
2529 if(tlbSegDir.pImpFiles.offset>0)
2531 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2532 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2533 UINT16 size;
2535 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2537 char *name;
2538 DWORD len;
2540 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2541 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2542 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2544 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2545 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2546 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2547 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2549 size >>= 2;
2550 name = TLB_Alloc(size+1);
2551 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2552 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2553 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2554 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2555 TLB_Free(name);
2557 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2558 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2560 ppImpLib = &(*ppImpLib)->next;
2564 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
2565 if(pTypeLibImpl->dispatch_href != -1)
2566 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
2568 /* type info's */
2569 if(tlbHeader.nrtypeinfos >= 0 )
2571 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2572 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2573 int i;
2575 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2577 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2579 ppTI = &((*ppTI)->next);
2580 (pTypeLibImpl->TypeInfoCount)++;
2584 TRACE("(%p)\n", pTypeLibImpl);
2585 return (ITypeLib2*) pTypeLibImpl;
2589 static BSTR TLB_MultiByteToBSTR(char *ptr)
2591 DWORD len;
2592 WCHAR *nameW;
2593 BSTR ret;
2595 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2596 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2597 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2598 ret = SysAllocString(nameW);
2599 HeapFree(GetProcessHeap(), 0, nameW);
2600 return ret;
2603 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2605 char b[3];
2606 int i;
2607 short s;
2609 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2610 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2611 return FALSE;
2614 guid->Data4[0] = s >> 8;
2615 guid->Data4[1] = s & 0xff;
2617 b[2] = '\0';
2618 for(i = 0; i < 6; i++) {
2619 memcpy(b, str + 24 + 2 * i, 2);
2620 guid->Data4[i + 2] = strtol(b, NULL, 16);
2622 return TRUE;
2625 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2627 WORD bytelen;
2628 DWORD len;
2629 WCHAR *nameW;
2631 *pBstr = NULL;
2632 bytelen = *(WORD*)ptr;
2633 if(bytelen == 0xffff) return 2;
2634 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2635 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2636 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2637 *pBstr = SysAllocStringLen(nameW, len);
2638 HeapFree(GetProcessHeap(), 0, nameW);
2639 return bytelen + 2;
2642 static WORD SLTG_ReadStringA(char *ptr, char **str)
2644 WORD bytelen;
2646 *str = NULL;
2647 bytelen = *(WORD*)ptr;
2648 if(bytelen == 0xffff) return 2;
2649 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2650 memcpy(*str, ptr + 2, bytelen);
2651 (*str)[bytelen] = '\0';
2652 return bytelen + 2;
2655 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2657 char *ptr = pLibBlk;
2658 WORD w;
2660 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2661 FIXME("libblk magic = %04x\n", w);
2662 return 0;
2665 ptr += 6;
2666 if((w = *(WORD*)ptr) != 0xffff) {
2667 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2668 ptr += w;
2670 ptr += 2;
2672 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2674 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2676 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2677 ptr += 4;
2679 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2680 ptr += 2;
2682 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2683 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2684 else
2685 pTypeLibImpl->LibAttr.lcid = 0;
2686 ptr += 2;
2688 ptr += 4; /* skip res12 */
2690 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2691 ptr += 2;
2693 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2694 ptr += 2;
2696 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2697 ptr += 2;
2699 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2700 ptr += sizeof(GUID);
2702 return ptr - (char*)pLibBlk;
2705 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD)
2707 BOOL done = FALSE;
2709 while(!done) {
2710 if((*pType & 0xe00) == 0xe00) {
2711 pTD->vt = VT_PTR;
2712 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2713 sizeof(TYPEDESC));
2714 pTD = pTD->u.lptdesc;
2716 switch(*pType & 0x3f) {
2717 case VT_PTR:
2718 pTD->vt = VT_PTR;
2719 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2720 sizeof(TYPEDESC));
2721 pTD = pTD->u.lptdesc;
2722 break;
2724 case VT_USERDEFINED:
2725 pTD->vt = VT_USERDEFINED;
2726 pTD->u.hreftype = *(++pType) / 4;
2727 done = TRUE;
2728 break;
2730 case VT_CARRAY:
2732 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2733 array */
2735 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2737 pTD->vt = VT_CARRAY;
2738 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2739 sizeof(ARRAYDESC) +
2740 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2741 pTD->u.lpadesc->cDims = pSA->cDims;
2742 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2743 pSA->cDims * sizeof(SAFEARRAYBOUND));
2745 pTD = &pTD->u.lpadesc->tdescElem;
2746 break;
2749 case VT_SAFEARRAY:
2751 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2752 useful? */
2754 pType++;
2755 pTD->vt = VT_SAFEARRAY;
2756 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2757 sizeof(TYPEDESC));
2758 pTD = pTD->u.lptdesc;
2759 break;
2761 default:
2762 pTD->vt = *pType & 0x3f;
2763 done = TRUE;
2764 break;
2766 pType++;
2768 return pType;
2771 static WORD *SLTG_DoElem(WORD *pType, char *pBlk, ELEMDESC *pElem)
2773 /* Handle [in/out] first */
2774 if((*pType & 0xc000) == 0xc000)
2775 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2776 else if(*pType & 0x8000)
2777 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2778 else if(*pType & 0x4000)
2779 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2780 else
2781 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2783 if(*pType & 0x2000)
2784 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2786 if(*pType & 0x80)
2787 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2789 return SLTG_DoType(pType, pBlk, &pElem->tdesc);
2793 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
2794 char *pNameTable)
2796 int ref;
2797 char *name;
2798 TLBRefType *ref_type;
2800 if(pRef->magic != SLTG_REF_MAGIC) {
2801 FIXME("Ref magic = %x\n", pRef->magic);
2802 return;
2804 name = ( (char*)(&pRef->names) + pRef->number);
2806 for(ref = 0; ref < pRef->number >> 3; ref++) {
2807 char *refname;
2808 unsigned int lib_offs, type_num;
2810 ref_type = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref_type));
2812 name += SLTG_ReadStringA(name, &refname);
2813 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2814 FIXME("Can't sscanf ref\n");
2815 if(lib_offs != 0xffff) {
2816 TLBImpLib **import = &pTL->pImpLibs;
2818 while(*import) {
2819 if((*import)->offset == lib_offs)
2820 break;
2821 import = &(*import)->next;
2823 if(!*import) {
2824 char fname[MAX_PATH+1];
2825 int len;
2827 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2828 sizeof(**import));
2829 (*import)->offset = lib_offs;
2830 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2831 &(*import)->guid);
2832 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
2833 &(*import)->wVersionMajor,
2834 &(*import)->wVersionMinor,
2835 &(*import)->lcid, fname) != 4) {
2836 FIXME("can't sscanf ref %s\n",
2837 pNameTable + lib_offs + 40);
2839 len = strlen(fname);
2840 if(fname[len-1] != '#')
2841 FIXME("fname = %s\n", fname);
2842 fname[len-1] = '\0';
2843 (*import)->name = TLB_MultiByteToBSTR(fname);
2845 ref_type->pImpTLInfo = *import;
2847 /* Store a reference to IDispatch */
2848 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
2849 pTL->dispatch_href = ref;
2851 } else { /* internal ref */
2852 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
2854 ref_type->reference = ref;
2855 ref_type->index = type_num;
2857 HeapFree(GetProcessHeap(), 0, refname);
2858 list_add_tail(&pTL->ref_list, &ref_type->entry);
2860 if((BYTE)*name != SLTG_REF_MAGIC)
2861 FIXME("End of ref block magic = %x\n", *name);
2862 dump_TLBRefType(pTL);
2865 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2866 BOOL OneOnly)
2868 SLTG_ImplInfo *info;
2869 TLBImplType **ppImplType = &pTI->impltypelist;
2870 /* I don't really get this structure, usually it's 0x16 bytes
2871 long, but iuser.tlb contains some that are 0x18 bytes long.
2872 That's ok because we can use the next ptr to jump to the next
2873 one. But how do we know the length of the last one? The WORD
2874 at offs 0x8 might be the clue. For now I'm just assuming that
2875 the last one is the regular 0x16 bytes. */
2877 info = (SLTG_ImplInfo*)pBlk;
2878 while(1) {
2879 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2880 sizeof(**ppImplType));
2881 (*ppImplType)->hRef = info->ref;
2882 (*ppImplType)->implflags = info->impltypeflags;
2883 pTI->TypeAttr.cImplTypes++;
2884 ppImplType = &(*ppImplType)->next;
2886 if(info->next == 0xffff)
2887 break;
2888 if(OneOnly)
2889 FIXME("Interface inheriting more than one interface\n");
2890 info = (SLTG_ImplInfo*)(pBlk + info->next);
2892 info++; /* see comment at top of function */
2893 return (char*)info;
2896 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars, char *pNameTable)
2898 TLBVarDesc **ppVarDesc = &pTI->varlist;
2899 BSTR bstrPrevName = NULL;
2900 SLTG_Variable *pItem;
2901 unsigned short i;
2902 WORD *pType;
2903 char buf[300];
2905 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
2906 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
2908 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2909 sizeof(**ppVarDesc));
2910 (*ppVarDesc)->vardesc.memid = pItem->memid;
2912 if (pItem->magic != SLTG_VAR_MAGIC &&
2913 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
2914 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
2915 return;
2918 if (pItem->name == 0xfffe)
2919 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
2920 else
2921 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2923 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
2924 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
2926 if (pItem->flags & 0x40) {
2927 TRACE_(typelib)("VAR_DISPATCH\n");
2928 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
2930 else if (pItem->flags & 0x10) {
2931 TRACE_(typelib)("VAR_CONST\n");
2932 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2933 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2934 sizeof(VARIANT));
2935 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2936 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2937 *(INT*)(pBlk + pItem->byte_offs);
2939 else {
2940 TRACE_(typelib)("VAR_PERINSTANCE\n");
2941 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2942 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2945 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
2946 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
2948 if (pItem->flags & 0x80)
2949 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
2951 if(pItem->flags & 0x02)
2952 pType = &pItem->type;
2953 else
2954 pType = (WORD*)(pBlk + pItem->type);
2956 if (pItem->flags & ~0xd2)
2957 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xd2);
2959 SLTG_DoElem(pType, pBlk,
2960 &(*ppVarDesc)->vardesc.elemdescVar);
2962 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2964 bstrPrevName = (*ppVarDesc)->Name;
2965 ppVarDesc = &((*ppVarDesc)->next);
2967 pTI->TypeAttr.cVars = cVars;
2970 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cFuncs, char *pNameTable)
2972 SLTG_Function *pFunc;
2973 unsigned short i;
2974 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2976 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
2977 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
2979 int param;
2980 WORD *pType, *pArg;
2982 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2983 sizeof(**ppFuncDesc));
2985 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
2986 case SLTG_FUNCTION_MAGIC:
2987 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
2988 break;
2989 case SLTG_DISPATCH_FUNCTION_MAGIC:
2990 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
2991 break;
2992 case SLTG_STATIC_FUNCTION_MAGIC:
2993 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
2994 break;
2995 default:
2996 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
2997 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
2998 *ppFuncDesc = NULL;
2999 return;
3001 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3003 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3004 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3005 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3006 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3007 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3008 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3010 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3011 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3013 if(pFunc->retnextopt & 0x80)
3014 pType = &pFunc->rettype;
3015 else
3016 pType = (WORD*)(pBlk + pFunc->rettype);
3018 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc);
3020 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3021 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3022 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3023 (*ppFuncDesc)->pParamDesc =
3024 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3025 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3027 pArg = (WORD*)(pBlk + pFunc->arg_off);
3029 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3030 char *paramName = pNameTable + *pArg;
3031 BOOL HaveOffs;
3032 /* If arg type follows then paramName points to the 2nd
3033 letter of the name, else the next WORD is an offset to
3034 the arg type and paramName points to the first letter.
3035 So let's take one char off paramName and see if we're
3036 pointing at an alpha-numeric char. However if *pArg is
3037 0xffff or 0xfffe then the param has no name, the former
3038 meaning that the next WORD is the type, the latter
3039 meaning the the next WORD is an offset to the type. */
3041 HaveOffs = FALSE;
3042 if(*pArg == 0xffff)
3043 paramName = NULL;
3044 else if(*pArg == 0xfffe) {
3045 paramName = NULL;
3046 HaveOffs = TRUE;
3048 else if(paramName[-1] && !isalnum(paramName[-1]))
3049 HaveOffs = TRUE;
3051 pArg++;
3053 if(HaveOffs) { /* the next word is an offset to type */
3054 pType = (WORD*)(pBlk + *pArg);
3055 SLTG_DoElem(pType, pBlk,
3056 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
3057 pArg++;
3058 } else {
3059 if(paramName)
3060 paramName--;
3061 pArg = SLTG_DoElem(pArg, pBlk,
3062 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
3065 /* Are we an optional param ? */
3066 if((*ppFuncDesc)->funcdesc.cParams - param <=
3067 (*ppFuncDesc)->funcdesc.cParamsOpt)
3068 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3070 if(paramName) {
3071 (*ppFuncDesc)->pParamDesc[param].Name =
3072 TLB_MultiByteToBSTR(paramName);
3076 ppFuncDesc = &((*ppFuncDesc)->next);
3077 if(pFunc->next == 0xffff) break;
3079 pTI->TypeAttr.cFuncs = cFuncs;
3082 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3083 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3084 SLTG_TypeInfoTail *pTITail)
3086 char *pFirstItem, *pNextItem;
3088 if(pTIHeader->href_table != 0xffffffff) {
3089 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3090 pNameTable);
3093 pFirstItem = pNextItem = pBlk;
3095 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3096 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
3101 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3102 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3103 SLTG_TypeInfoTail *pTITail)
3105 char *pFirstItem, *pNextItem;
3107 if(pTIHeader->href_table != 0xffffffff) {
3108 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3109 pNameTable);
3112 pFirstItem = pNextItem = pBlk;
3114 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3115 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
3118 if (pTITail->funcs_off != 0xffff)
3119 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3121 if (TRACE_ON(typelib))
3122 dump_TLBFuncDesc(pTI->funclist);
3125 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3126 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3127 SLTG_TypeInfoTail *pTITail)
3129 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3132 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3133 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3134 SLTG_TypeInfoTail *pTITail)
3136 WORD *pType;
3138 if (pTITail->simple_alias) {
3139 /* if simple alias, no more processing required */
3140 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3141 return;
3144 if(pTIHeader->href_table != 0xffffffff) {
3145 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3146 pNameTable);
3149 /* otherwise it is an offset to a type */
3150 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3152 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias);
3155 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3156 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3157 SLTG_TypeInfoTail *pTITail)
3159 if (pTIHeader->href_table != 0xffffffff)
3160 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3161 pNameTable);
3163 if (pTITail->vars_off != 0xffff)
3164 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3166 if (pTITail->funcs_off != 0xffff)
3167 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3169 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3170 * of dispinterface functons including the IDispatch ones, so
3171 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3172 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3174 if (TRACE_ON(typelib))
3175 dump_TLBFuncDesc(pTI->funclist);
3178 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3179 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3180 SLTG_TypeInfoTail *pTITail)
3182 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3185 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3186 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3187 SLTG_TypeInfoTail *pTITail)
3189 if (pTIHeader->href_table != 0xffffffff)
3190 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3191 pNameTable);
3193 if (pTITail->vars_off != 0xffff)
3194 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3196 if (pTITail->funcs_off != 0xffff)
3197 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3200 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3201 managable copy of it into this */
3202 typedef struct {
3203 WORD small_no;
3204 char *index_name;
3205 char *other_name;
3206 WORD res1a;
3207 WORD name_offs;
3208 WORD more_bytes;
3209 char *extra;
3210 WORD res20;
3211 DWORD helpcontext;
3212 WORD res26;
3213 GUID uuid;
3214 } SLTG_InternalOtherTypeInfo;
3216 /****************************************************************************
3217 * ITypeLib2_Constructor_SLTG
3219 * loading a SLTG typelib from an in-memory image
3221 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3223 ITypeLibImpl *pTypeLibImpl;
3224 SLTG_Header *pHeader;
3225 SLTG_BlkEntry *pBlkEntry;
3226 SLTG_Magic *pMagic;
3227 SLTG_Index *pIndex;
3228 SLTG_Pad9 *pPad9;
3229 LPVOID pBlk, pFirstBlk;
3230 SLTG_LibBlk *pLibBlk;
3231 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3232 char *pAfterOTIBlks = NULL;
3233 char *pNameTable, *ptr;
3234 int i;
3235 DWORD len, order;
3236 ITypeInfoImpl **ppTypeInfoImpl;
3238 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3241 pTypeLibImpl = TypeLibImpl_Constructor();
3242 if (!pTypeLibImpl) return NULL;
3244 pHeader = pLib;
3246 TRACE_(typelib)("header:\n");
3247 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3248 pHeader->nrOfFileBlks );
3249 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3250 FIXME("Header type magic 0x%08x not supported.\n",
3251 pHeader->SLTG_magic);
3252 return NULL;
3255 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3256 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3258 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3259 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3261 /* Next we have a magic block */
3262 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3264 /* Let's see if we're still in sync */
3265 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3266 sizeof(SLTG_COMPOBJ_MAGIC))) {
3267 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3268 return NULL;
3270 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3271 sizeof(SLTG_DIR_MAGIC))) {
3272 FIXME("dir magic = %s\n", pMagic->dir_magic);
3273 return NULL;
3276 pIndex = (SLTG_Index*)(pMagic+1);
3278 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3280 pFirstBlk = (LPVOID)(pPad9 + 1);
3282 /* We'll set up a ptr to the main library block, which is the last one. */
3284 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3285 pBlkEntry[order].next != 0;
3286 order = pBlkEntry[order].next - 1, i++) {
3287 pBlk = (char*)pBlk + pBlkEntry[order].len;
3289 pLibBlk = pBlk;
3291 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3293 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3294 interspersed */
3296 len += 0x40;
3298 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3300 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3301 sizeof(*pOtherTypeInfoBlks) *
3302 pTypeLibImpl->TypeInfoCount);
3305 ptr = (char*)pLibBlk + len;
3307 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3308 WORD w, extra;
3309 len = 0;
3311 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3313 w = *(WORD*)(ptr + 2);
3314 if(w != 0xffff) {
3315 len += w;
3316 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3317 w+1);
3318 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3319 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3321 w = *(WORD*)(ptr + 4 + len);
3322 if(w != 0xffff) {
3323 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3324 len += w;
3325 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3326 w+1);
3327 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3328 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3330 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3331 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3332 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3333 if(extra) {
3334 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3335 extra);
3336 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3337 len += extra;
3339 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3340 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3341 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3342 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3343 len += sizeof(SLTG_OtherTypeInfo);
3344 ptr += len;
3347 pAfterOTIBlks = ptr;
3349 /* Skip this WORD and get the next DWORD */
3350 len = *(DWORD*)(pAfterOTIBlks + 2);
3352 /* Now add this to pLibBLk look at what we're pointing at and
3353 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3354 dust and we should be pointing at the beginning of the name
3355 table */
3357 pNameTable = (char*)pLibBlk + len;
3359 switch(*(WORD*)pNameTable) {
3360 case 0xffff:
3361 break;
3362 case 0x0200:
3363 pNameTable += 0x20;
3364 break;
3365 default:
3366 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3367 break;
3370 pNameTable += 0x216;
3372 pNameTable += 2;
3374 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3376 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3379 /* Hopefully we now have enough ptrs set up to actually read in
3380 some TypeInfos. It's not clear which order to do them in, so
3381 I'll just follow the links along the BlkEntry chain and read
3382 them in the order in which they are in the file */
3384 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3386 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3387 pBlkEntry[order].next != 0;
3388 order = pBlkEntry[order].next - 1, i++) {
3390 SLTG_TypeInfoHeader *pTIHeader;
3391 SLTG_TypeInfoTail *pTITail;
3392 SLTG_MemberHeader *pMemHeader;
3394 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3395 pOtherTypeInfoBlks[i].index_name)) {
3396 FIXME("Index strings don't match\n");
3397 return NULL;
3400 pTIHeader = pBlk;
3401 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3402 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3403 return NULL;
3405 TRACE("pTIHeader->res06 = %x, pTIHeader->res0e = %x, pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3406 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3408 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3409 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3410 (*ppTypeInfoImpl)->index = i;
3411 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3412 pOtherTypeInfoBlks[i].name_offs +
3413 pNameTable);
3414 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3415 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3416 sizeof(GUID));
3417 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3418 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3419 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3420 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3421 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3423 if((pTIHeader->typeflags1 & 7) != 2)
3424 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3425 if(pTIHeader->typeflags3 != 2)
3426 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3428 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3429 debugstr_w((*ppTypeInfoImpl)->Name),
3430 typekind_desc[pTIHeader->typekind],
3431 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3432 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3434 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3436 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3438 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3439 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3440 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3442 switch(pTIHeader->typekind) {
3443 case TKIND_ENUM:
3444 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3445 pTIHeader, pTITail);
3446 break;
3448 case TKIND_RECORD:
3449 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3450 pTIHeader, pTITail);
3451 break;
3453 case TKIND_INTERFACE:
3454 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3455 pTIHeader, pTITail);
3456 break;
3458 case TKIND_COCLASS:
3459 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3460 pTIHeader, pTITail);
3461 break;
3463 case TKIND_ALIAS:
3464 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3465 pTIHeader, pTITail);
3466 break;
3468 case TKIND_DISPATCH:
3469 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3470 pTIHeader, pTITail);
3471 break;
3473 case TKIND_MODULE:
3474 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3475 pTIHeader, pTITail);
3476 break;
3478 default:
3479 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3480 break;
3484 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3485 but we've already set those */
3486 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3487 X(06);
3488 X(16);
3489 X(18);
3490 X(1a);
3491 X(1e);
3492 X(24);
3493 X(26);
3494 X(2a);
3495 X(2c);
3496 X(2e);
3497 X(30);
3498 X(32);
3499 X(34);
3501 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3502 pBlk = (char*)pBlk + pBlkEntry[order].len;
3505 if(i != pTypeLibImpl->TypeInfoCount) {
3506 FIXME("Somehow processed %d TypeInfos\n", i);
3507 return NULL;
3510 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3511 return (ITypeLib2*)pTypeLibImpl;
3514 /* ITypeLib::QueryInterface
3516 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3517 ITypeLib2 * iface,
3518 REFIID riid,
3519 VOID **ppvObject)
3521 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3523 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3525 *ppvObject=NULL;
3526 if(IsEqualIID(riid, &IID_IUnknown) ||
3527 IsEqualIID(riid,&IID_ITypeLib)||
3528 IsEqualIID(riid,&IID_ITypeLib2))
3530 *ppvObject = This;
3533 if(*ppvObject)
3535 ITypeLib2_AddRef(iface);
3536 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3537 return S_OK;
3539 TRACE("-- Interface: E_NOINTERFACE\n");
3540 return E_NOINTERFACE;
3543 /* ITypeLib::AddRef
3545 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3547 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3548 ULONG ref = InterlockedIncrement(&This->ref);
3550 TRACE("(%p)->ref was %u\n",This, ref - 1);
3552 return ref;
3555 /* ITypeLib::Release
3557 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3559 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3560 ULONG ref = InterlockedDecrement(&This->ref);
3562 TRACE("(%p)->(%u)\n",This, ref);
3564 if (!ref)
3566 TLBImpLib *pImpLib, *pImpLibNext;
3567 TLBCustData *pCustData, *pCustDataNext;
3568 TLBRefType *ref_type;
3569 void *cursor2;
3570 int i;
3572 /* remove cache entry */
3573 if(This->path)
3575 TRACE("removing from cache list\n");
3576 EnterCriticalSection(&cache_section);
3577 if (This->next) This->next->prev = This->prev;
3578 if (This->prev) This->prev->next = This->next;
3579 else tlb_cache_first = This->next;
3580 LeaveCriticalSection(&cache_section);
3581 HeapFree(GetProcessHeap(), 0, This->path);
3583 TRACE(" destroying ITypeLib(%p)\n",This);
3585 if (This->Name)
3587 SysFreeString(This->Name);
3588 This->Name = NULL;
3591 if (This->DocString)
3593 SysFreeString(This->DocString);
3594 This->DocString = NULL;
3597 if (This->HelpFile)
3599 SysFreeString(This->HelpFile);
3600 This->HelpFile = NULL;
3603 if (This->HelpStringDll)
3605 SysFreeString(This->HelpStringDll);
3606 This->HelpStringDll = NULL;
3609 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
3611 VariantClear(&pCustData->data);
3613 pCustDataNext = pCustData->next;
3614 TLB_Free(pCustData);
3617 for (i = 0; i < This->ctTypeDesc; i++)
3618 if (This->pTypeDesc[i].vt == VT_CARRAY)
3619 TLB_Free(This->pTypeDesc[i].u.lpadesc);
3621 TLB_Free(This->pTypeDesc);
3623 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
3625 if (pImpLib->pImpTypeLib)
3626 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
3627 TLB_Free(pImpLib->name);
3629 pImpLibNext = pImpLib->next;
3630 TLB_Free(pImpLib);
3633 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
3635 list_remove(&ref_type->entry);
3636 TLB_Free(ref_type);
3639 if (This->pTypeInfo) /* can be NULL */
3640 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3641 HeapFree(GetProcessHeap(),0,This);
3642 return 0;
3645 return ref;
3648 /* ITypeLib::GetTypeInfoCount
3650 * Returns the number of type descriptions in the type library
3652 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3654 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3655 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3656 return This->TypeInfoCount;
3659 /* ITypeLib::GetTypeInfo
3661 * retrieves the specified type description in the library.
3663 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3664 ITypeLib2 *iface,
3665 UINT index,
3666 ITypeInfo **ppTInfo)
3668 int i;
3670 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3671 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3673 TRACE("(%p)->(index=%d)\n", This, index);
3675 if (!ppTInfo) return E_INVALIDARG;
3677 /* search element n in list */
3678 for(i=0; i < index; i++)
3680 pTypeInfo = pTypeInfo->next;
3681 if (!pTypeInfo)
3683 TRACE("-- element not found\n");
3684 return TYPE_E_ELEMENTNOTFOUND;
3688 *ppTInfo = (ITypeInfo *) pTypeInfo;
3690 ITypeInfo_AddRef(*ppTInfo);
3691 TRACE("-- found (%p)\n",*ppTInfo);
3692 return S_OK;
3696 /* ITypeLibs::GetTypeInfoType
3698 * Retrieves the type of a type description.
3700 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3701 ITypeLib2 *iface,
3702 UINT index,
3703 TYPEKIND *pTKind)
3705 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3706 int i;
3707 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3709 if ((ITypeLib2_fnGetTypeInfoCount(iface) < index + 1) || (index < 0))
3710 return TYPE_E_ELEMENTNOTFOUND;
3712 TRACE("(%p) index %d\n", This, index);
3714 if(!pTKind) return E_INVALIDARG;
3716 /* search element n in list */
3717 for(i=0; i < index; i++)
3719 if(!pTInfo)
3721 TRACE("-- element not found\n");
3722 return TYPE_E_ELEMENTNOTFOUND;
3724 pTInfo = pTInfo->next;
3727 *pTKind = pTInfo->TypeAttr.typekind;
3728 TRACE("-- found Type (%d)\n", *pTKind);
3729 return S_OK;
3732 /* ITypeLib::GetTypeInfoOfGuid
3734 * Retrieves the type description that corresponds to the specified GUID.
3737 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3738 ITypeLib2 *iface,
3739 REFGUID guid,
3740 ITypeInfo **ppTInfo)
3742 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3743 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3745 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3747 if (!pTypeInfo)
3749 WARN("-- element not found\n");
3750 return TYPE_E_ELEMENTNOTFOUND;
3753 /* search linked list for guid */
3754 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3756 pTypeInfo = pTypeInfo->next;
3758 if (!pTypeInfo)
3760 /* end of list reached */
3761 WARN("-- element not found\n");
3762 return TYPE_E_ELEMENTNOTFOUND;
3766 TRACE("-- found (%p, %s)\n",
3767 pTypeInfo,
3768 debugstr_w(pTypeInfo->Name));
3770 *ppTInfo = (ITypeInfo*)pTypeInfo;
3771 ITypeInfo_AddRef(*ppTInfo);
3772 return S_OK;
3775 /* ITypeLib::GetLibAttr
3777 * Retrieves the structure that contains the library's attributes.
3780 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3781 ITypeLib2 *iface,
3782 LPTLIBATTR *ppTLibAttr)
3784 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3785 TRACE("(%p)\n",This);
3786 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3787 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3788 return S_OK;
3791 /* ITypeLib::GetTypeComp
3793 * Enables a client compiler to bind to a library's types, variables,
3794 * constants, and global functions.
3797 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3798 ITypeLib2 *iface,
3799 ITypeComp **ppTComp)
3801 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3803 TRACE("(%p)->(%p)\n",This,ppTComp);
3804 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3805 ITypeComp_AddRef(*ppTComp);
3807 return S_OK;
3810 /* ITypeLib::GetDocumentation
3812 * Retrieves the library's documentation string, the complete Help file name
3813 * and path, and the context identifier for the library Help topic in the Help
3814 * file.
3816 * On a successful return all non-null BSTR pointers will have been set,
3817 * possibly to NULL.
3819 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3820 ITypeLib2 *iface,
3821 INT index,
3822 BSTR *pBstrName,
3823 BSTR *pBstrDocString,
3824 DWORD *pdwHelpContext,
3825 BSTR *pBstrHelpFile)
3827 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3829 HRESULT result = E_INVALIDARG;
3831 ITypeInfo *pTInfo;
3834 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3835 This, index,
3836 pBstrName, pBstrDocString,
3837 pdwHelpContext, pBstrHelpFile);
3839 if(index<0)
3841 /* documentation for the typelib */
3842 if(pBstrName)
3844 if (This->Name)
3846 if(!(*pBstrName = SysAllocString(This->Name)))
3847 goto memerr1;
3849 else
3850 *pBstrName = NULL;
3852 if(pBstrDocString)
3854 if (This->DocString)
3856 if(!(*pBstrDocString = SysAllocString(This->DocString)))
3857 goto memerr2;
3859 else if (This->Name)
3861 if(!(*pBstrDocString = SysAllocString(This->Name)))
3862 goto memerr2;
3864 else
3865 *pBstrDocString = NULL;
3867 if(pdwHelpContext)
3869 *pdwHelpContext = This->dwHelpContext;
3871 if(pBstrHelpFile)
3873 if (This->HelpFile)
3875 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
3876 goto memerr3;
3878 else
3879 *pBstrHelpFile = NULL;
3882 result = S_OK;
3884 else
3886 /* for a typeinfo */
3887 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3889 if(SUCCEEDED(result))
3891 result = ITypeInfo_GetDocumentation(pTInfo,
3892 MEMBERID_NIL,
3893 pBstrName,
3894 pBstrDocString,
3895 pdwHelpContext, pBstrHelpFile);
3897 ITypeInfo_Release(pTInfo);
3900 return result;
3901 memerr3:
3902 if (pBstrDocString) SysFreeString (*pBstrDocString);
3903 memerr2:
3904 if (pBstrName) SysFreeString (*pBstrName);
3905 memerr1:
3906 return STG_E_INSUFFICIENTMEMORY;
3909 /* ITypeLib::IsName
3911 * Indicates whether a passed-in string contains the name of a type or member
3912 * described in the library.
3915 static HRESULT WINAPI ITypeLib2_fnIsName(
3916 ITypeLib2 *iface,
3917 LPOLESTR szNameBuf,
3918 ULONG lHashVal,
3919 BOOL *pfName)
3921 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3922 ITypeInfoImpl *pTInfo;
3923 TLBFuncDesc *pFInfo;
3924 TLBVarDesc *pVInfo;
3925 int i;
3926 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3928 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3929 pfName);
3931 *pfName=TRUE;
3932 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3933 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3934 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3935 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3936 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3937 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3938 goto ITypeLib2_fnIsName_exit;
3940 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3941 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3944 *pfName=FALSE;
3946 ITypeLib2_fnIsName_exit:
3947 TRACE("(%p)slow! search for %s: %s found!\n", This,
3948 debugstr_w(szNameBuf), *pfName?"NOT":"");
3950 return S_OK;
3953 /* ITypeLib::FindName
3955 * Finds occurrences of a type description in a type library. This may be used
3956 * to quickly verify that a name exists in a type library.
3959 static HRESULT WINAPI ITypeLib2_fnFindName(
3960 ITypeLib2 *iface,
3961 LPOLESTR szNameBuf,
3962 ULONG lHashVal,
3963 ITypeInfo **ppTInfo,
3964 MEMBERID *rgMemId,
3965 UINT16 *pcFound)
3967 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3968 ITypeInfoImpl *pTInfo;
3969 TLBFuncDesc *pFInfo;
3970 TLBVarDesc *pVInfo;
3971 int i,j = 0;
3972 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3974 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3975 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3976 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3977 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3978 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
3979 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3980 goto ITypeLib2_fnFindName_exit;
3983 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3984 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3985 continue;
3986 ITypeLib2_fnFindName_exit:
3987 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3988 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3989 j++;
3991 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3992 This, *pcFound, debugstr_w(szNameBuf), j);
3994 *pcFound=j;
3996 return S_OK;
3999 /* ITypeLib::ReleaseTLibAttr
4001 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4004 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4005 ITypeLib2 *iface,
4006 TLIBATTR *pTLibAttr)
4008 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4009 TRACE("freeing (%p)\n",This);
4010 HeapFree(GetProcessHeap(),0,pTLibAttr);
4014 /* ITypeLib2::GetCustData
4016 * gets the custom data
4018 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4019 ITypeLib2 * iface,
4020 REFGUID guid,
4021 VARIANT *pVarVal)
4023 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4024 TLBCustData *pCData;
4026 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4028 if( IsEqualIID(guid, &pCData->guid)) break;
4031 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4033 if(pCData)
4035 VariantInit( pVarVal);
4036 VariantCopy( pVarVal, &pCData->data);
4037 return S_OK;
4039 return E_INVALIDARG; /* FIXME: correct? */
4042 /* ITypeLib2::GetLibStatistics
4044 * Returns statistics about a type library that are required for efficient
4045 * sizing of hash tables.
4048 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4049 ITypeLib2 * iface,
4050 ULONG *pcUniqueNames,
4051 ULONG *pcchUniqueNames)
4053 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4055 FIXME("(%p): stub!\n", This);
4057 if(pcUniqueNames) *pcUniqueNames=1;
4058 if(pcchUniqueNames) *pcchUniqueNames=1;
4059 return S_OK;
4062 /* ITypeLib2::GetDocumentation2
4064 * Retrieves the library's documentation string, the complete Help file name
4065 * and path, the localization context to use, and the context ID for the
4066 * library Help topic in the Help file.
4069 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4070 ITypeLib2 * iface,
4071 INT index,
4072 LCID lcid,
4073 BSTR *pbstrHelpString,
4074 DWORD *pdwHelpStringContext,
4075 BSTR *pbstrHelpStringDll)
4077 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4078 HRESULT result;
4079 ITypeInfo *pTInfo;
4081 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4083 /* the help string should be obtained from the helpstringdll,
4084 * using the _DLLGetDocumentation function, based on the supplied
4085 * lcid. Nice to do sometime...
4087 if(index<0)
4089 /* documentation for the typelib */
4090 if(pbstrHelpString)
4091 *pbstrHelpString=SysAllocString(This->DocString);
4092 if(pdwHelpStringContext)
4093 *pdwHelpStringContext=This->dwHelpContext;
4094 if(pbstrHelpStringDll)
4095 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4097 result = S_OK;
4099 else
4101 /* for a typeinfo */
4102 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4104 if(SUCCEEDED(result))
4106 ITypeInfo2 * pTInfo2;
4107 result = ITypeInfo_QueryInterface(pTInfo,
4108 &IID_ITypeInfo2,
4109 (LPVOID*) &pTInfo2);
4111 if(SUCCEEDED(result))
4113 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4114 MEMBERID_NIL,
4115 lcid,
4116 pbstrHelpString,
4117 pdwHelpStringContext,
4118 pbstrHelpStringDll);
4120 ITypeInfo2_Release(pTInfo2);
4123 ITypeInfo_Release(pTInfo);
4126 return result;
4129 /* ITypeLib2::GetAllCustData
4131 * Gets all custom data items for the library.
4134 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4135 ITypeLib2 * iface,
4136 CUSTDATA *pCustData)
4138 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4139 TLBCustData *pCData;
4140 int i;
4141 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4142 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4143 if(pCustData->prgCustData ){
4144 pCustData->cCustData=This->ctCustData;
4145 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4146 pCustData->prgCustData[i].guid=pCData->guid;
4147 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4149 }else{
4150 ERR(" OUT OF MEMORY!\n");
4151 return E_OUTOFMEMORY;
4153 return S_OK;
4156 static const ITypeLib2Vtbl tlbvt = {
4157 ITypeLib2_fnQueryInterface,
4158 ITypeLib2_fnAddRef,
4159 ITypeLib2_fnRelease,
4160 ITypeLib2_fnGetTypeInfoCount,
4161 ITypeLib2_fnGetTypeInfo,
4162 ITypeLib2_fnGetTypeInfoType,
4163 ITypeLib2_fnGetTypeInfoOfGuid,
4164 ITypeLib2_fnGetLibAttr,
4165 ITypeLib2_fnGetTypeComp,
4166 ITypeLib2_fnGetDocumentation,
4167 ITypeLib2_fnIsName,
4168 ITypeLib2_fnFindName,
4169 ITypeLib2_fnReleaseTLibAttr,
4171 ITypeLib2_fnGetCustData,
4172 ITypeLib2_fnGetLibStatistics,
4173 ITypeLib2_fnGetDocumentation2,
4174 ITypeLib2_fnGetAllCustData
4178 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4180 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4182 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4185 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4187 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4189 return ITypeLib2_AddRef((ITypeLib2 *)This);
4192 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4194 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4196 return ITypeLib2_Release((ITypeLib2 *)This);
4199 static HRESULT WINAPI ITypeLibComp_fnBind(
4200 ITypeComp * iface,
4201 OLECHAR * szName,
4202 ULONG lHash,
4203 WORD wFlags,
4204 ITypeInfo ** ppTInfo,
4205 DESCKIND * pDescKind,
4206 BINDPTR * pBindPtr)
4208 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4209 ITypeInfoImpl *pTypeInfo;
4211 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4213 *pDescKind = DESCKIND_NONE;
4214 pBindPtr->lptcomp = NULL;
4215 *ppTInfo = NULL;
4217 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4219 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4221 /* FIXME: check wFlags here? */
4222 /* FIXME: we should use a hash table to look this info up using lHash
4223 * instead of an O(n) search */
4224 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4225 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4227 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4229 *pDescKind = DESCKIND_TYPECOMP;
4230 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4231 ITypeComp_AddRef(pBindPtr->lptcomp);
4232 TRACE("module or enum: %s\n", debugstr_w(szName));
4233 return S_OK;
4237 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4238 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4240 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4241 HRESULT hr;
4243 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4244 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4246 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4247 return S_OK;
4251 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4252 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4254 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4255 HRESULT hr;
4256 ITypeInfo *subtypeinfo;
4257 BINDPTR subbindptr;
4258 DESCKIND subdesckind;
4260 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4261 &subtypeinfo, &subdesckind, &subbindptr);
4262 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4264 TYPEDESC tdesc_appobject =
4267 (TYPEDESC *)pTypeInfo->hreftype
4269 VT_USERDEFINED
4271 const VARDESC vardesc_appobject =
4273 -2, /* memid */
4274 NULL, /* lpstrSchema */
4276 0 /* oInst */
4279 /* ELEMDESC */
4281 /* TYPEDESC */
4283 &tdesc_appobject
4285 VT_PTR
4288 0, /* wVarFlags */
4289 VAR_STATIC /* varkind */
4292 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4294 /* cleanup things filled in by Bind call so we can put our
4295 * application object data in there instead */
4296 switch (subdesckind)
4298 case DESCKIND_FUNCDESC:
4299 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4300 break;
4301 case DESCKIND_VARDESC:
4302 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4303 break;
4304 default:
4305 break;
4307 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4309 if (pTypeInfo->hreftype == -1)
4310 FIXME("no hreftype for interface %p\n", pTypeInfo);
4312 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4313 if (FAILED(hr))
4314 return hr;
4316 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4317 *ppTInfo = (ITypeInfo *)pTypeInfo;
4318 ITypeInfo_AddRef(*ppTInfo);
4319 return S_OK;
4324 TRACE("name not found %s\n", debugstr_w(szName));
4325 return S_OK;
4328 static HRESULT WINAPI ITypeLibComp_fnBindType(
4329 ITypeComp * iface,
4330 OLECHAR * szName,
4331 ULONG lHash,
4332 ITypeInfo ** ppTInfo,
4333 ITypeComp ** ppTComp)
4335 FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4336 return E_NOTIMPL;
4339 static const ITypeCompVtbl tlbtcvt =
4342 ITypeLibComp_fnQueryInterface,
4343 ITypeLibComp_fnAddRef,
4344 ITypeLibComp_fnRelease,
4346 ITypeLibComp_fnBind,
4347 ITypeLibComp_fnBindType
4350 /*================== ITypeInfo(2) Methods ===================================*/
4351 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4353 ITypeInfoImpl * pTypeInfoImpl;
4355 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4356 if (pTypeInfoImpl)
4358 pTypeInfoImpl->lpVtbl = &tinfvt;
4359 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4360 pTypeInfoImpl->ref=1;
4361 pTypeInfoImpl->hreftype = -1;
4362 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4363 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4365 TRACE("(%p)\n", pTypeInfoImpl);
4366 return (ITypeInfo2*) pTypeInfoImpl;
4369 /* ITypeInfo::QueryInterface
4371 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4372 ITypeInfo2 *iface,
4373 REFIID riid,
4374 VOID **ppvObject)
4376 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4378 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4380 *ppvObject=NULL;
4381 if(IsEqualIID(riid, &IID_IUnknown) ||
4382 IsEqualIID(riid,&IID_ITypeInfo)||
4383 IsEqualIID(riid,&IID_ITypeInfo2))
4384 *ppvObject = This;
4386 if(*ppvObject){
4387 ITypeInfo_AddRef(iface);
4388 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4389 return S_OK;
4391 TRACE("-- Interface: E_NOINTERFACE\n");
4392 return E_NOINTERFACE;
4395 /* ITypeInfo::AddRef
4397 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4399 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4400 ULONG ref = InterlockedIncrement(&This->ref);
4402 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4404 TRACE("(%p)->ref is %u\n",This, ref);
4405 return ref;
4408 /* ITypeInfo::Release
4410 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4412 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4413 ULONG ref = InterlockedDecrement(&This->ref);
4415 TRACE("(%p)->(%u)\n",This, ref);
4417 if (ref) {
4418 /* We don't release ITypeLib when ref=0 because
4419 it means that function is called by ITypeLib2_Release */
4420 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4421 } else {
4422 TLBFuncDesc *pFInfo, *pFInfoNext;
4423 TLBVarDesc *pVInfo, *pVInfoNext;
4424 TLBImplType *pImpl, *pImplNext;
4425 TLBCustData *pCustData, *pCustDataNext;
4427 TRACE("destroying ITypeInfo(%p)\n",This);
4429 if (This->no_free_data)
4430 goto finish_free;
4432 if (This->Name)
4434 SysFreeString(This->Name);
4435 This->Name = 0;
4438 if (This->DocString)
4440 SysFreeString(This->DocString);
4441 This->DocString = 0;
4444 if (This->DllName)
4446 SysFreeString(This->DllName);
4447 This->DllName = 0;
4450 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4452 UINT i;
4453 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4455 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4456 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4458 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4459 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4461 SysFreeString(pFInfo->pParamDesc[i].Name);
4463 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4464 TLB_Free(pFInfo->pParamDesc);
4465 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
4467 VariantClear(&pCustData->data);
4469 pCustDataNext = pCustData->next;
4470 TLB_Free(pCustData);
4472 if (HIWORD(pFInfo->Entry) != 0 && pFInfo->Entry != (BSTR)-1)
4473 SysFreeString(pFInfo->Entry);
4474 SysFreeString(pFInfo->HelpString);
4475 SysFreeString(pFInfo->Name);
4477 pFInfoNext = pFInfo->next;
4478 TLB_Free(pFInfo);
4480 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
4482 if (pVInfo->vardesc.varkind == VAR_CONST)
4484 VariantClear(pVInfo->vardesc.u.lpvarValue);
4485 TLB_Free(pVInfo->vardesc.u.lpvarValue);
4487 SysFreeString(pVInfo->Name);
4488 pVInfoNext = pVInfo->next;
4489 TLB_Free(pVInfo);
4491 for(pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
4493 for (pCustData = pImpl->pCustData; pCustData; pCustData = pCustDataNext)
4495 VariantClear(&pCustData->data);
4497 pCustDataNext = pCustData->next;
4498 TLB_Free(pCustData);
4500 pImplNext = pImpl->next;
4501 TLB_Free(pImpl);
4503 TLB_Free(This->pCustData);
4505 finish_free:
4506 if (This->next)
4508 ITypeInfo_Release((ITypeInfo*)This->next);
4511 HeapFree(GetProcessHeap(),0,This);
4512 return 0;
4514 return ref;
4517 /* ITypeInfo::GetTypeAttr
4519 * Retrieves a TYPEATTR structure that contains the attributes of the type
4520 * description.
4523 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4524 LPTYPEATTR *ppTypeAttr)
4526 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4527 SIZE_T size;
4529 TRACE("(%p)\n",This);
4531 size = sizeof(**ppTypeAttr);
4532 if (This->TypeAttr.typekind == TKIND_ALIAS)
4533 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4535 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4536 if (!*ppTypeAttr)
4537 return E_OUTOFMEMORY;
4539 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4541 if (This->TypeAttr.typekind == TKIND_ALIAS)
4542 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4543 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4545 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4546 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4547 funcs */
4548 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4549 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4551 return S_OK;
4554 /* ITypeInfo::GetTypeComp
4556 * Retrieves the ITypeComp interface for the type description, which enables a
4557 * client compiler to bind to the type description's members.
4560 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4561 ITypeComp * *ppTComp)
4563 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4565 TRACE("(%p)->(%p)\n", This, ppTComp);
4567 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4568 ITypeComp_AddRef(*ppTComp);
4569 return S_OK;
4572 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4574 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4575 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4576 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4577 return size;
4580 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4582 memcpy(dest, src, sizeof(ELEMDESC));
4583 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4584 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4586 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4587 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4588 *buffer += sizeof(PARAMDESCEX);
4589 memcpy(pparamdescex_dest, pparamdescex_src, sizeof(PARAMDESCEX));
4590 VariantInit(&pparamdescex_dest->varDefaultValue);
4591 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4592 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4594 else
4595 dest->u.paramdesc.pparamdescex = NULL;
4596 return S_OK;
4599 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4601 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4602 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4605 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4607 FUNCDESC *dest;
4608 char *buffer;
4609 SIZE_T size = sizeof(*src);
4610 SHORT i;
4611 HRESULT hr;
4613 size += sizeof(*src->lprgscode) * src->cScodes;
4614 size += TLB_SizeElemDesc(&src->elemdescFunc);
4615 for (i = 0; i < src->cParams; i++)
4617 size += sizeof(ELEMDESC);
4618 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4621 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4622 if (!dest) return E_OUTOFMEMORY;
4624 memcpy(dest, src, sizeof(FUNCDESC));
4625 buffer = (char *)(dest + 1);
4627 dest->lprgscode = (SCODE *)buffer;
4628 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4629 buffer += sizeof(*src->lprgscode) * src->cScodes;
4631 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4632 if (FAILED(hr))
4634 SysFreeString((BSTR)dest);
4635 return hr;
4638 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4639 buffer += sizeof(ELEMDESC) * src->cParams;
4640 for (i = 0; i < src->cParams; i++)
4642 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4643 if (FAILED(hr))
4644 break;
4646 if (FAILED(hr))
4648 /* undo the above actions */
4649 for (i = i - 1; i >= 0; i--)
4650 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4651 TLB_FreeElemDesc(&dest->elemdescFunc);
4652 SysFreeString((BSTR)dest);
4653 return hr;
4656 /* special treatment for dispinterfaces: this makes functions appear
4657 * to return their [retval] value when it is really returning an
4658 * HRESULT */
4659 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4661 if (dest->cParams &&
4662 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4664 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4665 if (elemdesc->tdesc.vt != VT_PTR)
4667 ERR("elemdesc should have started with VT_PTR instead of:\n");
4668 if (ERR_ON(ole))
4669 dump_ELEMDESC(elemdesc);
4670 return E_UNEXPECTED;
4673 /* copy last parameter to the return value. we are using a flat
4674 * buffer so there is no danger of leaking memory in
4675 * elemdescFunc */
4676 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4678 /* remove the last parameter */
4679 dest->cParams--;
4681 else
4682 /* otherwise this function is made to appear to have no return
4683 * value */
4684 dest->elemdescFunc.tdesc.vt = VT_VOID;
4688 *dest_ptr = dest;
4689 return S_OK;
4692 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4694 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4695 const TLBFuncDesc *pFDesc;
4696 int i;
4698 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4701 if (pFDesc)
4703 *ppFuncDesc = &pFDesc->funcdesc;
4704 return S_OK;
4707 return TYPE_E_ELEMENTNOTFOUND;
4710 /* internal function to make the inherited interfaces' methods appear
4711 * part of the interface */
4712 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
4713 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs)
4715 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4716 HRESULT hr;
4717 UINT implemented_funcs = 0;
4719 if (funcs)
4720 *funcs = 0;
4722 if(This->impltypelist)
4724 ITypeInfo *pSubTypeInfo;
4725 UINT sub_funcs;
4727 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
4728 if (FAILED(hr))
4729 return hr;
4731 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
4732 index,
4733 ppFuncDesc,
4734 &sub_funcs);
4735 implemented_funcs += sub_funcs;
4736 ITypeInfo_Release(pSubTypeInfo);
4737 if (SUCCEEDED(hr))
4738 return hr;
4741 if (funcs)
4742 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
4744 if (index < implemented_funcs)
4745 return E_INVALIDARG;
4746 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
4747 ppFuncDesc);
4750 /* ITypeInfo::GetFuncDesc
4752 * Retrieves the FUNCDESC structure that contains information about a
4753 * specified function.
4756 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4757 LPFUNCDESC *ppFuncDesc)
4759 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4760 const FUNCDESC *internal_funcdesc;
4761 HRESULT hr;
4763 TRACE("(%p) index %d\n", This, index);
4765 if (This->TypeAttr.typekind == TKIND_DISPATCH)
4766 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
4767 &internal_funcdesc, NULL);
4768 else
4769 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
4770 &internal_funcdesc);
4771 if (FAILED(hr))
4773 WARN("description for function %d not found\n", index);
4774 return hr;
4777 return TLB_AllocAndInitFuncDesc(
4778 internal_funcdesc,
4779 ppFuncDesc,
4780 This->TypeAttr.typekind == TKIND_DISPATCH);
4783 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
4785 VARDESC *dest;
4786 char *buffer;
4787 SIZE_T size = sizeof(*src);
4788 HRESULT hr;
4790 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
4791 if (src->varkind == VAR_CONST)
4792 size += sizeof(VARIANT);
4793 size += TLB_SizeElemDesc(&src->elemdescVar);
4795 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
4796 if (!dest) return E_OUTOFMEMORY;
4798 *dest = *src;
4799 buffer = (char *)(dest + 1);
4800 if (src->lpstrSchema)
4802 int len;
4803 dest->lpstrSchema = (LPOLESTR)buffer;
4804 len = strlenW(src->lpstrSchema);
4805 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
4806 buffer += (len + 1) * sizeof(WCHAR);
4809 if (src->varkind == VAR_CONST)
4811 HRESULT hr;
4813 dest->u.lpvarValue = (VARIANT *)buffer;
4814 *dest->u.lpvarValue = *src->u.lpvarValue;
4815 buffer += sizeof(VARIANT);
4816 VariantInit(dest->u.lpvarValue);
4817 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
4818 if (FAILED(hr))
4820 SysFreeString((BSTR)dest_ptr);
4821 return hr;
4824 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
4825 if (FAILED(hr))
4827 if (src->varkind == VAR_CONST)
4828 VariantClear(dest->u.lpvarValue);
4829 SysFreeString((BSTR)dest);
4830 return hr;
4832 *dest_ptr = dest;
4833 return S_OK;
4836 /* ITypeInfo::GetVarDesc
4838 * Retrieves a VARDESC structure that describes the specified variable.
4841 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4842 LPVARDESC *ppVarDesc)
4844 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4845 int i;
4846 const TLBVarDesc *pVDesc;
4848 TRACE("(%p) index %d\n", This, index);
4850 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4853 if (pVDesc)
4854 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
4856 return E_INVALIDARG;
4859 /* ITypeInfo_GetNames
4861 * Retrieves the variable with the specified member ID (or the name of the
4862 * property or method and its parameters) that correspond to the specified
4863 * function ID.
4865 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4866 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4868 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4869 const TLBFuncDesc *pFDesc;
4870 const TLBVarDesc *pVDesc;
4871 int i;
4872 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
4873 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4874 if(pFDesc)
4876 /* function found, now return function and parameter names */
4877 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4879 if(!i)
4880 *rgBstrNames=SysAllocString(pFDesc->Name);
4881 else
4882 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4884 *pcNames=i;
4886 else
4888 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4889 if(pVDesc)
4891 *rgBstrNames=SysAllocString(pVDesc->Name);
4892 *pcNames=1;
4894 else
4896 if(This->impltypelist &&
4897 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4898 /* recursive search */
4899 ITypeInfo *pTInfo;
4900 HRESULT result;
4901 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4902 &pTInfo);
4903 if(SUCCEEDED(result))
4905 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4906 ITypeInfo_Release(pTInfo);
4907 return result;
4909 WARN("Could not search inherited interface!\n");
4911 else
4913 WARN("no names found\n");
4915 *pcNames=0;
4916 return TYPE_E_ELEMENTNOTFOUND;
4919 return S_OK;
4923 /* ITypeInfo::GetRefTypeOfImplType
4925 * If a type description describes a COM class, it retrieves the type
4926 * description of the implemented interface types. For an interface,
4927 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4928 * if any exist.
4931 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4932 ITypeInfo2 *iface,
4933 UINT index,
4934 HREFTYPE *pRefType)
4936 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4937 int i;
4938 HRESULT hr = S_OK;
4939 const TLBImplType *pImpl = This->impltypelist;
4941 TRACE("(%p) index %d\n", This, index);
4942 if (TRACE_ON(ole)) dump_TypeInfo(This);
4944 if(index==(UINT)-1)
4946 /* only valid on dual interfaces;
4947 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4949 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4951 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4952 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4954 *pRefType = -1;
4956 else
4958 hr = TYPE_E_ELEMENTNOTFOUND;
4961 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
4963 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
4964 *pRefType = This->pTypeLib->dispatch_href;
4966 else
4968 /* get element n from linked list */
4969 for(i=0; pImpl && i<index; i++)
4971 pImpl = pImpl->next;
4974 if (pImpl)
4975 *pRefType = pImpl->hRef;
4976 else
4977 hr = TYPE_E_ELEMENTNOTFOUND;
4980 if(TRACE_ON(ole))
4982 if(SUCCEEDED(hr))
4983 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
4984 else
4985 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
4988 return hr;
4991 /* ITypeInfo::GetImplTypeFlags
4993 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4994 * or base interface in a type description.
4996 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4997 UINT index, INT *pImplTypeFlags)
4999 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5000 int i;
5001 TLBImplType *pImpl;
5003 TRACE("(%p) index %d\n", This, index);
5004 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5005 i++, pImpl=pImpl->next)
5007 if(i==index && pImpl){
5008 *pImplTypeFlags=pImpl->implflags;
5009 return S_OK;
5011 *pImplTypeFlags=0;
5012 return TYPE_E_ELEMENTNOTFOUND;
5015 /* GetIDsOfNames
5016 * Maps between member names and member IDs, and parameter names and
5017 * parameter IDs.
5019 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5020 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5022 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5023 const TLBFuncDesc *pFDesc;
5024 const TLBVarDesc *pVDesc;
5025 HRESULT ret=S_OK;
5026 int i;
5028 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5029 cNames);
5031 /* init out parameters in case of failure */
5032 for (i = 0; i < cNames; i++)
5033 pMemId[i] = MEMBERID_NIL;
5035 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5036 int j;
5037 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5038 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5039 for(i=1; i < cNames; i++){
5040 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5041 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5042 break;
5043 if( j<pFDesc->funcdesc.cParams)
5044 pMemId[i]=j;
5045 else
5046 ret=DISP_E_UNKNOWNNAME;
5048 TRACE("-- 0x%08x\n", ret);
5049 return ret;
5052 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5053 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5054 if(cNames) *pMemId=pVDesc->vardesc.memid;
5055 return ret;
5058 /* not found, see if it can be found in an inherited interface */
5059 if(This->impltypelist) {
5060 /* recursive search */
5061 ITypeInfo *pTInfo;
5062 ret=ITypeInfo_GetRefTypeInfo(iface,
5063 This->impltypelist->hRef, &pTInfo);
5064 if(SUCCEEDED(ret)){
5065 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5066 ITypeInfo_Release(pTInfo);
5067 return ret;
5069 WARN("Could not search inherited interface!\n");
5070 } else
5071 WARN("no names found\n");
5072 return DISP_E_UNKNOWNNAME;
5075 /* ITypeInfo::Invoke
5077 * Invokes a method, or accesses a property of an object, that implements the
5078 * interface described by the type description.
5080 DWORD
5081 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5082 DWORD res;
5084 if (TRACE_ON(ole)) {
5085 int i;
5086 TRACE("Calling %p(",func);
5087 for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
5088 TRACE(")\n");
5091 switch (callconv) {
5092 case CC_STDCALL:
5094 switch (nrargs) {
5095 case 0:
5096 res = func();
5097 break;
5098 case 1:
5099 res = func(args[0]);
5100 break;
5101 case 2:
5102 res = func(args[0],args[1]);
5103 break;
5104 case 3:
5105 res = func(args[0],args[1],args[2]);
5106 break;
5107 case 4:
5108 res = func(args[0],args[1],args[2],args[3]);
5109 break;
5110 case 5:
5111 res = func(args[0],args[1],args[2],args[3],args[4]);
5112 break;
5113 case 6:
5114 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
5115 break;
5116 case 7:
5117 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
5118 break;
5119 case 8:
5120 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
5121 break;
5122 case 9:
5123 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
5124 break;
5125 case 10:
5126 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
5127 break;
5128 case 11:
5129 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
5130 break;
5131 case 12:
5132 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11]);
5133 break;
5134 case 13:
5135 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12]);
5136 break;
5137 case 14:
5138 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13]);
5139 break;
5140 case 15:
5141 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14]);
5142 break;
5143 case 16:
5144 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15]);
5145 break;
5146 case 17:
5147 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16]);
5148 break;
5149 case 18:
5150 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17]);
5151 break;
5152 case 19:
5153 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18]);
5154 break;
5155 case 20:
5156 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19]);
5157 break;
5158 case 21:
5159 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20]);
5160 break;
5161 case 22:
5162 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21]);
5163 break;
5164 case 23:
5165 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22]);
5166 break;
5167 default:
5168 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
5169 res = -1;
5170 break;
5172 break;
5173 default:
5174 FIXME("unsupported calling convention %d\n",callconv);
5175 res = -1;
5176 break;
5178 TRACE("returns %08x\n",res);
5179 return res;
5182 extern int _argsize(DWORD vt);
5184 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5186 HRESULT hr = S_OK;
5187 ITypeInfo *tinfo2 = NULL;
5188 TYPEATTR *tattr = NULL;
5190 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5191 if (hr)
5193 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5194 "hr = 0x%08x\n",
5195 tdesc->u.hreftype, hr);
5196 return hr;
5198 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5199 if (hr)
5201 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5202 ITypeInfo_Release(tinfo2);
5203 return hr;
5206 switch (tattr->typekind)
5208 case TKIND_ENUM:
5209 *vt |= VT_I4;
5210 break;
5212 case TKIND_ALIAS:
5213 tdesc = &tattr->tdescAlias;
5214 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5215 break;
5217 case TKIND_INTERFACE:
5218 if (IsEqualIID(&IID_IDispatch, &tattr->guid))
5219 *vt |= VT_DISPATCH;
5220 else
5221 *vt |= VT_UNKNOWN;
5222 break;
5224 case TKIND_DISPATCH:
5225 *vt |= VT_DISPATCH;
5226 break;
5228 case TKIND_COCLASS:
5229 *vt |= VT_DISPATCH;
5230 break;
5232 case TKIND_RECORD:
5233 FIXME("TKIND_RECORD unhandled.\n");
5234 hr = E_NOTIMPL;
5235 break;
5237 case TKIND_UNION:
5238 FIXME("TKIND_UNION unhandled.\n");
5239 hr = E_NOTIMPL;
5240 break;
5242 default:
5243 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5244 hr = E_NOTIMPL;
5245 break;
5247 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5248 ITypeInfo_Release(tinfo2);
5249 return hr;
5252 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5254 HRESULT hr = S_OK;
5256 /* enforce only one level of pointer indirection */
5257 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5259 tdesc = tdesc->u.lptdesc;
5261 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5262 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5263 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5264 if ((tdesc->vt == VT_USERDEFINED) ||
5265 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5267 VARTYPE vt_userdefined = 0;
5268 const TYPEDESC *tdesc_userdefined = tdesc;
5269 if (tdesc->vt == VT_PTR)
5271 vt_userdefined = VT_BYREF;
5272 tdesc_userdefined = tdesc->u.lptdesc;
5274 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5275 if ((hr == S_OK) &&
5276 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5277 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5279 *vt |= vt_userdefined;
5280 return S_OK;
5283 *vt = VT_BYREF;
5286 switch (tdesc->vt)
5288 case VT_HRESULT:
5289 *vt |= VT_ERROR;
5290 break;
5291 case VT_USERDEFINED:
5292 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5293 break;
5294 case VT_VOID:
5295 case VT_CARRAY:
5296 case VT_PTR:
5297 case VT_LPSTR:
5298 case VT_LPWSTR:
5299 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5300 hr = DISP_E_BADVARTYPE;
5301 break;
5302 case VT_SAFEARRAY:
5303 *vt |= VT_ARRAY;
5304 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5305 break;
5306 default:
5307 *vt |= tdesc->vt;
5308 break;
5310 return hr;
5313 /***********************************************************************
5314 * DispCallFunc (OLEAUT32.@)
5316 * Invokes a function of the specifed calling convention, passing the
5317 * specified arguments and returns the result.
5319 * PARAMS
5320 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5321 * oVft [I] The offset in the vtable. See notes.
5322 * cc [I] Calling convention of the function to call.
5323 * vtReturn [I] The return type of the function.
5324 * cActuals [I] Number of parameters.
5325 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5326 * prgpvarg [I] The arguments to pass.
5327 * pvargResult [O] The return value of the function. Can be NULL.
5329 * RETURNS
5330 * Success: S_OK.
5331 * Failure: HRESULT code.
5333 * NOTES
5334 * The HRESULT return value of this function is not affected by the return
5335 * value of the user supplied function, which is returned in pvargResult.
5337 * If pvInstance is NULL then a non-object function is to be called and oVft
5338 * is the address of the function to call.
5340 * The cc parameter can be one of the following values:
5341 *|CC_FASTCALL
5342 *|CC_CDECL
5343 *|CC_PASCAL
5344 *|CC_STDCALL
5345 *|CC_FPFASTCALL
5346 *|CC_SYSCALL
5347 *|CC_MPWCDECL
5348 *|CC_MPWPASCAL
5351 HRESULT WINAPI
5352 DispCallFunc(
5353 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5354 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5356 int i, argsize, argspos;
5357 DWORD *args;
5358 HRESULT hres;
5360 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5361 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5362 pvargResult, V_VT(pvargResult));
5364 argsize = 0;
5365 if (pvInstance)
5366 argsize++; /* for This pointer */
5368 for (i=0;i<cActuals;i++)
5370 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5371 dump_Variant(prgpvarg[i]);
5372 argsize += _argsize(prgvt[i]);
5374 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5376 argspos = 0;
5377 if (pvInstance)
5379 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5380 argspos++;
5383 for (i=0;i<cActuals;i++)
5385 VARIANT *arg = prgpvarg[i];
5386 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5387 if (prgvt[i] == VT_VARIANT)
5388 memcpy(&args[argspos], arg, _argsize(prgvt[i]) * sizeof(DWORD));
5389 else
5390 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5391 argspos += _argsize(prgvt[i]);
5394 if (pvInstance)
5396 FARPROC *vtable = *(FARPROC**)pvInstance;
5397 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5399 else
5400 /* if we aren't invoking an object then the function pointer is stored
5401 * in oVft */
5402 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5404 if (pvargResult && (vtReturn != VT_EMPTY))
5406 TRACE("Method returned 0x%08x\n",hres);
5407 V_VT(pvargResult) = vtReturn;
5408 V_UI4(pvargResult) = hres;
5411 HeapFree(GetProcessHeap(),0,args);
5412 return S_OK;
5415 #define INVBUF_ELEMENT_SIZE \
5416 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5417 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5418 ((VARIANTARG *)(buffer))
5419 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5420 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5421 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5422 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5423 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5424 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5426 static HRESULT WINAPI ITypeInfo_fnInvoke(
5427 ITypeInfo2 *iface,
5428 VOID *pIUnk,
5429 MEMBERID memid,
5430 UINT16 wFlags,
5431 DISPPARAMS *pDispParams,
5432 VARIANT *pVarResult,
5433 EXCEPINFO *pExcepInfo,
5434 UINT *pArgErr)
5436 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5437 int i;
5438 unsigned int var_index;
5439 TYPEKIND type_kind;
5440 HRESULT hres;
5441 const TLBFuncDesc *pFuncInfo;
5443 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
5444 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5447 if (!pDispParams)
5449 ERR("NULL pDispParams not allowed\n");
5450 return E_INVALIDARG;
5453 dump_DispParms(pDispParams);
5455 if (pDispParams->cNamedArgs > pDispParams->cArgs)
5457 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
5458 pDispParams->cNamedArgs, pDispParams->cArgs);
5459 return E_INVALIDARG;
5462 /* we do this instead of using GetFuncDesc since it will return a fake
5463 * FUNCDESC for dispinterfaces and we want the real function description */
5464 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5465 if ((memid == pFuncInfo->funcdesc.memid) &&
5466 (wFlags & pFuncInfo->funcdesc.invkind))
5467 break;
5469 if (pFuncInfo) {
5470 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5472 if (TRACE_ON(ole))
5474 TRACE("invoking:\n");
5475 dump_TLBFuncDescOne(pFuncInfo);
5478 switch (func_desc->funckind) {
5479 case FUNC_PUREVIRTUAL:
5480 case FUNC_VIRTUAL: {
5481 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
5482 VARIANT varresult;
5483 VARIANT retval; /* pointer for storing byref retvals in */
5484 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
5485 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
5486 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
5487 UINT cNamedArgs = pDispParams->cNamedArgs;
5488 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
5490 hres = S_OK;
5492 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
5494 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
5496 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
5497 hres = DISP_E_PARAMNOTFOUND;
5498 goto func_fail;
5500 /* ignore the DISPID_PROPERTYPUT named argument from now on */
5501 cNamedArgs--;
5502 rgdispidNamedArgs++;
5505 for (i = 0; i < func_desc->cParams; i++)
5507 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5508 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
5509 if (FAILED(hres))
5510 goto func_fail;
5513 TRACE("changing args\n");
5514 for (i = 0; i < func_desc->cParams; i++)
5516 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5517 VARIANTARG *src_arg;
5519 if (cNamedArgs)
5521 USHORT j;
5522 src_arg = NULL;
5523 for (j = 0; j < cNamedArgs; j++)
5524 if (rgdispidNamedArgs[j] == i)
5526 src_arg = &pDispParams->rgvarg[j];
5527 break;
5530 else
5531 src_arg = i < pDispParams->cArgs ? &pDispParams->rgvarg[pDispParams->cArgs - 1 - i] : NULL;
5533 if (wParamFlags & PARAMFLAG_FRETVAL)
5535 /* under most conditions the caller is not allowed to
5536 * pass in a dispparam arg in the index of what would be
5537 * the retval parameter. however, there is an exception
5538 * where the extra parameter is used in an extra
5539 * IDispatch::Invoke below */
5540 if ((i < pDispParams->cArgs) &&
5541 ((func_desc->cParams != 1) || !pVarResult ||
5542 !(func_desc->invkind & INVOKE_PROPERTYGET)))
5544 hres = DISP_E_BADPARAMCOUNT;
5545 break;
5548 /* note: this check is placed so that if the caller passes
5549 * in a VARIANTARG for the retval we just ignore it, like
5550 * native does */
5551 if (i == func_desc->cParams - 1)
5553 VARIANTARG *arg;
5554 arg = prgpvarg[i] = &rgvarg[i];
5555 memset(arg, 0, sizeof(*arg));
5556 V_VT(arg) = rgvt[i];
5557 memset(&retval, 0, sizeof(retval));
5558 V_BYREF(arg) = &retval;
5560 else
5562 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
5563 hres = E_UNEXPECTED;
5564 break;
5567 else if (src_arg)
5569 dump_Variant(src_arg);
5571 if (rgvt[i] == VT_VARIANT)
5572 hres = VariantCopy(&rgvarg[i], src_arg);
5573 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
5575 if (rgvt[i] == V_VT(src_arg))
5576 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
5577 else
5579 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5580 hres = VariantCopy(&missing_arg[i], src_arg);
5581 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
5583 V_VT(&rgvarg[i]) = rgvt[i];
5585 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
5587 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5588 V_VT(&missing_arg[i]) = V_VT(src_arg);
5589 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
5590 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
5591 V_VT(&rgvarg[i]) = rgvt[i];
5593 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
5595 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
5596 V_VT(&rgvarg[i]) = rgvt[i];
5598 else
5600 /* FIXME: this doesn't work for VT_BYREF arguments if
5601 * they are not the same type as in the paramdesc */
5602 V_VT(&rgvarg[i]) = V_VT(src_arg);
5603 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
5604 V_VT(&rgvarg[i]) = rgvt[i];
5607 if (FAILED(hres))
5609 ERR("failed to convert param %d to %s%s from %s%s\n", i,
5610 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
5611 debugstr_VT(src_arg), debugstr_VF(src_arg));
5612 break;
5614 prgpvarg[i] = &rgvarg[i];
5616 else if (wParamFlags & PARAMFLAG_FOPT)
5618 VARIANTARG *arg;
5619 arg = prgpvarg[i] = &rgvarg[i];
5620 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5622 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
5623 if (FAILED(hres))
5624 break;
5626 else
5628 VARIANTARG *missing_arg;
5629 /* if the function wants a pointer to a variant then
5630 * set that up, otherwise just pass the VT_ERROR in
5631 * the argument by value */
5632 if (rgvt[i] & VT_BYREF)
5634 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
5635 V_VT(arg) = VT_VARIANT | VT_BYREF;
5636 V_VARIANTREF(arg) = missing_arg;
5638 else
5639 missing_arg = arg;
5640 V_VT(missing_arg) = VT_ERROR;
5641 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
5644 else
5646 hres = DISP_E_BADPARAMCOUNT;
5647 break;
5650 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5651 if (func_desc->cParamsOpt < 0)
5653 FIXME("Does not support safearray optional parameters\n");
5654 hres = DISP_E_BADPARAMCOUNT;
5655 goto func_fail; /* FIXME: we don't free changed types here */
5658 /* VT_VOID is a special case for return types, so it is not
5659 * handled in the general function */
5660 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
5661 V_VT(&varresult) = VT_EMPTY;
5662 else
5664 V_VT(&varresult) = 0;
5665 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
5666 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5669 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
5670 V_VT(&varresult), func_desc->cParams, rgvt,
5671 prgpvarg, &varresult);
5673 for (i = 0; i < func_desc->cParams; i++)
5675 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5676 if (wParamFlags & PARAMFLAG_FRETVAL)
5678 if (TRACE_ON(ole))
5680 TRACE("[retval] value: ");
5681 dump_Variant(prgpvarg[i]);
5684 if (pVarResult)
5686 VariantInit(pVarResult);
5687 /* deref return value */
5688 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
5691 /* free data stored in varresult. Note that
5692 * VariantClear doesn't do what we want because we are
5693 * working with byref types. */
5694 /* FIXME: clear safearrays, bstrs, records and
5695 * variants here too */
5696 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
5697 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
5699 if(*V_UNKNOWNREF(prgpvarg[i]))
5700 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
5702 break;
5704 else if (i < pDispParams->cArgs)
5706 if (wParamFlags & PARAMFLAG_FOUT)
5708 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5710 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
5711 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
5713 if (FAILED(hres))
5715 ERR("failed to convert param %d to vt %d\n", i,
5716 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
5717 break;
5720 VariantClear(&rgvarg[i]);
5722 else if (wParamFlags & PARAMFLAG_FOPT)
5724 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5725 VariantClear(&rgvarg[i]);
5729 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
5731 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
5732 hres = DISP_E_EXCEPTION;
5733 if (pExcepInfo)
5735 IErrorInfo *pErrorInfo;
5736 pExcepInfo->scode = V_ERROR(&varresult);
5737 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
5739 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
5740 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
5741 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
5742 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
5744 IErrorInfo_Release(pErrorInfo);
5748 if (V_VT(&varresult) != VT_ERROR)
5750 TRACE("varresult value: ");
5751 dump_Variant(&varresult);
5753 if (pVarResult)
5755 VariantClear(pVarResult);
5756 *pVarResult = varresult;
5758 else
5759 VariantClear(&varresult);
5762 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
5763 (wFlags == INVOKE_PROPERTYGET) &&
5764 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
5765 (pDispParams->cArgs != 0))
5767 if (V_VT(pVarResult) == VT_DISPATCH)
5769 IDispatch *pDispatch = V_DISPATCH(pVarResult);
5770 /* Note: not VariantClear; we still need the dispatch
5771 * pointer to be valid */
5772 VariantInit(pVarResult);
5773 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
5774 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
5775 pDispParams, pVarResult, pExcepInfo, pArgErr);
5776 IDispatch_Release(pDispatch);
5778 else
5780 VariantClear(pVarResult);
5781 hres = DISP_E_NOTACOLLECTION;
5785 func_fail:
5786 HeapFree(GetProcessHeap(), 0, buffer);
5787 break;
5789 case FUNC_DISPATCH: {
5790 IDispatch *disp;
5792 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5793 if (SUCCEEDED(hres)) {
5794 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5795 hres = IDispatch_Invoke(
5796 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
5797 pVarResult,pExcepInfo,pArgErr
5799 if (FAILED(hres))
5800 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
5801 IDispatch_Release(disp);
5802 } else
5803 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5804 break;
5806 default:
5807 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5808 hres = E_FAIL;
5809 break;
5812 TRACE("-- 0x%08x\n", hres);
5813 return hres;
5815 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5816 VARDESC *var_desc;
5818 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5819 if(FAILED(hres)) return hres;
5821 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5822 dump_VARDESC(var_desc);
5823 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
5824 return E_NOTIMPL;
5827 /* not found, look for it in inherited interfaces */
5828 ITypeInfo2_GetTypeKind(iface, &type_kind);
5829 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
5830 if(This->impltypelist) {
5831 /* recursive search */
5832 ITypeInfo *pTInfo;
5833 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
5834 if(SUCCEEDED(hres)){
5835 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
5836 ITypeInfo_Release(pTInfo);
5837 return hres;
5839 WARN("Could not search inherited interface!\n");
5842 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
5843 return DISP_E_MEMBERNOTFOUND;
5846 /* ITypeInfo::GetDocumentation
5848 * Retrieves the documentation string, the complete Help file name and path,
5849 * and the context ID for the Help topic for a specified type description.
5851 * (Can be tested by the Visual Basic Editor in Word for instance.)
5853 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
5854 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
5855 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
5857 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5858 const TLBFuncDesc *pFDesc;
5859 const TLBVarDesc *pVDesc;
5860 TRACE("(%p) memid %d Name(%p) DocString(%p)"
5861 " HelpContext(%p) HelpFile(%p)\n",
5862 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5863 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5864 if(pBstrName)
5865 *pBstrName=SysAllocString(This->Name);
5866 if(pBstrDocString)
5867 *pBstrDocString=SysAllocString(This->DocString);
5868 if(pdwHelpContext)
5869 *pdwHelpContext=This->dwHelpContext;
5870 if(pBstrHelpFile)
5871 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5872 return S_OK;
5873 }else {/* for a member */
5874 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5875 if(pFDesc->funcdesc.memid==memid){
5876 if(pBstrName)
5877 *pBstrName = SysAllocString(pFDesc->Name);
5878 if(pBstrDocString)
5879 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5880 if(pdwHelpContext)
5881 *pdwHelpContext=pFDesc->helpcontext;
5882 return S_OK;
5884 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5885 if(pVDesc->vardesc.memid==memid){
5886 if(pBstrName)
5887 *pBstrName = SysAllocString(pVDesc->Name);
5888 if(pBstrDocString)
5889 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5890 if(pdwHelpContext)
5891 *pdwHelpContext=pVDesc->HelpContext;
5892 return S_OK;
5896 if(This->impltypelist &&
5897 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5898 /* recursive search */
5899 ITypeInfo *pTInfo;
5900 HRESULT result;
5901 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5902 &pTInfo);
5903 if(SUCCEEDED(result)) {
5904 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
5905 pBstrDocString, pdwHelpContext, pBstrHelpFile);
5906 ITypeInfo_Release(pTInfo);
5907 return result;
5909 WARN("Could not search inherited interface!\n");
5912 WARN("member %d not found\n", memid);
5913 return TYPE_E_ELEMENTNOTFOUND;
5916 /* ITypeInfo::GetDllEntry
5918 * Retrieves a description or specification of an entry point for a function
5919 * in a DLL.
5921 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5922 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5923 WORD *pwOrdinal)
5925 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5926 const TLBFuncDesc *pFDesc;
5928 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5930 if (pBstrDllName) *pBstrDllName = NULL;
5931 if (pBstrName) *pBstrName = NULL;
5932 if (pwOrdinal) *pwOrdinal = 0;
5934 if (This->TypeAttr.typekind != TKIND_MODULE)
5935 return TYPE_E_BADMODULEKIND;
5937 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5938 if(pFDesc->funcdesc.memid==memid){
5939 dump_TypeInfo(This);
5940 if (TRACE_ON(ole))
5941 dump_TLBFuncDescOne(pFDesc);
5943 if (pBstrDllName)
5944 *pBstrDllName = SysAllocString(This->DllName);
5946 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5947 if (pBstrName)
5948 *pBstrName = SysAllocString(pFDesc->Entry);
5949 if (pwOrdinal)
5950 *pwOrdinal = -1;
5951 return S_OK;
5953 if (pBstrName)
5954 *pBstrName = NULL;
5955 if (pwOrdinal)
5956 *pwOrdinal = (DWORD)pFDesc->Entry;
5957 return S_OK;
5959 return TYPE_E_ELEMENTNOTFOUND;
5962 /* ITypeInfo::GetRefTypeInfo
5964 * If a type description references other type descriptions, it retrieves
5965 * the referenced type descriptions.
5967 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5968 ITypeInfo2 *iface,
5969 HREFTYPE hRefType,
5970 ITypeInfo **ppTInfo)
5972 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5973 HRESULT result = E_FAIL;
5975 if ((This->hreftype != -1) && (This->hreftype == hRefType))
5977 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5978 ITypeInfo_AddRef(*ppTInfo);
5979 result = S_OK;
5981 else if (hRefType == -1 &&
5982 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5983 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5985 /* when we meet a DUAL dispinterface, we must create the interface
5986 * version of it.
5988 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5991 /* the interface version contains the same information as the dispinterface
5992 * copy the contents of the structs.
5994 *pTypeInfoImpl = *This;
5995 pTypeInfoImpl->ref = 0;
5997 /* change the type to interface */
5998 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6000 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6002 /* we use data structures from This, so we need to keep a reference
6003 * to it to stop it being destroyed and signal to the new instance to
6004 * not free its data structures when it is destroyed */
6005 pTypeInfoImpl->no_free_data = TRUE;
6006 pTypeInfoImpl->next = This;
6007 ITypeInfo_AddRef((ITypeInfo*) This);
6009 ITypeInfo_AddRef(*ppTInfo);
6011 result = S_OK;
6013 } else {
6014 TLBRefType *ref_type;
6015 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6017 if(ref_type->reference == hRefType)
6018 break;
6020 if(&ref_type->entry == &This->pTypeLib->ref_list)
6022 FIXME("Can't find pRefType for ref %x\n", hRefType);
6023 goto end;
6025 if(hRefType != -1) {
6026 ITypeLib *pTLib = NULL;
6028 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6029 UINT Index;
6030 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6031 } else {
6032 if(ref_type->pImpTLInfo->pImpTypeLib) {
6033 TRACE("typeinfo in imported typelib that is already loaded\n");
6034 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6035 ITypeLib2_AddRef((ITypeLib*) pTLib);
6036 result = S_OK;
6037 } else {
6038 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6039 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6040 ref_type->pImpTLInfo->wVersionMajor,
6041 ref_type->pImpTLInfo->wVersionMinor,
6042 ref_type->pImpTLInfo->lcid,
6043 &pTLib);
6045 if(!SUCCEEDED(result)) {
6046 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6047 result=LoadTypeLib(libnam, &pTLib);
6048 SysFreeString(libnam);
6050 if(SUCCEEDED(result)) {
6051 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6052 ITypeLib2_AddRef(pTLib);
6056 if(SUCCEEDED(result)) {
6057 if(ref_type->index == TLB_REF_USE_GUID)
6058 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6059 &ref_type->guid,
6060 ppTInfo);
6061 else
6062 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6063 ppTInfo);
6065 if (pTLib != NULL)
6066 ITypeLib2_Release(pTLib);
6070 end:
6071 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6072 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6073 return result;
6076 /* ITypeInfo::AddressOfMember
6078 * Retrieves the addresses of static functions or variables, such as those
6079 * defined in a DLL.
6081 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6082 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6084 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6085 HRESULT hr;
6086 BSTR dll, entry;
6087 WORD ordinal;
6088 HMODULE module;
6090 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6092 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6093 if (FAILED(hr))
6094 return hr;
6096 module = LoadLibraryW(dll);
6097 if (!module)
6099 ERR("couldn't load %s\n", debugstr_w(dll));
6100 SysFreeString(dll);
6101 if (entry) SysFreeString(entry);
6102 return STG_E_FILENOTFOUND;
6104 /* FIXME: store library somewhere where we can free it */
6106 if (entry)
6108 LPSTR entryA;
6109 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6110 entryA = HeapAlloc(GetProcessHeap(), 0, len);
6111 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6113 *ppv = GetProcAddress(module, entryA);
6114 if (!*ppv)
6115 ERR("function not found %s\n", debugstr_a(entryA));
6117 HeapFree(GetProcessHeap(), 0, entryA);
6119 else
6121 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6122 if (!*ppv)
6123 ERR("function not found %d\n", ordinal);
6126 SysFreeString(dll);
6127 if (entry) SysFreeString(entry);
6129 if (!*ppv)
6130 return TYPE_E_DLLFUNCTIONNOTFOUND;
6132 return S_OK;
6135 /* ITypeInfo::CreateInstance
6137 * Creates a new instance of a type that describes a component object class
6138 * (coclass).
6140 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6141 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6143 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6144 HRESULT hr;
6145 TYPEATTR *pTA;
6147 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6149 *ppvObj = NULL;
6151 if(pOuterUnk)
6153 WARN("Not able to aggregate\n");
6154 return CLASS_E_NOAGGREGATION;
6157 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6158 if(FAILED(hr)) return hr;
6160 if(pTA->typekind != TKIND_COCLASS)
6162 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6163 hr = E_INVALIDARG;
6164 goto end;
6167 hr = S_FALSE;
6168 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6170 IUnknown *pUnk;
6171 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6172 TRACE("GetActiveObject rets %08x\n", hr);
6173 if(hr == S_OK)
6175 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6176 IUnknown_Release(pUnk);
6180 if(hr != S_OK)
6181 hr = CoCreateInstance(&pTA->guid, NULL,
6182 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6183 riid, ppvObj);
6185 end:
6186 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6187 return hr;
6190 /* ITypeInfo::GetMops
6192 * Retrieves marshalling information.
6194 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6195 BSTR *pBstrMops)
6197 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6198 FIXME("(%p) stub!\n", This);
6199 return S_OK;
6202 /* ITypeInfo::GetContainingTypeLib
6204 * Retrieves the containing type library and the index of the type description
6205 * within that type library.
6207 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6208 ITypeLib * *ppTLib, UINT *pIndex)
6210 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6212 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6213 if (pIndex) {
6214 *pIndex=This->index;
6215 TRACE("returning pIndex=%d\n", *pIndex);
6218 if (ppTLib) {
6219 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6220 ITypeLib2_AddRef(*ppTLib);
6221 TRACE("returning ppTLib=%p\n", *ppTLib);
6224 return S_OK;
6227 /* ITypeInfo::ReleaseTypeAttr
6229 * Releases a TYPEATTR previously returned by GetTypeAttr.
6232 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6233 TYPEATTR* pTypeAttr)
6235 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6236 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6237 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6240 /* ITypeInfo::ReleaseFuncDesc
6242 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6244 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6245 ITypeInfo2 *iface,
6246 FUNCDESC *pFuncDesc)
6248 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6249 SHORT i;
6251 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6253 for (i = 0; i < pFuncDesc->cParams; i++)
6254 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6255 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6257 SysFreeString((BSTR)pFuncDesc);
6260 /* ITypeInfo::ReleaseVarDesc
6262 * Releases a VARDESC previously returned by GetVarDesc.
6264 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6265 VARDESC *pVarDesc)
6267 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6268 TRACE("(%p)->(%p)\n", This, pVarDesc);
6270 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6271 if (pVarDesc->varkind == VAR_CONST)
6272 VariantClear(pVarDesc->u.lpvarValue);
6273 SysFreeString((BSTR)pVarDesc);
6276 /* ITypeInfo2::GetTypeKind
6278 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6281 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6282 TYPEKIND *pTypeKind)
6284 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6285 *pTypeKind=This->TypeAttr.typekind;
6286 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6287 return S_OK;
6290 /* ITypeInfo2::GetTypeFlags
6292 * Returns the type flags without any allocations. This returns a DWORD type
6293 * flag, which expands the type flags without growing the TYPEATTR (type
6294 * attribute).
6297 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6299 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6300 *pTypeFlags=This->TypeAttr.wTypeFlags;
6301 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6302 return S_OK;
6305 /* ITypeInfo2::GetFuncIndexOfMemId
6306 * Binds to a specific member based on a known DISPID, where the member name
6307 * is not known (for example, when binding to a default member).
6310 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
6311 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
6313 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6314 const TLBFuncDesc *pFuncInfo;
6315 int i;
6316 HRESULT result;
6318 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
6319 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
6320 break;
6321 if(pFuncInfo) {
6322 *pFuncIndex = i;
6323 result = S_OK;
6324 } else
6325 result = TYPE_E_ELEMENTNOTFOUND;
6327 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
6328 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6329 return result;
6332 /* TypeInfo2::GetVarIndexOfMemId
6334 * Binds to a specific member based on a known DISPID, where the member name
6335 * is not known (for example, when binding to a default member).
6338 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
6339 MEMBERID memid, UINT *pVarIndex)
6341 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6342 TLBVarDesc *pVarInfo;
6343 int i;
6344 HRESULT result;
6345 for(i=0, pVarInfo=This->varlist; pVarInfo &&
6346 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
6348 if(pVarInfo) {
6349 *pVarIndex = i;
6350 result = S_OK;
6351 } else
6352 result = TYPE_E_ELEMENTNOTFOUND;
6354 TRACE("(%p) memid 0x%08x -> %s\n", This,
6355 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6356 return result;
6359 /* ITypeInfo2::GetCustData
6361 * Gets the custom data
6363 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
6364 ITypeInfo2 * iface,
6365 REFGUID guid,
6366 VARIANT *pVarVal)
6368 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6369 TLBCustData *pCData;
6371 for(pCData=This->pCustData; pCData; pCData = pCData->next)
6372 if( IsEqualIID(guid, &pCData->guid)) break;
6374 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6376 if(pCData)
6378 VariantInit( pVarVal);
6379 VariantCopy( pVarVal, &pCData->data);
6380 return S_OK;
6382 return E_INVALIDARG; /* FIXME: correct? */
6385 /* ITypeInfo2::GetFuncCustData
6387 * Gets the custom data
6389 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
6390 ITypeInfo2 * iface,
6391 UINT index,
6392 REFGUID guid,
6393 VARIANT *pVarVal)
6395 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6396 TLBCustData *pCData=NULL;
6397 TLBFuncDesc * pFDesc;
6398 int i;
6399 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6400 pFDesc=pFDesc->next);
6402 if(pFDesc)
6403 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
6404 if( IsEqualIID(guid, &pCData->guid)) break;
6406 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6408 if(pCData){
6409 VariantInit( pVarVal);
6410 VariantCopy( pVarVal, &pCData->data);
6411 return S_OK;
6413 return E_INVALIDARG; /* FIXME: correct? */
6416 /* ITypeInfo2::GetParamCustData
6418 * Gets the custom data
6420 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
6421 ITypeInfo2 * iface,
6422 UINT indexFunc,
6423 UINT indexParam,
6424 REFGUID guid,
6425 VARIANT *pVarVal)
6427 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6428 TLBCustData *pCData=NULL;
6429 TLBFuncDesc * pFDesc;
6430 int i;
6432 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
6434 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
6435 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
6436 pCData = pCData->next)
6437 if( IsEqualIID(guid, &pCData->guid)) break;
6439 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6441 if(pCData)
6443 VariantInit( pVarVal);
6444 VariantCopy( pVarVal, &pCData->data);
6445 return S_OK;
6447 return E_INVALIDARG; /* FIXME: correct? */
6450 /* ITypeInfo2::GetVarCustData
6452 * Gets the custom data
6454 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
6455 ITypeInfo2 * iface,
6456 UINT index,
6457 REFGUID guid,
6458 VARIANT *pVarVal)
6460 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6461 TLBCustData *pCData=NULL;
6462 TLBVarDesc * pVDesc;
6463 int i;
6465 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
6467 if(pVDesc)
6469 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
6471 if( IsEqualIID(guid, &pCData->guid)) break;
6475 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6477 if(pCData)
6479 VariantInit( pVarVal);
6480 VariantCopy( pVarVal, &pCData->data);
6481 return S_OK;
6483 return E_INVALIDARG; /* FIXME: correct? */
6486 /* ITypeInfo2::GetImplCustData
6488 * Gets the custom data
6490 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6491 ITypeInfo2 * iface,
6492 UINT index,
6493 REFGUID guid,
6494 VARIANT *pVarVal)
6496 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6497 TLBCustData *pCData=NULL;
6498 TLBImplType * pRDesc;
6499 int i;
6501 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6503 if(pRDesc)
6505 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6507 if( IsEqualIID(guid, &pCData->guid)) break;
6511 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6513 if(pCData)
6515 VariantInit( pVarVal);
6516 VariantCopy( pVarVal, &pCData->data);
6517 return S_OK;
6519 return E_INVALIDARG; /* FIXME: correct? */
6522 /* ITypeInfo2::GetDocumentation2
6524 * Retrieves the documentation string, the complete Help file name and path,
6525 * the localization context to use, and the context ID for the library Help
6526 * topic in the Help file.
6529 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6530 ITypeInfo2 * iface,
6531 MEMBERID memid,
6532 LCID lcid,
6533 BSTR *pbstrHelpString,
6534 DWORD *pdwHelpStringContext,
6535 BSTR *pbstrHelpStringDll)
6537 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6538 const TLBFuncDesc *pFDesc;
6539 const TLBVarDesc *pVDesc;
6540 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
6541 "HelpStringContext(%p) HelpStringDll(%p)\n",
6542 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6543 pbstrHelpStringDll );
6544 /* the help string should be obtained from the helpstringdll,
6545 * using the _DLLGetDocumentation function, based on the supplied
6546 * lcid. Nice to do sometime...
6548 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6549 if(pbstrHelpString)
6550 *pbstrHelpString=SysAllocString(This->Name);
6551 if(pdwHelpStringContext)
6552 *pdwHelpStringContext=This->dwHelpStringContext;
6553 if(pbstrHelpStringDll)
6554 *pbstrHelpStringDll=
6555 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6556 return S_OK;
6557 }else {/* for a member */
6558 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6559 if(pFDesc->funcdesc.memid==memid){
6560 if(pbstrHelpString)
6561 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6562 if(pdwHelpStringContext)
6563 *pdwHelpStringContext=pFDesc->HelpStringContext;
6564 if(pbstrHelpStringDll)
6565 *pbstrHelpStringDll=
6566 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6567 return S_OK;
6569 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6570 if(pVDesc->vardesc.memid==memid){
6571 if(pbstrHelpString)
6572 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6573 if(pdwHelpStringContext)
6574 *pdwHelpStringContext=pVDesc->HelpStringContext;
6575 if(pbstrHelpStringDll)
6576 *pbstrHelpStringDll=
6577 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6578 return S_OK;
6581 return TYPE_E_ELEMENTNOTFOUND;
6584 /* ITypeInfo2::GetAllCustData
6586 * Gets all custom data items for the Type info.
6589 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6590 ITypeInfo2 * iface,
6591 CUSTDATA *pCustData)
6593 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6594 TLBCustData *pCData;
6595 int i;
6597 TRACE("(%p) returning %d items\n", This, This->ctCustData);
6599 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6600 if(pCustData->prgCustData ){
6601 pCustData->cCustData=This->ctCustData;
6602 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
6603 pCustData->prgCustData[i].guid=pCData->guid;
6604 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
6606 }else{
6607 ERR(" OUT OF MEMORY!\n");
6608 return E_OUTOFMEMORY;
6610 return S_OK;
6613 /* ITypeInfo2::GetAllFuncCustData
6615 * Gets all custom data items for the specified Function
6618 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
6619 ITypeInfo2 * iface,
6620 UINT index,
6621 CUSTDATA *pCustData)
6623 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6624 TLBCustData *pCData;
6625 TLBFuncDesc * pFDesc;
6626 int i;
6627 TRACE("(%p) index %d\n", This, index);
6628 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6629 pFDesc=pFDesc->next)
6631 if(pFDesc){
6632 pCustData->prgCustData =
6633 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
6634 if(pCustData->prgCustData ){
6635 pCustData->cCustData=pFDesc->ctCustData;
6636 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
6637 pCData = pCData->next){
6638 pCustData->prgCustData[i].guid=pCData->guid;
6639 VariantCopy(& pCustData->prgCustData[i].varValue,
6640 & pCData->data);
6642 }else{
6643 ERR(" OUT OF MEMORY!\n");
6644 return E_OUTOFMEMORY;
6646 return S_OK;
6648 return TYPE_E_ELEMENTNOTFOUND;
6651 /* ITypeInfo2::GetAllParamCustData
6653 * Gets all custom data items for the Functions
6656 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
6657 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
6659 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6660 TLBCustData *pCData=NULL;
6661 TLBFuncDesc * pFDesc;
6662 int i;
6663 TRACE("(%p) index %d\n", This, indexFunc);
6664 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
6665 pFDesc=pFDesc->next)
6667 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
6668 pCustData->prgCustData =
6669 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
6670 sizeof(CUSTDATAITEM));
6671 if(pCustData->prgCustData ){
6672 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
6673 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
6674 pCData; i++, pCData = pCData->next){
6675 pCustData->prgCustData[i].guid=pCData->guid;
6676 VariantCopy(& pCustData->prgCustData[i].varValue,
6677 & pCData->data);
6679 }else{
6680 ERR(" OUT OF MEMORY!\n");
6681 return E_OUTOFMEMORY;
6683 return S_OK;
6685 return TYPE_E_ELEMENTNOTFOUND;
6688 /* ITypeInfo2::GetAllVarCustData
6690 * Gets all custom data items for the specified Variable
6693 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
6694 UINT index, CUSTDATA *pCustData)
6696 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6697 TLBCustData *pCData;
6698 TLBVarDesc * pVDesc;
6699 int i;
6700 TRACE("(%p) index %d\n", This, index);
6701 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
6702 pVDesc=pVDesc->next)
6704 if(pVDesc){
6705 pCustData->prgCustData =
6706 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
6707 if(pCustData->prgCustData ){
6708 pCustData->cCustData=pVDesc->ctCustData;
6709 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
6710 pCData = pCData->next){
6711 pCustData->prgCustData[i].guid=pCData->guid;
6712 VariantCopy(& pCustData->prgCustData[i].varValue,
6713 & pCData->data);
6715 }else{
6716 ERR(" OUT OF MEMORY!\n");
6717 return E_OUTOFMEMORY;
6719 return S_OK;
6721 return TYPE_E_ELEMENTNOTFOUND;
6724 /* ITypeInfo2::GetAllImplCustData
6726 * Gets all custom data items for the specified implementation type
6729 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
6730 ITypeInfo2 * iface,
6731 UINT index,
6732 CUSTDATA *pCustData)
6734 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6735 TLBCustData *pCData;
6736 TLBImplType * pRDesc;
6737 int i;
6738 TRACE("(%p) index %d\n", This, index);
6739 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
6740 pRDesc=pRDesc->next)
6742 if(pRDesc){
6743 pCustData->prgCustData =
6744 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
6745 if(pCustData->prgCustData ){
6746 pCustData->cCustData=pRDesc->ctCustData;
6747 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
6748 pCData = pCData->next){
6749 pCustData->prgCustData[i].guid=pCData->guid;
6750 VariantCopy(& pCustData->prgCustData[i].varValue,
6751 & pCData->data);
6753 }else{
6754 ERR(" OUT OF MEMORY!\n");
6755 return E_OUTOFMEMORY;
6757 return S_OK;
6759 return TYPE_E_ELEMENTNOTFOUND;
6762 static const ITypeInfo2Vtbl tinfvt =
6765 ITypeInfo_fnQueryInterface,
6766 ITypeInfo_fnAddRef,
6767 ITypeInfo_fnRelease,
6769 ITypeInfo_fnGetTypeAttr,
6770 ITypeInfo_fnGetTypeComp,
6771 ITypeInfo_fnGetFuncDesc,
6772 ITypeInfo_fnGetVarDesc,
6773 ITypeInfo_fnGetNames,
6774 ITypeInfo_fnGetRefTypeOfImplType,
6775 ITypeInfo_fnGetImplTypeFlags,
6776 ITypeInfo_fnGetIDsOfNames,
6777 ITypeInfo_fnInvoke,
6778 ITypeInfo_fnGetDocumentation,
6779 ITypeInfo_fnGetDllEntry,
6780 ITypeInfo_fnGetRefTypeInfo,
6781 ITypeInfo_fnAddressOfMember,
6782 ITypeInfo_fnCreateInstance,
6783 ITypeInfo_fnGetMops,
6784 ITypeInfo_fnGetContainingTypeLib,
6785 ITypeInfo_fnReleaseTypeAttr,
6786 ITypeInfo_fnReleaseFuncDesc,
6787 ITypeInfo_fnReleaseVarDesc,
6789 ITypeInfo2_fnGetTypeKind,
6790 ITypeInfo2_fnGetTypeFlags,
6791 ITypeInfo2_fnGetFuncIndexOfMemId,
6792 ITypeInfo2_fnGetVarIndexOfMemId,
6793 ITypeInfo2_fnGetCustData,
6794 ITypeInfo2_fnGetFuncCustData,
6795 ITypeInfo2_fnGetParamCustData,
6796 ITypeInfo2_fnGetVarCustData,
6797 ITypeInfo2_fnGetImplTypeCustData,
6798 ITypeInfo2_fnGetDocumentation2,
6799 ITypeInfo2_fnGetAllCustData,
6800 ITypeInfo2_fnGetAllFuncCustData,
6801 ITypeInfo2_fnGetAllParamCustData,
6802 ITypeInfo2_fnGetAllVarCustData,
6803 ITypeInfo2_fnGetAllImplTypeCustData,
6806 /******************************************************************************
6807 * CreateDispTypeInfo [OLEAUT32.31]
6809 * Build type information for an object so it can be called through an
6810 * IDispatch interface.
6812 * RETURNS
6813 * Success: S_OK. pptinfo contains the created ITypeInfo object.
6814 * Failure: E_INVALIDARG, if one or more arguments is invalid.
6816 * NOTES
6817 * This call allows an objects methods to be accessed through IDispatch, by
6818 * building an ITypeInfo object that IDispatch can use to call through.
6820 HRESULT WINAPI CreateDispTypeInfo(
6821 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
6822 LCID lcid, /* [I] Locale Id */
6823 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
6825 ITypeInfoImpl *pTIClass, *pTIIface;
6826 ITypeLibImpl *pTypeLibImpl;
6827 int param, func;
6828 TLBFuncDesc **ppFuncDesc;
6829 TLBRefType *ref;
6831 TRACE("\n");
6832 pTypeLibImpl = TypeLibImpl_Constructor();
6833 if (!pTypeLibImpl) return E_FAIL;
6835 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
6836 pTIIface->pTypeLib = pTypeLibImpl;
6837 pTIIface->index = 0;
6838 pTIIface->Name = NULL;
6839 pTIIface->dwHelpContext = -1;
6840 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
6841 pTIIface->TypeAttr.lcid = lcid;
6842 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
6843 pTIIface->TypeAttr.wMajorVerNum = 0;
6844 pTIIface->TypeAttr.wMinorVerNum = 0;
6845 pTIIface->TypeAttr.cbAlignment = 2;
6846 pTIIface->TypeAttr.cbSizeInstance = -1;
6847 pTIIface->TypeAttr.cbSizeVft = -1;
6848 pTIIface->TypeAttr.cFuncs = 0;
6849 pTIIface->TypeAttr.cImplTypes = 0;
6850 pTIIface->TypeAttr.cVars = 0;
6851 pTIIface->TypeAttr.wTypeFlags = 0;
6853 ppFuncDesc = &pTIIface->funclist;
6854 for(func = 0; func < pidata->cMembers; func++) {
6855 METHODDATA *md = pidata->pmethdata + func;
6856 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
6857 (*ppFuncDesc)->Name = SysAllocString(md->szName);
6858 (*ppFuncDesc)->funcdesc.memid = md->dispid;
6859 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
6860 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
6861 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
6862 (*ppFuncDesc)->funcdesc.callconv = md->cc;
6863 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
6864 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
6865 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
6866 (*ppFuncDesc)->funcdesc.cScodes = 0;
6867 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
6868 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
6869 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
6870 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
6871 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6872 md->cArgs * sizeof(ELEMDESC));
6873 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6874 md->cArgs * sizeof(TLBParDesc));
6875 for(param = 0; param < md->cArgs; param++) {
6876 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
6877 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
6879 (*ppFuncDesc)->helpcontext = 0;
6880 (*ppFuncDesc)->HelpStringContext = 0;
6881 (*ppFuncDesc)->HelpString = NULL;
6882 (*ppFuncDesc)->Entry = NULL;
6883 (*ppFuncDesc)->ctCustData = 0;
6884 (*ppFuncDesc)->pCustData = NULL;
6885 (*ppFuncDesc)->next = NULL;
6886 pTIIface->TypeAttr.cFuncs++;
6887 ppFuncDesc = &(*ppFuncDesc)->next;
6890 dump_TypeInfo(pTIIface);
6892 pTypeLibImpl->pTypeInfo = pTIIface;
6893 pTypeLibImpl->TypeInfoCount++;
6895 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
6896 pTIClass->pTypeLib = pTypeLibImpl;
6897 pTIClass->index = 1;
6898 pTIClass->Name = NULL;
6899 pTIClass->dwHelpContext = -1;
6900 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
6901 pTIClass->TypeAttr.lcid = lcid;
6902 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
6903 pTIClass->TypeAttr.wMajorVerNum = 0;
6904 pTIClass->TypeAttr.wMinorVerNum = 0;
6905 pTIClass->TypeAttr.cbAlignment = 2;
6906 pTIClass->TypeAttr.cbSizeInstance = -1;
6907 pTIClass->TypeAttr.cbSizeVft = -1;
6908 pTIClass->TypeAttr.cFuncs = 0;
6909 pTIClass->TypeAttr.cImplTypes = 1;
6910 pTIClass->TypeAttr.cVars = 0;
6911 pTIClass->TypeAttr.wTypeFlags = 0;
6913 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
6914 pTIClass->impltypelist->hRef = 0;
6916 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
6917 ref->index = 0;
6918 ref->reference = 0;
6919 ref->pImpTLInfo = TLB_REF_INTERNAL;
6920 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
6922 dump_TypeInfo(pTIClass);
6924 pTIIface->next = pTIClass;
6925 pTypeLibImpl->TypeInfoCount++;
6927 *pptinfo = (ITypeInfo*)pTIClass;
6929 ITypeInfo_AddRef(*pptinfo);
6930 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
6932 return S_OK;
6936 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
6938 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6940 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
6943 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
6945 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6947 return ITypeInfo_AddRef((ITypeInfo *)This);
6950 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
6952 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6954 return ITypeInfo_Release((ITypeInfo *)This);
6957 static HRESULT WINAPI ITypeComp_fnBind(
6958 ITypeComp * iface,
6959 OLECHAR * szName,
6960 ULONG lHash,
6961 WORD wFlags,
6962 ITypeInfo ** ppTInfo,
6963 DESCKIND * pDescKind,
6964 BINDPTR * pBindPtr)
6966 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6967 const TLBFuncDesc *pFDesc;
6968 const TLBVarDesc *pVDesc;
6969 HRESULT hr = DISP_E_MEMBERNOTFOUND;
6971 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6973 *pDescKind = DESCKIND_NONE;
6974 pBindPtr->lpfuncdesc = NULL;
6975 *ppTInfo = NULL;
6977 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
6978 if (!strcmpiW(pFDesc->Name, szName)) {
6979 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
6980 break;
6981 else
6982 /* name found, but wrong flags */
6983 hr = TYPE_E_TYPEMISMATCH;
6986 if (pFDesc)
6988 HRESULT hr = TLB_AllocAndInitFuncDesc(
6989 &pFDesc->funcdesc,
6990 &pBindPtr->lpfuncdesc,
6991 This->TypeAttr.typekind == TKIND_DISPATCH);
6992 if (FAILED(hr))
6993 return hr;
6994 *pDescKind = DESCKIND_FUNCDESC;
6995 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6996 ITypeInfo_AddRef(*ppTInfo);
6997 return S_OK;
6998 } else {
6999 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7000 if (!strcmpiW(pVDesc->Name, szName)) {
7001 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7002 if (FAILED(hr))
7003 return hr;
7004 *pDescKind = DESCKIND_VARDESC;
7005 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7006 ITypeInfo_AddRef(*ppTInfo);
7007 return S_OK;
7011 /* FIXME: search each inherited interface, not just the first */
7012 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7013 /* recursive search */
7014 ITypeInfo *pTInfo;
7015 ITypeComp *pTComp;
7016 HRESULT hr;
7017 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7018 if (SUCCEEDED(hr))
7020 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7021 ITypeInfo_Release(pTInfo);
7023 if (SUCCEEDED(hr))
7025 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7026 ITypeComp_Release(pTComp);
7027 return hr;
7029 WARN("Could not search inherited interface!\n");
7031 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
7032 return hr;
7035 static HRESULT WINAPI ITypeComp_fnBindType(
7036 ITypeComp * iface,
7037 OLECHAR * szName,
7038 ULONG lHash,
7039 ITypeInfo ** ppTInfo,
7040 ITypeComp ** ppTComp)
7042 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7044 /* strange behaviour (does nothing) but like the
7045 * original */
7047 if (!ppTInfo || !ppTComp)
7048 return E_POINTER;
7050 *ppTInfo = NULL;
7051 *ppTComp = NULL;
7053 return S_OK;
7056 static const ITypeCompVtbl tcompvt =
7059 ITypeComp_fnQueryInterface,
7060 ITypeComp_fnAddRef,
7061 ITypeComp_fnRelease,
7063 ITypeComp_fnBind,
7064 ITypeComp_fnBindType