oleaut32: typelib - fix regression in MSFT typelib parsing.
[wine/wine-kai.git] / dlls / oleaut32 / typelib.c
bloba12deb13a8bda6799bab10e9690ed00849992f41
1 /*
2 * TYPELIB
4 * Copyright 1997 Marcus Meissner
5 * 1999 Rein Klazes
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 2005 Robert Shearman, for CodeWeavers
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 * --------------------------------------------------------------------------------------
25 * Known problems (2000, Francois Jacques)
27 * - Tested using OLEVIEW (Platform SDK tool) only.
29 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
30 * creating by doing a straight copy of the dispinterface instance and just changing
31 * its typekind. Pointed structures aren't copied - only the address of the pointers.
33 * - locale stuff is partially implemented but hasn't been tested.
35 * - typelib file is still read in its entirety, but it is released now.
37 * --------------------------------------------------------------------------------------
38 * Known problems left from previous implementation (1999, Rein Klazes) :
40 * -. Data structures are straightforward, but slow for look-ups.
41 * -. (related) nothing is hashed
42 * -. Most error return values are just guessed not checked with windows
43 * behaviour.
44 * -. lousy fatal error handling
48 #include "config.h"
49 #include "wine/port.h"
51 #include <stdlib.h>
52 #include <string.h>
53 #include <stdarg.h>
54 #include <stdio.h>
55 #include <ctype.h>
57 #define COBJMACROS
58 #define NONAMELESSUNION
59 #define NONAMELESSSTRUCT
61 #include "winerror.h"
62 #include "windef.h"
63 #include "winbase.h"
64 #include "winnls.h"
65 #include "winreg.h"
66 #include "winuser.h"
68 #include "wine/unicode.h"
69 #include "objbase.h"
70 #include "typelib.h"
71 #include "wine/debug.h"
72 #include "variant.h"
74 WINE_DEFAULT_DEBUG_CHANNEL(ole);
75 WINE_DECLARE_DEBUG_CHANNEL(typelib);
77 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
78 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
80 /****************************************************************************
81 * FromLExxx
83 * Takes p_iVal (which is in little endian) and returns it
84 * in the host machine's byte order.
86 #ifdef WORDS_BIGENDIAN
87 static WORD FromLEWord(WORD p_iVal)
89 return (((p_iVal & 0x00FF) << 8) |
90 ((p_iVal & 0xFF00) >> 8));
94 static DWORD FromLEDWord(DWORD p_iVal)
96 return (((p_iVal & 0x000000FF) << 24) |
97 ((p_iVal & 0x0000FF00) << 8) |
98 ((p_iVal & 0x00FF0000) >> 8) |
99 ((p_iVal & 0xFF000000) >> 24));
101 #else
102 #define FromLEWord(X) (X)
103 #define FromLEDWord(X) (X)
104 #endif
107 /****************************************************************************
108 * FromLExxx
110 * Fix byte order in any structure if necessary
112 #ifdef WORDS_BIGENDIAN
113 static void FromLEWords(void *p_Val, int p_iSize)
115 WORD *Val = p_Val;
117 p_iSize /= sizeof(WORD);
119 while (p_iSize) {
120 *Val = FromLEWord(*Val);
121 Val++;
122 p_iSize--;
127 static void FromLEDWords(void *p_Val, int p_iSize)
129 DWORD *Val = p_Val;
131 p_iSize /= sizeof(DWORD);
133 while (p_iSize) {
134 *Val = FromLEDWord(*Val);
135 Val++;
136 p_iSize--;
139 #else
140 #define FromLEWords(X,Y) /*nothing*/
141 #define FromLEDWords(X,Y) /*nothing*/
142 #endif
145 * Find a typelib key which matches a requested maj.min version.
147 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
149 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
150 WCHAR buffer[60];
151 char key_name[16];
152 DWORD len, i;
153 INT best_min = -1;
154 HKEY hkey;
156 memcpy( buffer, typelibW, sizeof(typelibW) );
157 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
159 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
160 return FALSE;
162 len = sizeof(key_name);
163 i = 0;
164 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
166 INT v_maj, v_min;
168 if (sscanf(key_name, "%u.%u", &v_maj, &v_min) == 2)
170 TRACE("found %s: %u.%u\n", debugstr_w(buffer), v_maj, v_min);
172 if (*wMaj == v_maj)
174 if (*wMin == v_min)
176 best_min = v_min;
177 break; /* exact match */
179 if (v_min > best_min) best_min = v_min;
182 len = sizeof(key_name);
184 RegCloseKey( hkey );
185 if (best_min >= 0)
187 *wMin = best_min;
188 return TRUE;
190 return FALSE;
193 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
194 /* buffer must be at least 60 characters long */
195 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
197 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
198 static const WCHAR VersionFormatW[] = {'\\','%','u','.','%','u',0};
200 memcpy( buffer, TypelibW, sizeof(TypelibW) );
201 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
202 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
203 return buffer;
206 /* get the path of an interface key, in the form "Interface\\<guid>" */
207 /* buffer must be at least 50 characters long */
208 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
210 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
212 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
213 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
214 return buffer;
217 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
218 /* buffer must be at least 16 characters long */
219 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
221 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
222 static const WCHAR win16W[] = {'w','i','n','1','6',0};
223 static const WCHAR win32W[] = {'w','i','n','3','2',0};
225 sprintfW( buffer, LcidFormatW, lcid );
226 switch(syskind)
228 case SYS_WIN16: strcatW( buffer, win16W ); break;
229 case SYS_WIN32: strcatW( buffer, win32W ); break;
230 default:
231 TRACE("Typelib is for unsupported syskind %i\n", syskind);
232 return NULL;
234 return buffer;
237 static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
240 /****************************************************************************
241 * QueryPathOfRegTypeLib [OLEAUT32.164]
243 * Gets the path to a registered type library.
245 * PARAMS
246 * guid [I] referenced guid
247 * wMaj [I] major version
248 * wMin [I] minor version
249 * lcid [I] locale id
250 * path [O] path of typelib
252 * RETURNS
253 * Success: S_OK.
254 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
255 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
256 * opened.
258 HRESULT WINAPI QueryPathOfRegTypeLib(
259 REFGUID guid,
260 WORD wMaj,
261 WORD wMin,
262 LCID lcid,
263 LPBSTR path )
265 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
266 LCID myLCID = lcid;
267 HKEY hkey;
268 WCHAR buffer[60];
269 WCHAR Path[MAX_PATH];
270 LONG res;
272 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
274 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
275 get_typelib_key( guid, wMaj, wMin, buffer );
277 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
278 if (res == ERROR_FILE_NOT_FOUND)
280 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
281 return TYPE_E_LIBNOTREGISTERED;
283 else if (res != ERROR_SUCCESS)
285 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
286 return TYPE_E_REGISTRYACCESS;
289 while (hr != S_OK)
291 LONG dwPathLen = sizeof(Path);
293 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
295 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
297 if (!lcid)
298 break;
299 else if (myLCID == lcid)
301 /* try with sub-langid */
302 myLCID = SUBLANGID(lcid);
304 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
306 /* try with system langid */
307 myLCID = 0;
309 else
311 break;
314 else
316 *path = SysAllocString( Path );
317 hr = S_OK;
320 RegCloseKey( hkey );
321 TRACE_(typelib)("-- 0x%08x\n", hr);
322 return hr;
325 /******************************************************************************
326 * CreateTypeLib [OLEAUT32.160] creates a typelib
328 * RETURNS
329 * Success: S_OK
330 * Failure: Status
332 HRESULT WINAPI CreateTypeLib(
333 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
335 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
336 return E_FAIL;
339 /******************************************************************************
340 * LoadTypeLib [OLEAUT32.161]
342 * Loads a type library
344 * PARAMS
345 * szFile [I] Name of file to load from.
346 * pptLib [O] Pointer that receives ITypeLib object on success.
348 * RETURNS
349 * Success: S_OK
350 * Failure: Status
352 * SEE
353 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
355 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
357 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
358 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
361 /******************************************************************************
362 * LoadTypeLibEx [OLEAUT32.183]
364 * Loads and optionally registers a type library
366 * RETURNS
367 * Success: S_OK
368 * Failure: Status
370 HRESULT WINAPI LoadTypeLibEx(
371 LPCOLESTR szFile, /* [in] Name of file to load from */
372 REGKIND regkind, /* [in] Specify kind of registration */
373 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
375 WCHAR szPath[MAX_PATH+1];
376 HRESULT res;
378 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
380 *pptLib = NULL;
382 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
384 if (SUCCEEDED(res))
385 switch(regkind)
387 case REGKIND_DEFAULT:
388 /* don't register typelibs supplied with full path. Experimentation confirms the following */
389 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
390 (szFile[0] && (szFile[1] == ':'))) break;
391 /* else fall-through */
393 case REGKIND_REGISTER:
394 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
396 IUnknown_Release(*pptLib);
397 *pptLib = 0;
399 break;
400 case REGKIND_NONE:
401 break;
404 TRACE(" returns %08x\n",res);
405 return res;
408 /******************************************************************************
409 * LoadRegTypeLib [OLEAUT32.162]
411 * Loads a registered type library.
413 * PARAMS
414 * rguid [I] GUID of the registered type library.
415 * wVerMajor [I] major version.
416 * wVerMinor [I] minor version.
417 * lcid [I] locale ID.
418 * ppTLib [O] pointer that receives an ITypeLib object on success.
420 * RETURNS
421 * Success: S_OK.
422 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
423 * LoadTypeLib.
425 HRESULT WINAPI LoadRegTypeLib(
426 REFGUID rguid,
427 WORD wVerMajor,
428 WORD wVerMinor,
429 LCID lcid,
430 ITypeLib **ppTLib)
432 BSTR bstr=NULL;
433 HRESULT res;
435 *ppTLib = NULL;
437 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
439 if(SUCCEEDED(res))
441 res= LoadTypeLib(bstr, ppTLib);
442 SysFreeString(bstr);
445 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
447 return res;
451 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
452 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
453 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
454 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
455 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
456 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
458 /******************************************************************************
459 * RegisterTypeLib [OLEAUT32.163]
460 * Adds information about a type library to the System Registry
461 * NOTES
462 * Docs: ITypeLib FAR * ptlib
463 * Docs: OLECHAR FAR* szFullPath
464 * Docs: OLECHAR FAR* szHelpDir
466 * RETURNS
467 * Success: S_OK
468 * Failure: Status
470 HRESULT WINAPI RegisterTypeLib(
471 ITypeLib * ptlib, /* [in] Pointer to the library*/
472 OLECHAR * szFullPath, /* [in] full Path of the library*/
473 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
474 may be NULL*/
476 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
477 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
478 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
479 HRESULT res;
480 TLIBATTR *attr;
481 WCHAR keyName[60];
482 WCHAR tmp[16];
483 HKEY key, subKey;
484 UINT types, tidx;
485 TYPEKIND kind;
486 DWORD disposition;
488 if (ptlib == NULL || szFullPath == NULL)
489 return E_INVALIDARG;
491 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
492 return E_FAIL;
494 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
496 res = S_OK;
497 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
498 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
500 LPOLESTR doc;
502 /* Set the human-readable name of the typelib */
503 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
505 if (RegSetValueExW(key, NULL, 0, REG_SZ,
506 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
507 res = E_FAIL;
509 SysFreeString(doc);
511 else
512 res = E_FAIL;
514 /* Make up the name of the typelib path subkey */
515 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
517 /* Create the typelib path subkey */
518 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
519 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
521 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
522 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
523 res = E_FAIL;
525 RegCloseKey(subKey);
527 else
528 res = E_FAIL;
530 /* Create the flags subkey */
531 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
532 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
534 /* FIXME: is %u correct? */
535 static const WCHAR formatW[] = {'%','u',0};
536 WCHAR buf[20];
537 sprintfW(buf, formatW, attr->wLibFlags);
538 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
539 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
540 res = E_FAIL;
542 RegCloseKey(subKey);
544 else
545 res = E_FAIL;
547 /* create the helpdir subkey */
548 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
549 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
551 BOOL freeHelpDir = FALSE;
552 OLECHAR* pIndexStr;
554 /* if we created a new key, and helpDir was null, set the helpdir
555 to the directory which contains the typelib. However,
556 if we just opened an existing key, we leave the helpdir alone */
557 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
558 szHelpDir = SysAllocString(szFullPath);
559 pIndexStr = strrchrW(szHelpDir, '\\');
560 if (pIndexStr) {
561 *pIndexStr = 0;
563 freeHelpDir = TRUE;
566 /* if we have an szHelpDir, set it! */
567 if (szHelpDir != NULL) {
568 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
569 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
570 res = E_FAIL;
574 /* tidy up */
575 if (freeHelpDir) SysFreeString(szHelpDir);
576 RegCloseKey(subKey);
578 } else {
579 res = E_FAIL;
582 RegCloseKey(key);
584 else
585 res = E_FAIL;
587 /* register OLE Automation-compatible interfaces for this typelib */
588 types = ITypeLib_GetTypeInfoCount(ptlib);
589 for (tidx=0; tidx<types; tidx++) {
590 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
591 LPOLESTR name = NULL;
592 ITypeInfo *tinfo = NULL;
594 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
596 switch (kind) {
597 case TKIND_INTERFACE:
598 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
599 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
600 break;
602 case TKIND_DISPATCH:
603 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
604 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
605 break;
607 default:
608 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
609 break;
612 if (tinfo) {
613 TYPEATTR *tattr = NULL;
614 ITypeInfo_GetTypeAttr(tinfo, &tattr);
616 if (tattr) {
617 TRACE_(typelib)("guid=%s, flags=%04x (",
618 debugstr_guid(&tattr->guid),
619 tattr->wTypeFlags);
621 if (TRACE_ON(typelib)) {
622 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
623 XX(FAPPOBJECT);
624 XX(FCANCREATE);
625 XX(FLICENSED);
626 XX(FPREDECLID);
627 XX(FHIDDEN);
628 XX(FCONTROL);
629 XX(FDUAL);
630 XX(FNONEXTENSIBLE);
631 XX(FOLEAUTOMATION);
632 XX(FRESTRICTED);
633 XX(FAGGREGATABLE);
634 XX(FREPLACEABLE);
635 XX(FDISPATCHABLE);
636 XX(FREVERSEBIND);
637 XX(FPROXY);
638 #undef XX
639 MESSAGE("\n");
642 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL|TYPEFLAG_FDISPATCHABLE))
644 /* register interface<->typelib coupling */
645 get_interface_key( &tattr->guid, keyName );
646 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
647 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
649 if (name)
650 RegSetValueExW(key, NULL, 0, REG_SZ,
651 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
653 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
654 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
655 RegSetValueExW(subKey, NULL, 0, REG_SZ,
656 (const BYTE *)PSOA, sizeof PSOA);
657 RegCloseKey(subKey);
660 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
661 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
662 RegSetValueExW(subKey, NULL, 0, REG_SZ,
663 (const BYTE *)PSOA, sizeof PSOA);
664 RegCloseKey(subKey);
667 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
668 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
670 WCHAR buffer[40];
671 static const WCHAR fmtver[] = {'%','u','.','%','u',0 };
672 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
674 StringFromGUID2(&attr->guid, buffer, 40);
675 RegSetValueExW(subKey, NULL, 0, REG_SZ,
676 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
677 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
678 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
679 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
680 RegCloseKey(subKey);
683 RegCloseKey(key);
687 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
690 ITypeInfo_Release(tinfo);
693 SysFreeString(name);
697 ITypeLib_ReleaseTLibAttr(ptlib, attr);
699 return res;
703 /******************************************************************************
704 * UnRegisterTypeLib [OLEAUT32.186]
705 * Removes information about a type library from the System Registry
706 * NOTES
708 * RETURNS
709 * Success: S_OK
710 * Failure: Status
712 HRESULT WINAPI UnRegisterTypeLib(
713 REFGUID libid, /* [in] Guid of the library */
714 WORD wVerMajor, /* [in] major version */
715 WORD wVerMinor, /* [in] minor version */
716 LCID lcid, /* [in] locale id */
717 SYSKIND syskind)
719 BSTR tlibPath = NULL;
720 DWORD tmpLength;
721 WCHAR keyName[60];
722 WCHAR subKeyName[50];
723 int result = S_OK;
724 DWORD i = 0;
725 BOOL deleteOtherStuff;
726 HKEY key = NULL;
727 HKEY subKey = NULL;
728 TYPEATTR* typeAttr = NULL;
729 TYPEKIND kind;
730 ITypeInfo* typeInfo = NULL;
731 ITypeLib* typeLib = NULL;
732 int numTypes;
734 TRACE("(IID: %s)\n",debugstr_guid(libid));
736 /* Create the path to the key */
737 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
739 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
741 TRACE("Unsupported syskind %i\n", syskind);
742 result = E_INVALIDARG;
743 goto end;
746 /* get the path to the typelib on disk */
747 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
748 result = E_INVALIDARG;
749 goto end;
752 /* Try and open the key to the type library. */
753 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
754 result = E_INVALIDARG;
755 goto end;
758 /* Try and load the type library */
759 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
760 result = TYPE_E_INVALIDSTATE;
761 goto end;
764 /* remove any types registered with this typelib */
765 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
766 for (i=0; i<numTypes; i++) {
767 /* get the kind of type */
768 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
769 goto enddeleteloop;
772 /* skip non-interfaces, and get type info for the type */
773 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
774 goto enddeleteloop;
776 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
777 goto enddeleteloop;
779 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
780 goto enddeleteloop;
783 /* the path to the type */
784 get_interface_key( &typeAttr->guid, subKeyName );
786 /* Delete its bits */
787 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS) {
788 goto enddeleteloop;
790 RegDeleteKeyW(subKey, ProxyStubClsidW);
791 RegDeleteKeyW(subKey, ProxyStubClsid32W);
792 RegDeleteKeyW(subKey, TypeLibW);
793 RegCloseKey(subKey);
794 subKey = NULL;
795 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
797 enddeleteloop:
798 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
799 typeAttr = NULL;
800 if (typeInfo) ITypeInfo_Release(typeInfo);
801 typeInfo = NULL;
804 /* Now, delete the type library path subkey */
805 get_lcid_subkey( lcid, syskind, subKeyName );
806 RegDeleteKeyW(key, subKeyName);
807 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
808 RegDeleteKeyW(key, subKeyName);
810 /* check if there is anything besides the FLAGS/HELPDIR keys.
811 If there is, we don't delete them */
812 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
813 deleteOtherStuff = TRUE;
814 i = 0;
815 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
816 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
818 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
819 if (!strcmpW(subKeyName, FLAGSW)) continue;
820 if (!strcmpW(subKeyName, HELPDIRW)) continue;
821 deleteOtherStuff = FALSE;
822 break;
825 /* only delete the other parts of the key if we're absolutely sure */
826 if (deleteOtherStuff) {
827 RegDeleteKeyW(key, FLAGSW);
828 RegDeleteKeyW(key, HELPDIRW);
829 RegCloseKey(key);
830 key = NULL;
832 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
833 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
834 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
837 end:
838 if (tlibPath) SysFreeString(tlibPath);
839 if (typeLib) ITypeLib_Release(typeLib);
840 if (subKey) RegCloseKey(subKey);
841 if (key) RegCloseKey(key);
842 return result;
845 /*======================= ITypeLib implementation =======================*/
847 typedef struct tagTLBCustData
849 GUID guid;
850 VARIANT data;
851 struct tagTLBCustData* next;
852 } TLBCustData;
854 /* data structure for import typelibs */
855 typedef struct tagTLBImpLib
857 int offset; /* offset in the file (MSFT)
858 offset in nametable (SLTG)
859 just used to identify library while reading
860 data from file */
861 GUID guid; /* libid */
862 BSTR name; /* name */
864 LCID lcid; /* lcid of imported typelib */
866 WORD wVersionMajor; /* major version number */
867 WORD wVersionMinor; /* minor version number */
869 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
870 NULL if not yet loaded */
871 struct tagTLBImpLib * next;
872 } TLBImpLib;
874 /* internal ITypeLib data */
875 typedef struct tagITypeLibImpl
877 const ITypeLib2Vtbl *lpVtbl;
878 const ITypeCompVtbl *lpVtblTypeComp;
879 LONG ref;
880 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
882 /* strings can be stored in tlb as multibyte strings BUT they are *always*
883 * exported to the application as a UNICODE string.
885 BSTR Name;
886 BSTR DocString;
887 BSTR HelpFile;
888 BSTR HelpStringDll;
889 unsigned long dwHelpContext;
890 int TypeInfoCount; /* nr of typeinfo's in librarry */
891 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
892 int ctCustData; /* number of items in cust data list */
893 TLBCustData * pCustData; /* linked list to cust data */
894 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
895 int ctTypeDesc; /* number of items in type desc array */
896 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
897 library. Only used while read MSFT
898 typelibs */
900 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
901 struct tagITypeLibImpl *next, *prev;
902 WCHAR *path;
903 INT index;
904 } ITypeLibImpl;
906 static const ITypeLib2Vtbl tlbvt;
907 static const ITypeCompVtbl tlbtcvt;
909 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
911 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
914 /* ITypeLib methods */
915 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
916 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
918 /*======================= ITypeInfo implementation =======================*/
920 /* data for referenced types */
921 typedef struct tagTLBRefType
923 INT index; /* Type index for internal ref or for external ref
924 it the format is SLTG. -2 indicates to
925 use guid */
927 GUID guid; /* guid of the referenced type */
928 /* if index == TLB_REF_USE_GUID */
930 HREFTYPE reference; /* The href of this ref */
931 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
932 TLB_REF_INTERNAL for internal refs
933 TLB_REF_NOT_FOUND for broken refs */
935 struct tagTLBRefType * next;
936 } TLBRefType;
938 #define TLB_REF_USE_GUID -2
940 #define TLB_REF_INTERNAL (void*)-2
941 #define TLB_REF_NOT_FOUND (void*)-1
943 /* internal Parameter data */
944 typedef struct tagTLBParDesc
946 BSTR Name;
947 int ctCustData;
948 TLBCustData * pCustData; /* linked list to cust data */
949 } TLBParDesc;
951 /* internal Function data */
952 typedef struct tagTLBFuncDesc
954 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
955 BSTR Name; /* the name of this function */
956 TLBParDesc *pParamDesc; /* array with param names and custom data */
957 int helpcontext;
958 int HelpStringContext;
959 BSTR HelpString;
960 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
961 int ctCustData;
962 TLBCustData * pCustData; /* linked list to cust data; */
963 struct tagTLBFuncDesc * next;
964 } TLBFuncDesc;
966 /* internal Variable data */
967 typedef struct tagTLBVarDesc
969 VARDESC vardesc; /* lots of info on the variable and its attributes. */
970 BSTR Name; /* the name of this variable */
971 int HelpContext;
972 int HelpStringContext; /* FIXME: where? */
973 BSTR HelpString;
974 int ctCustData;
975 TLBCustData * pCustData;/* linked list to cust data; */
976 struct tagTLBVarDesc * next;
977 } TLBVarDesc;
979 /* internal implemented interface data */
980 typedef struct tagTLBImplType
982 HREFTYPE hRef; /* hRef of interface */
983 int implflags; /* IMPLFLAG_*s */
984 int ctCustData;
985 TLBCustData * pCustData;/* linked list to custom data; */
986 struct tagTLBImplType *next;
987 } TLBImplType;
989 /* internal TypeInfo data */
990 typedef struct tagITypeInfoImpl
992 const ITypeInfo2Vtbl *lpVtbl;
993 const ITypeCompVtbl *lpVtblTypeComp;
994 LONG ref;
995 BOOL no_free_data; /* don't free data structurees */
996 TYPEATTR TypeAttr ; /* _lots_ of type information. */
997 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
998 int index; /* index in this typelib; */
999 HREFTYPE hreftype; /* hreftype for app object binding */
1000 /* type libs seem to store the doc strings in ascii
1001 * so why should we do it in unicode?
1003 BSTR Name;
1004 BSTR DocString;
1005 BSTR DllName;
1006 unsigned long dwHelpContext;
1007 unsigned long dwHelpStringContext;
1009 /* functions */
1010 TLBFuncDesc * funclist; /* linked list with function descriptions */
1012 /* variables */
1013 TLBVarDesc * varlist; /* linked list with variable descriptions */
1015 /* Implemented Interfaces */
1016 TLBImplType * impltypelist;
1018 TLBRefType * reflist;
1019 int ctCustData;
1020 TLBCustData * pCustData; /* linked list to cust data; */
1021 struct tagITypeInfoImpl * next;
1022 } ITypeInfoImpl;
1024 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1026 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1029 static const ITypeInfo2Vtbl tinfvt;
1030 static const ITypeCompVtbl tcompvt;
1032 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
1034 typedef struct tagTLBContext
1036 unsigned int oStart; /* start of TLB in file */
1037 unsigned int pos; /* current pos */
1038 unsigned int length; /* total length */
1039 void *mapping; /* memory mapping */
1040 MSFT_SegDir * pTblDir;
1041 ITypeLibImpl* pLibInfo;
1042 } TLBContext;
1045 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
1048 debug
1050 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1051 if (pTD->vt & VT_RESERVED)
1052 szVarType += strlen(strcpy(szVarType, "reserved | "));
1053 if (pTD->vt & VT_BYREF)
1054 szVarType += strlen(strcpy(szVarType, "ref to "));
1055 if (pTD->vt & VT_ARRAY)
1056 szVarType += strlen(strcpy(szVarType, "array of "));
1057 if (pTD->vt & VT_VECTOR)
1058 szVarType += strlen(strcpy(szVarType, "vector of "));
1059 switch(pTD->vt & VT_TYPEMASK) {
1060 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1061 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1062 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1063 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1064 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1065 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1066 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1067 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1068 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1069 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1070 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1071 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1072 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1073 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1074 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1075 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1076 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1077 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1078 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1079 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1080 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1081 pTD->u.hreftype); break;
1082 case VT_PTR: sprintf(szVarType, "ptr to ");
1083 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1084 break;
1085 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1086 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1087 break;
1088 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1089 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1090 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1091 break;
1093 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1097 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1098 char buf[200];
1099 USHORT flags = edesc->u.paramdesc.wParamFlags;
1100 dump_TypeDesc(&edesc->tdesc,buf);
1101 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1102 MESSAGE("\t\tu.paramdesc.wParamFlags");
1103 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1104 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1105 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1106 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1107 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1108 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1109 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1110 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1111 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1113 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1114 int i;
1115 MESSAGE("memid is %08x\n",funcdesc->memid);
1116 for (i=0;i<funcdesc->cParams;i++) {
1117 MESSAGE("Param %d:\n",i);
1118 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1120 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1121 switch (funcdesc->funckind) {
1122 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1123 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1124 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1125 case FUNC_STATIC: MESSAGE("static");break;
1126 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1127 default: MESSAGE("unknown");break;
1129 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1130 switch (funcdesc->invkind) {
1131 case INVOKE_FUNC: MESSAGE("func");break;
1132 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1133 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1134 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1136 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1137 switch (funcdesc->callconv) {
1138 case CC_CDECL: MESSAGE("cdecl");break;
1139 case CC_PASCAL: MESSAGE("pascal");break;
1140 case CC_STDCALL: MESSAGE("stdcall");break;
1141 case CC_SYSCALL: MESSAGE("syscall");break;
1142 default:break;
1144 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1145 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1146 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1148 MESSAGE("\telemdescFunc (return value type):\n");
1149 dump_ELEMDESC(&funcdesc->elemdescFunc);
1152 static const char * typekind_desc[] =
1154 "TKIND_ENUM",
1155 "TKIND_RECORD",
1156 "TKIND_MODULE",
1157 "TKIND_INTERFACE",
1158 "TKIND_DISPATCH",
1159 "TKIND_COCLASS",
1160 "TKIND_ALIAS",
1161 "TKIND_UNION",
1162 "TKIND_MAX"
1165 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1167 int i;
1168 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1169 for (i=0;i<pfd->funcdesc.cParams;i++)
1170 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1173 dump_FUNCDESC(&(pfd->funcdesc));
1175 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1176 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1178 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1180 while (pfd)
1182 dump_TLBFuncDescOne(pfd);
1183 pfd = pfd->next;
1186 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1188 while (pvd)
1190 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1191 pvd = pvd->next;
1195 static void dump_TLBImpLib(const TLBImpLib *import)
1197 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1198 debugstr_w(import->name));
1199 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1200 import->wVersionMinor, import->lcid, import->offset);
1203 static void dump_TLBRefType(const TLBRefType * prt)
1205 while (prt)
1207 TRACE_(typelib)("href:0x%08x\n", prt->reference);
1208 if(prt->index == -1)
1209 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1210 else
1211 TRACE_(typelib)("type no: %d\n", prt->index);
1213 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1214 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1215 TRACE_(typelib)("in lib\n");
1216 dump_TLBImpLib(prt->pImpTLInfo);
1218 prt = prt->next;
1222 static void dump_TLBImplType(const TLBImplType * impl)
1224 while (impl) {
1225 TRACE_(typelib)(
1226 "implementing/inheriting interface hRef = %x implflags %x\n",
1227 impl->hRef, impl->implflags);
1228 impl = impl->next;
1232 void dump_Variant(const VARIANT * pvar)
1234 SYSTEMTIME st;
1236 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1238 if (pvar)
1240 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1241 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1243 TRACE(",%p", V_BYREF(pvar));
1245 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1247 TRACE(",%p", V_ARRAY(pvar));
1249 else switch (V_TYPE(pvar))
1251 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1252 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1253 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1254 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1255 case VT_INT:
1256 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1257 case VT_UINT:
1258 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1259 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1260 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1261 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1262 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1263 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1264 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1265 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1266 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1267 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1268 V_CY(pvar).s.Lo); break;
1269 case VT_DATE:
1270 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1271 TRACE(",<invalid>");
1272 else
1273 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1274 st.wHour, st.wMinute, st.wSecond);
1275 break;
1276 case VT_ERROR:
1277 case VT_VOID:
1278 case VT_USERDEFINED:
1279 case VT_EMPTY:
1280 case VT_NULL: break;
1281 default: TRACE(",?"); break;
1284 TRACE("}\n");
1287 static void dump_DispParms(const DISPPARAMS * pdp)
1289 int index;
1291 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1293 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1295 TRACE("named args:\n");
1296 for (index = 0; index < pdp->cNamedArgs; index++)
1297 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1300 if (pdp->cArgs && pdp->rgvarg)
1302 TRACE("args:\n");
1303 for (index = 0; index < pdp->cArgs; index++)
1304 dump_Variant( &pdp->rgvarg[index] );
1308 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1310 TRACE("%p ref=%u\n", pty, pty->ref);
1311 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1312 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1313 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1314 TRACE("fct:%u var:%u impl:%u\n",
1315 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1316 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1317 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1318 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1319 if (TRACE_ON(ole))
1320 dump_TLBFuncDesc(pty->funclist);
1321 dump_TLBVarDesc(pty->varlist);
1322 dump_TLBImplType(pty->impltypelist);
1325 static void dump_VARDESC(const VARDESC *v)
1327 MESSAGE("memid %d\n",v->memid);
1328 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1329 MESSAGE("oInst %d\n",v->u.oInst);
1330 dump_ELEMDESC(&(v->elemdescVar));
1331 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1332 MESSAGE("varkind %d\n",v->varkind);
1335 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1337 /* VT_LPWSTR is largest type that */
1338 /* may appear in type description*/
1339 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1340 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1341 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1342 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1343 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1344 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1345 {{0},30},{{0},31}
1348 static void TLB_abort(void)
1350 DebugBreak();
1352 static void * TLB_Alloc(unsigned size)
1354 void * ret;
1355 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1356 /* FIXME */
1357 ERR("cannot allocate memory\n");
1359 return ret;
1362 static void TLB_Free(void * ptr)
1364 HeapFree(GetProcessHeap(), 0, ptr);
1367 /* returns the size required for a deep copy of a typedesc into a
1368 * flat buffer */
1369 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1371 SIZE_T size = 0;
1373 if (alloc_initial_space)
1374 size += sizeof(TYPEDESC);
1376 switch (tdesc->vt)
1378 case VT_PTR:
1379 case VT_SAFEARRAY:
1380 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1381 break;
1382 case VT_CARRAY:
1383 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1384 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1385 break;
1387 return size;
1390 /* deep copy a typedesc into a flat buffer */
1391 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1393 if (!dest)
1395 dest = buffer;
1396 buffer = (char *)buffer + sizeof(TYPEDESC);
1399 *dest = *src;
1401 switch (src->vt)
1403 case VT_PTR:
1404 case VT_SAFEARRAY:
1405 dest->u.lptdesc = buffer;
1406 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1407 break;
1408 case VT_CARRAY:
1409 dest->u.lpadesc = buffer;
1410 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1411 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1412 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1413 break;
1415 return buffer;
1418 /**********************************************************************
1420 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1422 static inline unsigned int MSFT_Tell(TLBContext *pcx)
1424 return pcx->pos;
1427 static inline void MSFT_Seek(TLBContext *pcx, long where)
1429 if (where != DO_NOT_SEEK)
1431 where += pcx->oStart;
1432 if (where > pcx->length)
1434 /* FIXME */
1435 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1436 TLB_abort();
1438 pcx->pos = where;
1442 /* read function */
1443 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1445 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1446 pcx->pos, count, pcx->oStart, pcx->length, where);
1448 MSFT_Seek(pcx, where);
1449 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1450 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1451 pcx->pos += count;
1452 return count;
1455 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1456 long where )
1458 DWORD ret;
1460 ret = MSFT_Read(buffer, count, pcx, where);
1461 FromLEDWords(buffer, ret);
1463 return ret;
1466 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1467 long where )
1469 DWORD ret;
1471 ret = MSFT_Read(buffer, count, pcx, where);
1472 FromLEWords(buffer, ret);
1474 return ret;
1477 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1479 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1480 memset(pGuid,0, sizeof(GUID));
1481 return;
1483 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1484 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1485 pGuid->Data2 = FromLEWord(pGuid->Data2);
1486 pGuid->Data3 = FromLEWord(pGuid->Data3);
1487 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1490 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1492 MSFT_NameIntro niName;
1494 if (offset < 0)
1496 ERR_(typelib)("bad offset %d\n", offset);
1497 return -1;
1500 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1501 pcx->pTblDir->pNametab.offset+offset);
1503 return niName.hreftype;
1506 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1508 char * name;
1509 MSFT_NameIntro niName;
1510 int lengthInChars;
1511 BSTR bstrName = NULL;
1513 if (offset < 0)
1515 ERR_(typelib)("bad offset %d\n", offset);
1516 return NULL;
1518 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1519 pcx->pTblDir->pNametab.offset+offset);
1520 niName.namelen &= 0xFF; /* FIXME: correct ? */
1521 name=TLB_Alloc((niName.namelen & 0xff) +1);
1522 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1523 name[niName.namelen & 0xff]='\0';
1525 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1526 name, -1, NULL, 0);
1528 /* no invalid characters in string */
1529 if (lengthInChars)
1531 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1533 /* don't check for invalid character since this has been done previously */
1534 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1536 TLB_Free(name);
1538 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1539 return bstrName;
1542 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1544 char * string;
1545 INT16 length;
1546 int lengthInChars;
1547 BSTR bstr = NULL;
1549 if(offset<0) return NULL;
1550 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1551 if(length <= 0) return 0;
1552 string=TLB_Alloc(length +1);
1553 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1554 string[length]='\0';
1556 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1557 string, -1, NULL, 0);
1559 /* no invalid characters in string */
1560 if (lengthInChars)
1562 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1564 /* don't check for invalid character since this has been done previously */
1565 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1567 TLB_Free(string);
1569 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1570 return bstr;
1573 * read a value and fill a VARIANT structure
1575 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1577 int size;
1579 TRACE_(typelib)("\n");
1581 if(offset <0) { /* data are packed in here */
1582 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1583 V_I4(pVar) = offset & 0x3ffffff;
1584 return;
1586 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1587 pcx->pTblDir->pCustData.offset + offset );
1588 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1589 switch (V_VT(pVar)){
1590 case VT_EMPTY: /* FIXME: is this right? */
1591 case VT_NULL: /* FIXME: is this right? */
1592 case VT_I2 : /* this should not happen */
1593 case VT_I4 :
1594 case VT_R4 :
1595 case VT_ERROR :
1596 case VT_BOOL :
1597 case VT_I1 :
1598 case VT_UI1 :
1599 case VT_UI2 :
1600 case VT_UI4 :
1601 case VT_INT :
1602 case VT_UINT :
1603 case VT_VOID : /* FIXME: is this right? */
1604 case VT_HRESULT :
1605 size=4; break;
1606 case VT_R8 :
1607 case VT_CY :
1608 case VT_DATE :
1609 case VT_I8 :
1610 case VT_UI8 :
1611 case VT_DECIMAL : /* FIXME: is this right? */
1612 case VT_FILETIME :
1613 size=8;break;
1614 /* pointer types with known behaviour */
1615 case VT_BSTR :{
1616 char * ptr;
1617 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1618 if(size < 0) {
1619 char next;
1620 DWORD origPos = MSFT_Tell(pcx), nullPos;
1622 do {
1623 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1624 } while (next);
1625 nullPos = MSFT_Tell(pcx);
1626 size = nullPos - origPos;
1627 MSFT_Seek(pcx, origPos);
1629 ptr=TLB_Alloc(size);/* allocate temp buffer */
1630 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1631 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1632 /* FIXME: do we need a AtoW conversion here? */
1633 V_UNION(pVar, bstrVal[size])=L'\0';
1634 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1635 TLB_Free(ptr);
1637 size=-4; break;
1638 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1639 case VT_DISPATCH :
1640 case VT_VARIANT :
1641 case VT_UNKNOWN :
1642 case VT_PTR :
1643 case VT_SAFEARRAY :
1644 case VT_CARRAY :
1645 case VT_USERDEFINED :
1646 case VT_LPSTR :
1647 case VT_LPWSTR :
1648 case VT_BLOB :
1649 case VT_STREAM :
1650 case VT_STORAGE :
1651 case VT_STREAMED_OBJECT :
1652 case VT_STORED_OBJECT :
1653 case VT_BLOB_OBJECT :
1654 case VT_CF :
1655 case VT_CLSID :
1656 default:
1657 size=0;
1658 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1659 V_VT(pVar));
1662 if(size>0) /* (big|small) endian correct? */
1663 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1664 return;
1667 * create a linked list with custom data
1669 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1671 MSFT_CDGuid entry;
1672 TLBCustData* pNew;
1673 int count=0;
1675 TRACE_(typelib)("\n");
1677 while(offset >=0){
1678 count++;
1679 pNew=TLB_Alloc(sizeof(TLBCustData));
1680 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1681 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1682 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1683 /* add new custom data at head of the list */
1684 pNew->next=*ppCustData;
1685 *ppCustData=pNew;
1686 offset = entry.next;
1688 return count;
1691 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1692 ITypeInfoImpl *pTI)
1694 if(type <0)
1695 pTd->vt=type & VT_TYPEMASK;
1696 else
1697 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1699 if(pTd->vt == VT_USERDEFINED)
1700 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1702 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1705 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1707 /* resolve referenced type if any */
1708 while (lpTypeDesc)
1710 switch (lpTypeDesc->vt)
1712 case VT_PTR:
1713 lpTypeDesc = lpTypeDesc->u.lptdesc;
1714 break;
1716 case VT_CARRAY:
1717 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1718 break;
1720 case VT_USERDEFINED:
1721 MSFT_DoRefType(pcx, pTI,
1722 lpTypeDesc->u.hreftype);
1724 lpTypeDesc = NULL;
1725 break;
1727 default:
1728 lpTypeDesc = NULL;
1733 static void
1734 MSFT_DoFuncs(TLBContext* pcx,
1735 ITypeInfoImpl* pTI,
1736 int cFuncs,
1737 int cVars,
1738 int offset,
1739 TLBFuncDesc** pptfd)
1742 * member information is stored in a data structure at offset
1743 * indicated by the memoffset field of the typeinfo structure
1744 * There are several distinctive parts.
1745 * The first part starts with a field that holds the total length
1746 * of this (first) part excluding this field. Then follow the records,
1747 * for each member there is one record.
1749 * The first entry is always the length of the record (including this
1750 * length word).
1751 * The rest of the record depends on the type of the member. If there is
1752 * a field indicating the member type (function, variable, interface, etc)
1753 * I have not found it yet. At this time we depend on the information
1754 * in the type info and the usual order how things are stored.
1756 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1757 * for each member;
1759 * Third is an equal sized array with file offsets to the name entry
1760 * of each member.
1762 * The fourth and last (?) part is an array with offsets to the records
1763 * in the first part of this file segment.
1766 int infolen, nameoffset, reclength, nrattributes, i;
1767 int recoffset = offset + sizeof(INT);
1769 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1770 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1771 TLBFuncDesc *ptfd_prev = NULL;
1773 TRACE_(typelib)("\n");
1775 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1777 for ( i = 0; i < cFuncs ; i++ )
1779 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1781 /* name, eventually add to a hash table */
1782 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1783 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1785 /* nameoffset is sometimes -1 on the second half of a propget/propput
1786 * pair of functions */
1787 if ((nameoffset == -1) && (i > 0))
1788 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1789 else
1790 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1792 /* read the function information record */
1793 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1795 reclength &= 0xffff;
1797 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1799 /* do the attributes */
1800 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1801 / sizeof(int);
1803 if ( nrattributes > 0 )
1805 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1807 if ( nrattributes > 1 )
1809 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1810 pFuncRec->OptAttr[1]) ;
1812 if ( nrattributes > 2 )
1814 if ( pFuncRec->FKCCIC & 0x2000 )
1816 if (HIWORD(pFuncRec->OptAttr[2]) != 0)
1817 ERR("ordinal 0x%08x invalid, HIWORD != 0\n", pFuncRec->OptAttr[2]);
1818 (*pptfd)->Entry = (BSTR)pFuncRec->OptAttr[2];
1820 else
1822 (*pptfd)->Entry = MSFT_ReadString(pcx,
1823 pFuncRec->OptAttr[2]);
1825 if( nrattributes > 5 )
1827 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1829 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1831 MSFT_CustData(pcx,
1832 pFuncRec->OptAttr[6],
1833 &(*pptfd)->pCustData);
1837 else
1839 (*pptfd)->Entry = (BSTR)-1;
1844 /* fill the FuncDesc Structure */
1845 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1846 offset + infolen + ( i + 1) * sizeof(INT));
1848 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1849 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1850 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1851 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1852 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1853 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1854 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1856 MSFT_GetTdesc(pcx,
1857 pFuncRec->DataType,
1858 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1859 pTI);
1860 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1862 /* do the parameters/arguments */
1863 if(pFuncRec->nrargs)
1865 int j = 0;
1866 MSFT_ParameterInfo paraminfo;
1868 (*pptfd)->funcdesc.lprgelemdescParam =
1869 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1871 (*pptfd)->pParamDesc =
1872 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1874 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1875 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1877 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1879 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1881 MSFT_GetTdesc(pcx,
1882 paraminfo.DataType,
1883 &elemdesc->tdesc,
1884 pTI);
1886 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1888 /* name */
1889 if (paraminfo.oName == -1)
1890 /* this occurs for [propput] or [propget] methods, so
1891 * we should just set the name of the parameter to the
1892 * name of the method. */
1893 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1894 else
1895 (*pptfd)->pParamDesc[j].Name =
1896 MSFT_ReadName( pcx, paraminfo.oName );
1897 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1899 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1901 /* default value */
1902 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1903 (pFuncRec->FKCCIC & 0x1000) )
1905 INT* pInt = (INT *)((char *)pFuncRec +
1906 reclength -
1907 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1909 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1911 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1912 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1914 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1915 pInt[j], pcx);
1917 else
1918 elemdesc->u.paramdesc.pparamdescex = NULL;
1919 /* custom info */
1920 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1922 MSFT_CustData(pcx,
1923 pFuncRec->OptAttr[7+j],
1924 &(*pptfd)->pParamDesc[j].pCustData);
1927 /* SEEK value = jump to offset,
1928 * from there jump to the end of record,
1929 * go back by (j-1) arguments
1931 MSFT_ReadLEDWords( &paraminfo ,
1932 sizeof(MSFT_ParameterInfo), pcx,
1933 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1934 * sizeof(MSFT_ParameterInfo)));
1938 /* scode is not used: archaic win16 stuff FIXME: right? */
1939 (*pptfd)->funcdesc.cScodes = 0 ;
1940 (*pptfd)->funcdesc.lprgscode = NULL ;
1942 ptfd_prev = *pptfd;
1943 pptfd = & ((*pptfd)->next);
1944 recoffset += reclength;
1946 HeapFree(GetProcessHeap(), 0, recbuf);
1949 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1950 int cVars, int offset, TLBVarDesc ** pptvd)
1952 int infolen, nameoffset, reclength;
1953 char recbuf[256];
1954 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1955 int i;
1956 int recoffset;
1958 TRACE_(typelib)("\n");
1960 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1961 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1962 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1963 recoffset += offset+sizeof(INT);
1964 for(i=0;i<cVars;i++){
1965 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1966 /* name, eventually add to a hash table */
1967 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1968 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
1969 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1970 /* read the variable information record */
1971 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1972 reclength &=0xff;
1973 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1974 /* Optional data */
1975 if(reclength >(6*sizeof(INT)) )
1976 (*pptvd)->HelpContext=pVarRec->HelpContext;
1977 if(reclength >(7*sizeof(INT)) )
1978 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1979 if(reclength >(8*sizeof(INT)) )
1980 if(reclength >(9*sizeof(INT)) )
1981 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1982 /* fill the VarDesc Structure */
1983 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1984 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
1985 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1986 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1987 MSFT_GetTdesc(pcx, pVarRec->DataType,
1988 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1989 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1990 if(pVarRec->VarKind == VAR_CONST ){
1991 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1992 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1993 pVarRec->OffsValue, pcx);
1994 } else
1995 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1996 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
1997 pptvd=&((*pptvd)->next);
1998 recoffset += reclength;
2001 /* fill in data for a hreftype (offset). When the referenced type is contained
2002 * in the typelib, it's just an (file) offset in the type info base dir.
2003 * If comes from import, it's an offset+1 in the ImpInfo table
2004 * */
2005 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
2006 int offset)
2008 int j;
2009 TLBRefType **ppRefType = &pTI->reflist;
2011 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2013 while(*ppRefType) {
2014 if((*ppRefType)->reference == offset)
2015 return;
2016 ppRefType = &(*ppRefType)->next;
2019 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2020 sizeof(**ppRefType));
2022 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2023 /* external typelib */
2024 MSFT_ImpInfo impinfo;
2025 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2027 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2029 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2030 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2031 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
2032 if(pImpLib->offset==impinfo.oImpFile) break;
2033 pImpLib=pImpLib->next;
2035 if(pImpLib){
2036 (*ppRefType)->reference=offset;
2037 (*ppRefType)->pImpTLInfo = pImpLib;
2038 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2039 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
2040 TRACE("importing by guid %s\n", debugstr_guid(&(*ppRefType)->guid));
2041 (*ppRefType)->index = TLB_REF_USE_GUID;
2042 } else
2043 (*ppRefType)->index = impinfo.oGuid;
2044 }else{
2045 ERR("Cannot find a reference\n");
2046 (*ppRefType)->reference=-1;
2047 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
2049 }else{
2050 /* in this typelib */
2051 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
2052 (*ppRefType)->reference=offset;
2053 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
2057 /* process Implemented Interfaces of a com class */
2058 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2059 int offset)
2061 int i;
2062 MSFT_RefRecord refrec;
2063 TLBImplType **ppImpl = &pTI->impltypelist;
2065 TRACE_(typelib)("\n");
2067 for(i=0;i<count;i++){
2068 if(offset<0) break; /* paranoia */
2069 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2070 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2071 MSFT_DoRefType(pcx, pTI, refrec.reftype);
2072 (*ppImpl)->hRef = refrec.reftype;
2073 (*ppImpl)->implflags=refrec.flags;
2074 (*ppImpl)->ctCustData=
2075 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2076 offset=refrec.onext;
2077 ppImpl=&((*ppImpl)->next);
2081 * process a typeinfo record
2083 static ITypeInfoImpl * MSFT_DoTypeInfo(
2084 TLBContext *pcx,
2085 int count,
2086 INT dispatch_href,
2087 ITypeLibImpl * pLibInfo)
2089 MSFT_TypeInfoBase tiBase;
2090 ITypeInfoImpl *ptiRet;
2092 TRACE_(typelib)("count=%u\n", count);
2094 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2095 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2096 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2098 /* this is where we are coming from */
2099 ptiRet->pTypeLib = pLibInfo;
2100 ptiRet->index=count;
2101 /* fill in the typeattr fields */
2103 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2104 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2105 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2106 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2107 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2108 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2109 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2110 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2111 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2112 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2113 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2114 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2115 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2116 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2117 MSFT_GetTdesc(pcx, tiBase.datatype1,
2118 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2120 /* FIXME: */
2121 /* IDLDESC idldescType; *//* never saw this one != zero */
2123 /* name, eventually add to a hash table */
2124 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2125 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2126 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2127 /* help info */
2128 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2129 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2130 ptiRet->dwHelpContext=tiBase.helpcontext;
2132 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2133 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2135 /* note: InfoType's Help file and HelpStringDll come from the containing
2136 * library. Further HelpString and Docstring appear to be the same thing :(
2138 /* functions */
2139 if(ptiRet->TypeAttr.cFuncs >0 )
2140 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2141 ptiRet->TypeAttr.cVars,
2142 tiBase.memoffset, & ptiRet->funclist);
2143 /* variables */
2144 if(ptiRet->TypeAttr.cVars >0 )
2145 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2146 ptiRet->TypeAttr.cVars,
2147 tiBase.memoffset, & ptiRet->varlist);
2148 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2149 switch(ptiRet->TypeAttr.typekind)
2151 case TKIND_COCLASS:
2152 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2153 tiBase.datatype1);
2154 break;
2155 case TKIND_DISPATCH:
2156 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2158 if (tiBase.datatype1 != -1)
2160 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2161 ptiRet->impltypelist->hRef = tiBase.datatype1;
2163 else
2165 MSFT_DoRefType(pcx, ptiRet, dispatch_href);
2166 ptiRet->impltypelist->hRef = dispatch_href;
2168 break;
2169 default:
2170 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2171 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2172 ptiRet->impltypelist->hRef = tiBase.datatype1;
2173 break;
2176 ptiRet->ctCustData=
2177 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2179 TRACE_(typelib)("%s guid: %s kind:%s\n",
2180 debugstr_w(ptiRet->Name),
2181 debugstr_guid(&ptiRet->TypeAttr.guid),
2182 typekind_desc[ptiRet->TypeAttr.typekind]);
2184 return ptiRet;
2187 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2188 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2189 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2190 * tradeoff here.
2192 static ITypeLibImpl *tlb_cache_first;
2193 static CRITICAL_SECTION cache_section;
2194 static CRITICAL_SECTION_DEBUG cache_section_debug =
2196 0, 0, &cache_section,
2197 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2198 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2200 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2203 /****************************************************************************
2204 * TLB_ReadTypeLib
2206 * find the type of the typelib file and map the typelib resource into
2207 * the memory
2209 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2210 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2211 static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2213 ITypeLibImpl *entry;
2214 int ret = TYPE_E_CANTLOADLIBRARY;
2215 INT index = 1;
2216 HINSTANCE hinstDLL;
2218 *ppTypeLib = NULL;
2220 lstrcpynW(pszPath, pszFileName, cchPath);
2222 /* first try loading as a dll and access the typelib as a resource */
2223 hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES |
2224 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2225 if (!hinstDLL)
2227 /* it may have been specified with resource index appended to the
2228 * path, so remove it and try again */
2229 const WCHAR *pIndexStr = strrchrW(pszFileName, '\\');
2230 if(pIndexStr && pIndexStr != pszFileName && *++pIndexStr != '\0')
2232 index = atoiW(pIndexStr);
2233 pszPath[pIndexStr - pszFileName - 1] = '\0';
2235 hinstDLL = LoadLibraryExW(pszPath, 0, DONT_RESOLVE_DLL_REFERENCES |
2236 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2240 /* get the path to the specified typelib file */
2241 if (!hinstDLL)
2243 /* otherwise, try loading as a regular file */
2244 if (!SearchPathW(NULL, pszFileName, NULL, cchPath, pszPath, NULL))
2245 return TYPE_E_CANTLOADLIBRARY;
2248 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2250 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2251 EnterCriticalSection(&cache_section);
2252 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2254 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2256 TRACE("cache hit\n");
2257 *ppTypeLib = (ITypeLib2*)entry;
2258 ITypeLib_AddRef(*ppTypeLib);
2259 LeaveCriticalSection(&cache_section);
2260 FreeLibrary(hinstDLL);
2261 return S_OK;
2264 LeaveCriticalSection(&cache_section);
2266 /* now actually load and parse the typelib */
2267 if (hinstDLL)
2269 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2270 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2271 if (hrsrc)
2273 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2274 if (hGlobal)
2276 LPVOID pBase = LockResource(hGlobal);
2277 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2279 if (pBase)
2281 /* try to load as incore resource */
2282 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2283 if (dwSignature == MSFT_SIGNATURE)
2284 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2285 else if (dwSignature == SLTG_SIGNATURE)
2286 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2287 else
2288 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2290 FreeResource( hGlobal );
2293 FreeLibrary(hinstDLL);
2295 else
2297 HANDLE hFile = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2298 if (INVALID_HANDLE_VALUE != hFile)
2300 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2301 if (hMapping)
2303 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2304 if(pBase)
2306 /* retrieve file size */
2307 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2308 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2310 if (dwSignature == MSFT_SIGNATURE)
2311 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2312 else if (dwSignature == SLTG_SIGNATURE)
2313 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2315 UnmapViewOfFile(pBase);
2317 CloseHandle(hMapping);
2319 CloseHandle(hFile);
2323 if(*ppTypeLib) {
2324 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2326 TRACE("adding to cache\n");
2327 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2328 lstrcpyW(impl->path, pszPath);
2329 /* We should really canonicalise the path here. */
2330 impl->index = index;
2332 /* FIXME: check if it has added already in the meantime */
2333 EnterCriticalSection(&cache_section);
2334 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2335 impl->prev = NULL;
2336 tlb_cache_first = impl;
2337 LeaveCriticalSection(&cache_section);
2338 ret = S_OK;
2339 } else
2340 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2342 return ret;
2345 /*================== ITypeLib(2) Methods ===================================*/
2347 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2349 ITypeLibImpl* pTypeLibImpl;
2351 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2352 if (!pTypeLibImpl) return NULL;
2354 pTypeLibImpl->lpVtbl = &tlbvt;
2355 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2356 pTypeLibImpl->ref = 1;
2358 return pTypeLibImpl;
2361 /****************************************************************************
2362 * ITypeLib2_Constructor_MSFT
2364 * loading an MSFT typelib from an in-memory image
2366 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2368 TLBContext cx;
2369 long lPSegDir;
2370 MSFT_Header tlbHeader;
2371 MSFT_SegDir tlbSegDir;
2372 ITypeLibImpl * pTypeLibImpl;
2374 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2376 pTypeLibImpl = TypeLibImpl_Constructor();
2377 if (!pTypeLibImpl) return NULL;
2379 /* get pointer to beginning of typelib data */
2380 cx.pos = 0;
2381 cx.oStart=0;
2382 cx.mapping = pLib;
2383 cx.pLibInfo = pTypeLibImpl;
2384 cx.length = dwTLBLength;
2386 /* read header */
2387 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2388 TRACE_(typelib)("header:\n");
2389 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2390 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2391 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2392 return NULL;
2394 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2396 /* there is a small amount of information here until the next important
2397 * part:
2398 * the segment directory . Try to calculate the amount of data */
2399 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2401 /* now read the segment directory */
2402 TRACE("read segment directory (at %ld)\n",lPSegDir);
2403 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2404 cx.pTblDir = &tlbSegDir;
2406 /* just check two entries */
2407 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2409 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2410 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2411 return NULL;
2414 /* now fill our internal data */
2415 /* TLIBATTR fields */
2416 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2418 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2419 /* Windows seems to have zero here, is this correct? */
2420 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2421 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2422 else
2423 pTypeLibImpl->LibAttr.lcid = 0;
2425 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2426 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2427 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2428 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2430 /* name, eventually add to a hash table */
2431 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2433 /* help info */
2434 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2435 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2437 if( tlbHeader.varflags & HELPDLLFLAG)
2439 int offset;
2440 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2441 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2444 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2446 /* custom data */
2447 if(tlbHeader.CustomDataOffset >= 0)
2449 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2452 /* fill in typedescriptions */
2453 if(tlbSegDir.pTypdescTab.length > 0)
2455 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2456 INT16 td[4];
2457 pTypeLibImpl->ctTypeDesc = cTD;
2458 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2459 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2460 for(i=0; i<cTD; )
2462 /* FIXME: add several sanity checks here */
2463 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2464 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2466 /* FIXME: check safearray */
2467 if(td[3] < 0)
2468 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2469 else
2470 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2472 else if(td[0] == VT_CARRAY)
2474 /* array descr table here */
2475 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2477 else if(td[0] == VT_USERDEFINED)
2479 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2481 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2484 /* second time around to fill the array subscript info */
2485 for(i=0;i<cTD;i++)
2487 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2488 if(tlbSegDir.pArrayDescriptions.offset>0)
2490 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2491 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2493 if(td[1]<0)
2494 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2495 else
2496 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2498 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2500 for(j = 0; j<td[2]; j++)
2502 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2503 sizeof(INT), &cx, DO_NOT_SEEK);
2504 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2505 sizeof(INT), &cx, DO_NOT_SEEK);
2508 else
2510 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2511 ERR("didn't find array description data\n");
2516 /* imported type libs */
2517 if(tlbSegDir.pImpFiles.offset>0)
2519 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2520 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2521 UINT16 size;
2523 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2525 char *name;
2526 DWORD len;
2528 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2529 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2530 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2532 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2533 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2534 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2535 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2537 size >>= 2;
2538 name = TLB_Alloc(size+1);
2539 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2540 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2541 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2542 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2543 TLB_Free(name);
2545 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2546 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2548 ppImpLib = &(*ppImpLib)->next;
2552 /* type info's */
2553 if(tlbHeader.nrtypeinfos >= 0 )
2555 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2556 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2557 int i;
2559 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2561 *ppTI = MSFT_DoTypeInfo(&cx, i, tlbHeader.dispatchpos, pTypeLibImpl);
2563 ppTI = &((*ppTI)->next);
2564 (pTypeLibImpl->TypeInfoCount)++;
2568 TRACE("(%p)\n", pTypeLibImpl);
2569 return (ITypeLib2*) pTypeLibImpl;
2573 static BSTR TLB_MultiByteToBSTR(char *ptr)
2575 DWORD len;
2576 WCHAR *nameW;
2577 BSTR ret;
2579 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2580 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2581 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2582 ret = SysAllocString(nameW);
2583 HeapFree(GetProcessHeap(), 0, nameW);
2584 return ret;
2587 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2589 char b[3];
2590 int i;
2591 short s;
2593 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2594 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2595 return FALSE;
2598 guid->Data4[0] = s >> 8;
2599 guid->Data4[1] = s & 0xff;
2601 b[2] = '\0';
2602 for(i = 0; i < 6; i++) {
2603 memcpy(b, str + 24 + 2 * i, 2);
2604 guid->Data4[i + 2] = strtol(b, NULL, 16);
2606 return TRUE;
2609 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2611 WORD bytelen;
2612 DWORD len;
2613 WCHAR *nameW;
2615 *pBstr = NULL;
2616 bytelen = *(WORD*)ptr;
2617 if(bytelen == 0xffff) return 2;
2618 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2619 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2620 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2621 *pBstr = SysAllocStringLen(nameW, len);
2622 HeapFree(GetProcessHeap(), 0, nameW);
2623 return bytelen + 2;
2626 static WORD SLTG_ReadStringA(char *ptr, char **str)
2628 WORD bytelen;
2630 *str = NULL;
2631 bytelen = *(WORD*)ptr;
2632 if(bytelen == 0xffff) return 2;
2633 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2634 memcpy(*str, ptr + 2, bytelen);
2635 (*str)[bytelen] = '\0';
2636 return bytelen + 2;
2639 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2641 char *ptr = pLibBlk;
2642 WORD w;
2644 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2645 FIXME("libblk magic = %04x\n", w);
2646 return 0;
2649 ptr += 6;
2650 if((w = *(WORD*)ptr) != 0xffff) {
2651 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2652 ptr += w;
2654 ptr += 2;
2656 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2658 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2660 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2661 ptr += 4;
2663 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2664 ptr += 2;
2666 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2667 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2668 else
2669 pTypeLibImpl->LibAttr.lcid = 0;
2670 ptr += 2;
2672 ptr += 4; /* skip res12 */
2674 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2675 ptr += 2;
2677 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2678 ptr += 2;
2680 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2681 ptr += 2;
2683 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2684 ptr += sizeof(GUID);
2686 return ptr - (char*)pLibBlk;
2689 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD)
2691 BOOL done = FALSE;
2693 while(!done) {
2694 if((*pType & 0xe00) == 0xe00) {
2695 pTD->vt = VT_PTR;
2696 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2697 sizeof(TYPEDESC));
2698 pTD = pTD->u.lptdesc;
2700 switch(*pType & 0x3f) {
2701 case VT_PTR:
2702 pTD->vt = VT_PTR;
2703 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2704 sizeof(TYPEDESC));
2705 pTD = pTD->u.lptdesc;
2706 break;
2708 case VT_USERDEFINED:
2709 pTD->vt = VT_USERDEFINED;
2710 pTD->u.hreftype = *(++pType) / 4;
2711 done = TRUE;
2712 break;
2714 case VT_CARRAY:
2716 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2717 array */
2719 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2721 pTD->vt = VT_CARRAY;
2722 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2723 sizeof(ARRAYDESC) +
2724 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2725 pTD->u.lpadesc->cDims = pSA->cDims;
2726 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2727 pSA->cDims * sizeof(SAFEARRAYBOUND));
2729 pTD = &pTD->u.lpadesc->tdescElem;
2730 break;
2733 case VT_SAFEARRAY:
2735 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2736 useful? */
2738 pType++;
2739 pTD->vt = VT_SAFEARRAY;
2740 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2741 sizeof(TYPEDESC));
2742 pTD = pTD->u.lptdesc;
2743 break;
2745 default:
2746 pTD->vt = *pType & 0x3f;
2747 done = TRUE;
2748 break;
2750 pType++;
2752 return pType;
2755 static WORD *SLTG_DoElem(WORD *pType, char *pBlk, ELEMDESC *pElem)
2757 /* Handle [in/out] first */
2758 if((*pType & 0xc000) == 0xc000)
2759 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2760 else if(*pType & 0x8000)
2761 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2762 else if(*pType & 0x4000)
2763 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2764 else
2765 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2767 if(*pType & 0x2000)
2768 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2770 if(*pType & 0x80)
2771 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2773 return SLTG_DoType(pType, pBlk, &pElem->tdesc);
2777 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2778 char *pNameTable)
2780 int ref;
2781 char *name;
2782 TLBRefType **ppRefType;
2784 if(pRef->magic != SLTG_REF_MAGIC) {
2785 FIXME("Ref magic = %x\n", pRef->magic);
2786 return;
2788 name = ( (char*)(&pRef->names) + pRef->number);
2790 ppRefType = &pTI->reflist;
2791 for(ref = 0; ref < pRef->number >> 3; ref++) {
2792 char *refname;
2793 unsigned int lib_offs, type_num;
2795 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2796 sizeof(**ppRefType));
2798 name += SLTG_ReadStringA(name, &refname);
2799 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2800 FIXME("Can't sscanf ref\n");
2801 if(lib_offs != 0xffff) {
2802 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2804 while(*import) {
2805 if((*import)->offset == lib_offs)
2806 break;
2807 import = &(*import)->next;
2809 if(!*import) {
2810 char fname[MAX_PATH+1];
2811 int len;
2813 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2814 sizeof(**import));
2815 (*import)->offset = lib_offs;
2816 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2817 &(*import)->guid);
2818 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
2819 &(*import)->wVersionMajor,
2820 &(*import)->wVersionMinor,
2821 &(*import)->lcid, fname) != 4) {
2822 FIXME("can't sscanf ref %s\n",
2823 pNameTable + lib_offs + 40);
2825 len = strlen(fname);
2826 if(fname[len-1] != '#')
2827 FIXME("fname = %s\n", fname);
2828 fname[len-1] = '\0';
2829 (*import)->name = TLB_MultiByteToBSTR(fname);
2831 (*ppRefType)->pImpTLInfo = *import;
2832 } else { /* internal ref */
2833 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2835 (*ppRefType)->reference = ref;
2836 (*ppRefType)->index = type_num;
2838 HeapFree(GetProcessHeap(), 0, refname);
2839 ppRefType = &(*ppRefType)->next;
2841 if((BYTE)*name != SLTG_REF_MAGIC)
2842 FIXME("End of ref block magic = %x\n", *name);
2843 dump_TLBRefType(pTI->reflist);
2846 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2847 BOOL OneOnly)
2849 SLTG_ImplInfo *info;
2850 TLBImplType **ppImplType = &pTI->impltypelist;
2851 /* I don't really get this structure, usually it's 0x16 bytes
2852 long, but iuser.tlb contains some that are 0x18 bytes long.
2853 That's ok because we can use the next ptr to jump to the next
2854 one. But how do we know the length of the last one? The WORD
2855 at offs 0x8 might be the clue. For now I'm just assuming that
2856 the last one is the regular 0x16 bytes. */
2858 info = (SLTG_ImplInfo*)pBlk;
2859 while(1) {
2860 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2861 sizeof(**ppImplType));
2862 (*ppImplType)->hRef = info->ref;
2863 (*ppImplType)->implflags = info->impltypeflags;
2864 pTI->TypeAttr.cImplTypes++;
2865 ppImplType = &(*ppImplType)->next;
2867 if(info->next == 0xffff)
2868 break;
2869 if(OneOnly)
2870 FIXME("Interface inheriting more than one interface\n");
2871 info = (SLTG_ImplInfo*)(pBlk + info->next);
2873 info++; /* see comment at top of function */
2874 return (char*)info;
2877 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars, char *pNameTable)
2879 TLBVarDesc **ppVarDesc = &pTI->varlist;
2880 BSTR bstrPrevName = NULL;
2881 SLTG_Variable *pItem;
2882 unsigned short i;
2883 WORD *pType;
2884 char buf[300];
2886 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
2887 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
2889 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2890 sizeof(**ppVarDesc));
2891 (*ppVarDesc)->vardesc.memid = pItem->memid;
2893 if (pItem->magic != SLTG_VAR_MAGIC &&
2894 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
2895 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
2896 return;
2899 if (pItem->name == 0xfffe)
2900 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
2901 else
2902 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2904 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
2905 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
2907 if (pItem->flags & 0x40) {
2908 TRACE_(typelib)("VAR_DISPATCH\n");
2909 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
2911 else if (pItem->flags & 0x10) {
2912 TRACE_(typelib)("VAR_CONST\n");
2913 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2914 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2915 sizeof(VARIANT));
2916 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2917 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2918 *(INT*)(pBlk + pItem->byte_offs);
2920 else {
2921 TRACE_(typelib)("VAR_PERINSTANCE\n");
2922 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2923 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2926 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
2927 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
2929 if (pItem->flags & 0x80)
2930 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
2932 if(pItem->flags & 0x02)
2933 pType = &pItem->type;
2934 else
2935 pType = (WORD*)(pBlk + pItem->type);
2937 if (pItem->flags & ~0xd2)
2938 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xd2);
2940 SLTG_DoElem(pType, pBlk,
2941 &(*ppVarDesc)->vardesc.elemdescVar);
2943 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2945 bstrPrevName = (*ppVarDesc)->Name;
2946 ppVarDesc = &((*ppVarDesc)->next);
2948 pTI->TypeAttr.cVars = cVars;
2951 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cFuncs, char *pNameTable)
2953 SLTG_Function *pFunc;
2954 unsigned short i;
2955 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2957 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
2958 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
2960 int param;
2961 WORD *pType, *pArg;
2963 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2964 sizeof(**ppFuncDesc));
2966 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
2967 case SLTG_FUNCTION_MAGIC:
2968 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
2969 break;
2970 case SLTG_DISPATCH_FUNCTION_MAGIC:
2971 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
2972 break;
2973 case SLTG_STATIC_FUNCTION_MAGIC:
2974 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
2975 break;
2976 default:
2977 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
2978 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
2979 *ppFuncDesc = NULL;
2980 return;
2982 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2984 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2985 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2986 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2987 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2988 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2989 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2991 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
2992 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2994 if(pFunc->retnextopt & 0x80)
2995 pType = &pFunc->rettype;
2996 else
2997 pType = (WORD*)(pBlk + pFunc->rettype);
2999 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc);
3001 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3002 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3003 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3004 (*ppFuncDesc)->pParamDesc =
3005 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3006 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3008 pArg = (WORD*)(pBlk + pFunc->arg_off);
3010 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3011 char *paramName = pNameTable + *pArg;
3012 BOOL HaveOffs;
3013 /* If arg type follows then paramName points to the 2nd
3014 letter of the name, else the next WORD is an offset to
3015 the arg type and paramName points to the first letter.
3016 So let's take one char off paramName and see if we're
3017 pointing at an alpha-numeric char. However if *pArg is
3018 0xffff or 0xfffe then the param has no name, the former
3019 meaning that the next WORD is the type, the latter
3020 meaning the the next WORD is an offset to the type. */
3022 HaveOffs = FALSE;
3023 if(*pArg == 0xffff)
3024 paramName = NULL;
3025 else if(*pArg == 0xfffe) {
3026 paramName = NULL;
3027 HaveOffs = TRUE;
3029 else if(paramName[-1] && !isalnum(paramName[-1]))
3030 HaveOffs = TRUE;
3032 pArg++;
3034 if(HaveOffs) { /* the next word is an offset to type */
3035 pType = (WORD*)(pBlk + *pArg);
3036 SLTG_DoElem(pType, pBlk,
3037 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
3038 pArg++;
3039 } else {
3040 if(paramName)
3041 paramName--;
3042 pArg = SLTG_DoElem(pArg, pBlk,
3043 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
3046 /* Are we an optional param ? */
3047 if((*ppFuncDesc)->funcdesc.cParams - param <=
3048 (*ppFuncDesc)->funcdesc.cParamsOpt)
3049 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3051 if(paramName) {
3052 (*ppFuncDesc)->pParamDesc[param].Name =
3053 TLB_MultiByteToBSTR(paramName);
3057 ppFuncDesc = &((*ppFuncDesc)->next);
3058 if(pFunc->next == 0xffff) break;
3060 pTI->TypeAttr.cFuncs = cFuncs;
3063 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3064 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3065 SLTG_TypeInfoTail *pTITail)
3067 char *pFirstItem, *pNextItem;
3069 if(pTIHeader->href_table != 0xffffffff) {
3070 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3071 pNameTable);
3074 pFirstItem = pNextItem = pBlk;
3076 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3077 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
3082 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3083 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3084 SLTG_TypeInfoTail *pTITail)
3086 char *pFirstItem, *pNextItem;
3088 if(pTIHeader->href_table != 0xffffffff) {
3089 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3090 pNameTable);
3093 pFirstItem = pNextItem = pBlk;
3095 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3096 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
3099 if (pTITail->funcs_off != 0xffff)
3100 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3102 if (TRACE_ON(typelib))
3103 dump_TLBFuncDesc(pTI->funclist);
3106 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3107 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3108 SLTG_TypeInfoTail *pTITail)
3110 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3113 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3114 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3115 SLTG_TypeInfoTail *pTITail)
3117 WORD *pType;
3119 if (pTITail->simple_alias) {
3120 /* if simple alias, no more processing required */
3121 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3122 return;
3125 if(pTIHeader->href_table != 0xffffffff) {
3126 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3127 pNameTable);
3130 /* otherwise it is an offset to a type */
3131 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3133 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias);
3136 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3137 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3138 SLTG_TypeInfoTail *pTITail)
3140 if (pTIHeader->href_table != 0xffffffff)
3141 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3142 pNameTable);
3144 if (pTITail->vars_off != 0xffff)
3145 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3147 if (pTITail->funcs_off != 0xffff)
3148 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3150 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3151 * of dispinterface functons including the IDispatch ones, so
3152 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3153 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3155 if (TRACE_ON(typelib))
3156 dump_TLBFuncDesc(pTI->funclist);
3159 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3160 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3161 SLTG_TypeInfoTail *pTITail)
3163 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3166 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3167 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3168 SLTG_TypeInfoTail *pTITail)
3170 if (pTIHeader->href_table != 0xffffffff)
3171 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3172 pNameTable);
3174 if (pTITail->vars_off != 0xffff)
3175 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3177 if (pTITail->funcs_off != 0xffff)
3178 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3181 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3182 managable copy of it into this */
3183 typedef struct {
3184 WORD small_no;
3185 char *index_name;
3186 char *other_name;
3187 WORD res1a;
3188 WORD name_offs;
3189 WORD more_bytes;
3190 char *extra;
3191 WORD res20;
3192 DWORD helpcontext;
3193 WORD res26;
3194 GUID uuid;
3195 } SLTG_InternalOtherTypeInfo;
3197 /****************************************************************************
3198 * ITypeLib2_Constructor_SLTG
3200 * loading a SLTG typelib from an in-memory image
3202 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3204 ITypeLibImpl *pTypeLibImpl;
3205 SLTG_Header *pHeader;
3206 SLTG_BlkEntry *pBlkEntry;
3207 SLTG_Magic *pMagic;
3208 SLTG_Index *pIndex;
3209 SLTG_Pad9 *pPad9;
3210 LPVOID pBlk, pFirstBlk;
3211 SLTG_LibBlk *pLibBlk;
3212 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3213 char *pAfterOTIBlks = NULL;
3214 char *pNameTable, *ptr;
3215 int i;
3216 DWORD len, order;
3217 ITypeInfoImpl **ppTypeInfoImpl;
3219 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3222 pTypeLibImpl = TypeLibImpl_Constructor();
3223 if (!pTypeLibImpl) return NULL;
3225 pHeader = pLib;
3227 TRACE_(typelib)("header:\n");
3228 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3229 pHeader->nrOfFileBlks );
3230 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3231 FIXME("Header type magic 0x%08x not supported.\n",
3232 pHeader->SLTG_magic);
3233 return NULL;
3236 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3237 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3239 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3240 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3242 /* Next we have a magic block */
3243 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3245 /* Let's see if we're still in sync */
3246 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3247 sizeof(SLTG_COMPOBJ_MAGIC))) {
3248 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3249 return NULL;
3251 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3252 sizeof(SLTG_DIR_MAGIC))) {
3253 FIXME("dir magic = %s\n", pMagic->dir_magic);
3254 return NULL;
3257 pIndex = (SLTG_Index*)(pMagic+1);
3259 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3261 pFirstBlk = (LPVOID)(pPad9 + 1);
3263 /* We'll set up a ptr to the main library block, which is the last one. */
3265 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3266 pBlkEntry[order].next != 0;
3267 order = pBlkEntry[order].next - 1, i++) {
3268 pBlk = (char*)pBlk + pBlkEntry[order].len;
3270 pLibBlk = pBlk;
3272 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3274 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3275 interspersed */
3277 len += 0x40;
3279 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3281 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3282 sizeof(*pOtherTypeInfoBlks) *
3283 pTypeLibImpl->TypeInfoCount);
3286 ptr = (char*)pLibBlk + len;
3288 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3289 WORD w, extra;
3290 len = 0;
3292 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3294 w = *(WORD*)(ptr + 2);
3295 if(w != 0xffff) {
3296 len += w;
3297 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3298 w+1);
3299 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3300 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3302 w = *(WORD*)(ptr + 4 + len);
3303 if(w != 0xffff) {
3304 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3305 len += w;
3306 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3307 w+1);
3308 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3309 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3311 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3312 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3313 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3314 if(extra) {
3315 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3316 extra);
3317 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3318 len += extra;
3320 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3321 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3322 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3323 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3324 len += sizeof(SLTG_OtherTypeInfo);
3325 ptr += len;
3328 pAfterOTIBlks = ptr;
3330 /* Skip this WORD and get the next DWORD */
3331 len = *(DWORD*)(pAfterOTIBlks + 2);
3333 /* Now add this to pLibBLk look at what we're pointing at and
3334 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3335 dust and we should be pointing at the beginning of the name
3336 table */
3338 pNameTable = (char*)pLibBlk + len;
3340 switch(*(WORD*)pNameTable) {
3341 case 0xffff:
3342 break;
3343 case 0x0200:
3344 pNameTable += 0x20;
3345 break;
3346 default:
3347 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3348 break;
3351 pNameTable += 0x216;
3353 pNameTable += 2;
3355 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3357 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3360 /* Hopefully we now have enough ptrs set up to actually read in
3361 some TypeInfos. It's not clear which order to do them in, so
3362 I'll just follow the links along the BlkEntry chain and read
3363 them in the order in which they are in the file */
3365 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3367 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3368 pBlkEntry[order].next != 0;
3369 order = pBlkEntry[order].next - 1, i++) {
3371 SLTG_TypeInfoHeader *pTIHeader;
3372 SLTG_TypeInfoTail *pTITail;
3373 SLTG_MemberHeader *pMemHeader;
3375 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3376 pOtherTypeInfoBlks[i].index_name)) {
3377 FIXME("Index strings don't match\n");
3378 return NULL;
3381 pTIHeader = pBlk;
3382 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3383 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3384 return NULL;
3386 TRACE("pTIHeader->res06 = %x, pTIHeader->res0e = %x, pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3387 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3389 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3390 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3391 (*ppTypeInfoImpl)->index = i;
3392 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3393 pOtherTypeInfoBlks[i].name_offs +
3394 pNameTable);
3395 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3396 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3397 sizeof(GUID));
3398 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3399 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3400 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3401 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3402 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3404 if((pTIHeader->typeflags1 & 7) != 2)
3405 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3406 if(pTIHeader->typeflags3 != 2)
3407 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3409 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3410 debugstr_w((*ppTypeInfoImpl)->Name),
3411 typekind_desc[pTIHeader->typekind],
3412 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3413 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3415 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3417 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3419 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3420 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3421 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3423 switch(pTIHeader->typekind) {
3424 case TKIND_ENUM:
3425 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3426 pTIHeader, pTITail);
3427 break;
3429 case TKIND_RECORD:
3430 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3431 pTIHeader, pTITail);
3432 break;
3434 case TKIND_INTERFACE:
3435 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3436 pTIHeader, pTITail);
3437 break;
3439 case TKIND_COCLASS:
3440 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3441 pTIHeader, pTITail);
3442 break;
3444 case TKIND_ALIAS:
3445 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3446 pTIHeader, pTITail);
3447 break;
3449 case TKIND_DISPATCH:
3450 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3451 pTIHeader, pTITail);
3452 break;
3454 case TKIND_MODULE:
3455 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3456 pTIHeader, pTITail);
3457 break;
3459 default:
3460 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3461 break;
3465 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3466 but we've already set those */
3467 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3468 X(06);
3469 X(16);
3470 X(18);
3471 X(1a);
3472 X(1e);
3473 X(24);
3474 X(26);
3475 X(2a);
3476 X(2c);
3477 X(2e);
3478 X(30);
3479 X(32);
3480 X(34);
3482 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3483 pBlk = (char*)pBlk + pBlkEntry[order].len;
3486 if(i != pTypeLibImpl->TypeInfoCount) {
3487 FIXME("Somehow processed %d TypeInfos\n", i);
3488 return NULL;
3491 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3492 return (ITypeLib2*)pTypeLibImpl;
3495 /* ITypeLib::QueryInterface
3497 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3498 ITypeLib2 * iface,
3499 REFIID riid,
3500 VOID **ppvObject)
3502 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3504 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3506 *ppvObject=NULL;
3507 if(IsEqualIID(riid, &IID_IUnknown) ||
3508 IsEqualIID(riid,&IID_ITypeLib)||
3509 IsEqualIID(riid,&IID_ITypeLib2))
3511 *ppvObject = This;
3514 if(*ppvObject)
3516 ITypeLib2_AddRef(iface);
3517 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3518 return S_OK;
3520 TRACE("-- Interface: E_NOINTERFACE\n");
3521 return E_NOINTERFACE;
3524 /* ITypeLib::AddRef
3526 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3528 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3529 ULONG ref = InterlockedIncrement(&This->ref);
3531 TRACE("(%p)->ref was %u\n",This, ref - 1);
3533 return ref;
3536 /* ITypeLib::Release
3538 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3540 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3541 ULONG ref = InterlockedDecrement(&This->ref);
3543 TRACE("(%p)->(%u)\n",This, ref);
3545 if (!ref)
3547 TLBImpLib *pImpLib, *pImpLibNext;
3548 TLBCustData *pCustData, *pCustDataNext;
3549 int i;
3551 /* remove cache entry */
3552 if(This->path)
3554 TRACE("removing from cache list\n");
3555 EnterCriticalSection(&cache_section);
3556 if (This->next) This->next->prev = This->prev;
3557 if (This->prev) This->prev->next = This->next;
3558 else tlb_cache_first = This->next;
3559 LeaveCriticalSection(&cache_section);
3560 HeapFree(GetProcessHeap(), 0, This->path);
3562 TRACE(" destroying ITypeLib(%p)\n",This);
3564 if (This->Name)
3566 SysFreeString(This->Name);
3567 This->Name = NULL;
3570 if (This->DocString)
3572 SysFreeString(This->DocString);
3573 This->DocString = NULL;
3576 if (This->HelpFile)
3578 SysFreeString(This->HelpFile);
3579 This->HelpFile = NULL;
3582 if (This->HelpStringDll)
3584 SysFreeString(This->HelpStringDll);
3585 This->HelpStringDll = NULL;
3588 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
3590 VariantClear(&pCustData->data);
3592 pCustDataNext = pCustData->next;
3593 TLB_Free(pCustData);
3596 for (i = 0; i < This->ctTypeDesc; i++)
3597 if (This->pTypeDesc[i].vt == VT_CARRAY)
3598 TLB_Free(This->pTypeDesc[i].u.lpadesc);
3600 TLB_Free(This->pTypeDesc);
3602 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
3604 if (pImpLib->pImpTypeLib)
3605 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
3606 TLB_Free(pImpLib->name);
3608 pImpLibNext = pImpLib->next;
3609 TLB_Free(pImpLib);
3612 if (This->pTypeInfo) /* can be NULL */
3613 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3614 HeapFree(GetProcessHeap(),0,This);
3615 return 0;
3618 return ref;
3621 /* ITypeLib::GetTypeInfoCount
3623 * Returns the number of type descriptions in the type library
3625 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3627 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3628 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3629 return This->TypeInfoCount;
3632 /* ITypeLib::GetTypeInfo
3634 * retrieves the specified type description in the library.
3636 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3637 ITypeLib2 *iface,
3638 UINT index,
3639 ITypeInfo **ppTInfo)
3641 int i;
3643 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3644 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3646 TRACE("(%p)->(index=%d)\n", This, index);
3648 if (!ppTInfo) return E_INVALIDARG;
3650 /* search element n in list */
3651 for(i=0; i < index; i++)
3653 pTypeInfo = pTypeInfo->next;
3654 if (!pTypeInfo)
3656 TRACE("-- element not found\n");
3657 return TYPE_E_ELEMENTNOTFOUND;
3661 *ppTInfo = (ITypeInfo *) pTypeInfo;
3663 ITypeInfo_AddRef(*ppTInfo);
3664 TRACE("-- found (%p)\n",*ppTInfo);
3665 return S_OK;
3669 /* ITypeLibs::GetTypeInfoType
3671 * Retrieves the type of a type description.
3673 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3674 ITypeLib2 *iface,
3675 UINT index,
3676 TYPEKIND *pTKind)
3678 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3679 int i;
3680 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3682 if ((ITypeLib2_fnGetTypeInfoCount(iface) < index + 1) || (index < 0))
3683 return TYPE_E_ELEMENTNOTFOUND;
3685 TRACE("(%p) index %d\n", This, index);
3687 if(!pTKind) return E_INVALIDARG;
3689 /* search element n in list */
3690 for(i=0; i < index; i++)
3692 if(!pTInfo)
3694 TRACE("-- element not found\n");
3695 return TYPE_E_ELEMENTNOTFOUND;
3697 pTInfo = pTInfo->next;
3700 *pTKind = pTInfo->TypeAttr.typekind;
3701 TRACE("-- found Type (%d)\n", *pTKind);
3702 return S_OK;
3705 /* ITypeLib::GetTypeInfoOfGuid
3707 * Retrieves the type description that corresponds to the specified GUID.
3710 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3711 ITypeLib2 *iface,
3712 REFGUID guid,
3713 ITypeInfo **ppTInfo)
3715 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3716 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3718 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3720 if (!pTypeInfo)
3722 WARN("-- element not found\n");
3723 return TYPE_E_ELEMENTNOTFOUND;
3726 /* search linked list for guid */
3727 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3729 pTypeInfo = pTypeInfo->next;
3731 if (!pTypeInfo)
3733 /* end of list reached */
3734 WARN("-- element not found\n");
3735 return TYPE_E_ELEMENTNOTFOUND;
3739 TRACE("-- found (%p, %s)\n",
3740 pTypeInfo,
3741 debugstr_w(pTypeInfo->Name));
3743 *ppTInfo = (ITypeInfo*)pTypeInfo;
3744 ITypeInfo_AddRef(*ppTInfo);
3745 return S_OK;
3748 /* ITypeLib::GetLibAttr
3750 * Retrieves the structure that contains the library's attributes.
3753 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3754 ITypeLib2 *iface,
3755 LPTLIBATTR *ppTLibAttr)
3757 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3758 TRACE("(%p)\n",This);
3759 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3760 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3761 return S_OK;
3764 /* ITypeLib::GetTypeComp
3766 * Enables a client compiler to bind to a library's types, variables,
3767 * constants, and global functions.
3770 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3771 ITypeLib2 *iface,
3772 ITypeComp **ppTComp)
3774 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3776 TRACE("(%p)->(%p)\n",This,ppTComp);
3777 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3778 ITypeComp_AddRef(*ppTComp);
3780 return S_OK;
3783 /* ITypeLib::GetDocumentation
3785 * Retrieves the library's documentation string, the complete Help file name
3786 * and path, and the context identifier for the library Help topic in the Help
3787 * file.
3789 * On a successful return all non-null BSTR pointers will have been set,
3790 * possibly to NULL.
3792 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3793 ITypeLib2 *iface,
3794 INT index,
3795 BSTR *pBstrName,
3796 BSTR *pBstrDocString,
3797 DWORD *pdwHelpContext,
3798 BSTR *pBstrHelpFile)
3800 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3802 HRESULT result = E_INVALIDARG;
3804 ITypeInfo *pTInfo;
3807 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3808 This, index,
3809 pBstrName, pBstrDocString,
3810 pdwHelpContext, pBstrHelpFile);
3812 if(index<0)
3814 /* documentation for the typelib */
3815 if(pBstrName)
3817 if (This->Name)
3819 if(!(*pBstrName = SysAllocString(This->Name)))
3820 goto memerr1;
3822 else
3823 *pBstrName = NULL;
3825 if(pBstrDocString)
3827 if (This->DocString)
3829 if(!(*pBstrDocString = SysAllocString(This->DocString)))
3830 goto memerr2;
3832 else if (This->Name)
3834 if(!(*pBstrDocString = SysAllocString(This->Name)))
3835 goto memerr2;
3837 else
3838 *pBstrDocString = NULL;
3840 if(pdwHelpContext)
3842 *pdwHelpContext = This->dwHelpContext;
3844 if(pBstrHelpFile)
3846 if (This->HelpFile)
3848 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
3849 goto memerr3;
3851 else
3852 *pBstrHelpFile = NULL;
3855 result = S_OK;
3857 else
3859 /* for a typeinfo */
3860 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3862 if(SUCCEEDED(result))
3864 result = ITypeInfo_GetDocumentation(pTInfo,
3865 MEMBERID_NIL,
3866 pBstrName,
3867 pBstrDocString,
3868 pdwHelpContext, pBstrHelpFile);
3870 ITypeInfo_Release(pTInfo);
3873 return result;
3874 memerr3:
3875 if (pBstrDocString) SysFreeString (*pBstrDocString);
3876 memerr2:
3877 if (pBstrName) SysFreeString (*pBstrName);
3878 memerr1:
3879 return STG_E_INSUFFICIENTMEMORY;
3882 /* ITypeLib::IsName
3884 * Indicates whether a passed-in string contains the name of a type or member
3885 * described in the library.
3888 static HRESULT WINAPI ITypeLib2_fnIsName(
3889 ITypeLib2 *iface,
3890 LPOLESTR szNameBuf,
3891 ULONG lHashVal,
3892 BOOL *pfName)
3894 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3895 ITypeInfoImpl *pTInfo;
3896 TLBFuncDesc *pFInfo;
3897 TLBVarDesc *pVInfo;
3898 int i;
3899 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3901 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3902 pfName);
3904 *pfName=TRUE;
3905 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3906 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3907 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3908 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3909 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3910 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3911 goto ITypeLib2_fnIsName_exit;
3913 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3914 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3917 *pfName=FALSE;
3919 ITypeLib2_fnIsName_exit:
3920 TRACE("(%p)slow! search for %s: %s found!\n", This,
3921 debugstr_w(szNameBuf), *pfName?"NOT":"");
3923 return S_OK;
3926 /* ITypeLib::FindName
3928 * Finds occurrences of a type description in a type library. This may be used
3929 * to quickly verify that a name exists in a type library.
3932 static HRESULT WINAPI ITypeLib2_fnFindName(
3933 ITypeLib2 *iface,
3934 LPOLESTR szNameBuf,
3935 ULONG lHashVal,
3936 ITypeInfo **ppTInfo,
3937 MEMBERID *rgMemId,
3938 UINT16 *pcFound)
3940 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3941 ITypeInfoImpl *pTInfo;
3942 TLBFuncDesc *pFInfo;
3943 TLBVarDesc *pVInfo;
3944 int i,j = 0;
3945 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3947 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3948 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3949 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3950 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3951 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
3952 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3953 goto ITypeLib2_fnFindName_exit;
3956 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3957 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3958 continue;
3959 ITypeLib2_fnFindName_exit:
3960 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3961 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3962 j++;
3964 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3965 This, *pcFound, debugstr_w(szNameBuf), j);
3967 *pcFound=j;
3969 return S_OK;
3972 /* ITypeLib::ReleaseTLibAttr
3974 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3977 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3978 ITypeLib2 *iface,
3979 TLIBATTR *pTLibAttr)
3981 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3982 TRACE("freeing (%p)\n",This);
3983 HeapFree(GetProcessHeap(),0,pTLibAttr);
3987 /* ITypeLib2::GetCustData
3989 * gets the custom data
3991 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3992 ITypeLib2 * iface,
3993 REFGUID guid,
3994 VARIANT *pVarVal)
3996 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3997 TLBCustData *pCData;
3999 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4001 if( IsEqualIID(guid, &pCData->guid)) break;
4004 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4006 if(pCData)
4008 VariantInit( pVarVal);
4009 VariantCopy( pVarVal, &pCData->data);
4010 return S_OK;
4012 return E_INVALIDARG; /* FIXME: correct? */
4015 /* ITypeLib2::GetLibStatistics
4017 * Returns statistics about a type library that are required for efficient
4018 * sizing of hash tables.
4021 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4022 ITypeLib2 * iface,
4023 ULONG *pcUniqueNames,
4024 ULONG *pcchUniqueNames)
4026 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4028 FIXME("(%p): stub!\n", This);
4030 if(pcUniqueNames) *pcUniqueNames=1;
4031 if(pcchUniqueNames) *pcchUniqueNames=1;
4032 return S_OK;
4035 /* ITypeLib2::GetDocumentation2
4037 * Retrieves the library's documentation string, the complete Help file name
4038 * and path, the localization context to use, and the context ID for the
4039 * library Help topic in the Help file.
4042 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4043 ITypeLib2 * iface,
4044 INT index,
4045 LCID lcid,
4046 BSTR *pbstrHelpString,
4047 DWORD *pdwHelpStringContext,
4048 BSTR *pbstrHelpStringDll)
4050 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4051 HRESULT result;
4052 ITypeInfo *pTInfo;
4054 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4056 /* the help string should be obtained from the helpstringdll,
4057 * using the _DLLGetDocumentation function, based on the supplied
4058 * lcid. Nice to do sometime...
4060 if(index<0)
4062 /* documentation for the typelib */
4063 if(pbstrHelpString)
4064 *pbstrHelpString=SysAllocString(This->DocString);
4065 if(pdwHelpStringContext)
4066 *pdwHelpStringContext=This->dwHelpContext;
4067 if(pbstrHelpStringDll)
4068 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4070 result = S_OK;
4072 else
4074 /* for a typeinfo */
4075 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4077 if(SUCCEEDED(result))
4079 ITypeInfo2 * pTInfo2;
4080 result = ITypeInfo_QueryInterface(pTInfo,
4081 &IID_ITypeInfo2,
4082 (LPVOID*) &pTInfo2);
4084 if(SUCCEEDED(result))
4086 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4087 MEMBERID_NIL,
4088 lcid,
4089 pbstrHelpString,
4090 pdwHelpStringContext,
4091 pbstrHelpStringDll);
4093 ITypeInfo2_Release(pTInfo2);
4096 ITypeInfo_Release(pTInfo);
4099 return result;
4102 /* ITypeLib2::GetAllCustData
4104 * Gets all custom data items for the library.
4107 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4108 ITypeLib2 * iface,
4109 CUSTDATA *pCustData)
4111 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4112 TLBCustData *pCData;
4113 int i;
4114 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4115 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4116 if(pCustData->prgCustData ){
4117 pCustData->cCustData=This->ctCustData;
4118 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4119 pCustData->prgCustData[i].guid=pCData->guid;
4120 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4122 }else{
4123 ERR(" OUT OF MEMORY!\n");
4124 return E_OUTOFMEMORY;
4126 return S_OK;
4129 static const ITypeLib2Vtbl tlbvt = {
4130 ITypeLib2_fnQueryInterface,
4131 ITypeLib2_fnAddRef,
4132 ITypeLib2_fnRelease,
4133 ITypeLib2_fnGetTypeInfoCount,
4134 ITypeLib2_fnGetTypeInfo,
4135 ITypeLib2_fnGetTypeInfoType,
4136 ITypeLib2_fnGetTypeInfoOfGuid,
4137 ITypeLib2_fnGetLibAttr,
4138 ITypeLib2_fnGetTypeComp,
4139 ITypeLib2_fnGetDocumentation,
4140 ITypeLib2_fnIsName,
4141 ITypeLib2_fnFindName,
4142 ITypeLib2_fnReleaseTLibAttr,
4144 ITypeLib2_fnGetCustData,
4145 ITypeLib2_fnGetLibStatistics,
4146 ITypeLib2_fnGetDocumentation2,
4147 ITypeLib2_fnGetAllCustData
4151 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4153 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4155 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4158 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4160 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4162 return ITypeLib2_AddRef((ITypeLib2 *)This);
4165 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4167 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4169 return ITypeLib2_Release((ITypeLib2 *)This);
4172 static HRESULT WINAPI ITypeLibComp_fnBind(
4173 ITypeComp * iface,
4174 OLECHAR * szName,
4175 ULONG lHash,
4176 WORD wFlags,
4177 ITypeInfo ** ppTInfo,
4178 DESCKIND * pDescKind,
4179 BINDPTR * pBindPtr)
4181 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4182 ITypeInfoImpl *pTypeInfo;
4184 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4186 *pDescKind = DESCKIND_NONE;
4187 pBindPtr->lptcomp = NULL;
4188 *ppTInfo = NULL;
4190 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4192 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4194 /* FIXME: check wFlags here? */
4195 /* FIXME: we should use a hash table to look this info up using lHash
4196 * instead of an O(n) search */
4197 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4198 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4200 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4202 *pDescKind = DESCKIND_TYPECOMP;
4203 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4204 ITypeComp_AddRef(pBindPtr->lptcomp);
4205 TRACE("module or enum: %s\n", debugstr_w(szName));
4206 return S_OK;
4210 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4211 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4213 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4214 HRESULT hr;
4216 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4217 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4219 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4220 return S_OK;
4224 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4225 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4227 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4228 HRESULT hr;
4229 ITypeInfo *subtypeinfo;
4230 BINDPTR subbindptr;
4231 DESCKIND subdesckind;
4233 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4234 &subtypeinfo, &subdesckind, &subbindptr);
4235 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4237 TYPEDESC tdesc_appobject =
4240 (TYPEDESC *)pTypeInfo->hreftype
4242 VT_USERDEFINED
4244 const VARDESC vardesc_appobject =
4246 -2, /* memid */
4247 NULL, /* lpstrSchema */
4249 0 /* oInst */
4252 /* ELEMDESC */
4254 /* TYPEDESC */
4256 &tdesc_appobject
4258 VT_PTR
4261 0, /* wVarFlags */
4262 VAR_STATIC /* varkind */
4265 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4267 /* cleanup things filled in by Bind call so we can put our
4268 * application object data in there instead */
4269 switch (subdesckind)
4271 case DESCKIND_FUNCDESC:
4272 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4273 break;
4274 case DESCKIND_VARDESC:
4275 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4276 break;
4277 default:
4278 break;
4280 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4282 if (pTypeInfo->hreftype == -1)
4283 FIXME("no hreftype for interface %p\n", pTypeInfo);
4285 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4286 if (FAILED(hr))
4287 return hr;
4289 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4290 *ppTInfo = (ITypeInfo *)pTypeInfo;
4291 ITypeInfo_AddRef(*ppTInfo);
4292 return S_OK;
4297 TRACE("name not found %s\n", debugstr_w(szName));
4298 return S_OK;
4301 static HRESULT WINAPI ITypeLibComp_fnBindType(
4302 ITypeComp * iface,
4303 OLECHAR * szName,
4304 ULONG lHash,
4305 ITypeInfo ** ppTInfo,
4306 ITypeComp ** ppTComp)
4308 FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4309 return E_NOTIMPL;
4312 static const ITypeCompVtbl tlbtcvt =
4315 ITypeLibComp_fnQueryInterface,
4316 ITypeLibComp_fnAddRef,
4317 ITypeLibComp_fnRelease,
4319 ITypeLibComp_fnBind,
4320 ITypeLibComp_fnBindType
4323 /*================== ITypeInfo(2) Methods ===================================*/
4324 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4326 ITypeInfoImpl * pTypeInfoImpl;
4328 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4329 if (pTypeInfoImpl)
4331 pTypeInfoImpl->lpVtbl = &tinfvt;
4332 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4333 pTypeInfoImpl->ref=1;
4334 pTypeInfoImpl->hreftype = -1;
4335 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4336 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4338 TRACE("(%p)\n", pTypeInfoImpl);
4339 return (ITypeInfo2*) pTypeInfoImpl;
4342 /* ITypeInfo::QueryInterface
4344 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4345 ITypeInfo2 *iface,
4346 REFIID riid,
4347 VOID **ppvObject)
4349 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4351 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4353 *ppvObject=NULL;
4354 if(IsEqualIID(riid, &IID_IUnknown) ||
4355 IsEqualIID(riid,&IID_ITypeInfo)||
4356 IsEqualIID(riid,&IID_ITypeInfo2))
4357 *ppvObject = This;
4359 if(*ppvObject){
4360 ITypeInfo_AddRef(iface);
4361 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4362 return S_OK;
4364 TRACE("-- Interface: E_NOINTERFACE\n");
4365 return E_NOINTERFACE;
4368 /* ITypeInfo::AddRef
4370 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4372 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4373 ULONG ref = InterlockedIncrement(&This->ref);
4375 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4377 TRACE("(%p)->ref is %u\n",This, ref);
4378 return ref;
4381 /* ITypeInfo::Release
4383 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4385 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4386 ULONG ref = InterlockedDecrement(&This->ref);
4388 TRACE("(%p)->(%u)\n",This, ref);
4390 if (ref) {
4391 /* We don't release ITypeLib when ref=0 because
4392 it means that function is called by ITypeLib2_Release */
4393 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4394 } else {
4395 TLBFuncDesc *pFInfo, *pFInfoNext;
4396 TLBVarDesc *pVInfo, *pVInfoNext;
4397 TLBImplType *pImpl, *pImplNext;
4398 TLBRefType *pRefType,*pRefTypeNext;
4399 TLBCustData *pCustData, *pCustDataNext;
4401 TRACE("destroying ITypeInfo(%p)\n",This);
4403 if (This->no_free_data)
4404 goto finish_free;
4406 if (This->Name)
4408 SysFreeString(This->Name);
4409 This->Name = 0;
4412 if (This->DocString)
4414 SysFreeString(This->DocString);
4415 This->DocString = 0;
4418 if (This->DllName)
4420 SysFreeString(This->DllName);
4421 This->DllName = 0;
4424 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4426 UINT i;
4427 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4429 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4430 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4432 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4433 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4435 SysFreeString(pFInfo->pParamDesc[i].Name);
4437 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4438 TLB_Free(pFInfo->pParamDesc);
4439 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
4441 VariantClear(&pCustData->data);
4443 pCustDataNext = pCustData->next;
4444 TLB_Free(pCustData);
4446 if (HIWORD(pFInfo->Entry) != 0 && pFInfo->Entry != (BSTR)-1)
4447 SysFreeString(pFInfo->Entry);
4448 SysFreeString(pFInfo->HelpString);
4449 SysFreeString(pFInfo->Name);
4451 pFInfoNext = pFInfo->next;
4452 TLB_Free(pFInfo);
4454 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
4456 if (pVInfo->vardesc.varkind == VAR_CONST)
4458 VariantClear(pVInfo->vardesc.u.lpvarValue);
4459 TLB_Free(pVInfo->vardesc.u.lpvarValue);
4461 SysFreeString(pVInfo->Name);
4462 pVInfoNext = pVInfo->next;
4463 TLB_Free(pVInfo);
4465 for(pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
4467 for (pCustData = pImpl->pCustData; pCustData; pCustData = pCustDataNext)
4469 VariantClear(&pCustData->data);
4471 pCustDataNext = pCustData->next;
4472 TLB_Free(pCustData);
4474 pImplNext = pImpl->next;
4475 TLB_Free(pImpl);
4477 for(pRefType = This->reflist; pRefType; pRefType = pRefTypeNext)
4479 pRefTypeNext = pRefType->next;
4480 TLB_Free(pRefType);
4482 TLB_Free(This->pCustData);
4484 finish_free:
4485 if (This->next)
4487 ITypeInfo_Release((ITypeInfo*)This->next);
4490 HeapFree(GetProcessHeap(),0,This);
4491 return 0;
4493 return ref;
4496 /* ITypeInfo::GetTypeAttr
4498 * Retrieves a TYPEATTR structure that contains the attributes of the type
4499 * description.
4502 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4503 LPTYPEATTR *ppTypeAttr)
4505 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4506 SIZE_T size;
4508 TRACE("(%p)\n",This);
4510 size = sizeof(**ppTypeAttr);
4511 if (This->TypeAttr.typekind == TKIND_ALIAS)
4512 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4514 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4515 if (!*ppTypeAttr)
4516 return E_OUTOFMEMORY;
4518 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4520 if (This->TypeAttr.typekind == TKIND_ALIAS)
4521 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4522 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4524 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4525 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4526 funcs */
4527 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4528 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4530 return S_OK;
4533 /* ITypeInfo::GetTypeComp
4535 * Retrieves the ITypeComp interface for the type description, which enables a
4536 * client compiler to bind to the type description's members.
4539 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4540 ITypeComp * *ppTComp)
4542 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4544 TRACE("(%p)->(%p)\n", This, ppTComp);
4546 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4547 ITypeComp_AddRef(*ppTComp);
4548 return S_OK;
4551 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4553 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4554 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4555 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4556 return size;
4559 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4561 memcpy(dest, src, sizeof(ELEMDESC));
4562 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4563 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4565 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4566 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4567 *buffer += sizeof(PARAMDESCEX);
4568 memcpy(pparamdescex_dest, pparamdescex_src, sizeof(PARAMDESCEX));
4569 VariantInit(&pparamdescex_dest->varDefaultValue);
4570 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4571 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4573 else
4574 dest->u.paramdesc.pparamdescex = NULL;
4575 return S_OK;
4578 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4580 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4581 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4584 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4586 FUNCDESC *dest;
4587 char *buffer;
4588 SIZE_T size = sizeof(*src);
4589 SHORT i;
4590 HRESULT hr;
4592 size += sizeof(*src->lprgscode) * src->cScodes;
4593 size += TLB_SizeElemDesc(&src->elemdescFunc);
4594 for (i = 0; i < src->cParams; i++)
4596 size += sizeof(ELEMDESC);
4597 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4600 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4601 if (!dest) return E_OUTOFMEMORY;
4603 memcpy(dest, src, sizeof(FUNCDESC));
4604 buffer = (char *)(dest + 1);
4606 dest->lprgscode = (SCODE *)buffer;
4607 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4608 buffer += sizeof(*src->lprgscode) * src->cScodes;
4610 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4611 if (FAILED(hr))
4613 SysFreeString((BSTR)dest);
4614 return hr;
4617 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4618 buffer += sizeof(ELEMDESC) * src->cParams;
4619 for (i = 0; i < src->cParams; i++)
4621 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4622 if (FAILED(hr))
4623 break;
4625 if (FAILED(hr))
4627 /* undo the above actions */
4628 for (i = i - 1; i >= 0; i--)
4629 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4630 TLB_FreeElemDesc(&dest->elemdescFunc);
4631 SysFreeString((BSTR)dest);
4632 return hr;
4635 /* special treatment for dispinterfaces: this makes functions appear
4636 * to return their [retval] value when it is really returning an
4637 * HRESULT */
4638 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4640 if (dest->cParams &&
4641 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4643 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4644 if (elemdesc->tdesc.vt != VT_PTR)
4646 ERR("elemdesc should have started with VT_PTR instead of:\n");
4647 if (ERR_ON(ole))
4648 dump_ELEMDESC(elemdesc);
4649 return E_UNEXPECTED;
4652 /* copy last parameter to the return value. we are using a flat
4653 * buffer so there is no danger of leaking memory in
4654 * elemdescFunc */
4655 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4657 /* remove the last parameter */
4658 dest->cParams--;
4660 else
4661 /* otherwise this function is made to appear to have no return
4662 * value */
4663 dest->elemdescFunc.tdesc.vt = VT_VOID;
4667 *dest_ptr = dest;
4668 return S_OK;
4671 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4673 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4674 const TLBFuncDesc *pFDesc;
4675 int i;
4677 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4680 if (pFDesc)
4682 *ppFuncDesc = &pFDesc->funcdesc;
4683 return S_OK;
4686 return E_INVALIDARG;
4689 /* internal function to make the inherited interfaces' methods appear
4690 * part of the interface */
4691 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
4692 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs)
4694 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4695 HRESULT hr;
4696 UINT i;
4697 UINT implemented_funcs = 0;
4699 if (funcs)
4700 *funcs = 0;
4702 for (i = 0; i < This->TypeAttr.cImplTypes; i++)
4704 HREFTYPE href;
4705 ITypeInfo *pSubTypeInfo;
4706 UINT sub_funcs;
4708 hr = ITypeInfo_GetRefTypeOfImplType(iface, i, &href);
4709 if (FAILED(hr))
4710 return hr;
4711 hr = ITypeInfo_GetRefTypeInfo(iface, href, &pSubTypeInfo);
4712 if (FAILED(hr))
4713 return hr;
4715 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
4716 index,
4717 ppFuncDesc,
4718 &sub_funcs);
4719 implemented_funcs += sub_funcs;
4720 ITypeInfo_Release(pSubTypeInfo);
4721 if (SUCCEEDED(hr))
4722 return hr;
4725 if (funcs)
4726 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
4728 if (index < implemented_funcs)
4729 return E_INVALIDARG;
4730 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
4731 ppFuncDesc);
4734 /* ITypeInfo::GetFuncDesc
4736 * Retrieves the FUNCDESC structure that contains information about a
4737 * specified function.
4740 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4741 LPFUNCDESC *ppFuncDesc)
4743 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4744 const FUNCDESC *internal_funcdesc;
4745 HRESULT hr;
4747 TRACE("(%p) index %d\n", This, index);
4749 if ((This->TypeAttr.typekind == TKIND_DISPATCH) &&
4750 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
4751 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
4752 &internal_funcdesc, NULL);
4753 else
4754 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
4755 &internal_funcdesc);
4756 if (FAILED(hr))
4758 WARN("description for function %d not found\n", index);
4759 return hr;
4762 return TLB_AllocAndInitFuncDesc(
4763 internal_funcdesc,
4764 ppFuncDesc,
4765 This->TypeAttr.typekind == TKIND_DISPATCH);
4768 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
4770 VARDESC *dest;
4771 char *buffer;
4772 SIZE_T size = sizeof(*src);
4773 HRESULT hr;
4775 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
4776 if (src->varkind == VAR_CONST)
4777 size += sizeof(VARIANT);
4778 size += TLB_SizeElemDesc(&src->elemdescVar);
4780 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
4781 if (!dest) return E_OUTOFMEMORY;
4783 *dest = *src;
4784 buffer = (char *)(dest + 1);
4785 if (src->lpstrSchema)
4787 int len;
4788 dest->lpstrSchema = (LPOLESTR)buffer;
4789 len = strlenW(src->lpstrSchema);
4790 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
4791 buffer += (len + 1) * sizeof(WCHAR);
4794 if (src->varkind == VAR_CONST)
4796 HRESULT hr;
4798 dest->u.lpvarValue = (VARIANT *)buffer;
4799 *dest->u.lpvarValue = *src->u.lpvarValue;
4800 buffer += sizeof(VARIANT);
4801 VariantInit(dest->u.lpvarValue);
4802 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
4803 if (FAILED(hr))
4805 SysFreeString((BSTR)dest_ptr);
4806 return hr;
4809 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
4810 if (FAILED(hr))
4812 if (src->varkind == VAR_CONST)
4813 VariantClear(dest->u.lpvarValue);
4814 SysFreeString((BSTR)dest);
4815 return hr;
4817 *dest_ptr = dest;
4818 return S_OK;
4821 /* ITypeInfo::GetVarDesc
4823 * Retrieves a VARDESC structure that describes the specified variable.
4826 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4827 LPVARDESC *ppVarDesc)
4829 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4830 int i;
4831 const TLBVarDesc *pVDesc;
4833 TRACE("(%p) index %d\n", This, index);
4835 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4838 if (pVDesc)
4839 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
4841 return E_INVALIDARG;
4844 /* ITypeInfo_GetNames
4846 * Retrieves the variable with the specified member ID (or the name of the
4847 * property or method and its parameters) that correspond to the specified
4848 * function ID.
4850 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4851 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4853 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4854 const TLBFuncDesc *pFDesc;
4855 const TLBVarDesc *pVDesc;
4856 int i;
4857 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
4858 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4859 if(pFDesc)
4861 /* function found, now return function and parameter names */
4862 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4864 if(!i)
4865 *rgBstrNames=SysAllocString(pFDesc->Name);
4866 else
4867 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4869 *pcNames=i;
4871 else
4873 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4874 if(pVDesc)
4876 *rgBstrNames=SysAllocString(pVDesc->Name);
4877 *pcNames=1;
4879 else
4881 if(This->TypeAttr.cImplTypes &&
4882 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4883 /* recursive search */
4884 ITypeInfo *pTInfo;
4885 HRESULT result;
4886 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4887 &pTInfo);
4888 if(SUCCEEDED(result))
4890 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4891 ITypeInfo_Release(pTInfo);
4892 return result;
4894 WARN("Could not search inherited interface!\n");
4896 else
4898 WARN("no names found\n");
4900 *pcNames=0;
4901 return TYPE_E_ELEMENTNOTFOUND;
4904 return S_OK;
4908 /* ITypeInfo::GetRefTypeOfImplType
4910 * If a type description describes a COM class, it retrieves the type
4911 * description of the implemented interface types. For an interface,
4912 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4913 * if any exist.
4916 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4917 ITypeInfo2 *iface,
4918 UINT index,
4919 HREFTYPE *pRefType)
4921 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4922 int i;
4923 HRESULT hr = S_OK;
4924 const TLBImplType *pImpl = This->impltypelist;
4926 TRACE("(%p) index %d\n", This, index);
4927 if (TRACE_ON(ole)) dump_TypeInfo(This);
4929 if(index==(UINT)-1)
4931 /* only valid on dual interfaces;
4932 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4934 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4936 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4937 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4939 *pRefType = -1;
4941 else
4943 hr = TYPE_E_ELEMENTNOTFOUND;
4946 else
4948 /* get element n from linked list */
4949 for(i=0; pImpl && i<index; i++)
4951 pImpl = pImpl->next;
4954 if (pImpl)
4955 *pRefType = pImpl->hRef;
4956 else
4957 hr = TYPE_E_ELEMENTNOTFOUND;
4960 if(TRACE_ON(ole))
4962 if(SUCCEEDED(hr))
4963 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
4964 else
4965 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
4968 return hr;
4971 /* ITypeInfo::GetImplTypeFlags
4973 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4974 * or base interface in a type description.
4976 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4977 UINT index, INT *pImplTypeFlags)
4979 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4980 int i;
4981 TLBImplType *pImpl;
4983 TRACE("(%p) index %d\n", This, index);
4984 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4985 i++, pImpl=pImpl->next)
4987 if(i==index && pImpl){
4988 *pImplTypeFlags=pImpl->implflags;
4989 return S_OK;
4991 *pImplTypeFlags=0;
4992 return TYPE_E_ELEMENTNOTFOUND;
4995 /* GetIDsOfNames
4996 * Maps between member names and member IDs, and parameter names and
4997 * parameter IDs.
4999 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5000 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5002 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5003 const TLBFuncDesc *pFDesc;
5004 const TLBVarDesc *pVDesc;
5005 HRESULT ret=S_OK;
5006 int i;
5008 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5009 cNames);
5011 /* init out parameters in case of failure */
5012 for (i = 0; i < cNames; i++)
5013 pMemId[i] = MEMBERID_NIL;
5015 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5016 int j;
5017 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5018 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5019 for(i=1; i < cNames; i++){
5020 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5021 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5022 break;
5023 if( j<pFDesc->funcdesc.cParams)
5024 pMemId[i]=j;
5025 else
5026 ret=DISP_E_UNKNOWNNAME;
5028 TRACE("-- 0x%08x\n", ret);
5029 return ret;
5032 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5033 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5034 if(cNames) *pMemId=pVDesc->vardesc.memid;
5035 return ret;
5038 /* not found, see if it can be found in an inherited interface */
5039 if(This->TypeAttr.cImplTypes) {
5040 /* recursive search */
5041 ITypeInfo *pTInfo;
5042 ret=ITypeInfo_GetRefTypeInfo(iface,
5043 This->impltypelist->hRef, &pTInfo);
5044 if(SUCCEEDED(ret)){
5045 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5046 ITypeInfo_Release(pTInfo);
5047 return ret;
5049 WARN("Could not search inherited interface!\n");
5050 } else
5051 WARN("no names found\n");
5052 return DISP_E_UNKNOWNNAME;
5055 /* ITypeInfo::Invoke
5057 * Invokes a method, or accesses a property of an object, that implements the
5058 * interface described by the type description.
5060 DWORD
5061 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5062 DWORD res;
5064 if (TRACE_ON(ole)) {
5065 int i;
5066 TRACE("Calling %p(",func);
5067 for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
5068 TRACE(")\n");
5071 switch (callconv) {
5072 case CC_STDCALL:
5074 switch (nrargs) {
5075 case 0:
5076 res = func();
5077 break;
5078 case 1:
5079 res = func(args[0]);
5080 break;
5081 case 2:
5082 res = func(args[0],args[1]);
5083 break;
5084 case 3:
5085 res = func(args[0],args[1],args[2]);
5086 break;
5087 case 4:
5088 res = func(args[0],args[1],args[2],args[3]);
5089 break;
5090 case 5:
5091 res = func(args[0],args[1],args[2],args[3],args[4]);
5092 break;
5093 case 6:
5094 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
5095 break;
5096 case 7:
5097 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
5098 break;
5099 case 8:
5100 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
5101 break;
5102 case 9:
5103 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
5104 break;
5105 case 10:
5106 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
5107 break;
5108 case 11:
5109 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
5110 break;
5111 case 12:
5112 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]);
5113 break;
5114 case 13:
5115 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]);
5116 break;
5117 case 14:
5118 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]);
5119 break;
5120 case 15:
5121 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]);
5122 break;
5123 case 16:
5124 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]);
5125 break;
5126 case 17:
5127 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]);
5128 break;
5129 case 18:
5130 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]);
5131 break;
5132 case 19:
5133 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]);
5134 break;
5135 case 20:
5136 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]);
5137 break;
5138 case 21:
5139 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]);
5140 break;
5141 case 22:
5142 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]);
5143 break;
5144 case 23:
5145 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]);
5146 break;
5147 default:
5148 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
5149 res = -1;
5150 break;
5152 break;
5153 default:
5154 FIXME("unsupported calling convention %d\n",callconv);
5155 res = -1;
5156 break;
5158 TRACE("returns %08x\n",res);
5159 return res;
5162 extern int _argsize(DWORD vt);
5164 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5166 HRESULT hr = S_OK;
5167 ITypeInfo *tinfo2 = NULL;
5168 TYPEATTR *tattr = NULL;
5170 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5171 if (hr)
5173 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5174 "hr = 0x%08x\n",
5175 tdesc->u.hreftype, hr);
5176 return hr;
5178 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5179 if (hr)
5181 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5182 ITypeInfo_Release(tinfo2);
5183 return hr;
5186 switch (tattr->typekind)
5188 case TKIND_ENUM:
5189 *vt |= VT_I4;
5190 break;
5192 case TKIND_ALIAS:
5193 tdesc = &tattr->tdescAlias;
5194 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5195 break;
5197 case TKIND_INTERFACE:
5198 if (IsEqualIID(&IID_IDispatch, &tattr->guid))
5199 *vt |= VT_DISPATCH;
5200 else
5201 *vt |= VT_UNKNOWN;
5202 break;
5204 case TKIND_DISPATCH:
5205 *vt |= VT_DISPATCH;
5206 break;
5208 case TKIND_COCLASS:
5209 *vt |= VT_UNKNOWN;
5210 break;
5212 case TKIND_RECORD:
5213 FIXME("TKIND_RECORD unhandled.\n");
5214 hr = E_NOTIMPL;
5215 break;
5217 case TKIND_UNION:
5218 FIXME("TKIND_UNION unhandled.\n");
5219 hr = E_NOTIMPL;
5220 break;
5222 default:
5223 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5224 hr = E_NOTIMPL;
5225 break;
5227 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5228 ITypeInfo_Release(tinfo2);
5229 return hr;
5232 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5234 HRESULT hr = S_OK;
5236 /* enforce only one level of pointer indirection */
5237 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5239 tdesc = tdesc->u.lptdesc;
5241 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5242 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5243 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5244 if ((tdesc->vt == VT_USERDEFINED) ||
5245 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5247 VARTYPE vt_userdefined = 0;
5248 const TYPEDESC *tdesc_userdefined = tdesc;
5249 if (tdesc->vt == VT_PTR)
5251 vt_userdefined = VT_BYREF;
5252 tdesc_userdefined = tdesc->u.lptdesc;
5254 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5255 if ((hr == S_OK) &&
5256 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5257 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5259 *vt |= vt_userdefined;
5260 return S_OK;
5263 *vt = VT_BYREF;
5266 switch (tdesc->vt)
5268 case VT_HRESULT:
5269 *vt |= VT_ERROR;
5270 break;
5271 case VT_USERDEFINED:
5272 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5273 break;
5274 case VT_VOID:
5275 case VT_CARRAY:
5276 case VT_PTR:
5277 case VT_LPSTR:
5278 case VT_LPWSTR:
5279 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5280 hr = DISP_E_BADVARTYPE;
5281 break;
5282 case VT_SAFEARRAY:
5283 *vt |= VT_ARRAY;
5284 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5285 break;
5286 default:
5287 *vt |= tdesc->vt;
5288 break;
5290 return hr;
5293 /***********************************************************************
5294 * DispCallFunc (OLEAUT32.@)
5296 * Invokes a function of the specifed calling convention, passing the
5297 * specified arguments and returns the result.
5299 * PARAMS
5300 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5301 * oVft [I] The offset in the vtable. See notes.
5302 * cc [I] Calling convention of the function to call.
5303 * vtReturn [I] The return type of the function.
5304 * cActuals [I] Number of parameters.
5305 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5306 * prgpvarg [I] The arguments to pass.
5307 * pvargResult [O] The return value of the function. Can be NULL.
5309 * RETURNS
5310 * Success: S_OK.
5311 * Failure: HRESULT code.
5313 * NOTES
5314 * The HRESULT return value of this function is not affected by the return
5315 * value of the user supplied function, which is returned in pvargResult.
5317 * If pvInstance is NULL then a non-object function is to be called and oVft
5318 * is the address of the function to call.
5320 * The cc parameter can be one of the following values:
5321 *|CC_FASTCALL
5322 *|CC_CDECL
5323 *|CC_PASCAL
5324 *|CC_STDCALL
5325 *|CC_FPFASTCALL
5326 *|CC_SYSCALL
5327 *|CC_MPWCDECL
5328 *|CC_MPWPASCAL
5331 HRESULT WINAPI
5332 DispCallFunc(
5333 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5334 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5336 int i, argsize, argspos;
5337 DWORD *args;
5338 HRESULT hres;
5340 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5341 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5342 pvargResult, V_VT(pvargResult));
5344 argsize = 0;
5345 if (pvInstance)
5346 argsize++; /* for This pointer */
5348 for (i=0;i<cActuals;i++)
5350 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5351 dump_Variant(prgpvarg[i]);
5352 argsize += _argsize(prgvt[i]);
5354 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5356 argspos = 0;
5357 if (pvInstance)
5359 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5360 argspos++;
5363 for (i=0;i<cActuals;i++)
5365 VARIANT *arg = prgpvarg[i];
5366 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5367 if (prgvt[i] == VT_VARIANT)
5368 memcpy(&args[argspos], arg, _argsize(prgvt[i]) * sizeof(DWORD));
5369 else
5370 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5371 argspos += _argsize(prgvt[i]);
5374 if (pvInstance)
5376 FARPROC *vtable = *(FARPROC**)pvInstance;
5377 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5379 else
5380 /* if we aren't invoking an object then the function pointer is stored
5381 * in oVft */
5382 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5384 if (pvargResult && (vtReturn != VT_EMPTY))
5386 TRACE("Method returned 0x%08x\n",hres);
5387 V_VT(pvargResult) = vtReturn;
5388 V_UI4(pvargResult) = hres;
5391 HeapFree(GetProcessHeap(),0,args);
5392 return S_OK;
5395 #define INVBUF_ELEMENT_SIZE \
5396 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5397 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5398 ((VARIANTARG *)(buffer))
5399 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5400 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5401 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5402 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5403 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5404 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5406 static HRESULT WINAPI ITypeInfo_fnInvoke(
5407 ITypeInfo2 *iface,
5408 VOID *pIUnk,
5409 MEMBERID memid,
5410 UINT16 wFlags,
5411 DISPPARAMS *pDispParams,
5412 VARIANT *pVarResult,
5413 EXCEPINFO *pExcepInfo,
5414 UINT *pArgErr)
5416 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5417 int i;
5418 unsigned int var_index;
5419 TYPEKIND type_kind;
5420 HRESULT hres;
5421 const TLBFuncDesc *pFuncInfo;
5423 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
5424 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5427 if (!pDispParams)
5429 ERR("NULL pDispParams not allowed\n");
5430 return E_INVALIDARG;
5433 dump_DispParms(pDispParams);
5435 if (pDispParams->cNamedArgs > pDispParams->cArgs)
5437 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
5438 pDispParams->cNamedArgs, pDispParams->cArgs);
5439 return E_INVALIDARG;
5442 /* we do this instead of using GetFuncDesc since it will return a fake
5443 * FUNCDESC for dispinterfaces and we want the real function description */
5444 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5445 if ((memid == pFuncInfo->funcdesc.memid) &&
5446 (wFlags & pFuncInfo->funcdesc.invkind))
5447 break;
5449 if (pFuncInfo) {
5450 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5452 if (TRACE_ON(ole))
5454 TRACE("invoking:\n");
5455 dump_TLBFuncDescOne(pFuncInfo);
5458 switch (func_desc->funckind) {
5459 case FUNC_PUREVIRTUAL:
5460 case FUNC_VIRTUAL: {
5461 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
5462 VARIANT varresult;
5463 VARIANT retval; /* pointer for storing byref retvals in */
5464 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
5465 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
5466 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
5468 hres = S_OK;
5469 for (i = 0; i < func_desc->cParams; i++)
5471 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5472 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
5473 if (FAILED(hres))
5474 goto func_fail;
5477 TRACE("changing args\n");
5478 for (i = 0; i < func_desc->cParams; i++)
5480 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5482 if (wParamFlags & PARAMFLAG_FRETVAL)
5484 /* note: this check is placed so that if the caller passes
5485 * in a VARIANTARG for the retval we just ignore it, like
5486 * native does */
5487 if (i == func_desc->cParams - 1)
5489 VARIANTARG *arg;
5490 arg = prgpvarg[i] = &rgvarg[i];
5491 memset(arg, 0, sizeof(*arg));
5492 V_VT(arg) = rgvt[i];
5493 memset(&retval, 0, sizeof(retval));
5494 V_BYREF(arg) = &retval;
5496 else
5498 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
5499 hres = E_UNEXPECTED;
5500 break;
5503 else if (i < pDispParams->cArgs)
5505 VARIANTARG *src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5506 dump_Variant(src_arg);
5508 if (rgvt[i] == VT_VARIANT)
5509 hres = VariantCopy(&rgvarg[i], src_arg);
5510 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
5512 if (rgvt[i] == V_VT(src_arg))
5513 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
5514 else
5516 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5517 hres = VariantCopy(&missing_arg[i], src_arg);
5518 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
5520 V_VT(&rgvarg[i]) = rgvt[i];
5522 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
5524 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5525 V_VT(&missing_arg[i]) = V_VT(src_arg);
5526 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
5527 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
5528 V_VT(&rgvarg[i]) = rgvt[i];
5530 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
5532 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
5533 V_VT(&rgvarg[i]) = rgvt[i];
5535 else
5537 /* FIXME: this doesn't work for VT_BYREF arguments if
5538 * they are not the same type as in the paramdesc */
5539 V_VT(&rgvarg[i]) = V_VT(src_arg);
5540 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
5541 V_VT(&rgvarg[i]) = rgvt[i];
5544 if (FAILED(hres))
5546 ERR("failed to convert param %d to %s%s from %s%s\n", i,
5547 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
5548 debugstr_VT(src_arg), debugstr_VF(src_arg));
5549 break;
5551 prgpvarg[i] = &rgvarg[i];
5553 else if (wParamFlags & PARAMFLAG_FOPT)
5555 VARIANTARG *arg;
5556 arg = prgpvarg[i] = &rgvarg[i];
5557 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5559 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
5560 if (FAILED(hres))
5561 break;
5563 else
5565 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5566 V_VT(arg) = VT_VARIANT | VT_BYREF;
5567 V_VARIANTREF(arg) = &missing_arg[i];
5568 V_VT(V_VARIANTREF(arg)) = VT_ERROR;
5569 V_ERROR(V_VARIANTREF(arg)) = DISP_E_PARAMNOTFOUND;
5572 else
5574 hres = DISP_E_BADPARAMCOUNT;
5575 break;
5578 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5579 if (func_desc->cParamsOpt < 0)
5581 FIXME("Does not support safearray optional parameters\n");
5582 hres = DISP_E_BADPARAMCOUNT;
5583 goto func_fail; /* FIXME: we don't free changed types here */
5586 /* VT_VOID is a special case for return types, so it is not
5587 * handled in the general function */
5588 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
5589 V_VT(&varresult) = VT_EMPTY;
5590 else
5592 V_VT(&varresult) = 0;
5593 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
5594 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5597 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
5598 V_VT(&varresult), func_desc->cParams, rgvt,
5599 prgpvarg, &varresult);
5601 for (i = 0; i < func_desc->cParams; i++)
5603 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5604 if (wParamFlags & PARAMFLAG_FRETVAL)
5606 if (TRACE_ON(ole))
5608 TRACE("[retval] value: ");
5609 dump_Variant(prgpvarg[i]);
5612 if (pVarResult)
5614 VariantInit(pVarResult);
5615 /* deref return value */
5616 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
5619 /* free data stored in varresult. Note that
5620 * VariantClear doesn't do what we want because we are
5621 * working with byref types. */
5622 /* FIXME: clear safearrays, bstrs, records and
5623 * variants here too */
5624 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
5625 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
5627 if(*V_UNKNOWNREF(prgpvarg[i]))
5628 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
5630 break;
5632 else if (i < pDispParams->cArgs)
5634 if (wParamFlags & PARAMFLAG_FOUT)
5636 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5638 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
5639 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
5641 if (FAILED(hres))
5643 ERR("failed to convert param %d to vt %d\n", i,
5644 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
5645 break;
5648 VariantClear(&rgvarg[i]);
5650 else if (wParamFlags & PARAMFLAG_FOPT)
5652 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5653 VariantClear(&rgvarg[i]);
5657 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
5659 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
5660 hres = DISP_E_EXCEPTION;
5661 if (pExcepInfo) pExcepInfo->scode = V_ERROR(&varresult);
5664 func_fail:
5665 HeapFree(GetProcessHeap(), 0, buffer);
5666 break;
5668 case FUNC_DISPATCH: {
5669 IDispatch *disp;
5671 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5672 if (SUCCEEDED(hres)) {
5673 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5674 hres = IDispatch_Invoke(
5675 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
5676 pVarResult,pExcepInfo,pArgErr
5678 if (FAILED(hres))
5679 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
5680 IDispatch_Release(disp);
5681 } else
5682 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5683 break;
5685 default:
5686 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5687 hres = E_FAIL;
5688 break;
5691 TRACE("-- 0x%08x\n", hres);
5692 return hres;
5694 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5695 VARDESC *var_desc;
5697 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5698 if(FAILED(hres)) return hres;
5700 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5701 dump_VARDESC(var_desc);
5702 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
5703 return E_NOTIMPL;
5706 /* not found, look for it in inherited interfaces */
5707 ITypeInfo2_GetTypeKind(iface, &type_kind);
5708 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
5709 HREFTYPE ref_type;
5710 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
5711 /* recursive search */
5712 ITypeInfo *pTInfo;
5713 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
5714 if(SUCCEEDED(hres)){
5715 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
5716 ITypeInfo_Release(pTInfo);
5717 return hres;
5719 WARN("Could not search inherited interface!\n");
5722 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
5723 return DISP_E_MEMBERNOTFOUND;
5726 /* ITypeInfo::GetDocumentation
5728 * Retrieves the documentation string, the complete Help file name and path,
5729 * and the context ID for the Help topic for a specified type description.
5731 * (Can be tested by the Visual Basic Editor in Word for instance.)
5733 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
5734 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
5735 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
5737 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5738 const TLBFuncDesc *pFDesc;
5739 const TLBVarDesc *pVDesc;
5740 TRACE("(%p) memid %d Name(%p) DocString(%p)"
5741 " HelpContext(%p) HelpFile(%p)\n",
5742 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5743 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5744 if(pBstrName)
5745 *pBstrName=SysAllocString(This->Name);
5746 if(pBstrDocString)
5747 *pBstrDocString=SysAllocString(This->DocString);
5748 if(pdwHelpContext)
5749 *pdwHelpContext=This->dwHelpContext;
5750 if(pBstrHelpFile)
5751 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5752 return S_OK;
5753 }else {/* for a member */
5754 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5755 if(pFDesc->funcdesc.memid==memid){
5756 if(pBstrName)
5757 *pBstrName = SysAllocString(pFDesc->Name);
5758 if(pBstrDocString)
5759 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5760 if(pdwHelpContext)
5761 *pdwHelpContext=pFDesc->helpcontext;
5762 return S_OK;
5764 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5765 if(pVDesc->vardesc.memid==memid){
5766 if(pBstrName)
5767 *pBstrName = SysAllocString(pVDesc->Name);
5768 if(pBstrDocString)
5769 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5770 if(pdwHelpContext)
5771 *pdwHelpContext=pVDesc->HelpContext;
5772 return S_OK;
5776 if(This->TypeAttr.cImplTypes &&
5777 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5778 /* recursive search */
5779 ITypeInfo *pTInfo;
5780 HRESULT result;
5781 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5782 &pTInfo);
5783 if(SUCCEEDED(result)) {
5784 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
5785 pBstrDocString, pdwHelpContext, pBstrHelpFile);
5786 ITypeInfo_Release(pTInfo);
5787 return result;
5789 WARN("Could not search inherited interface!\n");
5792 WARN("member %d not found\n", memid);
5793 return TYPE_E_ELEMENTNOTFOUND;
5796 /* ITypeInfo::GetDllEntry
5798 * Retrieves a description or specification of an entry point for a function
5799 * in a DLL.
5801 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5802 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5803 WORD *pwOrdinal)
5805 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5806 const TLBFuncDesc *pFDesc;
5808 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5810 if (pBstrDllName) *pBstrDllName = NULL;
5811 if (pBstrName) *pBstrName = NULL;
5812 if (pwOrdinal) *pwOrdinal = 0;
5814 if (This->TypeAttr.typekind != TKIND_MODULE)
5815 return TYPE_E_BADMODULEKIND;
5817 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5818 if(pFDesc->funcdesc.memid==memid){
5819 dump_TypeInfo(This);
5820 if (TRACE_ON(ole))
5821 dump_TLBFuncDescOne(pFDesc);
5823 if (pBstrDllName)
5824 *pBstrDllName = SysAllocString(This->DllName);
5826 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5827 if (pBstrName)
5828 *pBstrName = SysAllocString(pFDesc->Entry);
5829 if (pwOrdinal)
5830 *pwOrdinal = -1;
5831 return S_OK;
5833 if (pBstrName)
5834 *pBstrName = NULL;
5835 if (pwOrdinal)
5836 *pwOrdinal = (DWORD)pFDesc->Entry;
5837 return S_OK;
5839 return TYPE_E_ELEMENTNOTFOUND;
5842 /* ITypeInfo::GetRefTypeInfo
5844 * If a type description references other type descriptions, it retrieves
5845 * the referenced type descriptions.
5847 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5848 ITypeInfo2 *iface,
5849 HREFTYPE hRefType,
5850 ITypeInfo **ppTInfo)
5852 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5853 HRESULT result = E_FAIL;
5855 if ((This->hreftype != -1) && (This->hreftype == hRefType))
5857 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5858 ITypeInfo_AddRef(*ppTInfo);
5859 result = S_OK;
5861 else if (hRefType == -1 &&
5862 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5863 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5865 /* when we meet a DUAL dispinterface, we must create the interface
5866 * version of it.
5868 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5871 /* the interface version contains the same information as the dispinterface
5872 * copy the contents of the structs.
5874 *pTypeInfoImpl = *This;
5875 pTypeInfoImpl->ref = 0;
5877 /* change the type to interface */
5878 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5880 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5882 /* we use data structures from This, so we need to keep a reference
5883 * to it to stop it being destroyed and signal to the new instance to
5884 * not free its data structures when it is destroyed */
5885 pTypeInfoImpl->no_free_data = TRUE;
5886 pTypeInfoImpl->next = This;
5887 ITypeInfo_AddRef((ITypeInfo*) This);
5889 ITypeInfo_AddRef(*ppTInfo);
5891 result = S_OK;
5893 } else {
5894 TLBRefType *pRefType;
5895 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5896 if(pRefType->reference == hRefType)
5897 break;
5899 if(!pRefType)
5900 FIXME("Can't find pRefType for ref %x\n", hRefType);
5901 if(pRefType && hRefType != -1) {
5902 ITypeLib *pTLib = NULL;
5904 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5905 UINT Index;
5906 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5907 } else {
5908 if(pRefType->pImpTLInfo->pImpTypeLib) {
5909 TRACE("typeinfo in imported typelib that is already loaded\n");
5910 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5911 ITypeLib2_AddRef((ITypeLib*) pTLib);
5912 result = S_OK;
5913 } else {
5914 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5915 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5916 pRefType->pImpTLInfo->wVersionMajor,
5917 pRefType->pImpTLInfo->wVersionMinor,
5918 pRefType->pImpTLInfo->lcid,
5919 &pTLib);
5921 if(!SUCCEEDED(result)) {
5922 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5923 result=LoadTypeLib(libnam, &pTLib);
5924 SysFreeString(libnam);
5926 if(SUCCEEDED(result)) {
5927 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5928 ITypeLib2_AddRef(pTLib);
5932 if(SUCCEEDED(result)) {
5933 if(pRefType->index == TLB_REF_USE_GUID)
5934 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5935 &pRefType->guid,
5936 ppTInfo);
5937 else
5938 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5939 ppTInfo);
5941 if (pTLib != NULL)
5942 ITypeLib2_Release(pTLib);
5946 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
5947 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5948 return result;
5951 /* ITypeInfo::AddressOfMember
5953 * Retrieves the addresses of static functions or variables, such as those
5954 * defined in a DLL.
5956 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5957 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5959 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5960 HRESULT hr;
5961 BSTR dll, entry;
5962 WORD ordinal;
5963 HMODULE module;
5965 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
5967 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
5968 if (FAILED(hr))
5969 return hr;
5971 module = LoadLibraryW(dll);
5972 if (!module)
5974 ERR("couldn't load %s\n", debugstr_w(dll));
5975 SysFreeString(dll);
5976 if (entry) SysFreeString(entry);
5977 return STG_E_FILENOTFOUND;
5979 /* FIXME: store library somewhere where we can free it */
5981 if (entry)
5983 LPSTR entryA;
5984 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
5985 entryA = HeapAlloc(GetProcessHeap(), 0, len);
5986 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
5988 *ppv = GetProcAddress(module, entryA);
5989 if (!*ppv)
5990 ERR("function not found %s\n", debugstr_a(entryA));
5992 HeapFree(GetProcessHeap(), 0, entryA);
5994 else
5996 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
5997 if (!*ppv)
5998 ERR("function not found %d\n", ordinal);
6001 SysFreeString(dll);
6002 if (entry) SysFreeString(entry);
6004 if (!*ppv)
6005 return TYPE_E_DLLFUNCTIONNOTFOUND;
6007 return S_OK;
6010 /* ITypeInfo::CreateInstance
6012 * Creates a new instance of a type that describes a component object class
6013 * (coclass).
6015 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6016 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6018 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6019 HRESULT hr;
6020 TYPEATTR *pTA;
6022 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6024 *ppvObj = NULL;
6026 if(pOuterUnk)
6028 WARN("Not able to aggregate\n");
6029 return CLASS_E_NOAGGREGATION;
6032 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6033 if(FAILED(hr)) return hr;
6035 if(pTA->typekind != TKIND_COCLASS)
6037 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6038 hr = E_INVALIDARG;
6039 goto end;
6042 hr = S_FALSE;
6043 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6045 IUnknown *pUnk;
6046 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6047 TRACE("GetActiveObject rets %08x\n", hr);
6048 if(hr == S_OK)
6050 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6051 IUnknown_Release(pUnk);
6055 if(hr != S_OK)
6056 hr = CoCreateInstance(&pTA->guid, NULL,
6057 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6058 riid, ppvObj);
6060 end:
6061 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6062 return hr;
6065 /* ITypeInfo::GetMops
6067 * Retrieves marshalling information.
6069 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6070 BSTR *pBstrMops)
6072 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6073 FIXME("(%p) stub!\n", This);
6074 return S_OK;
6077 /* ITypeInfo::GetContainingTypeLib
6079 * Retrieves the containing type library and the index of the type description
6080 * within that type library.
6082 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6083 ITypeLib * *ppTLib, UINT *pIndex)
6085 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6087 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6088 if (pIndex) {
6089 *pIndex=This->index;
6090 TRACE("returning pIndex=%d\n", *pIndex);
6093 if (ppTLib) {
6094 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6095 ITypeLib2_AddRef(*ppTLib);
6096 TRACE("returning ppTLib=%p\n", *ppTLib);
6099 return S_OK;
6102 /* ITypeInfo::ReleaseTypeAttr
6104 * Releases a TYPEATTR previously returned by GetTypeAttr.
6107 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6108 TYPEATTR* pTypeAttr)
6110 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6111 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6112 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6115 /* ITypeInfo::ReleaseFuncDesc
6117 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6119 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6120 ITypeInfo2 *iface,
6121 FUNCDESC *pFuncDesc)
6123 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6124 SHORT i;
6126 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6128 for (i = 0; i < pFuncDesc->cParams; i++)
6129 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6130 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6132 SysFreeString((BSTR)pFuncDesc);
6135 /* ITypeInfo::ReleaseVarDesc
6137 * Releases a VARDESC previously returned by GetVarDesc.
6139 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6140 VARDESC *pVarDesc)
6142 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6143 TRACE("(%p)->(%p)\n", This, pVarDesc);
6145 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6146 if (pVarDesc->varkind == VAR_CONST)
6147 VariantClear(pVarDesc->u.lpvarValue);
6148 SysFreeString((BSTR)pVarDesc);
6151 /* ITypeInfo2::GetTypeKind
6153 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6156 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6157 TYPEKIND *pTypeKind)
6159 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6160 *pTypeKind=This->TypeAttr.typekind;
6161 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6162 return S_OK;
6165 /* ITypeInfo2::GetTypeFlags
6167 * Returns the type flags without any allocations. This returns a DWORD type
6168 * flag, which expands the type flags without growing the TYPEATTR (type
6169 * attribute).
6172 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6174 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6175 *pTypeFlags=This->TypeAttr.wTypeFlags;
6176 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6177 return S_OK;
6180 /* ITypeInfo2::GetFuncIndexOfMemId
6181 * Binds to a specific member based on a known DISPID, where the member name
6182 * is not known (for example, when binding to a default member).
6185 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
6186 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
6188 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6189 const TLBFuncDesc *pFuncInfo;
6190 int i;
6191 HRESULT result;
6193 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
6194 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
6195 break;
6196 if(pFuncInfo) {
6197 *pFuncIndex = i;
6198 result = S_OK;
6199 } else
6200 result = TYPE_E_ELEMENTNOTFOUND;
6202 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
6203 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6204 return result;
6207 /* TypeInfo2::GetVarIndexOfMemId
6209 * Binds to a specific member based on a known DISPID, where the member name
6210 * is not known (for example, when binding to a default member).
6213 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
6214 MEMBERID memid, UINT *pVarIndex)
6216 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6217 TLBVarDesc *pVarInfo;
6218 int i;
6219 HRESULT result;
6220 for(i=0, pVarInfo=This->varlist; pVarInfo &&
6221 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
6223 if(pVarInfo) {
6224 *pVarIndex = i;
6225 result = S_OK;
6226 } else
6227 result = TYPE_E_ELEMENTNOTFOUND;
6229 TRACE("(%p) memid 0x%08x -> %s\n", This,
6230 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6231 return result;
6234 /* ITypeInfo2::GetCustData
6236 * Gets the custom data
6238 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
6239 ITypeInfo2 * iface,
6240 REFGUID guid,
6241 VARIANT *pVarVal)
6243 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6244 TLBCustData *pCData;
6246 for(pCData=This->pCustData; pCData; pCData = pCData->next)
6247 if( IsEqualIID(guid, &pCData->guid)) break;
6249 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6251 if(pCData)
6253 VariantInit( pVarVal);
6254 VariantCopy( pVarVal, &pCData->data);
6255 return S_OK;
6257 return E_INVALIDARG; /* FIXME: correct? */
6260 /* ITypeInfo2::GetFuncCustData
6262 * Gets the custom data
6264 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
6265 ITypeInfo2 * iface,
6266 UINT index,
6267 REFGUID guid,
6268 VARIANT *pVarVal)
6270 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6271 TLBCustData *pCData=NULL;
6272 TLBFuncDesc * pFDesc;
6273 int i;
6274 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6275 pFDesc=pFDesc->next);
6277 if(pFDesc)
6278 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
6279 if( IsEqualIID(guid, &pCData->guid)) break;
6281 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6283 if(pCData){
6284 VariantInit( pVarVal);
6285 VariantCopy( pVarVal, &pCData->data);
6286 return S_OK;
6288 return E_INVALIDARG; /* FIXME: correct? */
6291 /* ITypeInfo2::GetParamCustData
6293 * Gets the custom data
6295 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
6296 ITypeInfo2 * iface,
6297 UINT indexFunc,
6298 UINT indexParam,
6299 REFGUID guid,
6300 VARIANT *pVarVal)
6302 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6303 TLBCustData *pCData=NULL;
6304 TLBFuncDesc * pFDesc;
6305 int i;
6307 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
6309 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
6310 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
6311 pCData = pCData->next)
6312 if( IsEqualIID(guid, &pCData->guid)) break;
6314 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6316 if(pCData)
6318 VariantInit( pVarVal);
6319 VariantCopy( pVarVal, &pCData->data);
6320 return S_OK;
6322 return E_INVALIDARG; /* FIXME: correct? */
6325 /* ITypeInfo2::GetVarCustData
6327 * Gets the custom data
6329 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
6330 ITypeInfo2 * iface,
6331 UINT index,
6332 REFGUID guid,
6333 VARIANT *pVarVal)
6335 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6336 TLBCustData *pCData=NULL;
6337 TLBVarDesc * pVDesc;
6338 int i;
6340 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
6342 if(pVDesc)
6344 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
6346 if( IsEqualIID(guid, &pCData->guid)) break;
6350 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6352 if(pCData)
6354 VariantInit( pVarVal);
6355 VariantCopy( pVarVal, &pCData->data);
6356 return S_OK;
6358 return E_INVALIDARG; /* FIXME: correct? */
6361 /* ITypeInfo2::GetImplCustData
6363 * Gets the custom data
6365 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6366 ITypeInfo2 * iface,
6367 UINT index,
6368 REFGUID guid,
6369 VARIANT *pVarVal)
6371 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6372 TLBCustData *pCData=NULL;
6373 TLBImplType * pRDesc;
6374 int i;
6376 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6378 if(pRDesc)
6380 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6382 if( IsEqualIID(guid, &pCData->guid)) break;
6386 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6388 if(pCData)
6390 VariantInit( pVarVal);
6391 VariantCopy( pVarVal, &pCData->data);
6392 return S_OK;
6394 return E_INVALIDARG; /* FIXME: correct? */
6397 /* ITypeInfo2::GetDocumentation2
6399 * Retrieves the documentation string, the complete Help file name and path,
6400 * the localization context to use, and the context ID for the library Help
6401 * topic in the Help file.
6404 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6405 ITypeInfo2 * iface,
6406 MEMBERID memid,
6407 LCID lcid,
6408 BSTR *pbstrHelpString,
6409 DWORD *pdwHelpStringContext,
6410 BSTR *pbstrHelpStringDll)
6412 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6413 const TLBFuncDesc *pFDesc;
6414 const TLBVarDesc *pVDesc;
6415 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
6416 "HelpStringContext(%p) HelpStringDll(%p)\n",
6417 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6418 pbstrHelpStringDll );
6419 /* the help string should be obtained from the helpstringdll,
6420 * using the _DLLGetDocumentation function, based on the supplied
6421 * lcid. Nice to do sometime...
6423 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6424 if(pbstrHelpString)
6425 *pbstrHelpString=SysAllocString(This->Name);
6426 if(pdwHelpStringContext)
6427 *pdwHelpStringContext=This->dwHelpStringContext;
6428 if(pbstrHelpStringDll)
6429 *pbstrHelpStringDll=
6430 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6431 return S_OK;
6432 }else {/* for a member */
6433 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6434 if(pFDesc->funcdesc.memid==memid){
6435 if(pbstrHelpString)
6436 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6437 if(pdwHelpStringContext)
6438 *pdwHelpStringContext=pFDesc->HelpStringContext;
6439 if(pbstrHelpStringDll)
6440 *pbstrHelpStringDll=
6441 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6442 return S_OK;
6444 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6445 if(pVDesc->vardesc.memid==memid){
6446 if(pbstrHelpString)
6447 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6448 if(pdwHelpStringContext)
6449 *pdwHelpStringContext=pVDesc->HelpStringContext;
6450 if(pbstrHelpStringDll)
6451 *pbstrHelpStringDll=
6452 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6453 return S_OK;
6456 return TYPE_E_ELEMENTNOTFOUND;
6459 /* ITypeInfo2::GetAllCustData
6461 * Gets all custom data items for the Type info.
6464 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6465 ITypeInfo2 * iface,
6466 CUSTDATA *pCustData)
6468 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6469 TLBCustData *pCData;
6470 int i;
6472 TRACE("(%p) returning %d items\n", This, This->ctCustData);
6474 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6475 if(pCustData->prgCustData ){
6476 pCustData->cCustData=This->ctCustData;
6477 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
6478 pCustData->prgCustData[i].guid=pCData->guid;
6479 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
6481 }else{
6482 ERR(" OUT OF MEMORY!\n");
6483 return E_OUTOFMEMORY;
6485 return S_OK;
6488 /* ITypeInfo2::GetAllFuncCustData
6490 * Gets all custom data items for the specified Function
6493 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
6494 ITypeInfo2 * iface,
6495 UINT index,
6496 CUSTDATA *pCustData)
6498 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6499 TLBCustData *pCData;
6500 TLBFuncDesc * pFDesc;
6501 int i;
6502 TRACE("(%p) index %d\n", This, index);
6503 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6504 pFDesc=pFDesc->next)
6506 if(pFDesc){
6507 pCustData->prgCustData =
6508 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
6509 if(pCustData->prgCustData ){
6510 pCustData->cCustData=pFDesc->ctCustData;
6511 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
6512 pCData = pCData->next){
6513 pCustData->prgCustData[i].guid=pCData->guid;
6514 VariantCopy(& pCustData->prgCustData[i].varValue,
6515 & pCData->data);
6517 }else{
6518 ERR(" OUT OF MEMORY!\n");
6519 return E_OUTOFMEMORY;
6521 return S_OK;
6523 return TYPE_E_ELEMENTNOTFOUND;
6526 /* ITypeInfo2::GetAllParamCustData
6528 * Gets all custom data items for the Functions
6531 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
6532 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
6534 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6535 TLBCustData *pCData=NULL;
6536 TLBFuncDesc * pFDesc;
6537 int i;
6538 TRACE("(%p) index %d\n", This, indexFunc);
6539 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
6540 pFDesc=pFDesc->next)
6542 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
6543 pCustData->prgCustData =
6544 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
6545 sizeof(CUSTDATAITEM));
6546 if(pCustData->prgCustData ){
6547 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
6548 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
6549 pCData; i++, pCData = pCData->next){
6550 pCustData->prgCustData[i].guid=pCData->guid;
6551 VariantCopy(& pCustData->prgCustData[i].varValue,
6552 & pCData->data);
6554 }else{
6555 ERR(" OUT OF MEMORY!\n");
6556 return E_OUTOFMEMORY;
6558 return S_OK;
6560 return TYPE_E_ELEMENTNOTFOUND;
6563 /* ITypeInfo2::GetAllVarCustData
6565 * Gets all custom data items for the specified Variable
6568 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
6569 UINT index, CUSTDATA *pCustData)
6571 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6572 TLBCustData *pCData;
6573 TLBVarDesc * pVDesc;
6574 int i;
6575 TRACE("(%p) index %d\n", This, index);
6576 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
6577 pVDesc=pVDesc->next)
6579 if(pVDesc){
6580 pCustData->prgCustData =
6581 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
6582 if(pCustData->prgCustData ){
6583 pCustData->cCustData=pVDesc->ctCustData;
6584 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
6585 pCData = pCData->next){
6586 pCustData->prgCustData[i].guid=pCData->guid;
6587 VariantCopy(& pCustData->prgCustData[i].varValue,
6588 & pCData->data);
6590 }else{
6591 ERR(" OUT OF MEMORY!\n");
6592 return E_OUTOFMEMORY;
6594 return S_OK;
6596 return TYPE_E_ELEMENTNOTFOUND;
6599 /* ITypeInfo2::GetAllImplCustData
6601 * Gets all custom data items for the specified implementation type
6604 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
6605 ITypeInfo2 * iface,
6606 UINT index,
6607 CUSTDATA *pCustData)
6609 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6610 TLBCustData *pCData;
6611 TLBImplType * pRDesc;
6612 int i;
6613 TRACE("(%p) index %d\n", This, index);
6614 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
6615 pRDesc=pRDesc->next)
6617 if(pRDesc){
6618 pCustData->prgCustData =
6619 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
6620 if(pCustData->prgCustData ){
6621 pCustData->cCustData=pRDesc->ctCustData;
6622 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
6623 pCData = pCData->next){
6624 pCustData->prgCustData[i].guid=pCData->guid;
6625 VariantCopy(& pCustData->prgCustData[i].varValue,
6626 & pCData->data);
6628 }else{
6629 ERR(" OUT OF MEMORY!\n");
6630 return E_OUTOFMEMORY;
6632 return S_OK;
6634 return TYPE_E_ELEMENTNOTFOUND;
6637 static const ITypeInfo2Vtbl tinfvt =
6640 ITypeInfo_fnQueryInterface,
6641 ITypeInfo_fnAddRef,
6642 ITypeInfo_fnRelease,
6644 ITypeInfo_fnGetTypeAttr,
6645 ITypeInfo_fnGetTypeComp,
6646 ITypeInfo_fnGetFuncDesc,
6647 ITypeInfo_fnGetVarDesc,
6648 ITypeInfo_fnGetNames,
6649 ITypeInfo_fnGetRefTypeOfImplType,
6650 ITypeInfo_fnGetImplTypeFlags,
6651 ITypeInfo_fnGetIDsOfNames,
6652 ITypeInfo_fnInvoke,
6653 ITypeInfo_fnGetDocumentation,
6654 ITypeInfo_fnGetDllEntry,
6655 ITypeInfo_fnGetRefTypeInfo,
6656 ITypeInfo_fnAddressOfMember,
6657 ITypeInfo_fnCreateInstance,
6658 ITypeInfo_fnGetMops,
6659 ITypeInfo_fnGetContainingTypeLib,
6660 ITypeInfo_fnReleaseTypeAttr,
6661 ITypeInfo_fnReleaseFuncDesc,
6662 ITypeInfo_fnReleaseVarDesc,
6664 ITypeInfo2_fnGetTypeKind,
6665 ITypeInfo2_fnGetTypeFlags,
6666 ITypeInfo2_fnGetFuncIndexOfMemId,
6667 ITypeInfo2_fnGetVarIndexOfMemId,
6668 ITypeInfo2_fnGetCustData,
6669 ITypeInfo2_fnGetFuncCustData,
6670 ITypeInfo2_fnGetParamCustData,
6671 ITypeInfo2_fnGetVarCustData,
6672 ITypeInfo2_fnGetImplTypeCustData,
6673 ITypeInfo2_fnGetDocumentation2,
6674 ITypeInfo2_fnGetAllCustData,
6675 ITypeInfo2_fnGetAllFuncCustData,
6676 ITypeInfo2_fnGetAllParamCustData,
6677 ITypeInfo2_fnGetAllVarCustData,
6678 ITypeInfo2_fnGetAllImplTypeCustData,
6681 /******************************************************************************
6682 * CreateDispTypeInfo [OLEAUT32.31]
6684 * Build type information for an object so it can be called through an
6685 * IDispatch interface.
6687 * RETURNS
6688 * Success: S_OK. pptinfo contains the created ITypeInfo object.
6689 * Failure: E_INVALIDARG, if one or more arguments is invalid.
6691 * NOTES
6692 * This call allows an objects methods to be accessed through IDispatch, by
6693 * building an ITypeInfo object that IDispatch can use to call through.
6695 HRESULT WINAPI CreateDispTypeInfo(
6696 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
6697 LCID lcid, /* [I] Locale Id */
6698 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
6700 ITypeInfoImpl *pTIClass, *pTIIface;
6701 ITypeLibImpl *pTypeLibImpl;
6702 int param, func;
6703 TLBFuncDesc **ppFuncDesc;
6705 TRACE("\n");
6706 pTypeLibImpl = TypeLibImpl_Constructor();
6707 if (!pTypeLibImpl) return E_FAIL;
6709 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
6710 pTIIface->pTypeLib = pTypeLibImpl;
6711 pTIIface->index = 0;
6712 pTIIface->Name = NULL;
6713 pTIIface->dwHelpContext = -1;
6714 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
6715 pTIIface->TypeAttr.lcid = lcid;
6716 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
6717 pTIIface->TypeAttr.wMajorVerNum = 0;
6718 pTIIface->TypeAttr.wMinorVerNum = 0;
6719 pTIIface->TypeAttr.cbAlignment = 2;
6720 pTIIface->TypeAttr.cbSizeInstance = -1;
6721 pTIIface->TypeAttr.cbSizeVft = -1;
6722 pTIIface->TypeAttr.cFuncs = 0;
6723 pTIIface->TypeAttr.cImplTypes = 0;
6724 pTIIface->TypeAttr.cVars = 0;
6725 pTIIface->TypeAttr.wTypeFlags = 0;
6727 ppFuncDesc = &pTIIface->funclist;
6728 for(func = 0; func < pidata->cMembers; func++) {
6729 METHODDATA *md = pidata->pmethdata + func;
6730 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
6731 (*ppFuncDesc)->Name = SysAllocString(md->szName);
6732 (*ppFuncDesc)->funcdesc.memid = md->dispid;
6733 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
6734 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
6735 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
6736 (*ppFuncDesc)->funcdesc.callconv = md->cc;
6737 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
6738 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
6739 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
6740 (*ppFuncDesc)->funcdesc.cScodes = 0;
6741 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
6742 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
6743 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
6744 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
6745 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6746 md->cArgs * sizeof(ELEMDESC));
6747 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6748 md->cArgs * sizeof(TLBParDesc));
6749 for(param = 0; param < md->cArgs; param++) {
6750 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
6751 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
6753 (*ppFuncDesc)->helpcontext = 0;
6754 (*ppFuncDesc)->HelpStringContext = 0;
6755 (*ppFuncDesc)->HelpString = NULL;
6756 (*ppFuncDesc)->Entry = NULL;
6757 (*ppFuncDesc)->ctCustData = 0;
6758 (*ppFuncDesc)->pCustData = NULL;
6759 (*ppFuncDesc)->next = NULL;
6760 ppFuncDesc = &(*ppFuncDesc)->next;
6763 dump_TypeInfo(pTIIface);
6765 pTypeLibImpl->pTypeInfo = pTIIface;
6766 pTypeLibImpl->TypeInfoCount++;
6768 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
6769 pTIClass->pTypeLib = pTypeLibImpl;
6770 pTIClass->index = 1;
6771 pTIClass->Name = NULL;
6772 pTIClass->dwHelpContext = -1;
6773 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
6774 pTIClass->TypeAttr.lcid = lcid;
6775 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
6776 pTIClass->TypeAttr.wMajorVerNum = 0;
6777 pTIClass->TypeAttr.wMinorVerNum = 0;
6778 pTIClass->TypeAttr.cbAlignment = 2;
6779 pTIClass->TypeAttr.cbSizeInstance = -1;
6780 pTIClass->TypeAttr.cbSizeVft = -1;
6781 pTIClass->TypeAttr.cFuncs = 0;
6782 pTIClass->TypeAttr.cImplTypes = 1;
6783 pTIClass->TypeAttr.cVars = 0;
6784 pTIClass->TypeAttr.wTypeFlags = 0;
6786 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
6787 pTIClass->impltypelist->hRef = 1;
6789 pTIClass->reflist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->reflist));
6790 pTIClass->reflist->index = 0;
6791 pTIClass->reflist->reference = 1;
6792 pTIClass->reflist->pImpTLInfo = TLB_REF_INTERNAL;
6794 dump_TypeInfo(pTIClass);
6796 pTIIface->next = pTIClass;
6797 pTypeLibImpl->TypeInfoCount++;
6799 *pptinfo = (ITypeInfo*)pTIClass;
6801 ITypeInfo_AddRef(*pptinfo);
6802 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
6804 return S_OK;
6808 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
6810 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6812 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
6815 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
6817 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6819 return ITypeInfo_AddRef((ITypeInfo *)This);
6822 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
6824 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6826 return ITypeInfo_Release((ITypeInfo *)This);
6829 static HRESULT WINAPI ITypeComp_fnBind(
6830 ITypeComp * iface,
6831 OLECHAR * szName,
6832 ULONG lHash,
6833 WORD wFlags,
6834 ITypeInfo ** ppTInfo,
6835 DESCKIND * pDescKind,
6836 BINDPTR * pBindPtr)
6838 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6839 const TLBFuncDesc *pFDesc;
6840 const TLBVarDesc *pVDesc;
6841 HRESULT hr = DISP_E_MEMBERNOTFOUND;
6843 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6845 *pDescKind = DESCKIND_NONE;
6846 pBindPtr->lpfuncdesc = NULL;
6847 *ppTInfo = NULL;
6849 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
6850 if (!strcmpiW(pFDesc->Name, szName)) {
6851 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
6852 break;
6853 else
6854 /* name found, but wrong flags */
6855 hr = TYPE_E_TYPEMISMATCH;
6858 if (pFDesc)
6860 HRESULT hr = TLB_AllocAndInitFuncDesc(
6861 &pFDesc->funcdesc,
6862 &pBindPtr->lpfuncdesc,
6863 This->TypeAttr.typekind == TKIND_DISPATCH);
6864 if (FAILED(hr))
6865 return hr;
6866 *pDescKind = DESCKIND_FUNCDESC;
6867 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6868 ITypeInfo_AddRef(*ppTInfo);
6869 return S_OK;
6870 } else {
6871 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
6872 if (!strcmpiW(pVDesc->Name, szName)) {
6873 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
6874 if (FAILED(hr))
6875 return hr;
6876 *pDescKind = DESCKIND_VARDESC;
6877 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6878 ITypeInfo_AddRef(*ppTInfo);
6879 return S_OK;
6883 /* FIXME: search each inherited interface, not just the first */
6884 if (hr == DISP_E_MEMBERNOTFOUND && This->TypeAttr.cImplTypes) {
6885 /* recursive search */
6886 ITypeInfo *pTInfo;
6887 ITypeComp *pTComp;
6888 HRESULT hr;
6889 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
6890 if (SUCCEEDED(hr))
6892 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
6893 ITypeInfo_Release(pTInfo);
6895 if (SUCCEEDED(hr))
6897 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6898 ITypeComp_Release(pTComp);
6899 return hr;
6901 WARN("Could not search inherited interface!\n");
6903 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
6904 return hr;
6907 static HRESULT WINAPI ITypeComp_fnBindType(
6908 ITypeComp * iface,
6909 OLECHAR * szName,
6910 ULONG lHash,
6911 ITypeInfo ** ppTInfo,
6912 ITypeComp ** ppTComp)
6914 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
6916 /* strange behaviour (does nothing) but like the
6917 * original */
6919 if (!ppTInfo || !ppTComp)
6920 return E_POINTER;
6922 *ppTInfo = NULL;
6923 *ppTComp = NULL;
6925 return S_OK;
6928 static const ITypeCompVtbl tcompvt =
6931 ITypeComp_fnQueryInterface,
6932 ITypeComp_fnAddRef,
6933 ITypeComp_fnRelease,
6935 ITypeComp_fnBind,
6936 ITypeComp_fnBindType