msvcrt/tests: Remove a space before a '\n'.
[wine/gsoc-2012-control.git] / dlls / oleaut32 / typelib.c
blob503aaf768eac5f58914ef8a16613f7bfb195ee10
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, (LPOLESTR)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 = (LPVOID)(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 if(pTITail) { /* 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);
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, (void *)(*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) \
5949 ((VARIANTARG *)(buffer))
5950 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5951 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5952 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5953 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5954 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5955 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5957 static HRESULT WINAPI ITypeInfo_fnInvoke(
5958 ITypeInfo2 *iface,
5959 VOID *pIUnk,
5960 MEMBERID memid,
5961 UINT16 wFlags,
5962 DISPPARAMS *pDispParams,
5963 VARIANT *pVarResult,
5964 EXCEPINFO *pExcepInfo,
5965 UINT *pArgErr)
5967 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5968 int i;
5969 unsigned int var_index;
5970 TYPEKIND type_kind;
5971 HRESULT hres;
5972 const TLBFuncDesc *pFuncInfo;
5974 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
5975 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5978 if (!pDispParams)
5980 ERR("NULL pDispParams not allowed\n");
5981 return E_INVALIDARG;
5984 dump_DispParms(pDispParams);
5986 if (pDispParams->cNamedArgs > pDispParams->cArgs)
5988 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
5989 pDispParams->cNamedArgs, pDispParams->cArgs);
5990 return E_INVALIDARG;
5993 /* we do this instead of using GetFuncDesc since it will return a fake
5994 * FUNCDESC for dispinterfaces and we want the real function description */
5995 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5996 if ((memid == pFuncInfo->funcdesc.memid) &&
5997 (wFlags & pFuncInfo->funcdesc.invkind))
5998 break;
6000 if (pFuncInfo) {
6001 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6003 if (TRACE_ON(ole))
6005 TRACE("invoking:\n");
6006 dump_TLBFuncDescOne(pFuncInfo);
6009 switch (func_desc->funckind) {
6010 case FUNC_PUREVIRTUAL:
6011 case FUNC_VIRTUAL: {
6012 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
6013 VARIANT varresult;
6014 VARIANT retval; /* pointer for storing byref retvals in */
6015 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6016 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6017 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6018 UINT cNamedArgs = pDispParams->cNamedArgs;
6019 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6021 hres = S_OK;
6023 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6025 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6027 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6028 hres = DISP_E_PARAMNOTFOUND;
6029 goto func_fail;
6031 /* ignore the DISPID_PROPERTYPUT named argument from now on */
6032 cNamedArgs--;
6033 rgdispidNamedArgs++;
6036 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6038 ERR("functions with the vararg attribute do not support named arguments\n");
6039 hres = DISP_E_NONAMEDARGS;
6040 goto func_fail;
6043 for (i = 0; i < func_desc->cParams; i++)
6045 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6046 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6047 if (FAILED(hres))
6048 goto func_fail;
6051 TRACE("changing args\n");
6052 for (i = 0; i < func_desc->cParams; i++)
6054 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6055 VARIANTARG *src_arg;
6057 if (cNamedArgs)
6059 USHORT j;
6060 src_arg = NULL;
6061 for (j = 0; j < cNamedArgs; j++)
6062 if (rgdispidNamedArgs[j] == i)
6064 src_arg = &pDispParams->rgvarg[j];
6065 break;
6068 else
6069 src_arg = i < pDispParams->cArgs ? &pDispParams->rgvarg[pDispParams->cArgs - 1 - i] : NULL;
6071 if (wParamFlags & PARAMFLAG_FRETVAL)
6073 /* under most conditions the caller is not allowed to
6074 * pass in a dispparam arg in the index of what would be
6075 * the retval parameter. however, there is an exception
6076 * where the extra parameter is used in an extra
6077 * IDispatch::Invoke below */
6078 if ((i < pDispParams->cArgs) &&
6079 ((func_desc->cParams != 1) || !pVarResult ||
6080 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6082 hres = DISP_E_BADPARAMCOUNT;
6083 break;
6086 /* note: this check is placed so that if the caller passes
6087 * in a VARIANTARG for the retval we just ignore it, like
6088 * native does */
6089 if (i == func_desc->cParams - 1)
6091 VARIANTARG *arg;
6092 arg = prgpvarg[i] = &rgvarg[i];
6093 memset(arg, 0, sizeof(*arg));
6094 V_VT(arg) = rgvt[i];
6095 memset(&retval, 0, sizeof(retval));
6096 V_BYREF(arg) = &retval;
6098 else
6100 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6101 hres = E_UNEXPECTED;
6102 break;
6105 else if (src_arg)
6107 dump_Variant(src_arg);
6109 if (rgvt[i] == VT_VARIANT)
6110 hres = VariantCopy(&rgvarg[i], src_arg);
6111 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6113 if (rgvt[i] == V_VT(src_arg))
6114 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6115 else
6117 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6118 hres = VariantCopy(&missing_arg[i], src_arg);
6119 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6121 V_VT(&rgvarg[i]) = rgvt[i];
6123 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6125 SAFEARRAY *a;
6126 SAFEARRAYBOUND bound;
6127 VARIANT *v;
6128 LONG j;
6129 bound.lLbound = 0;
6130 bound.cElements = pDispParams->cArgs-i;
6131 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6133 ERR("SafeArrayCreate failed\n");
6134 break;
6136 hres = SafeArrayAccessData(a, (LPVOID)&v);
6137 if (hres != S_OK)
6139 ERR("SafeArrayAccessData failed with %x\n", hres);
6140 break;
6142 for (j = 0; j < bound.cElements; j++)
6143 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6144 hres = SafeArrayUnaccessData(a);
6145 if (hres != S_OK)
6147 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6148 break;
6150 V_ARRAY(&rgvarg[i]) = a;
6151 V_VT(&rgvarg[i]) = rgvt[i];
6153 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6155 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6156 V_VT(&missing_arg[i]) = V_VT(src_arg);
6157 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6158 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6159 V_VT(&rgvarg[i]) = rgvt[i];
6161 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6163 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6164 V_VT(&rgvarg[i]) = rgvt[i];
6166 else
6168 /* FIXME: this doesn't work for VT_BYREF arguments if
6169 * they are not the same type as in the paramdesc */
6170 V_VT(&rgvarg[i]) = V_VT(src_arg);
6171 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6172 V_VT(&rgvarg[i]) = rgvt[i];
6175 if (FAILED(hres))
6177 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6178 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6179 debugstr_VT(src_arg), debugstr_VF(src_arg));
6180 break;
6182 prgpvarg[i] = &rgvarg[i];
6184 else if (wParamFlags & PARAMFLAG_FOPT)
6186 VARIANTARG *arg;
6187 arg = prgpvarg[i] = &rgvarg[i];
6188 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6190 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6191 if (FAILED(hres))
6192 break;
6194 else
6196 VARIANTARG *missing_arg;
6197 /* if the function wants a pointer to a variant then
6198 * set that up, otherwise just pass the VT_ERROR in
6199 * the argument by value */
6200 if (rgvt[i] & VT_BYREF)
6202 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6203 V_VT(arg) = VT_VARIANT | VT_BYREF;
6204 V_VARIANTREF(arg) = missing_arg;
6206 else
6207 missing_arg = arg;
6208 V_VT(missing_arg) = VT_ERROR;
6209 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6212 else
6214 hres = DISP_E_BADPARAMCOUNT;
6215 break;
6218 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6220 /* VT_VOID is a special case for return types, so it is not
6221 * handled in the general function */
6222 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6223 V_VT(&varresult) = VT_EMPTY;
6224 else
6226 V_VT(&varresult) = 0;
6227 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6228 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6231 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6232 V_VT(&varresult), func_desc->cParams, rgvt,
6233 prgpvarg, &varresult);
6235 for (i = 0; i < func_desc->cParams; i++)
6237 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6238 if (wParamFlags & PARAMFLAG_FRETVAL)
6240 if (TRACE_ON(ole))
6242 TRACE("[retval] value: ");
6243 dump_Variant(prgpvarg[i]);
6246 if (pVarResult)
6248 VariantInit(pVarResult);
6249 /* deref return value */
6250 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6253 /* free data stored in varresult. Note that
6254 * VariantClear doesn't do what we want because we are
6255 * working with byref types. */
6256 /* FIXME: clear safearrays, bstrs, records and
6257 * variants here too */
6258 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
6259 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
6261 if(*V_UNKNOWNREF(prgpvarg[i]))
6262 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
6264 break;
6266 else if (i < pDispParams->cArgs)
6268 if (wParamFlags & PARAMFLAG_FOUT)
6270 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
6272 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
6273 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6275 if (FAILED(hres))
6277 ERR("failed to convert param %d to vt %d\n", i,
6278 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
6279 break;
6282 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6283 func_desc->cParamsOpt < 0 &&
6284 i == func_desc->cParams-1)
6286 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6287 LONG j, ubound;
6288 VARIANT *v;
6289 hres = SafeArrayGetUBound(a, 1, &ubound);
6290 if (hres != S_OK)
6292 ERR("SafeArrayGetUBound failed with %x\n", hres);
6293 break;
6295 hres = SafeArrayAccessData(a, (LPVOID)&v);
6296 if (hres != S_OK)
6298 ERR("SafeArrayAccessData failed with %x\n", hres);
6299 break;
6301 for (j = 0; j <= ubound; j++)
6302 VariantClear(&v[j]);
6303 hres = SafeArrayUnaccessData(a);
6304 if (hres != S_OK)
6306 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6307 break;
6310 VariantClear(&rgvarg[i]);
6312 else if (wParamFlags & PARAMFLAG_FOPT)
6314 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6315 VariantClear(&rgvarg[i]);
6319 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6321 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6322 hres = DISP_E_EXCEPTION;
6323 if (pExcepInfo)
6325 IErrorInfo *pErrorInfo;
6326 pExcepInfo->scode = V_ERROR(&varresult);
6327 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6329 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6330 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6331 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6332 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6334 IErrorInfo_Release(pErrorInfo);
6338 if (V_VT(&varresult) != VT_ERROR)
6340 TRACE("varresult value: ");
6341 dump_Variant(&varresult);
6343 if (pVarResult)
6345 VariantClear(pVarResult);
6346 *pVarResult = varresult;
6348 else
6349 VariantClear(&varresult);
6352 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6353 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6354 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6355 (pDispParams->cArgs != 0))
6357 if (V_VT(pVarResult) == VT_DISPATCH)
6359 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6360 /* Note: not VariantClear; we still need the dispatch
6361 * pointer to be valid */
6362 VariantInit(pVarResult);
6363 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6364 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6365 pDispParams, pVarResult, pExcepInfo, pArgErr);
6366 IDispatch_Release(pDispatch);
6368 else
6370 VariantClear(pVarResult);
6371 hres = DISP_E_NOTACOLLECTION;
6375 func_fail:
6376 HeapFree(GetProcessHeap(), 0, buffer);
6377 break;
6379 case FUNC_DISPATCH: {
6380 IDispatch *disp;
6382 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6383 if (SUCCEEDED(hres)) {
6384 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6385 hres = IDispatch_Invoke(
6386 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6387 pVarResult,pExcepInfo,pArgErr
6389 if (FAILED(hres))
6390 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6391 IDispatch_Release(disp);
6392 } else
6393 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6394 break;
6396 default:
6397 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6398 hres = E_FAIL;
6399 break;
6402 TRACE("-- 0x%08x\n", hres);
6403 return hres;
6405 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6406 VARDESC *var_desc;
6408 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6409 if(FAILED(hres)) return hres;
6411 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6412 dump_VARDESC(var_desc);
6413 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6414 return E_NOTIMPL;
6417 /* not found, look for it in inherited interfaces */
6418 ITypeInfo2_GetTypeKind(iface, &type_kind);
6419 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6420 if(This->impltypelist) {
6421 /* recursive search */
6422 ITypeInfo *pTInfo;
6423 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6424 if(SUCCEEDED(hres)){
6425 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6426 ITypeInfo_Release(pTInfo);
6427 return hres;
6429 WARN("Could not search inherited interface!\n");
6432 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6433 return DISP_E_MEMBERNOTFOUND;
6436 /* ITypeInfo::GetDocumentation
6438 * Retrieves the documentation string, the complete Help file name and path,
6439 * and the context ID for the Help topic for a specified type description.
6441 * (Can be tested by the Visual Basic Editor in Word for instance.)
6443 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6444 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6445 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6447 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6448 const TLBFuncDesc *pFDesc;
6449 const TLBVarDesc *pVDesc;
6450 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6451 " HelpContext(%p) HelpFile(%p)\n",
6452 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6453 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6454 if(pBstrName)
6455 *pBstrName=SysAllocString(This->Name);
6456 if(pBstrDocString)
6457 *pBstrDocString=SysAllocString(This->DocString);
6458 if(pdwHelpContext)
6459 *pdwHelpContext=This->dwHelpContext;
6460 if(pBstrHelpFile)
6461 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6462 return S_OK;
6463 }else {/* for a member */
6464 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6465 if(pFDesc->funcdesc.memid==memid){
6466 if(pBstrName)
6467 *pBstrName = SysAllocString(pFDesc->Name);
6468 if(pBstrDocString)
6469 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6470 if(pdwHelpContext)
6471 *pdwHelpContext=pFDesc->helpcontext;
6472 return S_OK;
6474 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6475 if(pVDesc->vardesc.memid==memid){
6476 if(pBstrName)
6477 *pBstrName = SysAllocString(pVDesc->Name);
6478 if(pBstrDocString)
6479 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6480 if(pdwHelpContext)
6481 *pdwHelpContext=pVDesc->HelpContext;
6482 return S_OK;
6486 if(This->impltypelist &&
6487 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6488 /* recursive search */
6489 ITypeInfo *pTInfo;
6490 HRESULT result;
6491 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6492 &pTInfo);
6493 if(SUCCEEDED(result)) {
6494 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6495 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6496 ITypeInfo_Release(pTInfo);
6497 return result;
6499 WARN("Could not search inherited interface!\n");
6502 WARN("member %d not found\n", memid);
6503 return TYPE_E_ELEMENTNOTFOUND;
6506 /* ITypeInfo::GetDllEntry
6508 * Retrieves a description or specification of an entry point for a function
6509 * in a DLL.
6511 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6512 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6513 WORD *pwOrdinal)
6515 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6516 const TLBFuncDesc *pFDesc;
6518 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6520 if (pBstrDllName) *pBstrDllName = NULL;
6521 if (pBstrName) *pBstrName = NULL;
6522 if (pwOrdinal) *pwOrdinal = 0;
6524 if (This->TypeAttr.typekind != TKIND_MODULE)
6525 return TYPE_E_BADMODULEKIND;
6527 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6528 if(pFDesc->funcdesc.memid==memid){
6529 dump_TypeInfo(This);
6530 if (TRACE_ON(ole))
6531 dump_TLBFuncDescOne(pFDesc);
6533 if (pBstrDllName)
6534 *pBstrDllName = SysAllocString(This->DllName);
6536 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6537 if (pBstrName)
6538 *pBstrName = SysAllocString(pFDesc->Entry);
6539 if (pwOrdinal)
6540 *pwOrdinal = -1;
6541 return S_OK;
6543 if (pBstrName)
6544 *pBstrName = NULL;
6545 if (pwOrdinal)
6546 *pwOrdinal = (DWORD)pFDesc->Entry;
6547 return S_OK;
6549 return TYPE_E_ELEMENTNOTFOUND;
6552 /* internal function to make the inherited interfaces' methods appear
6553 * part of the interface */
6554 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6555 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6557 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6558 HRESULT hr;
6560 TRACE("%p, 0x%x\n", iface, *hRefType);
6562 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK))
6564 ITypeInfo *pSubTypeInfo;
6566 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
6567 if (FAILED(hr))
6568 return hr;
6570 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6571 hRefType, ppTInfo);
6572 ITypeInfo_Release(pSubTypeInfo);
6573 if (SUCCEEDED(hr))
6574 return hr;
6576 *hRefType -= DISPATCH_HREF_OFFSET;
6578 if (!(*hRefType & DISPATCH_HREF_MASK))
6579 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6580 else
6581 return E_FAIL;
6584 /* ITypeInfo::GetRefTypeInfo
6586 * If a type description references other type descriptions, it retrieves
6587 * the referenced type descriptions.
6589 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6590 ITypeInfo2 *iface,
6591 HREFTYPE hRefType,
6592 ITypeInfo **ppTInfo)
6594 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6595 HRESULT result = E_FAIL;
6597 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6599 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6600 ITypeInfo_AddRef(*ppTInfo);
6601 result = S_OK;
6603 else if (hRefType == -1 &&
6604 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6605 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6607 /* when we meet a DUAL dispinterface, we must create the interface
6608 * version of it.
6610 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
6613 /* the interface version contains the same information as the dispinterface
6614 * copy the contents of the structs.
6616 *pTypeInfoImpl = *This;
6617 pTypeInfoImpl->ref = 0;
6619 /* change the type to interface */
6620 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6622 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6624 /* we use data structures from This, so we need to keep a reference
6625 * to it to stop it being destroyed and signal to the new instance to
6626 * not free its data structures when it is destroyed */
6627 pTypeInfoImpl->no_free_data = TRUE;
6628 pTypeInfoImpl->next = This;
6629 ITypeInfo_AddRef((ITypeInfo*) This);
6631 ITypeInfo_AddRef(*ppTInfo);
6633 result = S_OK;
6635 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6636 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6637 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6639 HREFTYPE href_dispatch = hRefType;
6640 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6641 } else {
6642 TLBRefType *ref_type;
6643 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6645 if(ref_type->reference == hRefType)
6646 break;
6648 if(&ref_type->entry == &This->pTypeLib->ref_list)
6650 FIXME("Can't find pRefType for ref %x\n", hRefType);
6651 goto end;
6653 if(hRefType != -1) {
6654 ITypeLib *pTLib = NULL;
6656 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6657 UINT Index;
6658 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6659 } else {
6660 if(ref_type->pImpTLInfo->pImpTypeLib) {
6661 TRACE("typeinfo in imported typelib that is already loaded\n");
6662 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6663 ITypeLib2_AddRef(pTLib);
6664 result = S_OK;
6665 } else {
6666 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6667 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6668 ref_type->pImpTLInfo->wVersionMajor,
6669 ref_type->pImpTLInfo->wVersionMinor,
6670 ref_type->pImpTLInfo->lcid,
6671 &pTLib);
6673 if(FAILED(result)) {
6674 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6675 result=LoadTypeLib(libnam, &pTLib);
6676 SysFreeString(libnam);
6678 if(SUCCEEDED(result)) {
6679 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6680 ITypeLib2_AddRef(pTLib);
6684 if(SUCCEEDED(result)) {
6685 if(ref_type->index == TLB_REF_USE_GUID)
6686 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6687 &ref_type->guid,
6688 ppTInfo);
6689 else
6690 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6691 ppTInfo);
6693 if (pTLib != NULL)
6694 ITypeLib2_Release(pTLib);
6698 end:
6699 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6700 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6701 return result;
6704 /* ITypeInfo::AddressOfMember
6706 * Retrieves the addresses of static functions or variables, such as those
6707 * defined in a DLL.
6709 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6710 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6712 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6713 HRESULT hr;
6714 BSTR dll, entry;
6715 WORD ordinal;
6716 HMODULE module;
6718 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6720 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6721 if (FAILED(hr))
6722 return hr;
6724 module = LoadLibraryW(dll);
6725 if (!module)
6727 ERR("couldn't load %s\n", debugstr_w(dll));
6728 SysFreeString(dll);
6729 SysFreeString(entry);
6730 return STG_E_FILENOTFOUND;
6732 /* FIXME: store library somewhere where we can free it */
6734 if (entry)
6736 LPSTR entryA;
6737 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6738 entryA = HeapAlloc(GetProcessHeap(), 0, len);
6739 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6741 *ppv = GetProcAddress(module, entryA);
6742 if (!*ppv)
6743 ERR("function not found %s\n", debugstr_a(entryA));
6745 HeapFree(GetProcessHeap(), 0, entryA);
6747 else
6749 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6750 if (!*ppv)
6751 ERR("function not found %d\n", ordinal);
6754 SysFreeString(dll);
6755 SysFreeString(entry);
6757 if (!*ppv)
6758 return TYPE_E_DLLFUNCTIONNOTFOUND;
6760 return S_OK;
6763 /* ITypeInfo::CreateInstance
6765 * Creates a new instance of a type that describes a component object class
6766 * (coclass).
6768 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6769 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6771 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6772 HRESULT hr;
6773 TYPEATTR *pTA;
6775 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6777 *ppvObj = NULL;
6779 if(pOuterUnk)
6781 WARN("Not able to aggregate\n");
6782 return CLASS_E_NOAGGREGATION;
6785 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6786 if(FAILED(hr)) return hr;
6788 if(pTA->typekind != TKIND_COCLASS)
6790 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6791 hr = E_INVALIDARG;
6792 goto end;
6795 hr = S_FALSE;
6796 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6798 IUnknown *pUnk;
6799 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6800 TRACE("GetActiveObject rets %08x\n", hr);
6801 if(hr == S_OK)
6803 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6804 IUnknown_Release(pUnk);
6808 if(hr != S_OK)
6809 hr = CoCreateInstance(&pTA->guid, NULL,
6810 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6811 riid, ppvObj);
6813 end:
6814 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6815 return hr;
6818 /* ITypeInfo::GetMops
6820 * Retrieves marshalling information.
6822 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6823 BSTR *pBstrMops)
6825 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6826 FIXME("(%p) stub!\n", This);
6827 return S_OK;
6830 /* ITypeInfo::GetContainingTypeLib
6832 * Retrieves the containing type library and the index of the type description
6833 * within that type library.
6835 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6836 ITypeLib * *ppTLib, UINT *pIndex)
6838 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6840 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6841 if (pIndex) {
6842 *pIndex=This->index;
6843 TRACE("returning pIndex=%d\n", *pIndex);
6846 if (ppTLib) {
6847 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6848 ITypeLib2_AddRef(*ppTLib);
6849 TRACE("returning ppTLib=%p\n", *ppTLib);
6852 return S_OK;
6855 /* ITypeInfo::ReleaseTypeAttr
6857 * Releases a TYPEATTR previously returned by GetTypeAttr.
6860 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6861 TYPEATTR* pTypeAttr)
6863 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6864 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6865 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6868 /* ITypeInfo::ReleaseFuncDesc
6870 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6872 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6873 ITypeInfo2 *iface,
6874 FUNCDESC *pFuncDesc)
6876 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6877 SHORT i;
6879 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6881 for (i = 0; i < pFuncDesc->cParams; i++)
6882 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6883 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6885 SysFreeString((BSTR)pFuncDesc);
6888 /* ITypeInfo::ReleaseVarDesc
6890 * Releases a VARDESC previously returned by GetVarDesc.
6892 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6893 VARDESC *pVarDesc)
6895 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6896 TRACE("(%p)->(%p)\n", This, pVarDesc);
6898 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6899 if (pVarDesc->varkind == VAR_CONST)
6900 VariantClear(pVarDesc->u.lpvarValue);
6901 SysFreeString((BSTR)pVarDesc);
6904 /* ITypeInfo2::GetTypeKind
6906 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6909 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6910 TYPEKIND *pTypeKind)
6912 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6913 *pTypeKind=This->TypeAttr.typekind;
6914 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6915 return S_OK;
6918 /* ITypeInfo2::GetTypeFlags
6920 * Returns the type flags without any allocations. This returns a DWORD type
6921 * flag, which expands the type flags without growing the TYPEATTR (type
6922 * attribute).
6925 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6927 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6928 *pTypeFlags=This->TypeAttr.wTypeFlags;
6929 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6930 return S_OK;
6933 /* ITypeInfo2::GetFuncIndexOfMemId
6934 * Binds to a specific member based on a known DISPID, where the member name
6935 * is not known (for example, when binding to a default member).
6938 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
6939 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
6941 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6942 const TLBFuncDesc *pFuncInfo;
6943 int i;
6944 HRESULT result;
6946 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
6947 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
6948 break;
6949 if(pFuncInfo) {
6950 *pFuncIndex = i;
6951 result = S_OK;
6952 } else
6953 result = TYPE_E_ELEMENTNOTFOUND;
6955 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
6956 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6957 return result;
6960 /* TypeInfo2::GetVarIndexOfMemId
6962 * Binds to a specific member based on a known DISPID, where the member name
6963 * is not known (for example, when binding to a default member).
6966 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
6967 MEMBERID memid, UINT *pVarIndex)
6969 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6970 TLBVarDesc *pVarInfo;
6971 int i;
6972 HRESULT result;
6973 for(i=0, pVarInfo=This->varlist; pVarInfo &&
6974 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
6976 if(pVarInfo) {
6977 *pVarIndex = i;
6978 result = S_OK;
6979 } else
6980 result = TYPE_E_ELEMENTNOTFOUND;
6982 TRACE("(%p) memid 0x%08x -> %s\n", This,
6983 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6984 return result;
6987 /* ITypeInfo2::GetCustData
6989 * Gets the custom data
6991 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
6992 ITypeInfo2 * iface,
6993 REFGUID guid,
6994 VARIANT *pVarVal)
6996 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6997 TLBCustData *pCData;
6999 for(pCData=This->pCustData; pCData; pCData = pCData->next)
7000 if( IsEqualIID(guid, &pCData->guid)) break;
7002 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7004 if(pCData)
7006 VariantInit( pVarVal);
7007 VariantCopy( pVarVal, &pCData->data);
7008 return S_OK;
7010 return E_INVALIDARG; /* FIXME: correct? */
7013 /* ITypeInfo2::GetFuncCustData
7015 * Gets the custom data
7017 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7018 ITypeInfo2 * iface,
7019 UINT index,
7020 REFGUID guid,
7021 VARIANT *pVarVal)
7023 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7024 TLBCustData *pCData=NULL;
7025 TLBFuncDesc * pFDesc;
7026 UINT i;
7027 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7028 pFDesc=pFDesc->next);
7030 if(pFDesc)
7031 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
7032 if( IsEqualIID(guid, &pCData->guid)) break;
7034 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7036 if(pCData){
7037 VariantInit( pVarVal);
7038 VariantCopy( pVarVal, &pCData->data);
7039 return S_OK;
7041 return E_INVALIDARG; /* FIXME: correct? */
7044 /* ITypeInfo2::GetParamCustData
7046 * Gets the custom data
7048 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7049 ITypeInfo2 * iface,
7050 UINT indexFunc,
7051 UINT indexParam,
7052 REFGUID guid,
7053 VARIANT *pVarVal)
7055 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7056 TLBCustData *pCData=NULL;
7057 TLBFuncDesc * pFDesc;
7058 UINT i;
7060 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
7062 if(pFDesc && indexParam<pFDesc->funcdesc.cParams)
7063 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
7064 pCData = pCData->next)
7065 if( IsEqualIID(guid, &pCData->guid)) break;
7067 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7069 if(pCData)
7071 VariantInit( pVarVal);
7072 VariantCopy( pVarVal, &pCData->data);
7073 return S_OK;
7075 return E_INVALIDARG; /* FIXME: correct? */
7078 /* ITypeInfo2::GetVarCustData
7080 * Gets the custom data
7082 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7083 ITypeInfo2 * iface,
7084 UINT index,
7085 REFGUID guid,
7086 VARIANT *pVarVal)
7088 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7089 TLBCustData *pCData=NULL;
7090 TLBVarDesc * pVDesc;
7091 UINT i;
7093 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
7095 if(pVDesc)
7097 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
7099 if( IsEqualIID(guid, &pCData->guid)) break;
7103 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7105 if(pCData)
7107 VariantInit( pVarVal);
7108 VariantCopy( pVarVal, &pCData->data);
7109 return S_OK;
7111 return E_INVALIDARG; /* FIXME: correct? */
7114 /* ITypeInfo2::GetImplCustData
7116 * Gets the custom data
7118 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7119 ITypeInfo2 * iface,
7120 UINT index,
7121 REFGUID guid,
7122 VARIANT *pVarVal)
7124 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7125 TLBCustData *pCData=NULL;
7126 TLBImplType * pRDesc;
7127 UINT i;
7129 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
7131 if(pRDesc)
7133 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
7135 if( IsEqualIID(guid, &pCData->guid)) break;
7139 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7141 if(pCData)
7143 VariantInit( pVarVal);
7144 VariantCopy( pVarVal, &pCData->data);
7145 return S_OK;
7147 return E_INVALIDARG; /* FIXME: correct? */
7150 /* ITypeInfo2::GetDocumentation2
7152 * Retrieves the documentation string, the complete Help file name and path,
7153 * the localization context to use, and the context ID for the library Help
7154 * topic in the Help file.
7157 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7158 ITypeInfo2 * iface,
7159 MEMBERID memid,
7160 LCID lcid,
7161 BSTR *pbstrHelpString,
7162 DWORD *pdwHelpStringContext,
7163 BSTR *pbstrHelpStringDll)
7165 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7166 const TLBFuncDesc *pFDesc;
7167 const TLBVarDesc *pVDesc;
7168 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7169 "HelpStringContext(%p) HelpStringDll(%p)\n",
7170 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7171 pbstrHelpStringDll );
7172 /* the help string should be obtained from the helpstringdll,
7173 * using the _DLLGetDocumentation function, based on the supplied
7174 * lcid. Nice to do sometime...
7176 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7177 if(pbstrHelpString)
7178 *pbstrHelpString=SysAllocString(This->Name);
7179 if(pdwHelpStringContext)
7180 *pdwHelpStringContext=This->dwHelpStringContext;
7181 if(pbstrHelpStringDll)
7182 *pbstrHelpStringDll=
7183 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7184 return S_OK;
7185 }else {/* for a member */
7186 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
7187 if(pFDesc->funcdesc.memid==memid){
7188 if(pbstrHelpString)
7189 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
7190 if(pdwHelpStringContext)
7191 *pdwHelpStringContext=pFDesc->HelpStringContext;
7192 if(pbstrHelpStringDll)
7193 *pbstrHelpStringDll=
7194 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7195 return S_OK;
7197 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
7198 if(pVDesc->vardesc.memid==memid){
7199 if(pbstrHelpString)
7200 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
7201 if(pdwHelpStringContext)
7202 *pdwHelpStringContext=pVDesc->HelpStringContext;
7203 if(pbstrHelpStringDll)
7204 *pbstrHelpStringDll=
7205 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7206 return S_OK;
7209 return TYPE_E_ELEMENTNOTFOUND;
7212 /* ITypeInfo2::GetAllCustData
7214 * Gets all custom data items for the Type info.
7217 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7218 ITypeInfo2 * iface,
7219 CUSTDATA *pCustData)
7221 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7222 TLBCustData *pCData;
7223 int i;
7225 TRACE("(%p) returning %d items\n", This, This->ctCustData);
7227 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
7228 if(pCustData->prgCustData ){
7229 pCustData->cCustData=This->ctCustData;
7230 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
7231 pCustData->prgCustData[i].guid=pCData->guid;
7232 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
7234 }else{
7235 ERR(" OUT OF MEMORY!\n");
7236 return E_OUTOFMEMORY;
7238 return S_OK;
7241 /* ITypeInfo2::GetAllFuncCustData
7243 * Gets all custom data items for the specified Function
7246 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7247 ITypeInfo2 * iface,
7248 UINT index,
7249 CUSTDATA *pCustData)
7251 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7252 TLBCustData *pCData;
7253 TLBFuncDesc * pFDesc;
7254 UINT i;
7255 TRACE("(%p) index %d\n", This, index);
7256 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7257 pFDesc=pFDesc->next)
7259 if(pFDesc){
7260 pCustData->prgCustData =
7261 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
7262 if(pCustData->prgCustData ){
7263 pCustData->cCustData=pFDesc->ctCustData;
7264 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
7265 pCData = pCData->next){
7266 pCustData->prgCustData[i].guid=pCData->guid;
7267 VariantCopy(& pCustData->prgCustData[i].varValue,
7268 & pCData->data);
7270 }else{
7271 ERR(" OUT OF MEMORY!\n");
7272 return E_OUTOFMEMORY;
7274 return S_OK;
7276 return TYPE_E_ELEMENTNOTFOUND;
7279 /* ITypeInfo2::GetAllParamCustData
7281 * Gets all custom data items for the Functions
7284 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7285 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7287 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7288 TLBCustData *pCData=NULL;
7289 TLBFuncDesc * pFDesc;
7290 UINT i;
7291 TRACE("(%p) index %d\n", This, indexFunc);
7292 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
7293 pFDesc=pFDesc->next)
7295 if(pFDesc && indexParam<pFDesc->funcdesc.cParams){
7296 pCustData->prgCustData =
7297 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
7298 sizeof(CUSTDATAITEM));
7299 if(pCustData->prgCustData ){
7300 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
7301 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
7302 pCData; i++, pCData = pCData->next){
7303 pCustData->prgCustData[i].guid=pCData->guid;
7304 VariantCopy(& pCustData->prgCustData[i].varValue,
7305 & pCData->data);
7307 }else{
7308 ERR(" OUT OF MEMORY!\n");
7309 return E_OUTOFMEMORY;
7311 return S_OK;
7313 return TYPE_E_ELEMENTNOTFOUND;
7316 /* ITypeInfo2::GetAllVarCustData
7318 * Gets all custom data items for the specified Variable
7321 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7322 UINT index, CUSTDATA *pCustData)
7324 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7325 TLBCustData *pCData;
7326 TLBVarDesc * pVDesc;
7327 UINT i;
7328 TRACE("(%p) index %d\n", This, index);
7329 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
7330 pVDesc=pVDesc->next)
7332 if(pVDesc){
7333 pCustData->prgCustData =
7334 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
7335 if(pCustData->prgCustData ){
7336 pCustData->cCustData=pVDesc->ctCustData;
7337 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
7338 pCData = pCData->next){
7339 pCustData->prgCustData[i].guid=pCData->guid;
7340 VariantCopy(& pCustData->prgCustData[i].varValue,
7341 & pCData->data);
7343 }else{
7344 ERR(" OUT OF MEMORY!\n");
7345 return E_OUTOFMEMORY;
7347 return S_OK;
7349 return TYPE_E_ELEMENTNOTFOUND;
7352 /* ITypeInfo2::GetAllImplCustData
7354 * Gets all custom data items for the specified implementation type
7357 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7358 ITypeInfo2 * iface,
7359 UINT index,
7360 CUSTDATA *pCustData)
7362 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7363 TLBCustData *pCData;
7364 TLBImplType * pRDesc;
7365 UINT i;
7366 TRACE("(%p) index %d\n", This, index);
7367 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
7368 pRDesc=pRDesc->next)
7370 if(pRDesc){
7371 pCustData->prgCustData =
7372 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
7373 if(pCustData->prgCustData ){
7374 pCustData->cCustData=pRDesc->ctCustData;
7375 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
7376 pCData = pCData->next){
7377 pCustData->prgCustData[i].guid=pCData->guid;
7378 VariantCopy(& pCustData->prgCustData[i].varValue,
7379 & pCData->data);
7381 }else{
7382 ERR(" OUT OF MEMORY!\n");
7383 return E_OUTOFMEMORY;
7385 return S_OK;
7387 return TYPE_E_ELEMENTNOTFOUND;
7390 static const ITypeInfo2Vtbl tinfvt =
7393 ITypeInfo_fnQueryInterface,
7394 ITypeInfo_fnAddRef,
7395 ITypeInfo_fnRelease,
7397 ITypeInfo_fnGetTypeAttr,
7398 ITypeInfo_fnGetTypeComp,
7399 ITypeInfo_fnGetFuncDesc,
7400 ITypeInfo_fnGetVarDesc,
7401 ITypeInfo_fnGetNames,
7402 ITypeInfo_fnGetRefTypeOfImplType,
7403 ITypeInfo_fnGetImplTypeFlags,
7404 ITypeInfo_fnGetIDsOfNames,
7405 ITypeInfo_fnInvoke,
7406 ITypeInfo_fnGetDocumentation,
7407 ITypeInfo_fnGetDllEntry,
7408 ITypeInfo_fnGetRefTypeInfo,
7409 ITypeInfo_fnAddressOfMember,
7410 ITypeInfo_fnCreateInstance,
7411 ITypeInfo_fnGetMops,
7412 ITypeInfo_fnGetContainingTypeLib,
7413 ITypeInfo_fnReleaseTypeAttr,
7414 ITypeInfo_fnReleaseFuncDesc,
7415 ITypeInfo_fnReleaseVarDesc,
7417 ITypeInfo2_fnGetTypeKind,
7418 ITypeInfo2_fnGetTypeFlags,
7419 ITypeInfo2_fnGetFuncIndexOfMemId,
7420 ITypeInfo2_fnGetVarIndexOfMemId,
7421 ITypeInfo2_fnGetCustData,
7422 ITypeInfo2_fnGetFuncCustData,
7423 ITypeInfo2_fnGetParamCustData,
7424 ITypeInfo2_fnGetVarCustData,
7425 ITypeInfo2_fnGetImplTypeCustData,
7426 ITypeInfo2_fnGetDocumentation2,
7427 ITypeInfo2_fnGetAllCustData,
7428 ITypeInfo2_fnGetAllFuncCustData,
7429 ITypeInfo2_fnGetAllParamCustData,
7430 ITypeInfo2_fnGetAllVarCustData,
7431 ITypeInfo2_fnGetAllImplTypeCustData,
7434 /******************************************************************************
7435 * CreateDispTypeInfo [OLEAUT32.31]
7437 * Build type information for an object so it can be called through an
7438 * IDispatch interface.
7440 * RETURNS
7441 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7442 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7444 * NOTES
7445 * This call allows an objects methods to be accessed through IDispatch, by
7446 * building an ITypeInfo object that IDispatch can use to call through.
7448 HRESULT WINAPI CreateDispTypeInfo(
7449 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7450 LCID lcid, /* [I] Locale Id */
7451 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7453 ITypeInfoImpl *pTIClass, *pTIIface;
7454 ITypeLibImpl *pTypeLibImpl;
7455 unsigned int param, func;
7456 TLBFuncDesc **ppFuncDesc;
7457 TLBRefType *ref;
7459 TRACE("\n");
7460 pTypeLibImpl = TypeLibImpl_Constructor();
7461 if (!pTypeLibImpl) return E_FAIL;
7463 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
7464 pTIIface->pTypeLib = pTypeLibImpl;
7465 pTIIface->index = 0;
7466 pTIIface->Name = NULL;
7467 pTIIface->dwHelpContext = -1;
7468 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7469 pTIIface->TypeAttr.lcid = lcid;
7470 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7471 pTIIface->TypeAttr.wMajorVerNum = 0;
7472 pTIIface->TypeAttr.wMinorVerNum = 0;
7473 pTIIface->TypeAttr.cbAlignment = 2;
7474 pTIIface->TypeAttr.cbSizeInstance = -1;
7475 pTIIface->TypeAttr.cbSizeVft = -1;
7476 pTIIface->TypeAttr.cFuncs = 0;
7477 pTIIface->TypeAttr.cImplTypes = 0;
7478 pTIIface->TypeAttr.cVars = 0;
7479 pTIIface->TypeAttr.wTypeFlags = 0;
7481 ppFuncDesc = &pTIIface->funclist;
7482 for(func = 0; func < pidata->cMembers; func++) {
7483 METHODDATA *md = pidata->pmethdata + func;
7484 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
7485 (*ppFuncDesc)->Name = SysAllocString(md->szName);
7486 (*ppFuncDesc)->funcdesc.memid = md->dispid;
7487 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
7488 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
7489 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
7490 (*ppFuncDesc)->funcdesc.callconv = md->cc;
7491 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
7492 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
7493 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
7494 (*ppFuncDesc)->funcdesc.cScodes = 0;
7495 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
7496 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7497 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7498 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7499 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7500 md->cArgs * sizeof(ELEMDESC));
7501 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7502 md->cArgs * sizeof(TLBParDesc));
7503 for(param = 0; param < md->cArgs; param++) {
7504 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7505 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7507 (*ppFuncDesc)->helpcontext = 0;
7508 (*ppFuncDesc)->HelpStringContext = 0;
7509 (*ppFuncDesc)->HelpString = NULL;
7510 (*ppFuncDesc)->Entry = NULL;
7511 (*ppFuncDesc)->ctCustData = 0;
7512 (*ppFuncDesc)->pCustData = NULL;
7513 (*ppFuncDesc)->next = NULL;
7514 pTIIface->TypeAttr.cFuncs++;
7515 ppFuncDesc = &(*ppFuncDesc)->next;
7518 dump_TypeInfo(pTIIface);
7520 pTypeLibImpl->pTypeInfo = pTIIface;
7521 pTypeLibImpl->TypeInfoCount++;
7523 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
7524 pTIClass->pTypeLib = pTypeLibImpl;
7525 pTIClass->index = 1;
7526 pTIClass->Name = NULL;
7527 pTIClass->dwHelpContext = -1;
7528 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7529 pTIClass->TypeAttr.lcid = lcid;
7530 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7531 pTIClass->TypeAttr.wMajorVerNum = 0;
7532 pTIClass->TypeAttr.wMinorVerNum = 0;
7533 pTIClass->TypeAttr.cbAlignment = 2;
7534 pTIClass->TypeAttr.cbSizeInstance = -1;
7535 pTIClass->TypeAttr.cbSizeVft = -1;
7536 pTIClass->TypeAttr.cFuncs = 0;
7537 pTIClass->TypeAttr.cImplTypes = 1;
7538 pTIClass->TypeAttr.cVars = 0;
7539 pTIClass->TypeAttr.wTypeFlags = 0;
7541 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
7542 pTIClass->impltypelist->hRef = 0;
7544 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
7545 ref->index = 0;
7546 ref->reference = 0;
7547 ref->pImpTLInfo = TLB_REF_INTERNAL;
7548 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7550 dump_TypeInfo(pTIClass);
7552 pTIIface->next = pTIClass;
7553 pTypeLibImpl->TypeInfoCount++;
7555 *pptinfo = (ITypeInfo*)pTIClass;
7557 ITypeInfo_AddRef(*pptinfo);
7558 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7560 return S_OK;
7564 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7566 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7568 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7571 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7573 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7575 return ITypeInfo_AddRef((ITypeInfo *)This);
7578 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7580 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7582 return ITypeInfo_Release((ITypeInfo *)This);
7585 static HRESULT WINAPI ITypeComp_fnBind(
7586 ITypeComp * iface,
7587 OLECHAR * szName,
7588 ULONG lHash,
7589 WORD wFlags,
7590 ITypeInfo ** ppTInfo,
7591 DESCKIND * pDescKind,
7592 BINDPTR * pBindPtr)
7594 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7595 const TLBFuncDesc *pFDesc;
7596 const TLBVarDesc *pVDesc;
7597 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7599 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7601 *pDescKind = DESCKIND_NONE;
7602 pBindPtr->lpfuncdesc = NULL;
7603 *ppTInfo = NULL;
7605 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
7606 if (!strcmpiW(pFDesc->Name, szName)) {
7607 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7608 break;
7609 else
7610 /* name found, but wrong flags */
7611 hr = TYPE_E_TYPEMISMATCH;
7614 if (pFDesc)
7616 HRESULT hr = TLB_AllocAndInitFuncDesc(
7617 &pFDesc->funcdesc,
7618 &pBindPtr->lpfuncdesc,
7619 This->TypeAttr.typekind == TKIND_DISPATCH);
7620 if (FAILED(hr))
7621 return hr;
7622 *pDescKind = DESCKIND_FUNCDESC;
7623 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7624 ITypeInfo_AddRef(*ppTInfo);
7625 return S_OK;
7626 } else {
7627 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7628 if (!strcmpiW(pVDesc->Name, szName)) {
7629 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7630 if (FAILED(hr))
7631 return hr;
7632 *pDescKind = DESCKIND_VARDESC;
7633 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7634 ITypeInfo_AddRef(*ppTInfo);
7635 return S_OK;
7639 /* FIXME: search each inherited interface, not just the first */
7640 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7641 /* recursive search */
7642 ITypeInfo *pTInfo;
7643 ITypeComp *pTComp;
7644 HRESULT hr;
7645 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7646 if (SUCCEEDED(hr))
7648 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7649 ITypeInfo_Release(pTInfo);
7651 if (SUCCEEDED(hr))
7653 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7654 ITypeComp_Release(pTComp);
7655 return hr;
7657 WARN("Could not search inherited interface!\n");
7659 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
7660 return hr;
7663 static HRESULT WINAPI ITypeComp_fnBindType(
7664 ITypeComp * iface,
7665 OLECHAR * szName,
7666 ULONG lHash,
7667 ITypeInfo ** ppTInfo,
7668 ITypeComp ** ppTComp)
7670 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7672 /* strange behaviour (does nothing) but like the
7673 * original */
7675 if (!ppTInfo || !ppTComp)
7676 return E_POINTER;
7678 *ppTInfo = NULL;
7679 *ppTComp = NULL;
7681 return S_OK;
7684 static const ITypeCompVtbl tcompvt =
7687 ITypeComp_fnQueryInterface,
7688 ITypeComp_fnAddRef,
7689 ITypeComp_fnRelease,
7691 ITypeComp_fnBind,
7692 ITypeComp_fnBindType