msi: Fix handling of REINSTALL overrides.
[wine.git] / dlls / oleaut32 / typelib.c
blobd1a719b12da63680dc1ee3dc7e6dfa082ceb2b30
1 /*
2 * TYPELIB
4 * Copyright 1997 Marcus Meissner
5 * 1999 Rein Klazes
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 2005 Robert Shearman, for CodeWeavers
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 * --------------------------------------------------------------------------------------
25 * Known problems (2000, Francois Jacques)
27 * - Tested using OLEVIEW (Platform SDK tool) only.
29 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
30 * creating by doing a straight copy of the dispinterface instance and just changing
31 * its typekind. Pointed structures aren't copied - only the address of the pointers.
33 * - locale stuff is partially implemented but hasn't been tested.
35 * - typelib file is still read in its entirety, but it is released now.
37 * --------------------------------------------------------------------------------------
38 * Known problems left from previous implementation (1999, Rein Klazes) :
40 * -. Data structures are straightforward, but slow for look-ups.
41 * -. (related) nothing is hashed
42 * -. Most error return values are just guessed not checked with windows
43 * behaviour.
44 * -. lousy fatal error handling
48 #include "config.h"
49 #include "wine/port.h"
51 #include <stdlib.h>
52 #include <string.h>
53 #include <stdarg.h>
54 #include <stdio.h>
55 #include <ctype.h>
57 #define COBJMACROS
58 #define NONAMELESSUNION
59 #define NONAMELESSSTRUCT
61 #include "winerror.h"
62 #include "windef.h"
63 #include "winbase.h"
64 #include "winnls.h"
65 #include "winreg.h"
66 #include "winuser.h"
67 #include "lzexpand.h"
69 #include "wine/winbase16.h"
70 #include "wine/unicode.h"
71 #include "objbase.h"
72 #include "typelib.h"
73 #include "wine/debug.h"
74 #include "variant.h"
75 #include "wine/list.h"
77 WINE_DEFAULT_DEBUG_CHANNEL(ole);
78 WINE_DECLARE_DEBUG_CHANNEL(typelib);
80 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
81 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
83 /****************************************************************************
84 * FromLExxx
86 * Takes p_iVal (which is in little endian) and returns it
87 * in the host machine's byte order.
89 #ifdef WORDS_BIGENDIAN
90 static WORD FromLEWord(WORD p_iVal)
92 return (((p_iVal & 0x00FF) << 8) |
93 ((p_iVal & 0xFF00) >> 8));
97 static DWORD FromLEDWord(DWORD p_iVal)
99 return (((p_iVal & 0x000000FF) << 24) |
100 ((p_iVal & 0x0000FF00) << 8) |
101 ((p_iVal & 0x00FF0000) >> 8) |
102 ((p_iVal & 0xFF000000) >> 24));
104 #else
105 #define FromLEWord(X) (X)
106 #define FromLEDWord(X) (X)
107 #endif
109 #define DISPATCH_HREF_OFFSET 0x01000000
110 #define DISPATCH_HREF_MASK 0xff000000
112 /****************************************************************************
113 * FromLExxx
115 * Fix byte order in any structure if necessary
117 #ifdef WORDS_BIGENDIAN
118 static void FromLEWords(void *p_Val, int p_iSize)
120 WORD *Val = p_Val;
122 p_iSize /= sizeof(WORD);
124 while (p_iSize) {
125 *Val = FromLEWord(*Val);
126 Val++;
127 p_iSize--;
132 static void FromLEDWords(void *p_Val, int p_iSize)
134 DWORD *Val = p_Val;
136 p_iSize /= sizeof(DWORD);
138 while (p_iSize) {
139 *Val = FromLEDWord(*Val);
140 Val++;
141 p_iSize--;
144 #else
145 #define FromLEWords(X,Y) /*nothing*/
146 #define FromLEDWords(X,Y) /*nothing*/
147 #endif
150 * Find a typelib key which matches a requested maj.min version.
152 static BOOL find_typelib_key( REFGUID guid, WORD wMaj, WORD *wMin )
154 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
155 WCHAR buffer[60];
156 char key_name[16];
157 DWORD len, i;
158 INT best_min = -1;
159 HKEY hkey;
161 memcpy( buffer, typelibW, sizeof(typelibW) );
162 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
164 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
165 return FALSE;
167 len = sizeof(key_name);
168 i = 0;
169 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
171 INT v_maj, v_min;
173 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
175 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
177 if (wMaj == v_maj)
179 if (*wMin == v_min)
181 best_min = v_min;
182 break; /* exact match */
184 if (v_min > best_min) best_min = v_min;
187 len = sizeof(key_name);
189 RegCloseKey( hkey );
190 if (best_min >= 0)
192 *wMin = best_min;
193 return TRUE;
195 return FALSE;
198 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
199 /* buffer must be at least 60 characters long */
200 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
202 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
203 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
205 memcpy( buffer, TypelibW, sizeof(TypelibW) );
206 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
207 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
208 return buffer;
211 /* get the path of an interface key, in the form "Interface\\<guid>" */
212 /* buffer must be at least 50 characters long */
213 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
215 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
217 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
218 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
219 return buffer;
222 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
223 /* buffer must be at least 16 characters long */
224 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
226 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
227 static const WCHAR win16W[] = {'w','i','n','1','6',0};
228 static const WCHAR win32W[] = {'w','i','n','3','2',0};
230 sprintfW( buffer, LcidFormatW, lcid );
231 switch(syskind)
233 case SYS_WIN16: strcatW( buffer, win16W ); break;
234 case SYS_WIN32: strcatW( buffer, win32W ); break;
235 default:
236 TRACE("Typelib is for unsupported syskind %i\n", syskind);
237 return NULL;
239 return buffer;
242 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
245 /****************************************************************************
246 * QueryPathOfRegTypeLib [OLEAUT32.164]
248 * Gets the path to a registered type library.
250 * PARAMS
251 * guid [I] referenced guid
252 * wMaj [I] major version
253 * wMin [I] minor version
254 * lcid [I] locale id
255 * path [O] path of typelib
257 * RETURNS
258 * Success: S_OK.
259 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
260 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
261 * opened.
263 HRESULT WINAPI QueryPathOfRegTypeLib(
264 REFGUID guid,
265 WORD wMaj,
266 WORD wMin,
267 LCID lcid,
268 LPBSTR path )
270 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
271 LCID myLCID = lcid;
272 HKEY hkey;
273 WCHAR buffer[60];
274 WCHAR Path[MAX_PATH];
275 LONG res;
277 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
279 if (!find_typelib_key( guid, wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
280 get_typelib_key( guid, wMaj, wMin, buffer );
282 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
283 if (res == ERROR_FILE_NOT_FOUND)
285 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
286 return TYPE_E_LIBNOTREGISTERED;
288 else if (res != ERROR_SUCCESS)
290 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
291 return TYPE_E_REGISTRYACCESS;
294 while (hr != S_OK)
296 LONG dwPathLen = sizeof(Path);
298 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
300 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
302 if (!lcid)
303 break;
304 else if (myLCID == lcid)
306 /* try with sub-langid */
307 myLCID = SUBLANGID(lcid);
309 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
311 /* try with system langid */
312 myLCID = 0;
314 else
316 break;
319 else
321 *path = SysAllocString( Path );
322 hr = S_OK;
325 RegCloseKey( hkey );
326 TRACE_(typelib)("-- 0x%08x\n", hr);
327 return hr;
330 /******************************************************************************
331 * CreateTypeLib [OLEAUT32.160] creates a typelib
333 * RETURNS
334 * Success: S_OK
335 * Failure: Status
337 HRESULT WINAPI CreateTypeLib(
338 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
340 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
341 return E_FAIL;
344 /******************************************************************************
345 * LoadTypeLib [OLEAUT32.161]
347 * Loads a type library
349 * PARAMS
350 * szFile [I] Name of file to load from.
351 * pptLib [O] Pointer that receives ITypeLib object on success.
353 * RETURNS
354 * Success: S_OK
355 * Failure: Status
357 * SEE
358 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
360 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
362 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
363 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
366 /******************************************************************************
367 * LoadTypeLibEx [OLEAUT32.183]
369 * Loads and optionally registers a type library
371 * RETURNS
372 * Success: S_OK
373 * Failure: Status
375 HRESULT WINAPI LoadTypeLibEx(
376 LPCOLESTR szFile, /* [in] Name of file to load from */
377 REGKIND regkind, /* [in] Specify kind of registration */
378 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
380 WCHAR szPath[MAX_PATH+1];
381 HRESULT res;
383 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
385 *pptLib = NULL;
387 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
389 if (SUCCEEDED(res))
390 switch(regkind)
392 case REGKIND_DEFAULT:
393 /* don't register typelibs supplied with full path. Experimentation confirms the following */
394 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
395 (szFile[0] && (szFile[1] == ':'))) break;
396 /* else fall-through */
398 case REGKIND_REGISTER:
399 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
401 IUnknown_Release(*pptLib);
402 *pptLib = 0;
404 break;
405 case REGKIND_NONE:
406 break;
409 TRACE(" returns %08x\n",res);
410 return res;
413 /******************************************************************************
414 * LoadRegTypeLib [OLEAUT32.162]
416 * Loads a registered type library.
418 * PARAMS
419 * rguid [I] GUID of the registered type library.
420 * wVerMajor [I] major version.
421 * wVerMinor [I] minor version.
422 * lcid [I] locale ID.
423 * ppTLib [O] pointer that receives an ITypeLib object on success.
425 * RETURNS
426 * Success: S_OK.
427 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
428 * LoadTypeLib.
430 HRESULT WINAPI LoadRegTypeLib(
431 REFGUID rguid,
432 WORD wVerMajor,
433 WORD wVerMinor,
434 LCID lcid,
435 ITypeLib **ppTLib)
437 BSTR bstr=NULL;
438 HRESULT res;
440 *ppTLib = NULL;
442 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
444 if(SUCCEEDED(res))
446 res= LoadTypeLib(bstr, ppTLib);
447 SysFreeString(bstr);
450 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
452 return res;
456 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
457 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
458 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
459 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
460 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
461 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
463 /******************************************************************************
464 * RegisterTypeLib [OLEAUT32.163]
465 * Adds information about a type library to the System Registry
466 * NOTES
467 * Docs: ITypeLib FAR * ptlib
468 * Docs: OLECHAR FAR* szFullPath
469 * Docs: OLECHAR FAR* szHelpDir
471 * RETURNS
472 * Success: S_OK
473 * Failure: Status
475 HRESULT WINAPI RegisterTypeLib(
476 ITypeLib * ptlib, /* [in] Pointer to the library*/
477 OLECHAR * szFullPath, /* [in] full Path of the library*/
478 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
479 may be NULL*/
481 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
482 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
483 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
484 HRESULT res;
485 TLIBATTR *attr;
486 WCHAR keyName[60];
487 WCHAR tmp[16];
488 HKEY key, subKey;
489 UINT types, tidx;
490 TYPEKIND kind;
491 DWORD disposition;
493 if (ptlib == NULL || szFullPath == NULL)
494 return E_INVALIDARG;
496 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
497 return E_FAIL;
499 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
501 res = S_OK;
502 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
503 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
505 LPOLESTR doc;
507 /* Set the human-readable name of the typelib */
508 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
510 if (RegSetValueExW(key, NULL, 0, REG_SZ,
511 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
512 res = E_FAIL;
514 SysFreeString(doc);
516 else
517 res = E_FAIL;
519 /* Make up the name of the typelib path subkey */
520 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
522 /* Create the typelib path subkey */
523 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
524 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
526 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
527 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
528 res = E_FAIL;
530 RegCloseKey(subKey);
532 else
533 res = E_FAIL;
535 /* Create the flags subkey */
536 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
537 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
539 /* FIXME: is %u correct? */
540 static const WCHAR formatW[] = {'%','u',0};
541 WCHAR buf[20];
542 sprintfW(buf, formatW, attr->wLibFlags);
543 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
544 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
545 res = E_FAIL;
547 RegCloseKey(subKey);
549 else
550 res = E_FAIL;
552 /* create the helpdir subkey */
553 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
554 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
556 BOOL freeHelpDir = FALSE;
557 OLECHAR* pIndexStr;
559 /* if we created a new key, and helpDir was null, set the helpdir
560 to the directory which contains the typelib. However,
561 if we just opened an existing key, we leave the helpdir alone */
562 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
563 szHelpDir = SysAllocString(szFullPath);
564 pIndexStr = strrchrW(szHelpDir, '\\');
565 if (pIndexStr) {
566 *pIndexStr = 0;
568 freeHelpDir = TRUE;
571 /* if we have an szHelpDir, set it! */
572 if (szHelpDir != NULL) {
573 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
574 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
575 res = E_FAIL;
579 /* tidy up */
580 if (freeHelpDir) SysFreeString(szHelpDir);
581 RegCloseKey(subKey);
583 } else {
584 res = E_FAIL;
587 RegCloseKey(key);
589 else
590 res = E_FAIL;
592 /* register OLE Automation-compatible interfaces for this typelib */
593 types = ITypeLib_GetTypeInfoCount(ptlib);
594 for (tidx=0; tidx<types; tidx++) {
595 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
596 LPOLESTR name = NULL;
597 ITypeInfo *tinfo = NULL;
599 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
601 switch (kind) {
602 case TKIND_INTERFACE:
603 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
604 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
605 break;
607 case TKIND_DISPATCH:
608 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
609 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
610 break;
612 default:
613 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
614 break;
617 if (tinfo) {
618 TYPEATTR *tattr = NULL;
619 ITypeInfo_GetTypeAttr(tinfo, &tattr);
621 if (tattr) {
622 TRACE_(typelib)("guid=%s, flags=%04x (",
623 debugstr_guid(&tattr->guid),
624 tattr->wTypeFlags);
626 if (TRACE_ON(typelib)) {
627 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
628 XX(FAPPOBJECT);
629 XX(FCANCREATE);
630 XX(FLICENSED);
631 XX(FPREDECLID);
632 XX(FHIDDEN);
633 XX(FCONTROL);
634 XX(FDUAL);
635 XX(FNONEXTENSIBLE);
636 XX(FOLEAUTOMATION);
637 XX(FRESTRICTED);
638 XX(FAGGREGATABLE);
639 XX(FREPLACEABLE);
640 XX(FDISPATCHABLE);
641 XX(FREVERSEBIND);
642 XX(FPROXY);
643 #undef XX
644 MESSAGE("\n");
647 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL|TYPEFLAG_FDISPATCHABLE))
649 /* register interface<->typelib coupling */
650 get_interface_key( &tattr->guid, keyName );
651 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
652 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
654 if (name)
655 RegSetValueExW(key, NULL, 0, REG_SZ,
656 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
658 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
659 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
660 RegSetValueExW(subKey, NULL, 0, REG_SZ,
661 (const BYTE *)PSOA, sizeof PSOA);
662 RegCloseKey(subKey);
665 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
666 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
667 RegSetValueExW(subKey, NULL, 0, REG_SZ,
668 (const BYTE *)PSOA, sizeof PSOA);
669 RegCloseKey(subKey);
672 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
673 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
675 WCHAR buffer[40];
676 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
677 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
679 StringFromGUID2(&attr->guid, buffer, 40);
680 RegSetValueExW(subKey, NULL, 0, REG_SZ,
681 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
682 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
683 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
684 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
685 RegCloseKey(subKey);
688 RegCloseKey(key);
692 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
695 ITypeInfo_Release(tinfo);
698 SysFreeString(name);
702 ITypeLib_ReleaseTLibAttr(ptlib, attr);
704 return res;
708 /******************************************************************************
709 * UnRegisterTypeLib [OLEAUT32.186]
710 * Removes information about a type library from the System Registry
711 * NOTES
713 * RETURNS
714 * Success: S_OK
715 * Failure: Status
717 HRESULT WINAPI UnRegisterTypeLib(
718 REFGUID libid, /* [in] Guid of the library */
719 WORD wVerMajor, /* [in] major version */
720 WORD wVerMinor, /* [in] minor version */
721 LCID lcid, /* [in] locale id */
722 SYSKIND syskind)
724 BSTR tlibPath = NULL;
725 DWORD tmpLength;
726 WCHAR keyName[60];
727 WCHAR subKeyName[50];
728 int result = S_OK;
729 DWORD i = 0;
730 BOOL deleteOtherStuff;
731 HKEY key = NULL;
732 HKEY subKey = NULL;
733 TYPEATTR* typeAttr = NULL;
734 TYPEKIND kind;
735 ITypeInfo* typeInfo = NULL;
736 ITypeLib* typeLib = NULL;
737 int numTypes;
739 TRACE("(IID: %s)\n",debugstr_guid(libid));
741 /* Create the path to the key */
742 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
744 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
746 TRACE("Unsupported syskind %i\n", syskind);
747 result = E_INVALIDARG;
748 goto end;
751 /* get the path to the typelib on disk */
752 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
753 result = E_INVALIDARG;
754 goto end;
757 /* Try and open the key to the type library. */
758 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
759 result = E_INVALIDARG;
760 goto end;
763 /* Try and load the type library */
764 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
765 result = TYPE_E_INVALIDSTATE;
766 goto end;
769 /* remove any types registered with this typelib */
770 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
771 for (i=0; i<numTypes; i++) {
772 /* get the kind of type */
773 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
774 goto enddeleteloop;
777 /* skip non-interfaces, and get type info for the type */
778 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
779 goto enddeleteloop;
781 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
782 goto enddeleteloop;
784 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
785 goto enddeleteloop;
788 /* the path to the type */
789 get_interface_key( &typeAttr->guid, subKeyName );
791 /* Delete its bits */
792 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS) {
793 goto enddeleteloop;
795 RegDeleteKeyW(subKey, ProxyStubClsidW);
796 RegDeleteKeyW(subKey, ProxyStubClsid32W);
797 RegDeleteKeyW(subKey, TypeLibW);
798 RegCloseKey(subKey);
799 subKey = NULL;
800 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
802 enddeleteloop:
803 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
804 typeAttr = NULL;
805 if (typeInfo) ITypeInfo_Release(typeInfo);
806 typeInfo = NULL;
809 /* Now, delete the type library path subkey */
810 get_lcid_subkey( lcid, syskind, subKeyName );
811 RegDeleteKeyW(key, subKeyName);
812 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
813 RegDeleteKeyW(key, subKeyName);
815 /* check if there is anything besides the FLAGS/HELPDIR keys.
816 If there is, we don't delete them */
817 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
818 deleteOtherStuff = TRUE;
819 i = 0;
820 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
821 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
823 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
824 if (!strcmpW(subKeyName, FLAGSW)) continue;
825 if (!strcmpW(subKeyName, HELPDIRW)) continue;
826 deleteOtherStuff = FALSE;
827 break;
830 /* only delete the other parts of the key if we're absolutely sure */
831 if (deleteOtherStuff) {
832 RegDeleteKeyW(key, FLAGSW);
833 RegDeleteKeyW(key, HELPDIRW);
834 RegCloseKey(key);
835 key = NULL;
837 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
838 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
839 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
842 end:
843 SysFreeString(tlibPath);
844 if (typeLib) ITypeLib_Release(typeLib);
845 if (subKey) RegCloseKey(subKey);
846 if (key) RegCloseKey(key);
847 return result;
850 /*======================= ITypeLib implementation =======================*/
852 typedef struct tagTLBCustData
854 GUID guid;
855 VARIANT data;
856 struct tagTLBCustData* next;
857 } TLBCustData;
859 /* data structure for import typelibs */
860 typedef struct tagTLBImpLib
862 int offset; /* offset in the file (MSFT)
863 offset in nametable (SLTG)
864 just used to identify library while reading
865 data from file */
866 GUID guid; /* libid */
867 BSTR name; /* name */
869 LCID lcid; /* lcid of imported typelib */
871 WORD wVersionMajor; /* major version number */
872 WORD wVersionMinor; /* minor version number */
874 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
875 NULL if not yet loaded */
876 struct tagTLBImpLib * next;
877 } TLBImpLib;
879 /* internal ITypeLib data */
880 typedef struct tagITypeLibImpl
882 const ITypeLib2Vtbl *lpVtbl;
883 const ITypeCompVtbl *lpVtblTypeComp;
884 LONG ref;
885 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
887 /* strings can be stored in tlb as multibyte strings BUT they are *always*
888 * exported to the application as a UNICODE string.
890 BSTR Name;
891 BSTR DocString;
892 BSTR HelpFile;
893 BSTR HelpStringDll;
894 unsigned long dwHelpContext;
895 int TypeInfoCount; /* nr of typeinfo's in librarry */
896 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
897 int ctCustData; /* number of items in cust data list */
898 TLBCustData * pCustData; /* linked list to cust data */
899 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
900 int ctTypeDesc; /* number of items in type desc array */
901 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
902 library. Only used while reading MSFT
903 typelibs */
904 struct list ref_list; /* list of ref types in this typelib */
905 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
908 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
909 struct tagITypeLibImpl *next, *prev;
910 WCHAR *path;
911 INT index;
912 } ITypeLibImpl;
914 static const ITypeLib2Vtbl tlbvt;
915 static const ITypeCompVtbl tlbtcvt;
917 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
919 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
922 /* ITypeLib methods */
923 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
924 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
926 /*======================= ITypeInfo implementation =======================*/
928 /* data for referenced types */
929 typedef struct tagTLBRefType
931 INT index; /* Type index for internal ref or for external ref
932 it the format is SLTG. -2 indicates to
933 use guid */
935 GUID guid; /* guid of the referenced type */
936 /* if index == TLB_REF_USE_GUID */
938 HREFTYPE reference; /* The href of this ref */
939 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
940 TLB_REF_INTERNAL for internal refs
941 TLB_REF_NOT_FOUND for broken refs */
943 struct list entry;
944 } TLBRefType;
946 #define TLB_REF_USE_GUID -2
948 #define TLB_REF_INTERNAL (void*)-2
949 #define TLB_REF_NOT_FOUND (void*)-1
951 /* internal Parameter data */
952 typedef struct tagTLBParDesc
954 BSTR Name;
955 int ctCustData;
956 TLBCustData * pCustData; /* linked list to cust data */
957 } TLBParDesc;
959 /* internal Function data */
960 typedef struct tagTLBFuncDesc
962 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
963 BSTR Name; /* the name of this function */
964 TLBParDesc *pParamDesc; /* array with param names and custom data */
965 int helpcontext;
966 int HelpStringContext;
967 BSTR HelpString;
968 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
969 int ctCustData;
970 TLBCustData * pCustData; /* linked list to cust data; */
971 struct tagTLBFuncDesc * next;
972 } TLBFuncDesc;
974 /* internal Variable data */
975 typedef struct tagTLBVarDesc
977 VARDESC vardesc; /* lots of info on the variable and its attributes. */
978 BSTR Name; /* the name of this variable */
979 int HelpContext;
980 int HelpStringContext; /* FIXME: where? */
981 BSTR HelpString;
982 int ctCustData;
983 TLBCustData * pCustData;/* linked list to cust data; */
984 struct tagTLBVarDesc * next;
985 } TLBVarDesc;
987 /* internal implemented interface data */
988 typedef struct tagTLBImplType
990 HREFTYPE hRef; /* hRef of interface */
991 int implflags; /* IMPLFLAG_*s */
992 int ctCustData;
993 TLBCustData * pCustData;/* linked list to custom data; */
994 struct tagTLBImplType *next;
995 } TLBImplType;
997 /* internal TypeInfo data */
998 typedef struct tagITypeInfoImpl
1000 const ITypeInfo2Vtbl *lpVtbl;
1001 const ITypeCompVtbl *lpVtblTypeComp;
1002 LONG ref;
1003 BOOL no_free_data; /* don't free data structures */
1004 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1005 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1006 int index; /* index in this typelib; */
1007 HREFTYPE hreftype; /* hreftype for app object binding */
1008 /* type libs seem to store the doc strings in ascii
1009 * so why should we do it in unicode?
1011 BSTR Name;
1012 BSTR DocString;
1013 BSTR DllName;
1014 unsigned long dwHelpContext;
1015 unsigned long dwHelpStringContext;
1017 /* functions */
1018 TLBFuncDesc * funclist; /* linked list with function descriptions */
1020 /* variables */
1021 TLBVarDesc * varlist; /* linked list with variable descriptions */
1023 /* Implemented Interfaces */
1024 TLBImplType * impltypelist;
1026 int ctCustData;
1027 TLBCustData * pCustData; /* linked list to cust data; */
1028 struct tagITypeInfoImpl * next;
1029 } ITypeInfoImpl;
1031 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1033 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1036 static const ITypeInfo2Vtbl tinfvt;
1037 static const ITypeCompVtbl tcompvt;
1039 static ITypeInfo2 * ITypeInfo_Constructor(void);
1041 typedef struct tagTLBContext
1043 unsigned int oStart; /* start of TLB in file */
1044 unsigned int pos; /* current pos */
1045 unsigned int length; /* total length */
1046 void *mapping; /* memory mapping */
1047 MSFT_SegDir * pTblDir;
1048 ITypeLibImpl* pLibInfo;
1049 } TLBContext;
1052 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1055 debug
1057 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1058 if (pTD->vt & VT_RESERVED)
1059 szVarType += strlen(strcpy(szVarType, "reserved | "));
1060 if (pTD->vt & VT_BYREF)
1061 szVarType += strlen(strcpy(szVarType, "ref to "));
1062 if (pTD->vt & VT_ARRAY)
1063 szVarType += strlen(strcpy(szVarType, "array of "));
1064 if (pTD->vt & VT_VECTOR)
1065 szVarType += strlen(strcpy(szVarType, "vector of "));
1066 switch(pTD->vt & VT_TYPEMASK) {
1067 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1068 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1069 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1070 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1071 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1072 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1073 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1074 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1075 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1076 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1077 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1078 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1079 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1080 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1081 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1082 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1083 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1084 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1085 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1086 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1087 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1088 pTD->u.hreftype); break;
1089 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1090 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1091 case VT_PTR: sprintf(szVarType, "ptr to ");
1092 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1093 break;
1094 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1095 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1096 break;
1097 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1098 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1099 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1100 break;
1102 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1106 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1107 char buf[200];
1108 USHORT flags = edesc->u.paramdesc.wParamFlags;
1109 dump_TypeDesc(&edesc->tdesc,buf);
1110 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1111 MESSAGE("\t\tu.paramdesc.wParamFlags");
1112 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1113 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1114 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1115 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1116 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1117 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1118 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1119 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1120 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1122 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1123 int i;
1124 MESSAGE("memid is %08x\n",funcdesc->memid);
1125 for (i=0;i<funcdesc->cParams;i++) {
1126 MESSAGE("Param %d:\n",i);
1127 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1129 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1130 switch (funcdesc->funckind) {
1131 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1132 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1133 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1134 case FUNC_STATIC: MESSAGE("static");break;
1135 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1136 default: MESSAGE("unknown");break;
1138 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1139 switch (funcdesc->invkind) {
1140 case INVOKE_FUNC: MESSAGE("func");break;
1141 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1142 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1143 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1145 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1146 switch (funcdesc->callconv) {
1147 case CC_CDECL: MESSAGE("cdecl");break;
1148 case CC_PASCAL: MESSAGE("pascal");break;
1149 case CC_STDCALL: MESSAGE("stdcall");break;
1150 case CC_SYSCALL: MESSAGE("syscall");break;
1151 default:break;
1153 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1154 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1155 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1157 MESSAGE("\telemdescFunc (return value type):\n");
1158 dump_ELEMDESC(&funcdesc->elemdescFunc);
1161 static const char * const typekind_desc[] =
1163 "TKIND_ENUM",
1164 "TKIND_RECORD",
1165 "TKIND_MODULE",
1166 "TKIND_INTERFACE",
1167 "TKIND_DISPATCH",
1168 "TKIND_COCLASS",
1169 "TKIND_ALIAS",
1170 "TKIND_UNION",
1171 "TKIND_MAX"
1174 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1176 int i;
1177 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1178 for (i=0;i<pfd->funcdesc.cParams;i++)
1179 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1182 dump_FUNCDESC(&(pfd->funcdesc));
1184 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1185 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1187 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1189 while (pfd)
1191 dump_TLBFuncDescOne(pfd);
1192 pfd = pfd->next;
1195 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1197 while (pvd)
1199 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1200 pvd = pvd->next;
1204 static void dump_TLBImpLib(const TLBImpLib *import)
1206 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1207 debugstr_w(import->name));
1208 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1209 import->wVersionMinor, import->lcid, import->offset);
1212 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1214 TLBRefType *ref;
1216 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1218 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1219 if(ref->index == -1)
1220 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1221 else
1222 TRACE_(typelib)("type no: %d\n", ref->index);
1224 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1226 TRACE_(typelib)("in lib\n");
1227 dump_TLBImpLib(ref->pImpTLInfo);
1232 static void dump_TLBImplType(const TLBImplType * impl)
1234 while (impl) {
1235 TRACE_(typelib)(
1236 "implementing/inheriting interface hRef = %x implflags %x\n",
1237 impl->hRef, impl->implflags);
1238 impl = impl->next;
1242 static void dump_Variant(const VARIANT * pvar)
1244 SYSTEMTIME st;
1246 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1248 if (pvar)
1250 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1251 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1253 TRACE(",%p", V_BYREF(pvar));
1255 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1257 TRACE(",%p", V_ARRAY(pvar));
1259 else switch (V_TYPE(pvar))
1261 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1262 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1263 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1264 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1265 case VT_INT:
1266 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1267 case VT_UINT:
1268 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1269 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1270 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1271 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1272 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1273 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1274 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1275 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1276 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1277 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1278 V_CY(pvar).s.Lo); break;
1279 case VT_DATE:
1280 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1281 TRACE(",<invalid>");
1282 else
1283 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1284 st.wHour, st.wMinute, st.wSecond);
1285 break;
1286 case VT_ERROR:
1287 case VT_VOID:
1288 case VT_USERDEFINED:
1289 case VT_EMPTY:
1290 case VT_NULL: break;
1291 default: TRACE(",?"); break;
1294 TRACE("}\n");
1297 static void dump_DispParms(const DISPPARAMS * pdp)
1299 unsigned int index;
1301 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1303 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1305 TRACE("named args:\n");
1306 for (index = 0; index < pdp->cNamedArgs; index++)
1307 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1310 if (pdp->cArgs && pdp->rgvarg)
1312 TRACE("args:\n");
1313 for (index = 0; index < pdp->cArgs; index++)
1314 dump_Variant( &pdp->rgvarg[index] );
1318 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1320 TRACE("%p ref=%u\n", pty, pty->ref);
1321 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1322 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1323 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1324 TRACE("fct:%u var:%u impl:%u\n",
1325 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1326 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1327 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1328 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1329 if (TRACE_ON(ole))
1330 dump_TLBFuncDesc(pty->funclist);
1331 dump_TLBVarDesc(pty->varlist);
1332 dump_TLBImplType(pty->impltypelist);
1335 static void dump_VARDESC(const VARDESC *v)
1337 MESSAGE("memid %d\n",v->memid);
1338 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1339 MESSAGE("oInst %d\n",v->u.oInst);
1340 dump_ELEMDESC(&(v->elemdescVar));
1341 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1342 MESSAGE("varkind %d\n",v->varkind);
1345 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1347 /* VT_LPWSTR is largest type that */
1348 /* may appear in type description*/
1349 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1350 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1351 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1352 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1353 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1354 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1355 {{0},30},{{0},31}
1358 static void TLB_abort(void)
1360 DebugBreak();
1363 static void * TLB_Alloc(unsigned size) __WINE_ALLOC_SIZE(1);
1364 static void * TLB_Alloc(unsigned size)
1366 void * ret;
1367 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1368 /* FIXME */
1369 ERR("cannot allocate memory\n");
1371 return ret;
1374 static void TLB_Free(void * ptr)
1376 HeapFree(GetProcessHeap(), 0, ptr);
1379 /* returns the size required for a deep copy of a typedesc into a
1380 * flat buffer */
1381 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1383 SIZE_T size = 0;
1385 if (alloc_initial_space)
1386 size += sizeof(TYPEDESC);
1388 switch (tdesc->vt)
1390 case VT_PTR:
1391 case VT_SAFEARRAY:
1392 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1393 break;
1394 case VT_CARRAY:
1395 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1396 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1397 break;
1399 return size;
1402 /* deep copy a typedesc into a flat buffer */
1403 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1405 if (!dest)
1407 dest = buffer;
1408 buffer = (char *)buffer + sizeof(TYPEDESC);
1411 *dest = *src;
1413 switch (src->vt)
1415 case VT_PTR:
1416 case VT_SAFEARRAY:
1417 dest->u.lptdesc = buffer;
1418 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1419 break;
1420 case VT_CARRAY:
1421 dest->u.lpadesc = buffer;
1422 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1423 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1424 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1425 break;
1427 return buffer;
1430 /* free custom data allocated by MSFT_CustData */
1431 static inline void TLB_FreeCustData(TLBCustData *pCustData)
1433 TLBCustData *pCustDataNext;
1434 for (; pCustData; pCustData = pCustDataNext)
1436 VariantClear(&pCustData->data);
1438 pCustDataNext = pCustData->next;
1439 TLB_Free(pCustData);
1443 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1445 DWORD len;
1446 BSTR ret;
1448 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1449 ret = SysAllocStringLen(NULL, len - 1);
1450 if (!ret) return ret;
1451 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1452 return ret;
1455 /**********************************************************************
1457 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1459 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1461 return pcx->pos;
1464 static inline void MSFT_Seek(TLBContext *pcx, long where)
1466 if (where != DO_NOT_SEEK)
1468 where += pcx->oStart;
1469 if (where > pcx->length)
1471 /* FIXME */
1472 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1473 TLB_abort();
1475 pcx->pos = where;
1479 /* read function */
1480 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1482 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1483 pcx->pos, count, pcx->oStart, pcx->length, where);
1485 MSFT_Seek(pcx, where);
1486 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1487 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1488 pcx->pos += count;
1489 return count;
1492 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1493 long where )
1495 DWORD ret;
1497 ret = MSFT_Read(buffer, count, pcx, where);
1498 FromLEDWords(buffer, ret);
1500 return ret;
1503 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1504 long where )
1506 DWORD ret;
1508 ret = MSFT_Read(buffer, count, pcx, where);
1509 FromLEWords(buffer, ret);
1511 return ret;
1514 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1516 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1517 memset(pGuid,0, sizeof(GUID));
1518 return;
1520 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1521 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1522 pGuid->Data2 = FromLEWord(pGuid->Data2);
1523 pGuid->Data3 = FromLEWord(pGuid->Data3);
1524 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1527 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1529 MSFT_NameIntro niName;
1531 if (offset < 0)
1533 ERR_(typelib)("bad offset %d\n", offset);
1534 return -1;
1537 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1538 pcx->pTblDir->pNametab.offset+offset);
1540 return niName.hreftype;
1543 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1545 char * name;
1546 MSFT_NameIntro niName;
1547 int lengthInChars;
1548 BSTR bstrName = NULL;
1550 if (offset < 0)
1552 ERR_(typelib)("bad offset %d\n", offset);
1553 return NULL;
1555 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1556 pcx->pTblDir->pNametab.offset+offset);
1557 niName.namelen &= 0xFF; /* FIXME: correct ? */
1558 name=TLB_Alloc((niName.namelen & 0xff) +1);
1559 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1560 name[niName.namelen & 0xff]='\0';
1562 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1563 name, -1, NULL, 0);
1565 /* no invalid characters in string */
1566 if (lengthInChars)
1568 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1570 /* don't check for invalid character since this has been done previously */
1571 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1573 TLB_Free(name);
1575 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1576 return bstrName;
1579 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1581 char * string;
1582 INT16 length;
1583 int lengthInChars;
1584 BSTR bstr = NULL;
1586 if(offset<0) return NULL;
1587 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1588 if(length <= 0) return 0;
1589 string=TLB_Alloc(length +1);
1590 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1591 string[length]='\0';
1593 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1594 string, -1, NULL, 0);
1596 /* no invalid characters in string */
1597 if (lengthInChars)
1599 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1601 /* don't check for invalid character since this has been done previously */
1602 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1604 TLB_Free(string);
1606 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1607 return bstr;
1610 * read a value and fill a VARIANT structure
1612 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1614 int size;
1616 TRACE_(typelib)("\n");
1618 if(offset <0) { /* data are packed in here */
1619 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1620 V_I4(pVar) = offset & 0x3ffffff;
1621 return;
1623 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1624 pcx->pTblDir->pCustData.offset + offset );
1625 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1626 switch (V_VT(pVar)){
1627 case VT_EMPTY: /* FIXME: is this right? */
1628 case VT_NULL: /* FIXME: is this right? */
1629 case VT_I2 : /* this should not happen */
1630 case VT_I4 :
1631 case VT_R4 :
1632 case VT_ERROR :
1633 case VT_BOOL :
1634 case VT_I1 :
1635 case VT_UI1 :
1636 case VT_UI2 :
1637 case VT_UI4 :
1638 case VT_INT :
1639 case VT_UINT :
1640 case VT_VOID : /* FIXME: is this right? */
1641 case VT_HRESULT :
1642 size=4; break;
1643 case VT_R8 :
1644 case VT_CY :
1645 case VT_DATE :
1646 case VT_I8 :
1647 case VT_UI8 :
1648 case VT_DECIMAL : /* FIXME: is this right? */
1649 case VT_FILETIME :
1650 size=8;break;
1651 /* pointer types with known behaviour */
1652 case VT_BSTR :{
1653 char * ptr;
1654 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1655 if(size < 0) {
1656 char next;
1657 DWORD origPos = MSFT_Tell(pcx), nullPos;
1659 do {
1660 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1661 } while (next);
1662 nullPos = MSFT_Tell(pcx);
1663 size = nullPos - origPos;
1664 MSFT_Seek(pcx, origPos);
1666 ptr=TLB_Alloc(size);/* allocate temp buffer */
1667 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1668 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1669 /* FIXME: do we need a AtoW conversion here? */
1670 V_UNION(pVar, bstrVal[size])='\0';
1671 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1672 TLB_Free(ptr);
1674 size=-4; break;
1675 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1676 case VT_DISPATCH :
1677 case VT_VARIANT :
1678 case VT_UNKNOWN :
1679 case VT_PTR :
1680 case VT_SAFEARRAY :
1681 case VT_CARRAY :
1682 case VT_USERDEFINED :
1683 case VT_LPSTR :
1684 case VT_LPWSTR :
1685 case VT_BLOB :
1686 case VT_STREAM :
1687 case VT_STORAGE :
1688 case VT_STREAMED_OBJECT :
1689 case VT_STORED_OBJECT :
1690 case VT_BLOB_OBJECT :
1691 case VT_CF :
1692 case VT_CLSID :
1693 default:
1694 size=0;
1695 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1696 V_VT(pVar));
1699 if(size>0) /* (big|small) endian correct? */
1700 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1701 return;
1704 * create a linked list with custom data
1706 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1708 MSFT_CDGuid entry;
1709 TLBCustData* pNew;
1710 int count=0;
1712 TRACE_(typelib)("\n");
1714 while(offset >=0){
1715 count++;
1716 pNew=TLB_Alloc(sizeof(TLBCustData));
1717 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1718 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1719 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1720 /* add new custom data at head of the list */
1721 pNew->next=*ppCustData;
1722 *ppCustData=pNew;
1723 offset = entry.next;
1725 return count;
1728 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1729 ITypeInfoImpl *pTI)
1731 if(type <0)
1732 pTd->vt=type & VT_TYPEMASK;
1733 else
1734 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1736 if(pTd->vt == VT_USERDEFINED)
1737 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1739 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1742 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1744 /* resolve referenced type if any */
1745 while (lpTypeDesc)
1747 switch (lpTypeDesc->vt)
1749 case VT_PTR:
1750 lpTypeDesc = lpTypeDesc->u.lptdesc;
1751 break;
1753 case VT_CARRAY:
1754 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1755 break;
1757 case VT_USERDEFINED:
1758 MSFT_DoRefType(pcx, pTI->pTypeLib,
1759 lpTypeDesc->u.hreftype);
1761 lpTypeDesc = NULL;
1762 break;
1764 default:
1765 lpTypeDesc = NULL;
1770 static void
1771 MSFT_DoFuncs(TLBContext* pcx,
1772 ITypeInfoImpl* pTI,
1773 int cFuncs,
1774 int cVars,
1775 int offset,
1776 TLBFuncDesc** pptfd)
1779 * member information is stored in a data structure at offset
1780 * indicated by the memoffset field of the typeinfo structure
1781 * There are several distinctive parts.
1782 * The first part starts with a field that holds the total length
1783 * of this (first) part excluding this field. Then follow the records,
1784 * for each member there is one record.
1786 * The first entry is always the length of the record (including this
1787 * length word).
1788 * The rest of the record depends on the type of the member. If there is
1789 * a field indicating the member type (function, variable, interface, etc)
1790 * I have not found it yet. At this time we depend on the information
1791 * in the type info and the usual order how things are stored.
1793 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1794 * for each member;
1796 * Third is an equal sized array with file offsets to the name entry
1797 * of each member.
1799 * The fourth and last (?) part is an array with offsets to the records
1800 * in the first part of this file segment.
1803 int infolen, nameoffset, reclength, nrattributes, i;
1804 int recoffset = offset + sizeof(INT);
1806 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1807 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1808 TLBFuncDesc *ptfd_prev = NULL;
1810 TRACE_(typelib)("\n");
1812 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1814 for ( i = 0; i < cFuncs ; i++ )
1816 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1818 /* name, eventually add to a hash table */
1819 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1820 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1822 /* nameoffset is sometimes -1 on the second half of a propget/propput
1823 * pair of functions */
1824 if ((nameoffset == -1) && (i > 0))
1825 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1826 else
1827 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1829 /* read the function information record */
1830 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1832 reclength &= 0xffff;
1834 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1836 /* do the attributes */
1837 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1838 / sizeof(int);
1840 if ( nrattributes > 0 )
1842 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1844 if ( nrattributes > 1 )
1846 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1847 pFuncRec->OptAttr[1]) ;
1849 if ( nrattributes > 2 )
1851 if ( pFuncRec->FKCCIC & 0x2000 )
1853 if (HIWORD(pFuncRec->OptAttr[2]) != 0)
1854 ERR("ordinal 0x%08x invalid, HIWORD != 0\n", pFuncRec->OptAttr[2]);
1855 (*pptfd)->Entry = (BSTR)pFuncRec->OptAttr[2];
1857 else
1859 (*pptfd)->Entry = MSFT_ReadString(pcx,
1860 pFuncRec->OptAttr[2]);
1862 if( nrattributes > 5 )
1864 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1866 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1868 MSFT_CustData(pcx,
1869 pFuncRec->OptAttr[6],
1870 &(*pptfd)->pCustData);
1874 else
1876 (*pptfd)->Entry = (BSTR)-1;
1881 /* fill the FuncDesc Structure */
1882 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1883 offset + infolen + ( i + 1) * sizeof(INT));
1885 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1886 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1887 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1888 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1889 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1890 (*pptfd)->funcdesc.oVft = (pFuncRec->VtableOffset * sizeof(void *))/4;
1891 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1893 MSFT_GetTdesc(pcx,
1894 pFuncRec->DataType,
1895 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1896 pTI);
1897 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1899 /* do the parameters/arguments */
1900 if(pFuncRec->nrargs)
1902 int j = 0;
1903 MSFT_ParameterInfo paraminfo;
1905 (*pptfd)->funcdesc.lprgelemdescParam =
1906 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1908 (*pptfd)->pParamDesc =
1909 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1911 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1912 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1914 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1916 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1918 MSFT_GetTdesc(pcx,
1919 paraminfo.DataType,
1920 &elemdesc->tdesc,
1921 pTI);
1923 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1925 /* name */
1926 if (paraminfo.oName == -1)
1927 /* this occurs for [propput] or [propget] methods, so
1928 * we should just set the name of the parameter to the
1929 * name of the method. */
1930 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1931 else
1932 (*pptfd)->pParamDesc[j].Name =
1933 MSFT_ReadName( pcx, paraminfo.oName );
1934 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1936 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1938 /* default value */
1939 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1940 (pFuncRec->FKCCIC & 0x1000) )
1942 INT* pInt = (INT *)((char *)pFuncRec +
1943 reclength -
1944 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1946 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1948 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1949 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1951 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1952 pInt[j], pcx);
1954 else
1955 elemdesc->u.paramdesc.pparamdescex = NULL;
1956 /* custom info */
1957 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1959 MSFT_CustData(pcx,
1960 pFuncRec->OptAttr[7+j],
1961 &(*pptfd)->pParamDesc[j].pCustData);
1964 /* SEEK value = jump to offset,
1965 * from there jump to the end of record,
1966 * go back by (j-1) arguments
1968 MSFT_ReadLEDWords( &paraminfo ,
1969 sizeof(MSFT_ParameterInfo), pcx,
1970 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1971 * sizeof(MSFT_ParameterInfo)));
1975 /* scode is not used: archaic win16 stuff FIXME: right? */
1976 (*pptfd)->funcdesc.cScodes = 0 ;
1977 (*pptfd)->funcdesc.lprgscode = NULL ;
1979 ptfd_prev = *pptfd;
1980 pptfd = & ((*pptfd)->next);
1981 recoffset += reclength;
1983 HeapFree(GetProcessHeap(), 0, recbuf);
1986 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1987 int cVars, int offset, TLBVarDesc ** pptvd)
1989 int infolen, nameoffset, reclength;
1990 char recbuf[256];
1991 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1992 int i;
1993 int recoffset;
1995 TRACE_(typelib)("\n");
1997 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1998 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1999 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2000 recoffset += offset+sizeof(INT);
2001 for(i=0;i<cVars;i++){
2002 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
2003 /* name, eventually add to a hash table */
2004 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2005 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2006 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
2007 /* read the variable information record */
2008 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
2009 reclength &=0xff;
2010 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
2011 /* Optional data */
2012 if(reclength >(6*sizeof(INT)) )
2013 (*pptvd)->HelpContext=pVarRec->HelpContext;
2014 if(reclength >(7*sizeof(INT)) )
2015 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
2016 if(reclength >(8*sizeof(INT)) )
2017 if(reclength >(9*sizeof(INT)) )
2018 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
2019 /* fill the VarDesc Structure */
2020 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
2021 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2022 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
2023 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
2024 MSFT_GetTdesc(pcx, pVarRec->DataType,
2025 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
2026 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2027 if(pVarRec->VarKind == VAR_CONST ){
2028 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
2029 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
2030 pVarRec->OffsValue, pcx);
2031 } else
2032 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
2033 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
2034 pptvd=&((*pptvd)->next);
2035 recoffset += reclength;
2038 /* fill in data for a hreftype (offset). When the referenced type is contained
2039 * in the typelib, it's just an (file) offset in the type info base dir.
2040 * If comes from import, it's an offset+1 in the ImpInfo table
2041 * */
2042 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2043 int offset)
2045 TLBRefType *ref;
2047 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2049 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2051 if(ref->reference == offset) return;
2054 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
2055 list_add_tail(&pTL->ref_list, &ref->entry);
2057 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2058 /* external typelib */
2059 MSFT_ImpInfo impinfo;
2060 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2062 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2064 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2065 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2066 while (pImpLib){ /* search the known offsets of all import libraries */
2067 if(pImpLib->offset==impinfo.oImpFile) break;
2068 pImpLib=pImpLib->next;
2070 if(pImpLib){
2071 ref->reference = offset;
2072 ref->pImpTLInfo = pImpLib;
2073 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2074 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2075 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2076 ref->index = TLB_REF_USE_GUID;
2077 } else
2078 ref->index = impinfo.oGuid;
2079 }else{
2080 ERR("Cannot find a reference\n");
2081 ref->reference = -1;
2082 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2084 }else{
2085 /* in this typelib */
2086 ref->index = MSFT_HREFTYPE_INDEX(offset);
2087 ref->reference = offset;
2088 ref->pImpTLInfo = TLB_REF_INTERNAL;
2092 /* process Implemented Interfaces of a com class */
2093 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2094 int offset)
2096 int i;
2097 MSFT_RefRecord refrec;
2098 TLBImplType **ppImpl = &pTI->impltypelist;
2100 TRACE_(typelib)("\n");
2102 for(i=0;i<count;i++){
2103 if(offset<0) break; /* paranoia */
2104 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2105 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2106 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2107 (*ppImpl)->hRef = refrec.reftype;
2108 (*ppImpl)->implflags=refrec.flags;
2109 (*ppImpl)->ctCustData=
2110 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2111 offset=refrec.onext;
2112 ppImpl=&((*ppImpl)->next);
2116 * process a typeinfo record
2118 static ITypeInfoImpl * MSFT_DoTypeInfo(
2119 TLBContext *pcx,
2120 int count,
2121 ITypeLibImpl * pLibInfo)
2123 MSFT_TypeInfoBase tiBase;
2124 ITypeInfoImpl *ptiRet;
2126 TRACE_(typelib)("count=%u\n", count);
2128 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2129 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2130 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2132 /* this is where we are coming from */
2133 ptiRet->pTypeLib = pLibInfo;
2134 ptiRet->index=count;
2135 /* fill in the typeattr fields */
2137 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2138 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2139 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2140 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2141 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2142 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2143 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2144 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2145 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2146 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2147 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2148 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2149 ptiRet->TypeAttr.cbSizeVft=(tiBase.cbSizeVft * sizeof(void *))/4; /* FIXME: this is only the non inherited part */
2150 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2151 MSFT_GetTdesc(pcx, tiBase.datatype1,
2152 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2154 /* FIXME: */
2155 /* IDLDESC idldescType; *//* never saw this one != zero */
2157 /* name, eventually add to a hash table */
2158 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2159 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2160 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2161 /* help info */
2162 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2163 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2164 ptiRet->dwHelpContext=tiBase.helpcontext;
2166 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2167 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2169 /* note: InfoType's Help file and HelpStringDll come from the containing
2170 * library. Further HelpString and Docstring appear to be the same thing :(
2172 /* functions */
2173 if(ptiRet->TypeAttr.cFuncs >0 )
2174 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2175 ptiRet->TypeAttr.cVars,
2176 tiBase.memoffset, & ptiRet->funclist);
2177 /* variables */
2178 if(ptiRet->TypeAttr.cVars >0 )
2179 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2180 ptiRet->TypeAttr.cVars,
2181 tiBase.memoffset, & ptiRet->varlist);
2182 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2183 switch(ptiRet->TypeAttr.typekind)
2185 case TKIND_COCLASS:
2186 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2187 tiBase.datatype1);
2188 break;
2189 case TKIND_DISPATCH:
2190 /* This is not -1 when the interface is a non-base dual interface or
2191 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2192 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2193 not this interface.
2196 if (tiBase.datatype1 != -1)
2198 ptiRet->impltypelist = TLB_Alloc(sizeof(TLBImplType));
2199 ptiRet->impltypelist->hRef = tiBase.datatype1;
2200 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2202 break;
2203 default:
2204 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2205 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2206 ptiRet->impltypelist->hRef = tiBase.datatype1;
2207 break;
2210 ptiRet->ctCustData=
2211 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2213 TRACE_(typelib)("%s guid: %s kind:%s\n",
2214 debugstr_w(ptiRet->Name),
2215 debugstr_guid(&ptiRet->TypeAttr.guid),
2216 typekind_desc[ptiRet->TypeAttr.typekind]);
2217 if (TRACE_ON(typelib))
2218 dump_TypeInfo(ptiRet);
2220 return ptiRet;
2223 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2224 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2225 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2226 * tradeoff here.
2228 static ITypeLibImpl *tlb_cache_first;
2229 static CRITICAL_SECTION cache_section;
2230 static CRITICAL_SECTION_DEBUG cache_section_debug =
2232 0, 0, &cache_section,
2233 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2234 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2236 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2239 typedef struct TLB_PEFile
2241 const IUnknownVtbl *lpvtbl;
2242 LONG refs;
2243 HMODULE dll;
2244 HRSRC typelib_resource;
2245 HGLOBAL typelib_global;
2246 LPVOID typelib_base;
2247 } TLB_PEFile;
2249 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2251 if (IsEqualIID(riid, &IID_IUnknown))
2253 *ppv = iface;
2254 IUnknown_AddRef(iface);
2255 return S_OK;
2257 *ppv = NULL;
2258 return E_NOINTERFACE;
2261 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2263 TLB_PEFile *This = (TLB_PEFile *)iface;
2264 return InterlockedIncrement(&This->refs);
2267 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2269 TLB_PEFile *This = (TLB_PEFile *)iface;
2270 ULONG refs = InterlockedDecrement(&This->refs);
2271 if (!refs)
2273 if (This->typelib_global)
2274 FreeResource(This->typelib_global);
2275 if (This->dll)
2276 FreeLibrary(This->dll);
2277 HeapFree(GetProcessHeap(), 0, This);
2279 return refs;
2282 static const IUnknownVtbl TLB_PEFile_Vtable =
2284 TLB_PEFile_QueryInterface,
2285 TLB_PEFile_AddRef,
2286 TLB_PEFile_Release
2289 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2291 TLB_PEFile *This;
2293 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2294 if (!This)
2295 return E_OUTOFMEMORY;
2297 This->lpvtbl = &TLB_PEFile_Vtable;
2298 This->refs = 1;
2299 This->dll = NULL;
2300 This->typelib_resource = NULL;
2301 This->typelib_global = NULL;
2302 This->typelib_base = NULL;
2304 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2305 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2307 if (This->dll)
2309 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2310 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2311 if (This->typelib_resource)
2313 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2314 if (This->typelib_global)
2316 This->typelib_base = LockResource(This->typelib_global);
2318 if (This->typelib_base)
2320 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2321 *ppBase = This->typelib_base;
2322 *ppFile = (IUnknown *)&This->lpvtbl;
2323 return S_OK;
2329 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2330 return TYPE_E_CANTLOADLIBRARY;
2333 typedef struct TLB_NEFile
2335 const IUnknownVtbl *lpvtbl;
2336 LONG refs;
2337 LPVOID typelib_base;
2338 } TLB_NEFile;
2340 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2342 if (IsEqualIID(riid, &IID_IUnknown))
2344 *ppv = iface;
2345 IUnknown_AddRef(iface);
2346 return S_OK;
2348 *ppv = NULL;
2349 return E_NOINTERFACE;
2352 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2354 TLB_NEFile *This = (TLB_NEFile *)iface;
2355 return InterlockedIncrement(&This->refs);
2358 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2360 TLB_NEFile *This = (TLB_NEFile *)iface;
2361 ULONG refs = InterlockedDecrement(&This->refs);
2362 if (!refs)
2364 HeapFree(GetProcessHeap(), 0, This->typelib_base);
2365 HeapFree(GetProcessHeap(), 0, This);
2367 return refs;
2370 static const IUnknownVtbl TLB_NEFile_Vtable =
2372 TLB_NEFile_QueryInterface,
2373 TLB_NEFile_AddRef,
2374 TLB_NEFile_Release
2377 /***********************************************************************
2378 * read_xx_header [internal]
2380 static int read_xx_header( HFILE lzfd )
2382 IMAGE_DOS_HEADER mzh;
2383 char magic[3];
2385 LZSeek( lzfd, 0, SEEK_SET );
2386 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2387 return 0;
2388 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2389 return 0;
2391 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2392 if ( 2 != LZRead( lzfd, magic, 2 ) )
2393 return 0;
2395 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2397 if ( magic[0] == 'N' && magic[1] == 'E' )
2398 return IMAGE_OS2_SIGNATURE;
2399 if ( magic[0] == 'P' && magic[1] == 'E' )
2400 return IMAGE_NT_SIGNATURE;
2402 magic[2] = '\0';
2403 WARN("Can't handle %s files.\n", magic );
2404 return 0;
2408 /***********************************************************************
2409 * find_ne_resource [internal]
2411 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2412 DWORD *resLen, DWORD *resOff )
2414 IMAGE_OS2_HEADER nehd;
2415 NE_TYPEINFO *typeInfo;
2416 NE_NAMEINFO *nameInfo;
2417 DWORD nehdoffset;
2418 LPBYTE resTab;
2419 DWORD resTabSize;
2420 int count;
2422 /* Read in NE header */
2423 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2424 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2426 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2427 if ( !resTabSize )
2429 TRACE("No resources in NE dll\n" );
2430 return FALSE;
2433 /* Read in resource table */
2434 resTab = HeapAlloc( GetProcessHeap(), 0, resTabSize );
2435 if ( !resTab ) return FALSE;
2437 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2438 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2440 HeapFree( GetProcessHeap(), 0, resTab );
2441 return FALSE;
2444 /* Find resource */
2445 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2447 if (HIWORD(typeid) != 0) /* named type */
2449 BYTE len = strlen( typeid );
2450 while (typeInfo->type_id)
2452 if (!(typeInfo->type_id & 0x8000))
2454 BYTE *p = resTab + typeInfo->type_id;
2455 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2457 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2458 typeInfo->count * sizeof(NE_NAMEINFO));
2461 else /* numeric type id */
2463 WORD id = LOWORD(typeid) | 0x8000;
2464 while (typeInfo->type_id)
2466 if (typeInfo->type_id == id) goto found_type;
2467 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2468 typeInfo->count * sizeof(NE_NAMEINFO));
2471 TRACE("No typeid entry found for %p\n", typeid );
2472 HeapFree( GetProcessHeap(), 0, resTab );
2473 return FALSE;
2475 found_type:
2476 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2478 if (HIWORD(resid) != 0) /* named resource */
2480 BYTE len = strlen( resid );
2481 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2483 BYTE *p = resTab + nameInfo->id;
2484 if (nameInfo->id & 0x8000) continue;
2485 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2488 else /* numeric resource id */
2490 WORD id = LOWORD(resid) | 0x8000;
2491 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2492 if (nameInfo->id == id) goto found_name;
2494 TRACE("No resid entry found for %p\n", typeid );
2495 HeapFree( GetProcessHeap(), 0, resTab );
2496 return FALSE;
2498 found_name:
2499 /* Return resource data */
2500 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2501 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2503 HeapFree( GetProcessHeap(), 0, resTab );
2504 return TRUE;
2507 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
2509 HFILE lzfd = -1;
2510 OFSTRUCT ofs;
2511 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2512 TLB_NEFile *This = NULL;
2514 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2515 if (!This) return E_OUTOFMEMORY;
2517 This->lpvtbl = &TLB_NEFile_Vtable;
2518 This->refs = 1;
2519 This->typelib_base = NULL;
2521 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
2522 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
2524 DWORD reslen, offset;
2525 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
2527 This->typelib_base = HeapAlloc(GetProcessHeap(), 0, reslen);
2528 if( !This->typelib_base )
2529 hr = E_OUTOFMEMORY;
2530 else
2532 LZSeek( lzfd, offset, SEEK_SET );
2533 reslen = LZRead( lzfd, This->typelib_base, reslen );
2534 LZClose( lzfd );
2535 *ppBase = This->typelib_base;
2536 *pdwTLBLength = reslen;
2537 *ppFile = (IUnknown *)&This->lpvtbl;
2538 return S_OK;
2543 if( lzfd >= 0) LZClose( lzfd );
2544 TLB_NEFile_Release((IUnknown *)&This->lpvtbl);
2545 return hr;
2548 typedef struct TLB_Mapping
2550 const IUnknownVtbl *lpvtbl;
2551 LONG refs;
2552 HANDLE file;
2553 HANDLE mapping;
2554 LPVOID typelib_base;
2555 } TLB_Mapping;
2557 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2559 if (IsEqualIID(riid, &IID_IUnknown))
2561 *ppv = iface;
2562 IUnknown_AddRef(iface);
2563 return S_OK;
2565 *ppv = NULL;
2566 return E_NOINTERFACE;
2569 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2571 TLB_Mapping *This = (TLB_Mapping *)iface;
2572 return InterlockedIncrement(&This->refs);
2575 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2577 TLB_Mapping *This = (TLB_Mapping *)iface;
2578 ULONG refs = InterlockedDecrement(&This->refs);
2579 if (!refs)
2581 if (This->typelib_base)
2582 UnmapViewOfFile(This->typelib_base);
2583 if (This->mapping)
2584 CloseHandle(This->mapping);
2585 if (This->file != INVALID_HANDLE_VALUE)
2586 CloseHandle(This->file);
2587 HeapFree(GetProcessHeap(), 0, This);
2589 return refs;
2592 static const IUnknownVtbl TLB_Mapping_Vtable =
2594 TLB_Mapping_QueryInterface,
2595 TLB_Mapping_AddRef,
2596 TLB_Mapping_Release
2599 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2601 TLB_Mapping *This;
2603 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2604 if (!This)
2605 return E_OUTOFMEMORY;
2607 This->lpvtbl = &TLB_Mapping_Vtable;
2608 This->refs = 1;
2609 This->file = INVALID_HANDLE_VALUE;
2610 This->mapping = NULL;
2611 This->typelib_base = NULL;
2613 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2614 if (INVALID_HANDLE_VALUE != This->file)
2616 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2617 if (This->mapping)
2619 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2620 if(This->typelib_base)
2622 /* retrieve file size */
2623 *pdwTLBLength = GetFileSize(This->file, NULL);
2624 *ppBase = This->typelib_base;
2625 *ppFile = (IUnknown *)&This->lpvtbl;
2626 return S_OK;
2631 IUnknown_Release((IUnknown *)&This->lpvtbl);
2632 return TYPE_E_CANTLOADLIBRARY;
2635 /****************************************************************************
2636 * TLB_ReadTypeLib
2638 * find the type of the typelib file and map the typelib resource into
2639 * the memory
2641 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2642 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2643 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2645 ITypeLibImpl *entry;
2646 HRESULT ret;
2647 INT index = 1;
2648 LPWSTR index_str, file = (LPWSTR)pszFileName;
2649 LPVOID pBase = NULL;
2650 DWORD dwTLBLength = 0;
2651 IUnknown *pFile = NULL;
2653 *ppTypeLib = NULL;
2655 index_str = strrchrW(pszFileName, '\\');
2656 if(index_str && *++index_str != '\0')
2658 LPWSTR end_ptr;
2659 long idx = strtolW(index_str, &end_ptr, 10);
2660 if(*end_ptr == '\0')
2662 int str_len = index_str - pszFileName - 1;
2663 index = idx;
2664 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
2665 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2666 file[str_len] = 0;
2670 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2672 if(strchrW(file, '\\'))
2674 lstrcpyW(pszPath, file);
2676 else
2678 int len = GetSystemDirectoryW(pszPath, cchPath);
2679 pszPath[len] = '\\';
2680 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2684 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file);
2686 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2688 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2689 EnterCriticalSection(&cache_section);
2690 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2692 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2694 TRACE("cache hit\n");
2695 *ppTypeLib = (ITypeLib2*)entry;
2696 ITypeLib_AddRef(*ppTypeLib);
2697 LeaveCriticalSection(&cache_section);
2698 return S_OK;
2701 LeaveCriticalSection(&cache_section);
2703 /* now actually load and parse the typelib */
2705 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2706 if (ret == TYPE_E_CANTLOADLIBRARY)
2707 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2708 if (ret == TYPE_E_CANTLOADLIBRARY)
2709 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2710 if (SUCCEEDED(ret))
2712 if (dwTLBLength >= 4)
2714 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2715 if (dwSignature == MSFT_SIGNATURE)
2716 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2717 else if (dwSignature == SLTG_SIGNATURE)
2718 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2719 else
2721 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2722 ret = TYPE_E_CANTLOADLIBRARY;
2725 else
2726 ret = TYPE_E_CANTLOADLIBRARY;
2727 IUnknown_Release(pFile);
2730 if(*ppTypeLib) {
2731 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2733 TRACE("adding to cache\n");
2734 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2735 lstrcpyW(impl->path, pszPath);
2736 /* We should really canonicalise the path here. */
2737 impl->index = index;
2739 /* FIXME: check if it has added already in the meantime */
2740 EnterCriticalSection(&cache_section);
2741 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2742 impl->prev = NULL;
2743 tlb_cache_first = impl;
2744 LeaveCriticalSection(&cache_section);
2745 ret = S_OK;
2746 } else
2747 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2749 return ret;
2752 /*================== ITypeLib(2) Methods ===================================*/
2754 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2756 ITypeLibImpl* pTypeLibImpl;
2758 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2759 if (!pTypeLibImpl) return NULL;
2761 pTypeLibImpl->lpVtbl = &tlbvt;
2762 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2763 pTypeLibImpl->ref = 1;
2765 list_init(&pTypeLibImpl->ref_list);
2766 pTypeLibImpl->dispatch_href = -1;
2768 return pTypeLibImpl;
2771 /****************************************************************************
2772 * ITypeLib2_Constructor_MSFT
2774 * loading an MSFT typelib from an in-memory image
2776 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2778 TLBContext cx;
2779 long lPSegDir;
2780 MSFT_Header tlbHeader;
2781 MSFT_SegDir tlbSegDir;
2782 ITypeLibImpl * pTypeLibImpl;
2784 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2786 pTypeLibImpl = TypeLibImpl_Constructor();
2787 if (!pTypeLibImpl) return NULL;
2789 /* get pointer to beginning of typelib data */
2790 cx.pos = 0;
2791 cx.oStart=0;
2792 cx.mapping = pLib;
2793 cx.pLibInfo = pTypeLibImpl;
2794 cx.length = dwTLBLength;
2796 /* read header */
2797 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2798 TRACE_(typelib)("header:\n");
2799 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2800 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2801 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2802 return NULL;
2804 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2806 /* there is a small amount of information here until the next important
2807 * part:
2808 * the segment directory . Try to calculate the amount of data */
2809 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2811 /* now read the segment directory */
2812 TRACE("read segment directory (at %ld)\n",lPSegDir);
2813 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2814 cx.pTblDir = &tlbSegDir;
2816 /* just check two entries */
2817 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2819 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2820 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2821 return NULL;
2824 /* now fill our internal data */
2825 /* TLIBATTR fields */
2826 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2828 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2829 /* Windows seems to have zero here, is this correct? */
2830 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2831 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2832 else
2833 pTypeLibImpl->LibAttr.lcid = 0;
2835 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2836 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2837 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2838 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2840 /* name, eventually add to a hash table */
2841 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2843 /* help info */
2844 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2845 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2847 if( tlbHeader.varflags & HELPDLLFLAG)
2849 int offset;
2850 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2851 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2854 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2856 /* custom data */
2857 if(tlbHeader.CustomDataOffset >= 0)
2859 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2862 /* fill in type descriptions */
2863 if(tlbSegDir.pTypdescTab.length > 0)
2865 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2866 INT16 td[4];
2867 pTypeLibImpl->ctTypeDesc = cTD;
2868 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2869 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2870 for(i=0; i<cTD; )
2872 /* FIXME: add several sanity checks here */
2873 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2874 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2876 /* FIXME: check safearray */
2877 if(td[3] < 0)
2878 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2879 else
2880 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2882 else if(td[0] == VT_CARRAY)
2884 /* array descr table here */
2885 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2887 else if(td[0] == VT_USERDEFINED)
2889 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2891 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2894 /* second time around to fill the array subscript info */
2895 for(i=0;i<cTD;i++)
2897 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2898 if(tlbSegDir.pArrayDescriptions.offset>0)
2900 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2901 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2903 if(td[1]<0)
2904 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2905 else
2906 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2908 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2910 for(j = 0; j<td[2]; j++)
2912 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2913 sizeof(INT), &cx, DO_NOT_SEEK);
2914 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2915 sizeof(INT), &cx, DO_NOT_SEEK);
2918 else
2920 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2921 ERR("didn't find array description data\n");
2926 /* imported type libs */
2927 if(tlbSegDir.pImpFiles.offset>0)
2929 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2930 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2931 UINT16 size;
2933 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2935 char *name;
2937 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2938 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2939 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2941 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2942 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2943 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2944 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2946 size >>= 2;
2947 name = TLB_Alloc(size+1);
2948 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2949 (*ppImpLib)->name = TLB_MultiByteToBSTR(name);
2951 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2952 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2954 ppImpLib = &(*ppImpLib)->next;
2958 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
2959 if(pTypeLibImpl->dispatch_href != -1)
2960 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
2962 /* type info's */
2963 if(tlbHeader.nrtypeinfos >= 0 )
2965 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2966 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2967 int i;
2969 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
2971 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2973 ppTI = &((*ppTI)->next);
2974 (pTypeLibImpl->TypeInfoCount)++;
2978 TRACE("(%p)\n", pTypeLibImpl);
2979 return (ITypeLib2*) pTypeLibImpl;
2983 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
2985 char b[3];
2986 int i;
2987 short s;
2989 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2990 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2991 return FALSE;
2994 guid->Data4[0] = s >> 8;
2995 guid->Data4[1] = s & 0xff;
2997 b[2] = '\0';
2998 for(i = 0; i < 6; i++) {
2999 memcpy(b, str + 24 + 2 * i, 2);
3000 guid->Data4[i + 2] = strtol(b, NULL, 16);
3002 return TRUE;
3005 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
3007 WORD bytelen;
3008 DWORD len;
3010 *pBstr = NULL;
3011 bytelen = *(const WORD*)ptr;
3012 if(bytelen == 0xffff) return 2;
3013 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3014 *pBstr = SysAllocStringLen(NULL, len - 1);
3015 if (*pBstr)
3016 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
3017 return bytelen + 2;
3020 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3022 WORD bytelen;
3024 *str = NULL;
3025 bytelen = *(const WORD*)ptr;
3026 if(bytelen == 0xffff) return 2;
3027 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
3028 memcpy(*str, ptr + 2, bytelen);
3029 (*str)[bytelen] = '\0';
3030 return bytelen + 2;
3033 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3035 char *ptr = pLibBlk;
3036 WORD w;
3038 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3039 FIXME("libblk magic = %04x\n", w);
3040 return 0;
3043 ptr += 6;
3044 if((w = *(WORD*)ptr) != 0xffff) {
3045 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3046 ptr += w;
3048 ptr += 2;
3050 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
3052 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
3054 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3055 ptr += 4;
3057 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
3058 ptr += 2;
3060 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3061 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3062 else
3063 pTypeLibImpl->LibAttr.lcid = 0;
3064 ptr += 2;
3066 ptr += 4; /* skip res12 */
3068 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
3069 ptr += 2;
3071 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
3072 ptr += 2;
3074 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
3075 ptr += 2;
3077 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
3078 ptr += sizeof(GUID);
3080 return ptr - (char*)pLibBlk;
3083 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3084 typedef struct
3086 unsigned int num;
3087 HREFTYPE refs[1];
3088 } sltg_ref_lookup_t;
3090 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3091 HREFTYPE *typelib_ref)
3093 if(typeinfo_ref < table->num)
3095 *typelib_ref = table->refs[typeinfo_ref];
3096 return S_OK;
3099 ERR_(typelib)("Unable to find reference\n");
3100 *typelib_ref = -1;
3101 return E_FAIL;
3104 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3106 BOOL done = FALSE;
3108 while(!done) {
3109 if((*pType & 0xe00) == 0xe00) {
3110 pTD->vt = VT_PTR;
3111 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3112 sizeof(TYPEDESC));
3113 pTD = pTD->u.lptdesc;
3115 switch(*pType & 0x3f) {
3116 case VT_PTR:
3117 pTD->vt = VT_PTR;
3118 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3119 sizeof(TYPEDESC));
3120 pTD = pTD->u.lptdesc;
3121 break;
3123 case VT_USERDEFINED:
3124 pTD->vt = VT_USERDEFINED;
3125 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3126 done = TRUE;
3127 break;
3129 case VT_CARRAY:
3131 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3132 array */
3134 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3136 pTD->vt = VT_CARRAY;
3137 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3138 sizeof(ARRAYDESC) +
3139 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3140 pTD->u.lpadesc->cDims = pSA->cDims;
3141 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3142 pSA->cDims * sizeof(SAFEARRAYBOUND));
3144 pTD = &pTD->u.lpadesc->tdescElem;
3145 break;
3148 case VT_SAFEARRAY:
3150 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3151 useful? */
3153 pType++;
3154 pTD->vt = VT_SAFEARRAY;
3155 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3156 sizeof(TYPEDESC));
3157 pTD = pTD->u.lptdesc;
3158 break;
3160 default:
3161 pTD->vt = *pType & 0x3f;
3162 done = TRUE;
3163 break;
3165 pType++;
3167 return pType;
3170 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3171 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3173 /* Handle [in/out] first */
3174 if((*pType & 0xc000) == 0xc000)
3175 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3176 else if(*pType & 0x8000)
3177 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3178 else if(*pType & 0x4000)
3179 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3180 else
3181 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3183 if(*pType & 0x2000)
3184 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3186 if(*pType & 0x80)
3187 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3189 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3193 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3194 char *pNameTable)
3196 unsigned int ref;
3197 char *name;
3198 TLBRefType *ref_type;
3199 sltg_ref_lookup_t *table;
3200 HREFTYPE typelib_ref;
3202 if(pRef->magic != SLTG_REF_MAGIC) {
3203 FIXME("Ref magic = %x\n", pRef->magic);
3204 return NULL;
3206 name = ( (char*)pRef->names + pRef->number);
3208 table = HeapAlloc(GetProcessHeap(), 0, sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3209 table->num = pRef->number >> 3;
3211 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3213 /* We don't want the first href to be 0 */
3214 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3216 for(ref = 0; ref < pRef->number >> 3; ref++) {
3217 char *refname;
3218 unsigned int lib_offs, type_num;
3220 ref_type = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref_type));
3222 name += SLTG_ReadStringA(name, &refname);
3223 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3224 FIXME_(typelib)("Can't sscanf ref\n");
3225 if(lib_offs != 0xffff) {
3226 TLBImpLib **import = &pTL->pImpLibs;
3228 while(*import) {
3229 if((*import)->offset == lib_offs)
3230 break;
3231 import = &(*import)->next;
3233 if(!*import) {
3234 char fname[MAX_PATH+1];
3235 int len;
3237 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3238 sizeof(**import));
3239 (*import)->offset = lib_offs;
3240 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3241 &(*import)->guid);
3242 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3243 &(*import)->wVersionMajor,
3244 &(*import)->wVersionMinor,
3245 &(*import)->lcid, fname) != 4) {
3246 FIXME_(typelib)("can't sscanf ref %s\n",
3247 pNameTable + lib_offs + 40);
3249 len = strlen(fname);
3250 if(fname[len-1] != '#')
3251 FIXME("fname = %s\n", fname);
3252 fname[len-1] = '\0';
3253 (*import)->name = TLB_MultiByteToBSTR(fname);
3255 ref_type->pImpTLInfo = *import;
3257 /* Store a reference to IDispatch */
3258 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
3259 pTL->dispatch_href = typelib_ref;
3261 } else { /* internal ref */
3262 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3264 ref_type->reference = typelib_ref;
3265 ref_type->index = type_num;
3267 HeapFree(GetProcessHeap(), 0, refname);
3268 list_add_tail(&pTL->ref_list, &ref_type->entry);
3270 table->refs[ref] = typelib_ref;
3271 typelib_ref += 4;
3273 if((BYTE)*name != SLTG_REF_MAGIC)
3274 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3275 dump_TLBRefType(pTL);
3276 return table;
3279 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3280 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3282 SLTG_ImplInfo *info;
3283 TLBImplType **ppImplType = &pTI->impltypelist;
3284 /* I don't really get this structure, usually it's 0x16 bytes
3285 long, but iuser.tlb contains some that are 0x18 bytes long.
3286 That's ok because we can use the next ptr to jump to the next
3287 one. But how do we know the length of the last one? The WORD
3288 at offs 0x8 might be the clue. For now I'm just assuming that
3289 the last one is the regular 0x16 bytes. */
3291 info = (SLTG_ImplInfo*)pBlk;
3292 while(1) {
3293 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3294 sizeof(**ppImplType));
3295 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef);
3296 (*ppImplType)->implflags = info->impltypeflags;
3297 pTI->TypeAttr.cImplTypes++;
3298 ppImplType = &(*ppImplType)->next;
3300 if(info->next == 0xffff)
3301 break;
3302 if(OneOnly)
3303 FIXME_(typelib)("Interface inheriting more than one interface\n");
3304 info = (SLTG_ImplInfo*)(pBlk + info->next);
3306 info++; /* see comment at top of function */
3307 return (char*)info;
3310 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3311 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3313 TLBVarDesc **ppVarDesc = &pTI->varlist;
3314 BSTR bstrPrevName = NULL;
3315 SLTG_Variable *pItem;
3316 unsigned short i;
3317 WORD *pType;
3319 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3320 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
3322 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3323 sizeof(**ppVarDesc));
3324 (*ppVarDesc)->vardesc.memid = pItem->memid;
3326 if (pItem->magic != SLTG_VAR_MAGIC &&
3327 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3328 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3329 return;
3332 if (pItem->name == 0xfffe)
3333 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
3334 else
3335 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3337 TRACE_(typelib)("name: %s\n", debugstr_w((*ppVarDesc)->Name));
3338 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3339 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3341 if(pItem->flags & 0x02)
3342 pType = &pItem->type;
3343 else
3344 pType = (WORD*)(pBlk + pItem->type);
3346 if (pItem->flags & ~0xda)
3347 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3349 SLTG_DoElem(pType, pBlk,
3350 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup);
3352 if (TRACE_ON(typelib)) {
3353 char buf[300];
3354 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3355 TRACE_(typelib)("elemdescVar: %s\n", buf);
3358 if (pItem->flags & 0x40) {
3359 TRACE_(typelib)("VAR_DISPATCH\n");
3360 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
3362 else if (pItem->flags & 0x10) {
3363 TRACE_(typelib)("VAR_CONST\n");
3364 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3365 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3366 sizeof(VARIANT));
3367 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3368 if (pItem->flags & 0x08)
3369 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) = pItem->byte_offs;
3370 else {
3371 switch ((*ppVarDesc)->vardesc.elemdescVar.tdesc.vt)
3373 case VT_LPSTR:
3374 case VT_LPWSTR:
3375 case VT_BSTR:
3377 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3378 BSTR str;
3379 TRACE_(typelib)("len = %u\n", len);
3380 if (len == 0xffff) {
3381 str = NULL;
3382 } else {
3383 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3384 str = SysAllocStringLen(NULL, alloc_len);
3385 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3387 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_BSTR;
3388 V_BSTR((*ppVarDesc)->vardesc.u.lpvarValue) = str;
3389 break;
3391 case VT_I2:
3392 case VT_UI2:
3393 case VT_I4:
3394 case VT_UI4:
3395 case VT_INT:
3396 case VT_UINT:
3397 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) =
3398 *(INT*)(pBlk + pItem->byte_offs);
3399 break;
3400 default:
3401 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt);
3405 else {
3406 TRACE_(typelib)("VAR_PERINSTANCE\n");
3407 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3408 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3411 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3412 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
3414 if (pItem->flags & 0x80)
3415 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3417 bstrPrevName = (*ppVarDesc)->Name;
3418 ppVarDesc = &((*ppVarDesc)->next);
3420 pTI->TypeAttr.cVars = cVars;
3423 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3424 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3426 SLTG_Function *pFunc;
3427 unsigned short i;
3428 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3430 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3431 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3433 int param;
3434 WORD *pType, *pArg;
3436 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3437 sizeof(**ppFuncDesc));
3439 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3440 case SLTG_FUNCTION_MAGIC:
3441 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3442 break;
3443 case SLTG_DISPATCH_FUNCTION_MAGIC:
3444 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3445 break;
3446 case SLTG_STATIC_FUNCTION_MAGIC:
3447 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3448 break;
3449 default:
3450 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3451 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
3452 *ppFuncDesc = NULL;
3453 return;
3455 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3457 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3458 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3459 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3460 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3461 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3462 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3464 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3465 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3467 if(pFunc->retnextopt & 0x80)
3468 pType = &pFunc->rettype;
3469 else
3470 pType = (WORD*)(pBlk + pFunc->rettype);
3472 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3474 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3475 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3476 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3477 (*ppFuncDesc)->pParamDesc =
3478 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3479 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3481 pArg = (WORD*)(pBlk + pFunc->arg_off);
3483 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3484 char *paramName = pNameTable + *pArg;
3485 BOOL HaveOffs;
3486 /* If arg type follows then paramName points to the 2nd
3487 letter of the name, else the next WORD is an offset to
3488 the arg type and paramName points to the first letter.
3489 So let's take one char off paramName and see if we're
3490 pointing at an alpha-numeric char. However if *pArg is
3491 0xffff or 0xfffe then the param has no name, the former
3492 meaning that the next WORD is the type, the latter
3493 meaning that the next WORD is an offset to the type. */
3495 HaveOffs = FALSE;
3496 if(*pArg == 0xffff)
3497 paramName = NULL;
3498 else if(*pArg == 0xfffe) {
3499 paramName = NULL;
3500 HaveOffs = TRUE;
3502 else if(paramName[-1] && !isalnum(paramName[-1]))
3503 HaveOffs = TRUE;
3505 pArg++;
3507 if(HaveOffs) { /* the next word is an offset to type */
3508 pType = (WORD*)(pBlk + *pArg);
3509 SLTG_DoElem(pType, pBlk,
3510 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3511 pArg++;
3512 } else {
3513 if(paramName)
3514 paramName--;
3515 pArg = SLTG_DoElem(pArg, pBlk,
3516 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3519 /* Are we an optional param ? */
3520 if((*ppFuncDesc)->funcdesc.cParams - param <=
3521 (*ppFuncDesc)->funcdesc.cParamsOpt)
3522 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3524 if(paramName) {
3525 (*ppFuncDesc)->pParamDesc[param].Name =
3526 TLB_MultiByteToBSTR(paramName);
3527 } else {
3528 (*ppFuncDesc)->pParamDesc[param].Name =
3529 SysAllocString((*ppFuncDesc)->Name);
3533 ppFuncDesc = &((*ppFuncDesc)->next);
3534 if(pFunc->next == 0xffff) break;
3536 pTI->TypeAttr.cFuncs = cFuncs;
3539 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3540 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3541 SLTG_TypeInfoTail *pTITail)
3543 char *pFirstItem;
3544 sltg_ref_lookup_t *ref_lookup = NULL;
3546 if(pTIHeader->href_table != 0xffffffff) {
3547 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3548 pNameTable);
3551 pFirstItem = pBlk;
3553 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3554 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3556 HeapFree(GetProcessHeap(), 0, ref_lookup);
3560 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3561 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3562 const SLTG_TypeInfoTail *pTITail)
3564 char *pFirstItem;
3565 sltg_ref_lookup_t *ref_lookup = NULL;
3567 if(pTIHeader->href_table != 0xffffffff) {
3568 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3569 pNameTable);
3572 pFirstItem = pBlk;
3574 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3575 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3578 if (pTITail->funcs_off != 0xffff)
3579 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3581 HeapFree(GetProcessHeap(), 0, ref_lookup);
3583 if (TRACE_ON(typelib))
3584 dump_TLBFuncDesc(pTI->funclist);
3587 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3588 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3589 const SLTG_TypeInfoTail *pTITail)
3591 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3594 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3595 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3596 const SLTG_TypeInfoTail *pTITail)
3598 WORD *pType;
3599 sltg_ref_lookup_t *ref_lookup = NULL;
3601 if (pTITail->simple_alias) {
3602 /* if simple alias, no more processing required */
3603 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3604 return;
3607 if(pTIHeader->href_table != 0xffffffff) {
3608 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3609 pNameTable);
3612 /* otherwise it is an offset to a type */
3613 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3615 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3617 HeapFree(GetProcessHeap(), 0, ref_lookup);
3620 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3621 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3622 const SLTG_TypeInfoTail *pTITail)
3624 sltg_ref_lookup_t *ref_lookup = NULL;
3625 if (pTIHeader->href_table != 0xffffffff)
3626 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3627 pNameTable);
3629 if (pTITail->vars_off != 0xffff)
3630 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3632 if (pTITail->funcs_off != 0xffff)
3633 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3635 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3636 * of dispinterface functions including the IDispatch ones, so
3637 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3638 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3640 HeapFree(GetProcessHeap(), 0, ref_lookup);
3641 if (TRACE_ON(typelib))
3642 dump_TLBFuncDesc(pTI->funclist);
3645 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3646 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3647 const SLTG_TypeInfoTail *pTITail)
3649 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3652 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3653 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3654 const SLTG_TypeInfoTail *pTITail)
3656 sltg_ref_lookup_t *ref_lookup = NULL;
3657 if (pTIHeader->href_table != 0xffffffff)
3658 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3659 pNameTable);
3661 if (pTITail->vars_off != 0xffff)
3662 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3664 if (pTITail->funcs_off != 0xffff)
3665 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3666 HeapFree(GetProcessHeap(), 0, ref_lookup);
3667 if (TRACE_ON(typelib))
3668 dump_TypeInfo(pTI);
3671 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3672 managable copy of it into this */
3673 typedef struct {
3674 WORD small_no;
3675 char *index_name;
3676 char *other_name;
3677 WORD res1a;
3678 WORD name_offs;
3679 WORD more_bytes;
3680 char *extra;
3681 WORD res20;
3682 DWORD helpcontext;
3683 WORD res26;
3684 GUID uuid;
3685 } SLTG_InternalOtherTypeInfo;
3687 /****************************************************************************
3688 * ITypeLib2_Constructor_SLTG
3690 * loading a SLTG typelib from an in-memory image
3692 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3694 ITypeLibImpl *pTypeLibImpl;
3695 SLTG_Header *pHeader;
3696 SLTG_BlkEntry *pBlkEntry;
3697 SLTG_Magic *pMagic;
3698 SLTG_Index *pIndex;
3699 SLTG_Pad9 *pPad9;
3700 LPVOID pBlk, pFirstBlk;
3701 SLTG_LibBlk *pLibBlk;
3702 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3703 char *pAfterOTIBlks = NULL;
3704 char *pNameTable, *ptr;
3705 int i;
3706 DWORD len, order;
3707 ITypeInfoImpl **ppTypeInfoImpl;
3709 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3712 pTypeLibImpl = TypeLibImpl_Constructor();
3713 if (!pTypeLibImpl) return NULL;
3715 pHeader = pLib;
3717 TRACE_(typelib)("header:\n");
3718 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3719 pHeader->nrOfFileBlks );
3720 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3721 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3722 pHeader->SLTG_magic);
3723 return NULL;
3726 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3727 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3729 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3730 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3732 /* Next we have a magic block */
3733 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3735 /* Let's see if we're still in sync */
3736 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3737 sizeof(SLTG_COMPOBJ_MAGIC))) {
3738 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3739 return NULL;
3741 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3742 sizeof(SLTG_DIR_MAGIC))) {
3743 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
3744 return NULL;
3747 pIndex = (SLTG_Index*)(pMagic+1);
3749 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3751 pFirstBlk = pPad9 + 1;
3753 /* We'll set up a ptr to the main library block, which is the last one. */
3755 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3756 pBlkEntry[order].next != 0;
3757 order = pBlkEntry[order].next - 1, i++) {
3758 pBlk = (char*)pBlk + pBlkEntry[order].len;
3760 pLibBlk = pBlk;
3762 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3764 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3765 interspersed */
3767 len += 0x40;
3769 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3771 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3772 sizeof(*pOtherTypeInfoBlks) *
3773 pTypeLibImpl->TypeInfoCount);
3776 ptr = (char*)pLibBlk + len;
3778 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3779 WORD w, extra;
3780 len = 0;
3782 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3784 w = *(WORD*)(ptr + 2);
3785 if(w != 0xffff) {
3786 len += w;
3787 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3788 w+1);
3789 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3790 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3792 w = *(WORD*)(ptr + 4 + len);
3793 if(w != 0xffff) {
3794 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3795 len += w;
3796 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3797 w+1);
3798 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3799 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3801 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3802 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3803 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3804 if(extra) {
3805 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3806 extra);
3807 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3808 len += extra;
3810 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3811 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3812 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3813 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3814 len += sizeof(SLTG_OtherTypeInfo);
3815 ptr += len;
3818 pAfterOTIBlks = ptr;
3820 /* Skip this WORD and get the next DWORD */
3821 len = *(DWORD*)(pAfterOTIBlks + 2);
3823 /* Now add this to pLibBLk look at what we're pointing at and
3824 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3825 dust and we should be pointing at the beginning of the name
3826 table */
3828 pNameTable = (char*)pLibBlk + len;
3830 switch(*(WORD*)pNameTable) {
3831 case 0xffff:
3832 break;
3833 case 0x0200:
3834 pNameTable += 0x20;
3835 break;
3836 default:
3837 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
3838 break;
3841 pNameTable += 0x216;
3843 pNameTable += 2;
3845 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
3847 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3850 /* Hopefully we now have enough ptrs set up to actually read in
3851 some TypeInfos. It's not clear which order to do them in, so
3852 I'll just follow the links along the BlkEntry chain and read
3853 them in the order in which they are in the file */
3855 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3857 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3858 pBlkEntry[order].next != 0;
3859 order = pBlkEntry[order].next - 1, i++) {
3861 SLTG_TypeInfoHeader *pTIHeader;
3862 SLTG_TypeInfoTail *pTITail;
3863 SLTG_MemberHeader *pMemHeader;
3865 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3866 pOtherTypeInfoBlks[i].index_name)) {
3867 FIXME_(typelib)("Index strings don't match\n");
3868 return NULL;
3871 pTIHeader = pBlk;
3872 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3873 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3874 return NULL;
3876 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
3877 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3878 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3880 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3881 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3882 (*ppTypeInfoImpl)->index = i;
3883 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3884 pOtherTypeInfoBlks[i].name_offs +
3885 pNameTable);
3886 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3887 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
3888 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3889 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3890 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3891 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3892 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3894 if((pTIHeader->typeflags1 & 7) != 2)
3895 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
3896 if(pTIHeader->typeflags3 != 2)
3897 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
3899 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3900 debugstr_w((*ppTypeInfoImpl)->Name),
3901 typekind_desc[pTIHeader->typekind],
3902 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3903 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3905 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3907 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3909 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3910 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3911 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = (pTITail->cbSizeVft * sizeof(void *))/4;
3913 switch(pTIHeader->typekind) {
3914 case TKIND_ENUM:
3915 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3916 pTIHeader, pTITail);
3917 break;
3919 case TKIND_RECORD:
3920 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3921 pTIHeader, pTITail);
3922 break;
3924 case TKIND_INTERFACE:
3925 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3926 pTIHeader, pTITail);
3927 break;
3929 case TKIND_COCLASS:
3930 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3931 pTIHeader, pTITail);
3932 break;
3934 case TKIND_ALIAS:
3935 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3936 pTIHeader, pTITail);
3937 break;
3939 case TKIND_DISPATCH:
3940 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3941 pTIHeader, pTITail);
3942 break;
3944 case TKIND_MODULE:
3945 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3946 pTIHeader, pTITail);
3947 break;
3949 default:
3950 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3951 break;
3955 /* could get cFuncs, cVars and cImplTypes from here
3956 but we've already set those */
3957 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3958 X(06);
3959 X(16);
3960 X(18);
3961 X(1a);
3962 X(1e);
3963 X(24);
3964 X(26);
3965 X(2a);
3966 X(2c);
3967 X(2e);
3968 X(30);
3969 X(32);
3970 X(34);
3971 #undef X
3972 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3973 pBlk = (char*)pBlk + pBlkEntry[order].len;
3976 if(i != pTypeLibImpl->TypeInfoCount) {
3977 FIXME("Somehow processed %d TypeInfos\n", i);
3978 return NULL;
3981 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3982 return (ITypeLib2*)pTypeLibImpl;
3985 /* ITypeLib::QueryInterface
3987 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3988 ITypeLib2 * iface,
3989 REFIID riid,
3990 VOID **ppvObject)
3992 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3994 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3996 *ppvObject=NULL;
3997 if(IsEqualIID(riid, &IID_IUnknown) ||
3998 IsEqualIID(riid,&IID_ITypeLib)||
3999 IsEqualIID(riid,&IID_ITypeLib2))
4001 *ppvObject = This;
4004 if(*ppvObject)
4006 ITypeLib2_AddRef(iface);
4007 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4008 return S_OK;
4010 TRACE("-- Interface: E_NOINTERFACE\n");
4011 return E_NOINTERFACE;
4014 /* ITypeLib::AddRef
4016 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4018 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4019 ULONG ref = InterlockedIncrement(&This->ref);
4021 TRACE("(%p)->ref was %u\n",This, ref - 1);
4023 return ref;
4026 /* ITypeLib::Release
4028 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4030 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4031 ULONG ref = InterlockedDecrement(&This->ref);
4033 TRACE("(%p)->(%u)\n",This, ref);
4035 if (!ref)
4037 TLBImpLib *pImpLib, *pImpLibNext;
4038 TLBCustData *pCustData, *pCustDataNext;
4039 TLBRefType *ref_type;
4040 void *cursor2;
4041 int i;
4043 /* remove cache entry */
4044 if(This->path)
4046 TRACE("removing from cache list\n");
4047 EnterCriticalSection(&cache_section);
4048 if (This->next) This->next->prev = This->prev;
4049 if (This->prev) This->prev->next = This->next;
4050 else tlb_cache_first = This->next;
4051 LeaveCriticalSection(&cache_section);
4052 HeapFree(GetProcessHeap(), 0, This->path);
4054 TRACE(" destroying ITypeLib(%p)\n",This);
4056 SysFreeString(This->Name);
4057 This->Name = NULL;
4059 SysFreeString(This->DocString);
4060 This->DocString = NULL;
4062 SysFreeString(This->HelpFile);
4063 This->HelpFile = NULL;
4065 SysFreeString(This->HelpStringDll);
4066 This->HelpStringDll = NULL;
4068 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
4070 VariantClear(&pCustData->data);
4072 pCustDataNext = pCustData->next;
4073 TLB_Free(pCustData);
4076 for (i = 0; i < This->ctTypeDesc; i++)
4077 if (This->pTypeDesc[i].vt == VT_CARRAY)
4078 TLB_Free(This->pTypeDesc[i].u.lpadesc);
4080 TLB_Free(This->pTypeDesc);
4082 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
4084 if (pImpLib->pImpTypeLib)
4085 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
4086 SysFreeString(pImpLib->name);
4088 pImpLibNext = pImpLib->next;
4089 TLB_Free(pImpLib);
4092 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4094 list_remove(&ref_type->entry);
4095 TLB_Free(ref_type);
4098 if (This->pTypeInfo) /* can be NULL */
4099 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
4100 HeapFree(GetProcessHeap(),0,This);
4101 return 0;
4104 return ref;
4107 /* ITypeLib::GetTypeInfoCount
4109 * Returns the number of type descriptions in the type library
4111 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4113 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4114 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4115 return This->TypeInfoCount;
4118 /* ITypeLib::GetTypeInfo
4120 * retrieves the specified type description in the library.
4122 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4123 ITypeLib2 *iface,
4124 UINT index,
4125 ITypeInfo **ppTInfo)
4127 UINT i;
4129 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4130 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
4132 TRACE("(%p)->(index=%d)\n", This, index);
4134 if (!ppTInfo) return E_INVALIDARG;
4136 /* search element n in list */
4137 for(i=0; i < index; i++)
4139 pTypeInfo = pTypeInfo->next;
4140 if (!pTypeInfo)
4142 TRACE("-- element not found\n");
4143 return TYPE_E_ELEMENTNOTFOUND;
4147 *ppTInfo = (ITypeInfo *) pTypeInfo;
4149 ITypeInfo_AddRef(*ppTInfo);
4150 TRACE("-- found (%p)\n",*ppTInfo);
4151 return S_OK;
4155 /* ITypeLibs::GetTypeInfoType
4157 * Retrieves the type of a type description.
4159 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4160 ITypeLib2 *iface,
4161 UINT index,
4162 TYPEKIND *pTKind)
4164 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4165 UINT i;
4166 ITypeInfoImpl *pTInfo = This->pTypeInfo;
4168 if (ITypeLib2_fnGetTypeInfoCount(iface) < index + 1)
4169 return TYPE_E_ELEMENTNOTFOUND;
4171 TRACE("(%p) index %d\n", This, index);
4173 if(!pTKind) return E_INVALIDARG;
4175 /* search element n in list */
4176 for(i=0; i < index; i++)
4178 if(!pTInfo)
4180 TRACE("-- element not found\n");
4181 return TYPE_E_ELEMENTNOTFOUND;
4183 pTInfo = pTInfo->next;
4186 *pTKind = pTInfo->TypeAttr.typekind;
4187 TRACE("-- found Type (%d)\n", *pTKind);
4188 return S_OK;
4191 /* ITypeLib::GetTypeInfoOfGuid
4193 * Retrieves the type description that corresponds to the specified GUID.
4196 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4197 ITypeLib2 *iface,
4198 REFGUID guid,
4199 ITypeInfo **ppTInfo)
4201 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4202 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
4204 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
4206 if (!pTypeInfo)
4208 WARN("-- element not found\n");
4209 return TYPE_E_ELEMENTNOTFOUND;
4212 /* search linked list for guid */
4213 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
4215 pTypeInfo = pTypeInfo->next;
4217 if (!pTypeInfo)
4219 /* end of list reached */
4220 WARN("-- element not found\n");
4221 return TYPE_E_ELEMENTNOTFOUND;
4225 TRACE("-- found (%p, %s)\n",
4226 pTypeInfo,
4227 debugstr_w(pTypeInfo->Name));
4229 *ppTInfo = (ITypeInfo*)pTypeInfo;
4230 ITypeInfo_AddRef(*ppTInfo);
4231 return S_OK;
4234 /* ITypeLib::GetLibAttr
4236 * Retrieves the structure that contains the library's attributes.
4239 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4240 ITypeLib2 *iface,
4241 LPTLIBATTR *ppTLibAttr)
4243 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4244 TRACE("(%p)\n",This);
4245 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
4246 **ppTLibAttr = This->LibAttr;
4247 return S_OK;
4250 /* ITypeLib::GetTypeComp
4252 * Enables a client compiler to bind to a library's types, variables,
4253 * constants, and global functions.
4256 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4257 ITypeLib2 *iface,
4258 ITypeComp **ppTComp)
4260 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4262 TRACE("(%p)->(%p)\n",This,ppTComp);
4263 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4264 ITypeComp_AddRef(*ppTComp);
4266 return S_OK;
4269 /* ITypeLib::GetDocumentation
4271 * Retrieves the library's documentation string, the complete Help file name
4272 * and path, and the context identifier for the library Help topic in the Help
4273 * file.
4275 * On a successful return all non-null BSTR pointers will have been set,
4276 * possibly to NULL.
4278 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4279 ITypeLib2 *iface,
4280 INT index,
4281 BSTR *pBstrName,
4282 BSTR *pBstrDocString,
4283 DWORD *pdwHelpContext,
4284 BSTR *pBstrHelpFile)
4286 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4288 HRESULT result = E_INVALIDARG;
4290 ITypeInfo *pTInfo;
4293 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4294 This, index,
4295 pBstrName, pBstrDocString,
4296 pdwHelpContext, pBstrHelpFile);
4298 if(index<0)
4300 /* documentation for the typelib */
4301 if(pBstrName)
4303 if (This->Name)
4305 if(!(*pBstrName = SysAllocString(This->Name)))
4306 goto memerr1;
4308 else
4309 *pBstrName = NULL;
4311 if(pBstrDocString)
4313 if (This->DocString)
4315 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4316 goto memerr2;
4318 else if (This->Name)
4320 if(!(*pBstrDocString = SysAllocString(This->Name)))
4321 goto memerr2;
4323 else
4324 *pBstrDocString = NULL;
4326 if(pdwHelpContext)
4328 *pdwHelpContext = This->dwHelpContext;
4330 if(pBstrHelpFile)
4332 if (This->HelpFile)
4334 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4335 goto memerr3;
4337 else
4338 *pBstrHelpFile = NULL;
4341 result = S_OK;
4343 else
4345 /* for a typeinfo */
4346 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4348 if(SUCCEEDED(result))
4350 result = ITypeInfo_GetDocumentation(pTInfo,
4351 MEMBERID_NIL,
4352 pBstrName,
4353 pBstrDocString,
4354 pdwHelpContext, pBstrHelpFile);
4356 ITypeInfo_Release(pTInfo);
4359 return result;
4360 memerr3:
4361 if (pBstrDocString) SysFreeString (*pBstrDocString);
4362 memerr2:
4363 if (pBstrName) SysFreeString (*pBstrName);
4364 memerr1:
4365 return STG_E_INSUFFICIENTMEMORY;
4368 /* ITypeLib::IsName
4370 * Indicates whether a passed-in string contains the name of a type or member
4371 * described in the library.
4374 static HRESULT WINAPI ITypeLib2_fnIsName(
4375 ITypeLib2 *iface,
4376 LPOLESTR szNameBuf,
4377 ULONG lHashVal,
4378 BOOL *pfName)
4380 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4381 ITypeInfoImpl *pTInfo;
4382 TLBFuncDesc *pFInfo;
4383 TLBVarDesc *pVInfo;
4384 int i;
4385 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4387 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4388 pfName);
4390 *pfName=TRUE;
4391 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
4392 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4393 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4394 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4395 for(i=0;i<pFInfo->funcdesc.cParams;i++)
4396 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
4397 goto ITypeLib2_fnIsName_exit;
4399 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4400 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4403 *pfName=FALSE;
4405 ITypeLib2_fnIsName_exit:
4406 TRACE("(%p)slow! search for %s: %s found!\n", This,
4407 debugstr_w(szNameBuf), *pfName?"NOT":"");
4409 return S_OK;
4412 /* ITypeLib::FindName
4414 * Finds occurrences of a type description in a type library. This may be used
4415 * to quickly verify that a name exists in a type library.
4418 static HRESULT WINAPI ITypeLib2_fnFindName(
4419 ITypeLib2 *iface,
4420 LPOLESTR szNameBuf,
4421 ULONG lHashVal,
4422 ITypeInfo **ppTInfo,
4423 MEMBERID *rgMemId,
4424 UINT16 *pcFound)
4426 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4427 ITypeInfoImpl *pTInfo;
4428 TLBFuncDesc *pFInfo;
4429 TLBVarDesc *pVInfo;
4430 int i,j = 0;
4431 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4433 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
4434 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4435 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4436 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4437 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
4438 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
4439 goto ITypeLib2_fnFindName_exit;
4442 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4443 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4444 continue;
4445 ITypeLib2_fnFindName_exit:
4446 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4447 ppTInfo[j]=(LPTYPEINFO)pTInfo;
4448 j++;
4450 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4451 This, *pcFound, debugstr_w(szNameBuf), j);
4453 *pcFound=j;
4455 return S_OK;
4458 /* ITypeLib::ReleaseTLibAttr
4460 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4463 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4464 ITypeLib2 *iface,
4465 TLIBATTR *pTLibAttr)
4467 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4468 TRACE("freeing (%p)\n",This);
4469 HeapFree(GetProcessHeap(),0,pTLibAttr);
4473 /* ITypeLib2::GetCustData
4475 * gets the custom data
4477 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4478 ITypeLib2 * iface,
4479 REFGUID guid,
4480 VARIANT *pVarVal)
4482 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4483 TLBCustData *pCData;
4485 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4487 if( IsEqualIID(guid, &pCData->guid)) break;
4490 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4492 if(pCData)
4494 VariantInit( pVarVal);
4495 VariantCopy( pVarVal, &pCData->data);
4496 return S_OK;
4498 return E_INVALIDARG; /* FIXME: correct? */
4501 /* ITypeLib2::GetLibStatistics
4503 * Returns statistics about a type library that are required for efficient
4504 * sizing of hash tables.
4507 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4508 ITypeLib2 * iface,
4509 ULONG *pcUniqueNames,
4510 ULONG *pcchUniqueNames)
4512 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4514 FIXME("(%p): stub!\n", This);
4516 if(pcUniqueNames) *pcUniqueNames=1;
4517 if(pcchUniqueNames) *pcchUniqueNames=1;
4518 return S_OK;
4521 /* ITypeLib2::GetDocumentation2
4523 * Retrieves the library's documentation string, the complete Help file name
4524 * and path, the localization context to use, and the context ID for the
4525 * library Help topic in the Help file.
4528 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4529 ITypeLib2 * iface,
4530 INT index,
4531 LCID lcid,
4532 BSTR *pbstrHelpString,
4533 DWORD *pdwHelpStringContext,
4534 BSTR *pbstrHelpStringDll)
4536 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4537 HRESULT result;
4538 ITypeInfo *pTInfo;
4540 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4542 /* the help string should be obtained from the helpstringdll,
4543 * using the _DLLGetDocumentation function, based on the supplied
4544 * lcid. Nice to do sometime...
4546 if(index<0)
4548 /* documentation for the typelib */
4549 if(pbstrHelpString)
4550 *pbstrHelpString=SysAllocString(This->DocString);
4551 if(pdwHelpStringContext)
4552 *pdwHelpStringContext=This->dwHelpContext;
4553 if(pbstrHelpStringDll)
4554 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4556 result = S_OK;
4558 else
4560 /* for a typeinfo */
4561 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4563 if(SUCCEEDED(result))
4565 ITypeInfo2 * pTInfo2;
4566 result = ITypeInfo_QueryInterface(pTInfo,
4567 &IID_ITypeInfo2,
4568 (LPVOID*) &pTInfo2);
4570 if(SUCCEEDED(result))
4572 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4573 MEMBERID_NIL,
4574 lcid,
4575 pbstrHelpString,
4576 pdwHelpStringContext,
4577 pbstrHelpStringDll);
4579 ITypeInfo2_Release(pTInfo2);
4582 ITypeInfo_Release(pTInfo);
4585 return result;
4588 /* ITypeLib2::GetAllCustData
4590 * Gets all custom data items for the library.
4593 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4594 ITypeLib2 * iface,
4595 CUSTDATA *pCustData)
4597 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4598 TLBCustData *pCData;
4599 int i;
4600 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4601 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4602 if(pCustData->prgCustData ){
4603 pCustData->cCustData=This->ctCustData;
4604 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4605 pCustData->prgCustData[i].guid=pCData->guid;
4606 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4608 }else{
4609 ERR(" OUT OF MEMORY!\n");
4610 return E_OUTOFMEMORY;
4612 return S_OK;
4615 static const ITypeLib2Vtbl tlbvt = {
4616 ITypeLib2_fnQueryInterface,
4617 ITypeLib2_fnAddRef,
4618 ITypeLib2_fnRelease,
4619 ITypeLib2_fnGetTypeInfoCount,
4620 ITypeLib2_fnGetTypeInfo,
4621 ITypeLib2_fnGetTypeInfoType,
4622 ITypeLib2_fnGetTypeInfoOfGuid,
4623 ITypeLib2_fnGetLibAttr,
4624 ITypeLib2_fnGetTypeComp,
4625 ITypeLib2_fnGetDocumentation,
4626 ITypeLib2_fnIsName,
4627 ITypeLib2_fnFindName,
4628 ITypeLib2_fnReleaseTLibAttr,
4630 ITypeLib2_fnGetCustData,
4631 ITypeLib2_fnGetLibStatistics,
4632 ITypeLib2_fnGetDocumentation2,
4633 ITypeLib2_fnGetAllCustData
4637 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4639 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4641 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4644 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4646 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4648 return ITypeLib2_AddRef((ITypeLib2 *)This);
4651 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4653 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4655 return ITypeLib2_Release((ITypeLib2 *)This);
4658 static HRESULT WINAPI ITypeLibComp_fnBind(
4659 ITypeComp * iface,
4660 OLECHAR * szName,
4661 ULONG lHash,
4662 WORD wFlags,
4663 ITypeInfo ** ppTInfo,
4664 DESCKIND * pDescKind,
4665 BINDPTR * pBindPtr)
4667 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4668 ITypeInfoImpl *pTypeInfo;
4670 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4672 *pDescKind = DESCKIND_NONE;
4673 pBindPtr->lptcomp = NULL;
4674 *ppTInfo = NULL;
4676 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4678 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4680 /* FIXME: check wFlags here? */
4681 /* FIXME: we should use a hash table to look this info up using lHash
4682 * instead of an O(n) search */
4683 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4684 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4686 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4688 *pDescKind = DESCKIND_TYPECOMP;
4689 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4690 ITypeComp_AddRef(pBindPtr->lptcomp);
4691 TRACE("module or enum: %s\n", debugstr_w(szName));
4692 return S_OK;
4696 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4697 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4699 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4700 HRESULT hr;
4702 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4703 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4705 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4706 return S_OK;
4710 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4711 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4713 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4714 HRESULT hr;
4715 ITypeInfo *subtypeinfo;
4716 BINDPTR subbindptr;
4717 DESCKIND subdesckind;
4719 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4720 &subtypeinfo, &subdesckind, &subbindptr);
4721 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4723 TYPEDESC tdesc_appobject =
4726 (TYPEDESC *)pTypeInfo->hreftype
4728 VT_USERDEFINED
4730 const VARDESC vardesc_appobject =
4732 -2, /* memid */
4733 NULL, /* lpstrSchema */
4735 0 /* oInst */
4738 /* ELEMDESC */
4740 /* TYPEDESC */
4742 &tdesc_appobject
4744 VT_PTR
4747 0, /* wVarFlags */
4748 VAR_STATIC /* varkind */
4751 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4753 /* cleanup things filled in by Bind call so we can put our
4754 * application object data in there instead */
4755 switch (subdesckind)
4757 case DESCKIND_FUNCDESC:
4758 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4759 break;
4760 case DESCKIND_VARDESC:
4761 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4762 break;
4763 default:
4764 break;
4766 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4768 if (pTypeInfo->hreftype == -1)
4769 FIXME("no hreftype for interface %p\n", pTypeInfo);
4771 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4772 if (FAILED(hr))
4773 return hr;
4775 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4776 *ppTInfo = (ITypeInfo *)pTypeInfo;
4777 ITypeInfo_AddRef(*ppTInfo);
4778 return S_OK;
4783 TRACE("name not found %s\n", debugstr_w(szName));
4784 return S_OK;
4787 static HRESULT WINAPI ITypeLibComp_fnBindType(
4788 ITypeComp * iface,
4789 OLECHAR * szName,
4790 ULONG lHash,
4791 ITypeInfo ** ppTInfo,
4792 ITypeComp ** ppTComp)
4794 FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4795 return E_NOTIMPL;
4798 static const ITypeCompVtbl tlbtcvt =
4801 ITypeLibComp_fnQueryInterface,
4802 ITypeLibComp_fnAddRef,
4803 ITypeLibComp_fnRelease,
4805 ITypeLibComp_fnBind,
4806 ITypeLibComp_fnBindType
4809 /*================== ITypeInfo(2) Methods ===================================*/
4810 static ITypeInfo2 * ITypeInfo_Constructor(void)
4812 ITypeInfoImpl * pTypeInfoImpl;
4814 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4815 if (pTypeInfoImpl)
4817 pTypeInfoImpl->lpVtbl = &tinfvt;
4818 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4819 pTypeInfoImpl->ref=1;
4820 pTypeInfoImpl->hreftype = -1;
4821 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4822 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4824 TRACE("(%p)\n", pTypeInfoImpl);
4825 return (ITypeInfo2*) pTypeInfoImpl;
4828 /* ITypeInfo::QueryInterface
4830 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4831 ITypeInfo2 *iface,
4832 REFIID riid,
4833 VOID **ppvObject)
4835 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4837 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4839 *ppvObject=NULL;
4840 if(IsEqualIID(riid, &IID_IUnknown) ||
4841 IsEqualIID(riid,&IID_ITypeInfo)||
4842 IsEqualIID(riid,&IID_ITypeInfo2))
4843 *ppvObject = This;
4845 if(*ppvObject){
4846 ITypeInfo_AddRef(iface);
4847 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4848 return S_OK;
4850 TRACE("-- Interface: E_NOINTERFACE\n");
4851 return E_NOINTERFACE;
4854 /* ITypeInfo::AddRef
4856 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4858 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4859 ULONG ref = InterlockedIncrement(&This->ref);
4861 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4863 TRACE("(%p)->ref is %u\n",This, ref);
4864 return ref;
4867 /* ITypeInfo::Release
4869 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4871 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4872 ULONG ref = InterlockedDecrement(&This->ref);
4874 TRACE("(%p)->(%u)\n",This, ref);
4876 if (ref) {
4877 /* We don't release ITypeLib when ref=0 because
4878 it means that function is called by ITypeLib2_Release */
4879 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4880 } else {
4881 TLBFuncDesc *pFInfo, *pFInfoNext;
4882 TLBVarDesc *pVInfo, *pVInfoNext;
4883 TLBImplType *pImpl, *pImplNext;
4885 TRACE("destroying ITypeInfo(%p)\n",This);
4887 if (This->no_free_data)
4888 goto finish_free;
4890 SysFreeString(This->Name);
4891 This->Name = NULL;
4893 SysFreeString(This->DocString);
4894 This->DocString = NULL;
4896 SysFreeString(This->DllName);
4897 This->DllName = NULL;
4899 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4901 INT i;
4902 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4904 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4905 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4907 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4908 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4910 SysFreeString(pFInfo->pParamDesc[i].Name);
4912 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4913 TLB_Free(pFInfo->pParamDesc);
4914 TLB_FreeCustData(pFInfo->pCustData);
4915 if (HIWORD(pFInfo->Entry) != 0 && pFInfo->Entry != (BSTR)-1)
4916 SysFreeString(pFInfo->Entry);
4917 SysFreeString(pFInfo->HelpString);
4918 SysFreeString(pFInfo->Name);
4920 pFInfoNext = pFInfo->next;
4921 TLB_Free(pFInfo);
4923 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
4925 if (pVInfo->vardesc.varkind == VAR_CONST)
4927 VariantClear(pVInfo->vardesc.u.lpvarValue);
4928 TLB_Free(pVInfo->vardesc.u.lpvarValue);
4930 TLB_FreeCustData(pVInfo->pCustData);
4931 SysFreeString(pVInfo->Name);
4932 pVInfoNext = pVInfo->next;
4933 TLB_Free(pVInfo);
4935 for(pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
4937 TLB_FreeCustData(pImpl->pCustData);
4938 pImplNext = pImpl->next;
4939 TLB_Free(pImpl);
4941 TLB_FreeCustData(This->pCustData);
4943 finish_free:
4944 if (This->next)
4946 ITypeInfo_Release((ITypeInfo*)This->next);
4949 HeapFree(GetProcessHeap(),0,This);
4950 return 0;
4952 return ref;
4955 /* ITypeInfo::GetTypeAttr
4957 * Retrieves a TYPEATTR structure that contains the attributes of the type
4958 * description.
4961 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4962 LPTYPEATTR *ppTypeAttr)
4964 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4965 SIZE_T size;
4967 TRACE("(%p)\n",This);
4969 size = sizeof(**ppTypeAttr);
4970 if (This->TypeAttr.typekind == TKIND_ALIAS)
4971 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4973 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4974 if (!*ppTypeAttr)
4975 return E_OUTOFMEMORY;
4977 **ppTypeAttr = This->TypeAttr;
4979 if (This->TypeAttr.typekind == TKIND_ALIAS)
4980 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4981 &This->TypeAttr.tdescAlias, *ppTypeAttr + 1);
4983 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4984 /* This should include all the inherited funcs */
4985 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
4986 (*ppTypeAttr)->cbSizeVft = 7 * sizeof(void *); /* This is always the size of IDispatch's vtbl */
4987 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4989 return S_OK;
4992 /* ITypeInfo::GetTypeComp
4994 * Retrieves the ITypeComp interface for the type description, which enables a
4995 * client compiler to bind to the type description's members.
4998 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4999 ITypeComp * *ppTComp)
5001 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5003 TRACE("(%p)->(%p)\n", This, ppTComp);
5005 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
5006 ITypeComp_AddRef(*ppTComp);
5007 return S_OK;
5010 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5012 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5013 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5014 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5015 return size;
5018 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5020 *dest = *src;
5021 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5022 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5024 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5025 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5026 *buffer += sizeof(PARAMDESCEX);
5027 *pparamdescex_dest = *pparamdescex_src;
5028 VariantInit(&pparamdescex_dest->varDefaultValue);
5029 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5030 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5032 else
5033 dest->u.paramdesc.pparamdescex = NULL;
5034 return S_OK;
5037 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5039 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5040 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5043 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5045 FUNCDESC *dest;
5046 char *buffer;
5047 SIZE_T size = sizeof(*src);
5048 SHORT i;
5049 HRESULT hr;
5051 size += sizeof(*src->lprgscode) * src->cScodes;
5052 size += TLB_SizeElemDesc(&src->elemdescFunc);
5053 for (i = 0; i < src->cParams; i++)
5055 size += sizeof(ELEMDESC);
5056 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5059 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5060 if (!dest) return E_OUTOFMEMORY;
5062 *dest = *src;
5063 if (dispinterface) /* overwrite funckind */
5064 dest->funckind = FUNC_DISPATCH;
5065 buffer = (char *)(dest + 1);
5067 dest->lprgscode = (SCODE *)buffer;
5068 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5069 buffer += sizeof(*src->lprgscode) * src->cScodes;
5071 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5072 if (FAILED(hr))
5074 SysFreeString((BSTR)dest);
5075 return hr;
5078 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5079 buffer += sizeof(ELEMDESC) * src->cParams;
5080 for (i = 0; i < src->cParams; i++)
5082 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5083 if (FAILED(hr))
5084 break;
5086 if (FAILED(hr))
5088 /* undo the above actions */
5089 for (i = i - 1; i >= 0; i--)
5090 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5091 TLB_FreeElemDesc(&dest->elemdescFunc);
5092 SysFreeString((BSTR)dest);
5093 return hr;
5096 /* special treatment for dispinterfaces: this makes functions appear
5097 * to return their [retval] value when it is really returning an
5098 * HRESULT */
5099 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5101 if (dest->cParams &&
5102 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5104 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5105 if (elemdesc->tdesc.vt != VT_PTR)
5107 ERR("elemdesc should have started with VT_PTR instead of:\n");
5108 if (ERR_ON(ole))
5109 dump_ELEMDESC(elemdesc);
5110 return E_UNEXPECTED;
5113 /* copy last parameter to the return value. we are using a flat
5114 * buffer so there is no danger of leaking memory in
5115 * elemdescFunc */
5116 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5118 /* remove the last parameter */
5119 dest->cParams--;
5121 else
5122 /* otherwise this function is made to appear to have no return
5123 * value */
5124 dest->elemdescFunc.tdesc.vt = VT_VOID;
5128 *dest_ptr = dest;
5129 return S_OK;
5132 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5134 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5135 const TLBFuncDesc *pFDesc;
5136 UINT i;
5138 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
5141 if (pFDesc)
5143 *ppFuncDesc = &pFDesc->funcdesc;
5144 return S_OK;
5147 return TYPE_E_ELEMENTNOTFOUND;
5150 /* internal function to make the inherited interfaces' methods appear
5151 * part of the interface */
5152 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5153 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5155 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5156 HRESULT hr;
5157 UINT implemented_funcs = 0;
5159 if (funcs)
5160 *funcs = 0;
5161 else
5162 *hrefoffset = DISPATCH_HREF_OFFSET;
5164 if(This->impltypelist)
5166 ITypeInfo *pSubTypeInfo;
5167 UINT sub_funcs;
5169 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
5170 if (FAILED(hr))
5171 return hr;
5173 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5174 index,
5175 ppFuncDesc,
5176 &sub_funcs, hrefoffset);
5177 implemented_funcs += sub_funcs;
5178 ITypeInfo_Release(pSubTypeInfo);
5179 if (SUCCEEDED(hr))
5180 return hr;
5181 *hrefoffset += DISPATCH_HREF_OFFSET;
5184 if (funcs)
5185 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
5186 else
5187 *hrefoffset = 0;
5189 if (index < implemented_funcs)
5190 return E_INVALIDARG;
5191 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5192 ppFuncDesc);
5195 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5197 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5198 while (TRUE)
5200 switch (pTypeDesc->vt)
5202 case VT_USERDEFINED:
5203 pTypeDesc->u.hreftype += hrefoffset;
5204 return;
5205 case VT_PTR:
5206 case VT_SAFEARRAY:
5207 pTypeDesc = pTypeDesc->u.lptdesc;
5208 break;
5209 case VT_CARRAY:
5210 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5211 break;
5212 default:
5213 return;
5218 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5220 SHORT i;
5221 for (i = 0; i < pFuncDesc->cParams; i++)
5222 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5223 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5226 /* ITypeInfo::GetFuncDesc
5228 * Retrieves the FUNCDESC structure that contains information about a
5229 * specified function.
5232 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5233 LPFUNCDESC *ppFuncDesc)
5235 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5236 const FUNCDESC *internal_funcdesc;
5237 HRESULT hr;
5238 UINT hrefoffset = 0;
5240 TRACE("(%p) index %d\n", This, index);
5242 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5243 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5244 &internal_funcdesc, NULL,
5245 &hrefoffset);
5246 else
5247 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5248 &internal_funcdesc);
5249 if (FAILED(hr))
5251 WARN("description for function %d not found\n", index);
5252 return hr;
5255 hr = TLB_AllocAndInitFuncDesc(
5256 internal_funcdesc,
5257 ppFuncDesc,
5258 This->TypeAttr.typekind == TKIND_DISPATCH);
5260 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5261 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5263 TRACE("-- 0x%08x\n", hr);
5264 return hr;
5267 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5269 VARDESC *dest;
5270 char *buffer;
5271 SIZE_T size = sizeof(*src);
5272 HRESULT hr;
5274 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5275 if (src->varkind == VAR_CONST)
5276 size += sizeof(VARIANT);
5277 size += TLB_SizeElemDesc(&src->elemdescVar);
5279 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5280 if (!dest) return E_OUTOFMEMORY;
5282 *dest = *src;
5283 buffer = (char *)(dest + 1);
5284 if (src->lpstrSchema)
5286 int len;
5287 dest->lpstrSchema = (LPOLESTR)buffer;
5288 len = strlenW(src->lpstrSchema);
5289 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5290 buffer += (len + 1) * sizeof(WCHAR);
5293 if (src->varkind == VAR_CONST)
5295 HRESULT hr;
5297 dest->u.lpvarValue = (VARIANT *)buffer;
5298 *dest->u.lpvarValue = *src->u.lpvarValue;
5299 buffer += sizeof(VARIANT);
5300 VariantInit(dest->u.lpvarValue);
5301 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5302 if (FAILED(hr))
5304 SysFreeString((BSTR)dest_ptr);
5305 return hr;
5308 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5309 if (FAILED(hr))
5311 if (src->varkind == VAR_CONST)
5312 VariantClear(dest->u.lpvarValue);
5313 SysFreeString((BSTR)dest);
5314 return hr;
5316 *dest_ptr = dest;
5317 return S_OK;
5320 /* ITypeInfo::GetVarDesc
5322 * Retrieves a VARDESC structure that describes the specified variable.
5325 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5326 LPVARDESC *ppVarDesc)
5328 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5329 UINT i;
5330 const TLBVarDesc *pVDesc;
5332 TRACE("(%p) index %d\n", This, index);
5334 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
5337 if (pVDesc)
5338 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5340 return E_INVALIDARG;
5343 /* ITypeInfo_GetNames
5345 * Retrieves the variable with the specified member ID (or the name of the
5346 * property or method and its parameters) that correspond to the specified
5347 * function ID.
5349 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5350 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5352 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5353 const TLBFuncDesc *pFDesc;
5354 const TLBVarDesc *pVDesc;
5355 int i;
5356 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5357 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
5358 if(pFDesc)
5360 /* function found, now return function and parameter names */
5361 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5363 if(!i)
5364 *rgBstrNames=SysAllocString(pFDesc->Name);
5365 else
5366 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5368 *pcNames=i;
5370 else
5372 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
5373 if(pVDesc)
5375 *rgBstrNames=SysAllocString(pVDesc->Name);
5376 *pcNames=1;
5378 else
5380 if(This->impltypelist &&
5381 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5382 /* recursive search */
5383 ITypeInfo *pTInfo;
5384 HRESULT result;
5385 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5386 &pTInfo);
5387 if(SUCCEEDED(result))
5389 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5390 ITypeInfo_Release(pTInfo);
5391 return result;
5393 WARN("Could not search inherited interface!\n");
5395 else
5397 WARN("no names found\n");
5399 *pcNames=0;
5400 return TYPE_E_ELEMENTNOTFOUND;
5403 return S_OK;
5407 /* ITypeInfo::GetRefTypeOfImplType
5409 * If a type description describes a COM class, it retrieves the type
5410 * description of the implemented interface types. For an interface,
5411 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5412 * if any exist.
5415 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5416 ITypeInfo2 *iface,
5417 UINT index,
5418 HREFTYPE *pRefType)
5420 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5421 UINT i;
5422 HRESULT hr = S_OK;
5423 const TLBImplType *pImpl = This->impltypelist;
5425 TRACE("(%p) index %d\n", This, index);
5426 if (TRACE_ON(ole)) dump_TypeInfo(This);
5428 if(index==(UINT)-1)
5430 /* only valid on dual interfaces;
5431 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5433 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5435 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
5436 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
5438 *pRefType = -1;
5440 else
5442 hr = TYPE_E_ELEMENTNOTFOUND;
5445 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5447 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5448 *pRefType = This->pTypeLib->dispatch_href;
5450 else
5452 /* get element n from linked list */
5453 for(i=0; pImpl && i<index; i++)
5455 pImpl = pImpl->next;
5458 if (pImpl)
5459 *pRefType = pImpl->hRef;
5460 else
5461 hr = TYPE_E_ELEMENTNOTFOUND;
5464 if(TRACE_ON(ole))
5466 if(SUCCEEDED(hr))
5467 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5468 else
5469 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5472 return hr;
5475 /* ITypeInfo::GetImplTypeFlags
5477 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5478 * or base interface in a type description.
5480 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5481 UINT index, INT *pImplTypeFlags)
5483 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5484 UINT i;
5485 TLBImplType *pImpl;
5487 TRACE("(%p) index %d\n", This, index);
5488 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5489 i++, pImpl=pImpl->next)
5491 if(i==index && pImpl){
5492 *pImplTypeFlags=pImpl->implflags;
5493 return S_OK;
5495 *pImplTypeFlags=0;
5496 return TYPE_E_ELEMENTNOTFOUND;
5499 /* GetIDsOfNames
5500 * Maps between member names and member IDs, and parameter names and
5501 * parameter IDs.
5503 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5504 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5506 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5507 const TLBFuncDesc *pFDesc;
5508 const TLBVarDesc *pVDesc;
5509 HRESULT ret=S_OK;
5510 UINT i;
5512 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5513 cNames);
5515 /* init out parameters in case of failure */
5516 for (i = 0; i < cNames; i++)
5517 pMemId[i] = MEMBERID_NIL;
5519 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5520 int j;
5521 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5522 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5523 for(i=1; i < cNames; i++){
5524 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5525 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5526 break;
5527 if( j<pFDesc->funcdesc.cParams)
5528 pMemId[i]=j;
5529 else
5530 ret=DISP_E_UNKNOWNNAME;
5532 TRACE("-- 0x%08x\n", ret);
5533 return ret;
5536 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5537 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5538 if(cNames) *pMemId=pVDesc->vardesc.memid;
5539 return ret;
5542 /* not found, see if it can be found in an inherited interface */
5543 if(This->impltypelist) {
5544 /* recursive search */
5545 ITypeInfo *pTInfo;
5546 ret=ITypeInfo_GetRefTypeInfo(iface,
5547 This->impltypelist->hRef, &pTInfo);
5548 if(SUCCEEDED(ret)){
5549 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5550 ITypeInfo_Release(pTInfo);
5551 return ret;
5553 WARN("Could not search inherited interface!\n");
5554 } else
5555 WARN("no names found\n");
5556 return DISP_E_UNKNOWNNAME;
5559 /* ITypeInfo::Invoke
5561 * Invokes a method, or accesses a property of an object, that implements the
5562 * interface described by the type description.
5564 DWORD
5565 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5566 DWORD res;
5568 if (TRACE_ON(ole)) {
5569 int i;
5570 TRACE("Calling %p(",func);
5571 for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
5572 TRACE(")\n");
5575 switch (callconv) {
5576 case CC_STDCALL:
5578 switch (nrargs) {
5579 case 0:
5580 res = func();
5581 break;
5582 case 1:
5583 res = func(args[0]);
5584 break;
5585 case 2:
5586 res = func(args[0],args[1]);
5587 break;
5588 case 3:
5589 res = func(args[0],args[1],args[2]);
5590 break;
5591 case 4:
5592 res = func(args[0],args[1],args[2],args[3]);
5593 break;
5594 case 5:
5595 res = func(args[0],args[1],args[2],args[3],args[4]);
5596 break;
5597 case 6:
5598 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
5599 break;
5600 case 7:
5601 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
5602 break;
5603 case 8:
5604 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
5605 break;
5606 case 9:
5607 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
5608 break;
5609 case 10:
5610 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
5611 break;
5612 case 11:
5613 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
5614 break;
5615 case 12:
5616 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]);
5617 break;
5618 case 13:
5619 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]);
5620 break;
5621 case 14:
5622 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]);
5623 break;
5624 case 15:
5625 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]);
5626 break;
5627 case 16:
5628 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]);
5629 break;
5630 case 17:
5631 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]);
5632 break;
5633 case 18:
5634 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]);
5635 break;
5636 case 19:
5637 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]);
5638 break;
5639 case 20:
5640 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]);
5641 break;
5642 case 21:
5643 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]);
5644 break;
5645 case 22:
5646 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]);
5647 break;
5648 case 23:
5649 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]);
5650 break;
5651 case 24:
5652 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],args[23]);
5653 break;
5654 case 25:
5655 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],args[23],args[24]);
5656 break;
5657 case 26:
5658 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],args[23],args[24],args[25]);
5659 break;
5660 case 27:
5661 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],args[23],args[24],args[25],args[26]);
5662 break;
5663 case 28:
5664 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],args[23],args[24],args[25],args[26],args[27]);
5665 break;
5666 case 29:
5667 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],args[23],args[24],args[25],args[26],args[27],args[28]);
5668 break;
5669 case 30:
5670 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],args[23],args[24],args[25],args[26],args[27],args[28],args[29]);
5671 break;
5672 default:
5673 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
5674 res = -1;
5675 break;
5677 break;
5678 default:
5679 FIXME("unsupported calling convention %d\n",callconv);
5680 res = -1;
5681 break;
5683 TRACE("returns %08x\n",res);
5684 return res;
5687 /* The size of the argument on the stack in DWORD units (in all x86 call
5688 * convetions the arguments on the stack are DWORD-aligned)
5690 static int _dispargsize(VARTYPE vt)
5692 switch (vt) {
5693 case VT_I8:
5694 case VT_UI8:
5695 return 8/sizeof(DWORD);
5696 case VT_R8:
5697 return sizeof(double)/sizeof(DWORD);
5698 case VT_DECIMAL:
5699 return (sizeof(DECIMAL)+3)/sizeof(DWORD);
5700 case VT_CY:
5701 return sizeof(CY)/sizeof(DWORD);
5702 case VT_DATE:
5703 return sizeof(DATE)/sizeof(DWORD);
5704 case VT_VARIANT:
5705 return (sizeof(VARIANT)+3)/sizeof(DWORD);
5706 case VT_RECORD:
5707 FIXME("VT_RECORD not implemented\n");
5708 return 1;
5709 default:
5710 return 1;
5714 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5716 HRESULT hr = S_OK;
5717 ITypeInfo *tinfo2 = NULL;
5718 TYPEATTR *tattr = NULL;
5720 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5721 if (hr)
5723 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5724 "hr = 0x%08x\n",
5725 tdesc->u.hreftype, hr);
5726 return hr;
5728 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5729 if (hr)
5731 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5732 ITypeInfo_Release(tinfo2);
5733 return hr;
5736 switch (tattr->typekind)
5738 case TKIND_ENUM:
5739 *vt |= VT_I4;
5740 break;
5742 case TKIND_ALIAS:
5743 tdesc = &tattr->tdescAlias;
5744 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5745 break;
5747 case TKIND_INTERFACE:
5748 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5749 *vt |= VT_DISPATCH;
5750 else
5751 *vt |= VT_UNKNOWN;
5752 break;
5754 case TKIND_DISPATCH:
5755 *vt |= VT_DISPATCH;
5756 break;
5758 case TKIND_COCLASS:
5759 *vt |= VT_DISPATCH;
5760 break;
5762 case TKIND_RECORD:
5763 FIXME("TKIND_RECORD unhandled.\n");
5764 hr = E_NOTIMPL;
5765 break;
5767 case TKIND_UNION:
5768 FIXME("TKIND_UNION unhandled.\n");
5769 hr = E_NOTIMPL;
5770 break;
5772 default:
5773 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5774 hr = E_NOTIMPL;
5775 break;
5777 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5778 ITypeInfo_Release(tinfo2);
5779 return hr;
5782 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5784 HRESULT hr = S_OK;
5786 /* enforce only one level of pointer indirection */
5787 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5789 tdesc = tdesc->u.lptdesc;
5791 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5792 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5793 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5794 if ((tdesc->vt == VT_USERDEFINED) ||
5795 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5797 VARTYPE vt_userdefined = 0;
5798 const TYPEDESC *tdesc_userdefined = tdesc;
5799 if (tdesc->vt == VT_PTR)
5801 vt_userdefined = VT_BYREF;
5802 tdesc_userdefined = tdesc->u.lptdesc;
5804 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5805 if ((hr == S_OK) &&
5806 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5807 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5809 *vt |= vt_userdefined;
5810 return S_OK;
5813 *vt = VT_BYREF;
5816 switch (tdesc->vt)
5818 case VT_HRESULT:
5819 *vt |= VT_ERROR;
5820 break;
5821 case VT_USERDEFINED:
5822 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5823 break;
5824 case VT_VOID:
5825 case VT_CARRAY:
5826 case VT_PTR:
5827 case VT_LPSTR:
5828 case VT_LPWSTR:
5829 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5830 hr = DISP_E_BADVARTYPE;
5831 break;
5832 case VT_SAFEARRAY:
5833 *vt |= VT_ARRAY;
5834 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5835 break;
5836 default:
5837 *vt |= tdesc->vt;
5838 break;
5840 return hr;
5843 /***********************************************************************
5844 * DispCallFunc (OLEAUT32.@)
5846 * Invokes a function of the specified calling convention, passing the
5847 * specified arguments and returns the result.
5849 * PARAMS
5850 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5851 * oVft [I] The offset in the vtable. See notes.
5852 * cc [I] Calling convention of the function to call.
5853 * vtReturn [I] The return type of the function.
5854 * cActuals [I] Number of parameters.
5855 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5856 * prgpvarg [I] The arguments to pass.
5857 * pvargResult [O] The return value of the function. Can be NULL.
5859 * RETURNS
5860 * Success: S_OK.
5861 * Failure: HRESULT code.
5863 * NOTES
5864 * The HRESULT return value of this function is not affected by the return
5865 * value of the user supplied function, which is returned in pvargResult.
5867 * If pvInstance is NULL then a non-object function is to be called and oVft
5868 * is the address of the function to call.
5870 * The cc parameter can be one of the following values:
5871 *|CC_FASTCALL
5872 *|CC_CDECL
5873 *|CC_PASCAL
5874 *|CC_STDCALL
5875 *|CC_FPFASTCALL
5876 *|CC_SYSCALL
5877 *|CC_MPWCDECL
5878 *|CC_MPWPASCAL
5881 HRESULT WINAPI
5882 DispCallFunc(
5883 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5884 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5886 int argsize, argspos;
5887 UINT i;
5888 DWORD *args;
5889 HRESULT hres;
5891 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5892 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5893 pvargResult, V_VT(pvargResult));
5895 argsize = 0;
5896 if (pvInstance)
5897 argsize++; /* for This pointer */
5899 for (i=0;i<cActuals;i++)
5901 TRACE("arg %u: type %d, size %d\n",i,prgvt[i],_dispargsize(prgvt[i]));
5902 dump_Variant(prgpvarg[i]);
5903 argsize += _dispargsize(prgvt[i]);
5905 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5907 argspos = 0;
5908 if (pvInstance)
5910 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5911 argspos++;
5914 for (i=0;i<cActuals;i++)
5916 VARIANT *arg = prgpvarg[i];
5917 TRACE("Storing arg %u (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5918 if (prgvt[i] == VT_VARIANT)
5919 memcpy(&args[argspos], arg, _dispargsize(prgvt[i]) * sizeof(DWORD));
5920 else
5921 memcpy(&args[argspos], &V_NONE(arg), _dispargsize(prgvt[i]) * sizeof(DWORD));
5922 argspos += _dispargsize(prgvt[i]);
5925 if (pvInstance)
5927 FARPROC *vtable = *(FARPROC**)pvInstance;
5928 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5930 else
5931 /* if we aren't invoking an object then the function pointer is stored
5932 * in oVft */
5933 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5935 if (pvargResult && (vtReturn != VT_EMPTY))
5937 TRACE("Method returned 0x%08x\n",hres);
5938 V_VT(pvargResult) = vtReturn;
5939 V_UI4(pvargResult) = hres;
5942 HeapFree(GetProcessHeap(),0,args);
5943 return S_OK;
5946 #define INVBUF_ELEMENT_SIZE \
5947 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5948 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
5949 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5950 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5951 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5952 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5953 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5954 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5956 static HRESULT WINAPI ITypeInfo_fnInvoke(
5957 ITypeInfo2 *iface,
5958 VOID *pIUnk,
5959 MEMBERID memid,
5960 UINT16 wFlags,
5961 DISPPARAMS *pDispParams,
5962 VARIANT *pVarResult,
5963 EXCEPINFO *pExcepInfo,
5964 UINT *pArgErr)
5966 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5967 int i;
5968 unsigned int var_index;
5969 TYPEKIND type_kind;
5970 HRESULT hres;
5971 const TLBFuncDesc *pFuncInfo;
5973 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
5974 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5977 if (!pDispParams)
5979 ERR("NULL pDispParams not allowed\n");
5980 return E_INVALIDARG;
5983 dump_DispParms(pDispParams);
5985 if (pDispParams->cNamedArgs > pDispParams->cArgs)
5987 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
5988 pDispParams->cNamedArgs, pDispParams->cArgs);
5989 return E_INVALIDARG;
5992 /* we do this instead of using GetFuncDesc since it will return a fake
5993 * FUNCDESC for dispinterfaces and we want the real function description */
5994 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5995 if ((memid == pFuncInfo->funcdesc.memid) &&
5996 (wFlags & pFuncInfo->funcdesc.invkind))
5997 break;
5999 if (pFuncInfo) {
6000 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6002 if (TRACE_ON(ole))
6004 TRACE("invoking:\n");
6005 dump_TLBFuncDescOne(pFuncInfo);
6008 switch (func_desc->funckind) {
6009 case FUNC_PUREVIRTUAL:
6010 case FUNC_VIRTUAL: {
6011 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
6012 VARIANT varresult;
6013 VARIANT retval; /* pointer for storing byref retvals in */
6014 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6015 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6016 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6017 UINT cNamedArgs = pDispParams->cNamedArgs;
6018 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6020 hres = S_OK;
6022 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6024 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6026 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6027 hres = DISP_E_PARAMNOTFOUND;
6028 goto func_fail;
6030 /* ignore the DISPID_PROPERTYPUT named argument from now on */
6031 cNamedArgs--;
6032 rgdispidNamedArgs++;
6035 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6037 ERR("functions with the vararg attribute do not support named arguments\n");
6038 hres = DISP_E_NONAMEDARGS;
6039 goto func_fail;
6042 for (i = 0; i < func_desc->cParams; i++)
6044 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6045 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6046 if (FAILED(hres))
6047 goto func_fail;
6050 TRACE("changing args\n");
6051 for (i = 0; i < func_desc->cParams; i++)
6053 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6054 VARIANTARG *src_arg;
6056 if (cNamedArgs)
6058 USHORT j;
6059 src_arg = NULL;
6060 for (j = 0; j < cNamedArgs; j++)
6061 if (rgdispidNamedArgs[j] == i)
6063 src_arg = &pDispParams->rgvarg[j];
6064 break;
6067 else
6068 src_arg = i < pDispParams->cArgs ? &pDispParams->rgvarg[pDispParams->cArgs - 1 - i] : NULL;
6070 if (wParamFlags & PARAMFLAG_FRETVAL)
6072 /* under most conditions the caller is not allowed to
6073 * pass in a dispparam arg in the index of what would be
6074 * the retval parameter. however, there is an exception
6075 * where the extra parameter is used in an extra
6076 * IDispatch::Invoke below */
6077 if ((i < pDispParams->cArgs) &&
6078 ((func_desc->cParams != 1) || !pVarResult ||
6079 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6081 hres = DISP_E_BADPARAMCOUNT;
6082 break;
6085 /* note: this check is placed so that if the caller passes
6086 * in a VARIANTARG for the retval we just ignore it, like
6087 * native does */
6088 if (i == func_desc->cParams - 1)
6090 VARIANTARG *arg;
6091 arg = prgpvarg[i] = &rgvarg[i];
6092 memset(arg, 0, sizeof(*arg));
6093 V_VT(arg) = rgvt[i];
6094 memset(&retval, 0, sizeof(retval));
6095 V_BYREF(arg) = &retval;
6097 else
6099 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6100 hres = E_UNEXPECTED;
6101 break;
6104 else if (src_arg)
6106 dump_Variant(src_arg);
6108 if (rgvt[i] == VT_VARIANT)
6109 hres = VariantCopy(&rgvarg[i], src_arg);
6110 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6112 if (rgvt[i] == V_VT(src_arg))
6113 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6114 else
6116 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6117 hres = VariantCopy(&missing_arg[i], src_arg);
6118 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6120 V_VT(&rgvarg[i]) = rgvt[i];
6122 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6124 SAFEARRAY *a;
6125 SAFEARRAYBOUND bound;
6126 VARIANT *v;
6127 LONG j;
6128 bound.lLbound = 0;
6129 bound.cElements = pDispParams->cArgs-i;
6130 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6132 ERR("SafeArrayCreate failed\n");
6133 break;
6135 hres = SafeArrayAccessData(a, (LPVOID)&v);
6136 if (hres != S_OK)
6138 ERR("SafeArrayAccessData failed with %x\n", hres);
6139 break;
6141 for (j = 0; j < bound.cElements; j++)
6142 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6143 hres = SafeArrayUnaccessData(a);
6144 if (hres != S_OK)
6146 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6147 break;
6149 V_ARRAY(&rgvarg[i]) = a;
6150 V_VT(&rgvarg[i]) = rgvt[i];
6152 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6154 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6155 V_VT(&missing_arg[i]) = V_VT(src_arg);
6156 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6157 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6158 V_VT(&rgvarg[i]) = rgvt[i];
6160 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6162 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6163 V_VT(&rgvarg[i]) = rgvt[i];
6165 else
6167 /* FIXME: this doesn't work for VT_BYREF arguments if
6168 * they are not the same type as in the paramdesc */
6169 V_VT(&rgvarg[i]) = V_VT(src_arg);
6170 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6171 V_VT(&rgvarg[i]) = rgvt[i];
6174 if (FAILED(hres))
6176 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6177 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6178 debugstr_VT(src_arg), debugstr_VF(src_arg));
6179 break;
6181 prgpvarg[i] = &rgvarg[i];
6183 else if (wParamFlags & PARAMFLAG_FOPT)
6185 VARIANTARG *arg;
6186 arg = prgpvarg[i] = &rgvarg[i];
6187 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6189 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6190 if (FAILED(hres))
6191 break;
6193 else
6195 VARIANTARG *missing_arg;
6196 /* if the function wants a pointer to a variant then
6197 * set that up, otherwise just pass the VT_ERROR in
6198 * the argument by value */
6199 if (rgvt[i] & VT_BYREF)
6201 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6202 V_VT(arg) = VT_VARIANT | VT_BYREF;
6203 V_VARIANTREF(arg) = missing_arg;
6205 else
6206 missing_arg = arg;
6207 V_VT(missing_arg) = VT_ERROR;
6208 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6211 else
6213 hres = DISP_E_BADPARAMCOUNT;
6214 break;
6217 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6219 /* VT_VOID is a special case for return types, so it is not
6220 * handled in the general function */
6221 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6222 V_VT(&varresult) = VT_EMPTY;
6223 else
6225 V_VT(&varresult) = 0;
6226 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6227 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6230 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6231 V_VT(&varresult), func_desc->cParams, rgvt,
6232 prgpvarg, &varresult);
6234 for (i = 0; i < func_desc->cParams; i++)
6236 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6237 if (wParamFlags & PARAMFLAG_FRETVAL)
6239 if (TRACE_ON(ole))
6241 TRACE("[retval] value: ");
6242 dump_Variant(prgpvarg[i]);
6245 if (pVarResult)
6247 VariantInit(pVarResult);
6248 /* deref return value */
6249 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6252 /* free data stored in varresult. Note that
6253 * VariantClear doesn't do what we want because we are
6254 * working with byref types. */
6255 /* FIXME: clear safearrays, bstrs, records and
6256 * variants here too */
6257 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
6258 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
6260 if(*V_UNKNOWNREF(prgpvarg[i]))
6261 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
6263 break;
6265 else if (i < pDispParams->cArgs)
6267 if (wParamFlags & PARAMFLAG_FOUT)
6269 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
6271 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
6272 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6274 if (FAILED(hres))
6276 ERR("failed to convert param %d to vt %d\n", i,
6277 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
6278 break;
6281 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6282 func_desc->cParamsOpt < 0 &&
6283 i == func_desc->cParams-1)
6285 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6286 LONG j, ubound;
6287 VARIANT *v;
6288 hres = SafeArrayGetUBound(a, 1, &ubound);
6289 if (hres != S_OK)
6291 ERR("SafeArrayGetUBound failed with %x\n", hres);
6292 break;
6294 hres = SafeArrayAccessData(a, (LPVOID)&v);
6295 if (hres != S_OK)
6297 ERR("SafeArrayAccessData failed with %x\n", hres);
6298 break;
6300 for (j = 0; j <= ubound; j++)
6301 VariantClear(&v[j]);
6302 hres = SafeArrayUnaccessData(a);
6303 if (hres != S_OK)
6305 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6306 break;
6309 VariantClear(&rgvarg[i]);
6311 else if (wParamFlags & PARAMFLAG_FOPT)
6313 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6314 VariantClear(&rgvarg[i]);
6318 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6320 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6321 hres = DISP_E_EXCEPTION;
6322 if (pExcepInfo)
6324 IErrorInfo *pErrorInfo;
6325 pExcepInfo->scode = V_ERROR(&varresult);
6326 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6328 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6329 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6330 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6331 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6333 IErrorInfo_Release(pErrorInfo);
6337 if (V_VT(&varresult) != VT_ERROR)
6339 TRACE("varresult value: ");
6340 dump_Variant(&varresult);
6342 if (pVarResult)
6344 VariantClear(pVarResult);
6345 *pVarResult = varresult;
6347 else
6348 VariantClear(&varresult);
6351 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6352 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6353 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6354 (pDispParams->cArgs != 0))
6356 if (V_VT(pVarResult) == VT_DISPATCH)
6358 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6359 /* Note: not VariantClear; we still need the dispatch
6360 * pointer to be valid */
6361 VariantInit(pVarResult);
6362 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6363 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6364 pDispParams, pVarResult, pExcepInfo, pArgErr);
6365 IDispatch_Release(pDispatch);
6367 else
6369 VariantClear(pVarResult);
6370 hres = DISP_E_NOTACOLLECTION;
6374 func_fail:
6375 HeapFree(GetProcessHeap(), 0, buffer);
6376 break;
6378 case FUNC_DISPATCH: {
6379 IDispatch *disp;
6381 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6382 if (SUCCEEDED(hres)) {
6383 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6384 hres = IDispatch_Invoke(
6385 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6386 pVarResult,pExcepInfo,pArgErr
6388 if (FAILED(hres))
6389 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6390 IDispatch_Release(disp);
6391 } else
6392 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6393 break;
6395 default:
6396 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6397 hres = E_FAIL;
6398 break;
6401 TRACE("-- 0x%08x\n", hres);
6402 return hres;
6404 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6405 VARDESC *var_desc;
6407 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6408 if(FAILED(hres)) return hres;
6410 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6411 dump_VARDESC(var_desc);
6412 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6413 return E_NOTIMPL;
6416 /* not found, look for it in inherited interfaces */
6417 ITypeInfo2_GetTypeKind(iface, &type_kind);
6418 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6419 if(This->impltypelist) {
6420 /* recursive search */
6421 ITypeInfo *pTInfo;
6422 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6423 if(SUCCEEDED(hres)){
6424 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6425 ITypeInfo_Release(pTInfo);
6426 return hres;
6428 WARN("Could not search inherited interface!\n");
6431 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6432 return DISP_E_MEMBERNOTFOUND;
6435 /* ITypeInfo::GetDocumentation
6437 * Retrieves the documentation string, the complete Help file name and path,
6438 * and the context ID for the Help topic for a specified type description.
6440 * (Can be tested by the Visual Basic Editor in Word for instance.)
6442 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6443 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6444 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6446 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6447 const TLBFuncDesc *pFDesc;
6448 const TLBVarDesc *pVDesc;
6449 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6450 " HelpContext(%p) HelpFile(%p)\n",
6451 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6452 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6453 if(pBstrName)
6454 *pBstrName=SysAllocString(This->Name);
6455 if(pBstrDocString)
6456 *pBstrDocString=SysAllocString(This->DocString);
6457 if(pdwHelpContext)
6458 *pdwHelpContext=This->dwHelpContext;
6459 if(pBstrHelpFile)
6460 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6461 return S_OK;
6462 }else {/* for a member */
6463 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6464 if(pFDesc->funcdesc.memid==memid){
6465 if(pBstrName)
6466 *pBstrName = SysAllocString(pFDesc->Name);
6467 if(pBstrDocString)
6468 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6469 if(pdwHelpContext)
6470 *pdwHelpContext=pFDesc->helpcontext;
6471 return S_OK;
6473 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6474 if(pVDesc->vardesc.memid==memid){
6475 if(pBstrName)
6476 *pBstrName = SysAllocString(pVDesc->Name);
6477 if(pBstrDocString)
6478 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6479 if(pdwHelpContext)
6480 *pdwHelpContext=pVDesc->HelpContext;
6481 return S_OK;
6485 if(This->impltypelist &&
6486 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6487 /* recursive search */
6488 ITypeInfo *pTInfo;
6489 HRESULT result;
6490 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6491 &pTInfo);
6492 if(SUCCEEDED(result)) {
6493 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6494 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6495 ITypeInfo_Release(pTInfo);
6496 return result;
6498 WARN("Could not search inherited interface!\n");
6501 WARN("member %d not found\n", memid);
6502 return TYPE_E_ELEMENTNOTFOUND;
6505 /* ITypeInfo::GetDllEntry
6507 * Retrieves a description or specification of an entry point for a function
6508 * in a DLL.
6510 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6511 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6512 WORD *pwOrdinal)
6514 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6515 const TLBFuncDesc *pFDesc;
6517 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6519 if (pBstrDllName) *pBstrDllName = NULL;
6520 if (pBstrName) *pBstrName = NULL;
6521 if (pwOrdinal) *pwOrdinal = 0;
6523 if (This->TypeAttr.typekind != TKIND_MODULE)
6524 return TYPE_E_BADMODULEKIND;
6526 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6527 if(pFDesc->funcdesc.memid==memid){
6528 dump_TypeInfo(This);
6529 if (TRACE_ON(ole))
6530 dump_TLBFuncDescOne(pFDesc);
6532 if (pBstrDllName)
6533 *pBstrDllName = SysAllocString(This->DllName);
6535 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6536 if (pBstrName)
6537 *pBstrName = SysAllocString(pFDesc->Entry);
6538 if (pwOrdinal)
6539 *pwOrdinal = -1;
6540 return S_OK;
6542 if (pBstrName)
6543 *pBstrName = NULL;
6544 if (pwOrdinal)
6545 *pwOrdinal = (DWORD)pFDesc->Entry;
6546 return S_OK;
6548 return TYPE_E_ELEMENTNOTFOUND;
6551 /* internal function to make the inherited interfaces' methods appear
6552 * part of the interface */
6553 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6554 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6556 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6557 HRESULT hr;
6559 TRACE("%p, 0x%x\n", iface, *hRefType);
6561 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK))
6563 ITypeInfo *pSubTypeInfo;
6565 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
6566 if (FAILED(hr))
6567 return hr;
6569 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6570 hRefType, ppTInfo);
6571 ITypeInfo_Release(pSubTypeInfo);
6572 if (SUCCEEDED(hr))
6573 return hr;
6575 *hRefType -= DISPATCH_HREF_OFFSET;
6577 if (!(*hRefType & DISPATCH_HREF_MASK))
6578 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6579 else
6580 return E_FAIL;
6583 /* ITypeInfo::GetRefTypeInfo
6585 * If a type description references other type descriptions, it retrieves
6586 * the referenced type descriptions.
6588 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6589 ITypeInfo2 *iface,
6590 HREFTYPE hRefType,
6591 ITypeInfo **ppTInfo)
6593 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6594 HRESULT result = E_FAIL;
6596 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6598 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6599 ITypeInfo_AddRef(*ppTInfo);
6600 result = S_OK;
6602 else if (hRefType == -1 &&
6603 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6604 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6606 /* when we meet a DUAL dispinterface, we must create the interface
6607 * version of it.
6609 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
6612 /* the interface version contains the same information as the dispinterface
6613 * copy the contents of the structs.
6615 *pTypeInfoImpl = *This;
6616 pTypeInfoImpl->ref = 0;
6618 /* change the type to interface */
6619 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6621 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6623 /* we use data structures from This, so we need to keep a reference
6624 * to it to stop it being destroyed and signal to the new instance to
6625 * not free its data structures when it is destroyed */
6626 pTypeInfoImpl->no_free_data = TRUE;
6627 pTypeInfoImpl->next = This;
6628 ITypeInfo_AddRef((ITypeInfo*) This);
6630 ITypeInfo_AddRef(*ppTInfo);
6632 result = S_OK;
6634 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6635 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6636 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6638 HREFTYPE href_dispatch = hRefType;
6639 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6640 } else {
6641 TLBRefType *ref_type;
6642 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6644 if(ref_type->reference == hRefType)
6645 break;
6647 if(&ref_type->entry == &This->pTypeLib->ref_list)
6649 FIXME("Can't find pRefType for ref %x\n", hRefType);
6650 goto end;
6652 if(hRefType != -1) {
6653 ITypeLib *pTLib = NULL;
6655 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6656 UINT Index;
6657 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6658 } else {
6659 if(ref_type->pImpTLInfo->pImpTypeLib) {
6660 TRACE("typeinfo in imported typelib that is already loaded\n");
6661 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6662 ITypeLib2_AddRef(pTLib);
6663 result = S_OK;
6664 } else {
6665 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6666 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6667 ref_type->pImpTLInfo->wVersionMajor,
6668 ref_type->pImpTLInfo->wVersionMinor,
6669 ref_type->pImpTLInfo->lcid,
6670 &pTLib);
6672 if(FAILED(result)) {
6673 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6674 result=LoadTypeLib(libnam, &pTLib);
6675 SysFreeString(libnam);
6677 if(SUCCEEDED(result)) {
6678 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6679 ITypeLib2_AddRef(pTLib);
6683 if(SUCCEEDED(result)) {
6684 if(ref_type->index == TLB_REF_USE_GUID)
6685 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6686 &ref_type->guid,
6687 ppTInfo);
6688 else
6689 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6690 ppTInfo);
6692 if (pTLib != NULL)
6693 ITypeLib2_Release(pTLib);
6697 end:
6698 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6699 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6700 return result;
6703 /* ITypeInfo::AddressOfMember
6705 * Retrieves the addresses of static functions or variables, such as those
6706 * defined in a DLL.
6708 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6709 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6711 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6712 HRESULT hr;
6713 BSTR dll, entry;
6714 WORD ordinal;
6715 HMODULE module;
6717 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6719 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6720 if (FAILED(hr))
6721 return hr;
6723 module = LoadLibraryW(dll);
6724 if (!module)
6726 ERR("couldn't load %s\n", debugstr_w(dll));
6727 SysFreeString(dll);
6728 SysFreeString(entry);
6729 return STG_E_FILENOTFOUND;
6731 /* FIXME: store library somewhere where we can free it */
6733 if (entry)
6735 LPSTR entryA;
6736 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6737 entryA = HeapAlloc(GetProcessHeap(), 0, len);
6738 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6740 *ppv = GetProcAddress(module, entryA);
6741 if (!*ppv)
6742 ERR("function not found %s\n", debugstr_a(entryA));
6744 HeapFree(GetProcessHeap(), 0, entryA);
6746 else
6748 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6749 if (!*ppv)
6750 ERR("function not found %d\n", ordinal);
6753 SysFreeString(dll);
6754 SysFreeString(entry);
6756 if (!*ppv)
6757 return TYPE_E_DLLFUNCTIONNOTFOUND;
6759 return S_OK;
6762 /* ITypeInfo::CreateInstance
6764 * Creates a new instance of a type that describes a component object class
6765 * (coclass).
6767 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6768 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6770 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6771 HRESULT hr;
6772 TYPEATTR *pTA;
6774 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6776 *ppvObj = NULL;
6778 if(pOuterUnk)
6780 WARN("Not able to aggregate\n");
6781 return CLASS_E_NOAGGREGATION;
6784 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6785 if(FAILED(hr)) return hr;
6787 if(pTA->typekind != TKIND_COCLASS)
6789 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6790 hr = E_INVALIDARG;
6791 goto end;
6794 hr = S_FALSE;
6795 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6797 IUnknown *pUnk;
6798 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6799 TRACE("GetActiveObject rets %08x\n", hr);
6800 if(hr == S_OK)
6802 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6803 IUnknown_Release(pUnk);
6807 if(hr != S_OK)
6808 hr = CoCreateInstance(&pTA->guid, NULL,
6809 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6810 riid, ppvObj);
6812 end:
6813 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6814 return hr;
6817 /* ITypeInfo::GetMops
6819 * Retrieves marshalling information.
6821 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6822 BSTR *pBstrMops)
6824 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6825 FIXME("(%p) stub!\n", This);
6826 return S_OK;
6829 /* ITypeInfo::GetContainingTypeLib
6831 * Retrieves the containing type library and the index of the type description
6832 * within that type library.
6834 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6835 ITypeLib * *ppTLib, UINT *pIndex)
6837 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6839 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6840 if (pIndex) {
6841 *pIndex=This->index;
6842 TRACE("returning pIndex=%d\n", *pIndex);
6845 if (ppTLib) {
6846 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6847 ITypeLib2_AddRef(*ppTLib);
6848 TRACE("returning ppTLib=%p\n", *ppTLib);
6851 return S_OK;
6854 /* ITypeInfo::ReleaseTypeAttr
6856 * Releases a TYPEATTR previously returned by GetTypeAttr.
6859 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6860 TYPEATTR* pTypeAttr)
6862 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6863 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6864 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6867 /* ITypeInfo::ReleaseFuncDesc
6869 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6871 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6872 ITypeInfo2 *iface,
6873 FUNCDESC *pFuncDesc)
6875 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6876 SHORT i;
6878 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6880 for (i = 0; i < pFuncDesc->cParams; i++)
6881 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6882 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6884 SysFreeString((BSTR)pFuncDesc);
6887 /* ITypeInfo::ReleaseVarDesc
6889 * Releases a VARDESC previously returned by GetVarDesc.
6891 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6892 VARDESC *pVarDesc)
6894 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6895 TRACE("(%p)->(%p)\n", This, pVarDesc);
6897 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6898 if (pVarDesc->varkind == VAR_CONST)
6899 VariantClear(pVarDesc->u.lpvarValue);
6900 SysFreeString((BSTR)pVarDesc);
6903 /* ITypeInfo2::GetTypeKind
6905 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6908 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6909 TYPEKIND *pTypeKind)
6911 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6912 *pTypeKind=This->TypeAttr.typekind;
6913 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6914 return S_OK;
6917 /* ITypeInfo2::GetTypeFlags
6919 * Returns the type flags without any allocations. This returns a DWORD type
6920 * flag, which expands the type flags without growing the TYPEATTR (type
6921 * attribute).
6924 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6926 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6927 *pTypeFlags=This->TypeAttr.wTypeFlags;
6928 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6929 return S_OK;
6932 /* ITypeInfo2::GetFuncIndexOfMemId
6933 * Binds to a specific member based on a known DISPID, where the member name
6934 * is not known (for example, when binding to a default member).
6937 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
6938 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
6940 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6941 const TLBFuncDesc *pFuncInfo;
6942 int i;
6943 HRESULT result;
6945 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
6946 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
6947 break;
6948 if(pFuncInfo) {
6949 *pFuncIndex = i;
6950 result = S_OK;
6951 } else
6952 result = TYPE_E_ELEMENTNOTFOUND;
6954 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
6955 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6956 return result;
6959 /* TypeInfo2::GetVarIndexOfMemId
6961 * Binds to a specific member based on a known DISPID, where the member name
6962 * is not known (for example, when binding to a default member).
6965 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
6966 MEMBERID memid, UINT *pVarIndex)
6968 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6969 TLBVarDesc *pVarInfo;
6970 int i;
6971 HRESULT result;
6972 for(i=0, pVarInfo=This->varlist; pVarInfo &&
6973 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
6975 if(pVarInfo) {
6976 *pVarIndex = i;
6977 result = S_OK;
6978 } else
6979 result = TYPE_E_ELEMENTNOTFOUND;
6981 TRACE("(%p) memid 0x%08x -> %s\n", This,
6982 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6983 return result;
6986 /* ITypeInfo2::GetCustData
6988 * Gets the custom data
6990 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
6991 ITypeInfo2 * iface,
6992 REFGUID guid,
6993 VARIANT *pVarVal)
6995 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6996 TLBCustData *pCData;
6998 for(pCData=This->pCustData; pCData; pCData = pCData->next)
6999 if( IsEqualIID(guid, &pCData->guid)) break;
7001 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7003 if(pCData)
7005 VariantInit( pVarVal);
7006 VariantCopy( pVarVal, &pCData->data);
7007 return S_OK;
7009 return E_INVALIDARG; /* FIXME: correct? */
7012 /* ITypeInfo2::GetFuncCustData
7014 * Gets the custom data
7016 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7017 ITypeInfo2 * iface,
7018 UINT index,
7019 REFGUID guid,
7020 VARIANT *pVarVal)
7022 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7023 TLBCustData *pCData=NULL;
7024 TLBFuncDesc * pFDesc;
7025 UINT i;
7026 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7027 pFDesc=pFDesc->next);
7029 if(pFDesc)
7030 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
7031 if( IsEqualIID(guid, &pCData->guid)) break;
7033 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7035 if(pCData){
7036 VariantInit( pVarVal);
7037 VariantCopy( pVarVal, &pCData->data);
7038 return S_OK;
7040 return E_INVALIDARG; /* FIXME: correct? */
7043 /* ITypeInfo2::GetParamCustData
7045 * Gets the custom data
7047 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7048 ITypeInfo2 * iface,
7049 UINT indexFunc,
7050 UINT indexParam,
7051 REFGUID guid,
7052 VARIANT *pVarVal)
7054 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7055 TLBCustData *pCData=NULL;
7056 TLBFuncDesc * pFDesc;
7057 UINT i;
7059 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
7061 if(pFDesc && indexParam<pFDesc->funcdesc.cParams)
7062 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
7063 pCData = pCData->next)
7064 if( IsEqualIID(guid, &pCData->guid)) break;
7066 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7068 if(pCData)
7070 VariantInit( pVarVal);
7071 VariantCopy( pVarVal, &pCData->data);
7072 return S_OK;
7074 return E_INVALIDARG; /* FIXME: correct? */
7077 /* ITypeInfo2::GetVarCustData
7079 * Gets the custom data
7081 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7082 ITypeInfo2 * iface,
7083 UINT index,
7084 REFGUID guid,
7085 VARIANT *pVarVal)
7087 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7088 TLBCustData *pCData=NULL;
7089 TLBVarDesc * pVDesc;
7090 UINT i;
7092 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
7094 if(pVDesc)
7096 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
7098 if( IsEqualIID(guid, &pCData->guid)) break;
7102 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7104 if(pCData)
7106 VariantInit( pVarVal);
7107 VariantCopy( pVarVal, &pCData->data);
7108 return S_OK;
7110 return E_INVALIDARG; /* FIXME: correct? */
7113 /* ITypeInfo2::GetImplCustData
7115 * Gets the custom data
7117 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7118 ITypeInfo2 * iface,
7119 UINT index,
7120 REFGUID guid,
7121 VARIANT *pVarVal)
7123 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7124 TLBCustData *pCData=NULL;
7125 TLBImplType * pRDesc;
7126 UINT i;
7128 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
7130 if(pRDesc)
7132 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
7134 if( IsEqualIID(guid, &pCData->guid)) break;
7138 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7140 if(pCData)
7142 VariantInit( pVarVal);
7143 VariantCopy( pVarVal, &pCData->data);
7144 return S_OK;
7146 return E_INVALIDARG; /* FIXME: correct? */
7149 /* ITypeInfo2::GetDocumentation2
7151 * Retrieves the documentation string, the complete Help file name and path,
7152 * the localization context to use, and the context ID for the library Help
7153 * topic in the Help file.
7156 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7157 ITypeInfo2 * iface,
7158 MEMBERID memid,
7159 LCID lcid,
7160 BSTR *pbstrHelpString,
7161 DWORD *pdwHelpStringContext,
7162 BSTR *pbstrHelpStringDll)
7164 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7165 const TLBFuncDesc *pFDesc;
7166 const TLBVarDesc *pVDesc;
7167 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7168 "HelpStringContext(%p) HelpStringDll(%p)\n",
7169 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7170 pbstrHelpStringDll );
7171 /* the help string should be obtained from the helpstringdll,
7172 * using the _DLLGetDocumentation function, based on the supplied
7173 * lcid. Nice to do sometime...
7175 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7176 if(pbstrHelpString)
7177 *pbstrHelpString=SysAllocString(This->Name);
7178 if(pdwHelpStringContext)
7179 *pdwHelpStringContext=This->dwHelpStringContext;
7180 if(pbstrHelpStringDll)
7181 *pbstrHelpStringDll=
7182 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7183 return S_OK;
7184 }else {/* for a member */
7185 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
7186 if(pFDesc->funcdesc.memid==memid){
7187 if(pbstrHelpString)
7188 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
7189 if(pdwHelpStringContext)
7190 *pdwHelpStringContext=pFDesc->HelpStringContext;
7191 if(pbstrHelpStringDll)
7192 *pbstrHelpStringDll=
7193 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7194 return S_OK;
7196 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
7197 if(pVDesc->vardesc.memid==memid){
7198 if(pbstrHelpString)
7199 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
7200 if(pdwHelpStringContext)
7201 *pdwHelpStringContext=pVDesc->HelpStringContext;
7202 if(pbstrHelpStringDll)
7203 *pbstrHelpStringDll=
7204 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7205 return S_OK;
7208 return TYPE_E_ELEMENTNOTFOUND;
7211 /* ITypeInfo2::GetAllCustData
7213 * Gets all custom data items for the Type info.
7216 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7217 ITypeInfo2 * iface,
7218 CUSTDATA *pCustData)
7220 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7221 TLBCustData *pCData;
7222 int i;
7224 TRACE("(%p) returning %d items\n", This, This->ctCustData);
7226 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
7227 if(pCustData->prgCustData ){
7228 pCustData->cCustData=This->ctCustData;
7229 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
7230 pCustData->prgCustData[i].guid=pCData->guid;
7231 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
7233 }else{
7234 ERR(" OUT OF MEMORY!\n");
7235 return E_OUTOFMEMORY;
7237 return S_OK;
7240 /* ITypeInfo2::GetAllFuncCustData
7242 * Gets all custom data items for the specified Function
7245 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7246 ITypeInfo2 * iface,
7247 UINT index,
7248 CUSTDATA *pCustData)
7250 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7251 TLBCustData *pCData;
7252 TLBFuncDesc * pFDesc;
7253 UINT i;
7254 TRACE("(%p) index %d\n", This, index);
7255 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7256 pFDesc=pFDesc->next)
7258 if(pFDesc){
7259 pCustData->prgCustData =
7260 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
7261 if(pCustData->prgCustData ){
7262 pCustData->cCustData=pFDesc->ctCustData;
7263 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
7264 pCData = pCData->next){
7265 pCustData->prgCustData[i].guid=pCData->guid;
7266 VariantCopy(& pCustData->prgCustData[i].varValue,
7267 & pCData->data);
7269 }else{
7270 ERR(" OUT OF MEMORY!\n");
7271 return E_OUTOFMEMORY;
7273 return S_OK;
7275 return TYPE_E_ELEMENTNOTFOUND;
7278 /* ITypeInfo2::GetAllParamCustData
7280 * Gets all custom data items for the Functions
7283 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7284 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7286 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7287 TLBCustData *pCData=NULL;
7288 TLBFuncDesc * pFDesc;
7289 UINT i;
7290 TRACE("(%p) index %d\n", This, indexFunc);
7291 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
7292 pFDesc=pFDesc->next)
7294 if(pFDesc && indexParam<pFDesc->funcdesc.cParams){
7295 pCustData->prgCustData =
7296 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
7297 sizeof(CUSTDATAITEM));
7298 if(pCustData->prgCustData ){
7299 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
7300 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
7301 pCData; i++, pCData = pCData->next){
7302 pCustData->prgCustData[i].guid=pCData->guid;
7303 VariantCopy(& pCustData->prgCustData[i].varValue,
7304 & pCData->data);
7306 }else{
7307 ERR(" OUT OF MEMORY!\n");
7308 return E_OUTOFMEMORY;
7310 return S_OK;
7312 return TYPE_E_ELEMENTNOTFOUND;
7315 /* ITypeInfo2::GetAllVarCustData
7317 * Gets all custom data items for the specified Variable
7320 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7321 UINT index, CUSTDATA *pCustData)
7323 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7324 TLBCustData *pCData;
7325 TLBVarDesc * pVDesc;
7326 UINT i;
7327 TRACE("(%p) index %d\n", This, index);
7328 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
7329 pVDesc=pVDesc->next)
7331 if(pVDesc){
7332 pCustData->prgCustData =
7333 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
7334 if(pCustData->prgCustData ){
7335 pCustData->cCustData=pVDesc->ctCustData;
7336 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
7337 pCData = pCData->next){
7338 pCustData->prgCustData[i].guid=pCData->guid;
7339 VariantCopy(& pCustData->prgCustData[i].varValue,
7340 & pCData->data);
7342 }else{
7343 ERR(" OUT OF MEMORY!\n");
7344 return E_OUTOFMEMORY;
7346 return S_OK;
7348 return TYPE_E_ELEMENTNOTFOUND;
7351 /* ITypeInfo2::GetAllImplCustData
7353 * Gets all custom data items for the specified implementation type
7356 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7357 ITypeInfo2 * iface,
7358 UINT index,
7359 CUSTDATA *pCustData)
7361 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7362 TLBCustData *pCData;
7363 TLBImplType * pRDesc;
7364 UINT i;
7365 TRACE("(%p) index %d\n", This, index);
7366 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
7367 pRDesc=pRDesc->next)
7369 if(pRDesc){
7370 pCustData->prgCustData =
7371 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
7372 if(pCustData->prgCustData ){
7373 pCustData->cCustData=pRDesc->ctCustData;
7374 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
7375 pCData = pCData->next){
7376 pCustData->prgCustData[i].guid=pCData->guid;
7377 VariantCopy(& pCustData->prgCustData[i].varValue,
7378 & pCData->data);
7380 }else{
7381 ERR(" OUT OF MEMORY!\n");
7382 return E_OUTOFMEMORY;
7384 return S_OK;
7386 return TYPE_E_ELEMENTNOTFOUND;
7389 static const ITypeInfo2Vtbl tinfvt =
7392 ITypeInfo_fnQueryInterface,
7393 ITypeInfo_fnAddRef,
7394 ITypeInfo_fnRelease,
7396 ITypeInfo_fnGetTypeAttr,
7397 ITypeInfo_fnGetTypeComp,
7398 ITypeInfo_fnGetFuncDesc,
7399 ITypeInfo_fnGetVarDesc,
7400 ITypeInfo_fnGetNames,
7401 ITypeInfo_fnGetRefTypeOfImplType,
7402 ITypeInfo_fnGetImplTypeFlags,
7403 ITypeInfo_fnGetIDsOfNames,
7404 ITypeInfo_fnInvoke,
7405 ITypeInfo_fnGetDocumentation,
7406 ITypeInfo_fnGetDllEntry,
7407 ITypeInfo_fnGetRefTypeInfo,
7408 ITypeInfo_fnAddressOfMember,
7409 ITypeInfo_fnCreateInstance,
7410 ITypeInfo_fnGetMops,
7411 ITypeInfo_fnGetContainingTypeLib,
7412 ITypeInfo_fnReleaseTypeAttr,
7413 ITypeInfo_fnReleaseFuncDesc,
7414 ITypeInfo_fnReleaseVarDesc,
7416 ITypeInfo2_fnGetTypeKind,
7417 ITypeInfo2_fnGetTypeFlags,
7418 ITypeInfo2_fnGetFuncIndexOfMemId,
7419 ITypeInfo2_fnGetVarIndexOfMemId,
7420 ITypeInfo2_fnGetCustData,
7421 ITypeInfo2_fnGetFuncCustData,
7422 ITypeInfo2_fnGetParamCustData,
7423 ITypeInfo2_fnGetVarCustData,
7424 ITypeInfo2_fnGetImplTypeCustData,
7425 ITypeInfo2_fnGetDocumentation2,
7426 ITypeInfo2_fnGetAllCustData,
7427 ITypeInfo2_fnGetAllFuncCustData,
7428 ITypeInfo2_fnGetAllParamCustData,
7429 ITypeInfo2_fnGetAllVarCustData,
7430 ITypeInfo2_fnGetAllImplTypeCustData,
7433 /******************************************************************************
7434 * CreateDispTypeInfo [OLEAUT32.31]
7436 * Build type information for an object so it can be called through an
7437 * IDispatch interface.
7439 * RETURNS
7440 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7441 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7443 * NOTES
7444 * This call allows an objects methods to be accessed through IDispatch, by
7445 * building an ITypeInfo object that IDispatch can use to call through.
7447 HRESULT WINAPI CreateDispTypeInfo(
7448 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7449 LCID lcid, /* [I] Locale Id */
7450 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7452 ITypeInfoImpl *pTIClass, *pTIIface;
7453 ITypeLibImpl *pTypeLibImpl;
7454 unsigned int param, func;
7455 TLBFuncDesc **ppFuncDesc;
7456 TLBRefType *ref;
7458 TRACE("\n");
7459 pTypeLibImpl = TypeLibImpl_Constructor();
7460 if (!pTypeLibImpl) return E_FAIL;
7462 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
7463 pTIIface->pTypeLib = pTypeLibImpl;
7464 pTIIface->index = 0;
7465 pTIIface->Name = NULL;
7466 pTIIface->dwHelpContext = -1;
7467 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7468 pTIIface->TypeAttr.lcid = lcid;
7469 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7470 pTIIface->TypeAttr.wMajorVerNum = 0;
7471 pTIIface->TypeAttr.wMinorVerNum = 0;
7472 pTIIface->TypeAttr.cbAlignment = 2;
7473 pTIIface->TypeAttr.cbSizeInstance = -1;
7474 pTIIface->TypeAttr.cbSizeVft = -1;
7475 pTIIface->TypeAttr.cFuncs = 0;
7476 pTIIface->TypeAttr.cImplTypes = 0;
7477 pTIIface->TypeAttr.cVars = 0;
7478 pTIIface->TypeAttr.wTypeFlags = 0;
7480 ppFuncDesc = &pTIIface->funclist;
7481 for(func = 0; func < pidata->cMembers; func++) {
7482 METHODDATA *md = pidata->pmethdata + func;
7483 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
7484 (*ppFuncDesc)->Name = SysAllocString(md->szName);
7485 (*ppFuncDesc)->funcdesc.memid = md->dispid;
7486 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
7487 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
7488 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
7489 (*ppFuncDesc)->funcdesc.callconv = md->cc;
7490 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
7491 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
7492 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
7493 (*ppFuncDesc)->funcdesc.cScodes = 0;
7494 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
7495 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7496 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7497 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7498 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7499 md->cArgs * sizeof(ELEMDESC));
7500 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7501 md->cArgs * sizeof(TLBParDesc));
7502 for(param = 0; param < md->cArgs; param++) {
7503 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7504 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7506 (*ppFuncDesc)->helpcontext = 0;
7507 (*ppFuncDesc)->HelpStringContext = 0;
7508 (*ppFuncDesc)->HelpString = NULL;
7509 (*ppFuncDesc)->Entry = NULL;
7510 (*ppFuncDesc)->ctCustData = 0;
7511 (*ppFuncDesc)->pCustData = NULL;
7512 (*ppFuncDesc)->next = NULL;
7513 pTIIface->TypeAttr.cFuncs++;
7514 ppFuncDesc = &(*ppFuncDesc)->next;
7517 dump_TypeInfo(pTIIface);
7519 pTypeLibImpl->pTypeInfo = pTIIface;
7520 pTypeLibImpl->TypeInfoCount++;
7522 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
7523 pTIClass->pTypeLib = pTypeLibImpl;
7524 pTIClass->index = 1;
7525 pTIClass->Name = NULL;
7526 pTIClass->dwHelpContext = -1;
7527 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7528 pTIClass->TypeAttr.lcid = lcid;
7529 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7530 pTIClass->TypeAttr.wMajorVerNum = 0;
7531 pTIClass->TypeAttr.wMinorVerNum = 0;
7532 pTIClass->TypeAttr.cbAlignment = 2;
7533 pTIClass->TypeAttr.cbSizeInstance = -1;
7534 pTIClass->TypeAttr.cbSizeVft = -1;
7535 pTIClass->TypeAttr.cFuncs = 0;
7536 pTIClass->TypeAttr.cImplTypes = 1;
7537 pTIClass->TypeAttr.cVars = 0;
7538 pTIClass->TypeAttr.wTypeFlags = 0;
7540 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
7541 pTIClass->impltypelist->hRef = 0;
7543 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
7544 ref->index = 0;
7545 ref->reference = 0;
7546 ref->pImpTLInfo = TLB_REF_INTERNAL;
7547 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7549 dump_TypeInfo(pTIClass);
7551 pTIIface->next = pTIClass;
7552 pTypeLibImpl->TypeInfoCount++;
7554 *pptinfo = (ITypeInfo*)pTIClass;
7556 ITypeInfo_AddRef(*pptinfo);
7557 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7559 return S_OK;
7563 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7565 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7567 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7570 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7572 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7574 return ITypeInfo_AddRef((ITypeInfo *)This);
7577 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7579 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7581 return ITypeInfo_Release((ITypeInfo *)This);
7584 static HRESULT WINAPI ITypeComp_fnBind(
7585 ITypeComp * iface,
7586 OLECHAR * szName,
7587 ULONG lHash,
7588 WORD wFlags,
7589 ITypeInfo ** ppTInfo,
7590 DESCKIND * pDescKind,
7591 BINDPTR * pBindPtr)
7593 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7594 const TLBFuncDesc *pFDesc;
7595 const TLBVarDesc *pVDesc;
7596 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7598 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7600 *pDescKind = DESCKIND_NONE;
7601 pBindPtr->lpfuncdesc = NULL;
7602 *ppTInfo = NULL;
7604 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
7605 if (!strcmpiW(pFDesc->Name, szName)) {
7606 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7607 break;
7608 else
7609 /* name found, but wrong flags */
7610 hr = TYPE_E_TYPEMISMATCH;
7613 if (pFDesc)
7615 HRESULT hr = TLB_AllocAndInitFuncDesc(
7616 &pFDesc->funcdesc,
7617 &pBindPtr->lpfuncdesc,
7618 This->TypeAttr.typekind == TKIND_DISPATCH);
7619 if (FAILED(hr))
7620 return hr;
7621 *pDescKind = DESCKIND_FUNCDESC;
7622 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7623 ITypeInfo_AddRef(*ppTInfo);
7624 return S_OK;
7625 } else {
7626 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7627 if (!strcmpiW(pVDesc->Name, szName)) {
7628 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7629 if (FAILED(hr))
7630 return hr;
7631 *pDescKind = DESCKIND_VARDESC;
7632 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7633 ITypeInfo_AddRef(*ppTInfo);
7634 return S_OK;
7638 /* FIXME: search each inherited interface, not just the first */
7639 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7640 /* recursive search */
7641 ITypeInfo *pTInfo;
7642 ITypeComp *pTComp;
7643 HRESULT hr;
7644 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7645 if (SUCCEEDED(hr))
7647 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7648 ITypeInfo_Release(pTInfo);
7650 if (SUCCEEDED(hr))
7652 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7653 ITypeComp_Release(pTComp);
7654 return hr;
7656 WARN("Could not search inherited interface!\n");
7658 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
7659 return hr;
7662 static HRESULT WINAPI ITypeComp_fnBindType(
7663 ITypeComp * iface,
7664 OLECHAR * szName,
7665 ULONG lHash,
7666 ITypeInfo ** ppTInfo,
7667 ITypeComp ** ppTComp)
7669 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7671 /* strange behaviour (does nothing) but like the
7672 * original */
7674 if (!ppTInfo || !ppTComp)
7675 return E_POINTER;
7677 *ppTInfo = NULL;
7678 *ppTComp = NULL;
7680 return S_OK;
7683 static const ITypeCompVtbl tcompvt =
7686 ITypeComp_fnQueryInterface,
7687 ITypeComp_fnAddRef,
7688 ITypeComp_fnRelease,
7690 ITypeComp_fnBind,
7691 ITypeComp_fnBindType