oleaut: Implement processing of modules for SLTG typelibs.
[wine/testsucceed.git] / dlls / oleaut32 / typelib.c
blob8483aa96e958568a05215768645f78f67e7082a7
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.
32 * So when you release the dispinterface, you delete the vtable-interface structures
33 * as well... fortunately, clean up of structures is not implemented.
35 * - locale stuff is partially implemented but hasn't been tested.
37 * - typelib file is still read in its entirety, but it is released now.
38 * - some garbage is read from function names on some very rare occasions.
40 * --------------------------------------------------------------------------------------
41 * Known problems left from previous implementation (1999, Rein Klazes) :
43 * -. Data structures are straightforward, but slow for look-ups.
44 * -. (related) nothing is hashed
45 * -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most
46 * of them I don't know yet how to implement them.
47 * -. Most error return values are just guessed not checked with windows
48 * behaviour.
49 * -. didn't bother with a c++ interface
50 * -. lousy fatal error handling
51 * -. some methods just return pointers to internal data structures, this is
52 * partly laziness, partly I want to check how windows does it.
56 #include "config.h"
57 #include "wine/port.h"
59 #include <stdlib.h>
60 #include <string.h>
61 #include <stdarg.h>
62 #include <stdio.h>
63 #include <ctype.h>
65 #define COBJMACROS
66 #define NONAMELESSUNION
67 #define NONAMELESSSTRUCT
69 #include "winerror.h"
70 #include "windef.h"
71 #include "winbase.h"
72 #include "winnls.h"
73 #include "winreg.h"
74 #include "winuser.h"
76 #include "wine/unicode.h"
77 #include "objbase.h"
78 #include "typelib.h"
79 #include "wine/debug.h"
80 #include "variant.h"
82 WINE_DEFAULT_DEBUG_CHANNEL(ole);
83 WINE_DECLARE_DEBUG_CHANNEL(typelib);
85 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
86 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
88 /****************************************************************************
89 * FromLExxx
91 * Takes p_iVal (which is in little endian) and returns it
92 * in the host machine's byte order.
94 #ifdef WORDS_BIGENDIAN
95 static WORD FromLEWord(WORD p_iVal)
97 return (((p_iVal & 0x00FF) << 8) |
98 ((p_iVal & 0xFF00) >> 8));
102 static DWORD FromLEDWord(DWORD p_iVal)
104 return (((p_iVal & 0x000000FF) << 24) |
105 ((p_iVal & 0x0000FF00) << 8) |
106 ((p_iVal & 0x00FF0000) >> 8) |
107 ((p_iVal & 0xFF000000) >> 24));
109 #else
110 #define FromLEWord(X) (X)
111 #define FromLEDWord(X) (X)
112 #endif
115 /****************************************************************************
116 * FromLExxx
118 * Fix byte order in any structure if necessary
120 #ifdef WORDS_BIGENDIAN
121 static void FromLEWords(void *p_Val, int p_iSize)
123 WORD *Val = p_Val;
125 p_iSize /= sizeof(WORD);
127 while (p_iSize) {
128 *Val = FromLEWord(*Val);
129 Val++;
130 p_iSize--;
135 static void FromLEDWords(void *p_Val, int p_iSize)
137 DWORD *Val = p_Val;
139 p_iSize /= sizeof(DWORD);
141 while (p_iSize) {
142 *Val = FromLEDWord(*Val);
143 Val++;
144 p_iSize--;
147 #else
148 #define FromLEWords(X,Y) /*nothing*/
149 #define FromLEDWords(X,Y) /*nothing*/
150 #endif
152 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
153 /* buffer must be at least 60 characters long */
154 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
156 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
157 static const WCHAR VersionFormatW[] = {'\\','%','u','.','%','u',0};
159 memcpy( buffer, TypelibW, sizeof(TypelibW) );
160 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
161 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
162 return buffer;
165 /* get the path of an interface key, in the form "Interface\\<guid>" */
166 /* buffer must be at least 50 characters long */
167 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
169 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
171 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
172 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
173 return buffer;
176 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
177 /* buffer must be at least 16 characters long */
178 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
180 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
181 static const WCHAR win16W[] = {'w','i','n','1','6',0};
182 static const WCHAR win32W[] = {'w','i','n','3','2',0};
184 sprintfW( buffer, LcidFormatW, lcid );
185 switch(syskind)
187 case SYS_WIN16: strcatW( buffer, win16W ); break;
188 case SYS_WIN32: strcatW( buffer, win32W ); break;
189 default:
190 TRACE("Typelib is for unsupported syskind %i\n", syskind);
191 return NULL;
193 return buffer;
196 static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
199 /****************************************************************************
200 * QueryPathOfRegTypeLib [OLEAUT32.164]
202 * Gets the path to a registered type library.
204 * PARAMS
205 * guid [I] referenced guid
206 * wMaj [I] major version
207 * wMin [I] minor version
208 * lcid [I] locale id
209 * path [O] path of typelib
211 * RETURNS
212 * Success: S_OK.
213 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
214 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
215 * opened.
217 HRESULT WINAPI QueryPathOfRegTypeLib(
218 REFGUID guid,
219 WORD wMaj,
220 WORD wMin,
221 LCID lcid,
222 LPBSTR path )
224 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
225 LCID myLCID = lcid;
226 HKEY hkey;
227 WCHAR buffer[60];
228 WCHAR Path[MAX_PATH];
229 LONG res;
231 TRACE_(typelib)("(%s, %x.%x, 0x%lx, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
233 get_typelib_key( guid, wMaj, wMin, buffer );
235 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
236 if (res == ERROR_FILE_NOT_FOUND)
238 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
239 return TYPE_E_LIBNOTREGISTERED;
241 else if (res != ERROR_SUCCESS)
243 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
244 return TYPE_E_REGISTRYACCESS;
247 while (hr != S_OK)
249 LONG dwPathLen = sizeof(Path);
251 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
253 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
255 if (!lcid)
256 break;
257 else if (myLCID == lcid)
259 /* try with sub-langid */
260 myLCID = SUBLANGID(lcid);
262 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
264 /* try with system langid */
265 myLCID = 0;
267 else
269 break;
272 else
274 *path = SysAllocString( Path );
275 hr = S_OK;
278 RegCloseKey( hkey );
279 TRACE_(typelib)("-- 0x%08lx\n", hr);
280 return hr;
283 /******************************************************************************
284 * CreateTypeLib [OLEAUT32.160] creates a typelib
286 * RETURNS
287 * Success: S_OK
288 * Failure: Status
290 HRESULT WINAPI CreateTypeLib(
291 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
293 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
294 return E_FAIL;
297 /******************************************************************************
298 * LoadTypeLib [OLEAUT32.161]
300 * Loads a type library
302 * PARAMS
303 * szFile [I] Name of file to load from.
304 * pptLib [O] Pointer that receives ITypeLib object on success.
306 * RETURNS
307 * Success: S_OK
308 * Failure: Status
310 * SEE
311 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
313 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
315 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
316 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
319 /******************************************************************************
320 * LoadTypeLibEx [OLEAUT32.183]
322 * Loads and optionally registers a type library
324 * RETURNS
325 * Success: S_OK
326 * Failure: Status
328 HRESULT WINAPI LoadTypeLibEx(
329 LPCOLESTR szFile, /* [in] Name of file to load from */
330 REGKIND regkind, /* [in] Specify kind of registration */
331 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
333 WCHAR szPath[MAX_PATH+1];
334 HRESULT res;
336 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
338 *pptLib = NULL;
340 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
342 if (SUCCEEDED(res))
343 switch(regkind)
345 case REGKIND_DEFAULT:
346 /* don't register typelibs supplied with full path. Experimentation confirms the following */
347 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
348 (szFile[0] && (szFile[1] == ':'))) break;
349 /* else fall-through */
351 case REGKIND_REGISTER:
352 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
354 IUnknown_Release(*pptLib);
355 *pptLib = 0;
357 break;
358 case REGKIND_NONE:
359 break;
362 TRACE(" returns %08lx\n",res);
363 return res;
366 /******************************************************************************
367 * LoadRegTypeLib [OLEAUT32.162]
369 * Loads a registered type library.
371 * PARAMS
372 * rguid [I] GUID of the registered type library.
373 * wVerMajor [I] major version.
374 * wVerMinor [I] minor version.
375 * lcid [I] locale ID.
376 * ppTLib [O] pointer that receives an ITypeLib object on success.
378 * RETURNS
379 * Success: S_OK.
380 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
381 * LoadTypeLib.
383 HRESULT WINAPI LoadRegTypeLib(
384 REFGUID rguid,
385 WORD wVerMajor,
386 WORD wVerMinor,
387 LCID lcid,
388 ITypeLib **ppTLib)
390 BSTR bstr=NULL;
391 HRESULT res;
393 *ppTLib = NULL;
395 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
397 if(SUCCEEDED(res))
399 res= LoadTypeLib(bstr, ppTLib);
400 SysFreeString(bstr);
403 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
405 return res;
409 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
410 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
411 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
412 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
413 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
414 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
416 /******************************************************************************
417 * RegisterTypeLib [OLEAUT32.163]
418 * Adds information about a type library to the System Registry
419 * NOTES
420 * Docs: ITypeLib FAR * ptlib
421 * Docs: OLECHAR FAR* szFullPath
422 * Docs: OLECHAR FAR* szHelpDir
424 * RETURNS
425 * Success: S_OK
426 * Failure: Status
428 HRESULT WINAPI RegisterTypeLib(
429 ITypeLib * ptlib, /* [in] Pointer to the library*/
430 OLECHAR * szFullPath, /* [in] full Path of the library*/
431 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
432 may be NULL*/
434 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
435 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
436 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
437 HRESULT res;
438 TLIBATTR *attr;
439 WCHAR keyName[60];
440 WCHAR tmp[16];
441 HKEY key, subKey;
442 UINT types, tidx;
443 TYPEKIND kind;
444 DWORD disposition;
446 if (ptlib == NULL || szFullPath == NULL)
447 return E_INVALIDARG;
449 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
450 return E_FAIL;
452 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
454 res = S_OK;
455 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
456 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
458 LPOLESTR doc;
460 /* Set the human-readable name of the typelib */
461 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
463 if (RegSetValueExW(key, NULL, 0, REG_SZ,
464 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
465 res = E_FAIL;
467 SysFreeString(doc);
469 else
470 res = E_FAIL;
472 /* Make up the name of the typelib path subkey */
473 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
475 /* Create the typelib path subkey */
476 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
477 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
479 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
480 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
481 res = E_FAIL;
483 RegCloseKey(subKey);
485 else
486 res = E_FAIL;
488 /* Create the flags subkey */
489 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
490 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
492 /* FIXME: is %u correct? */
493 static const WCHAR formatW[] = {'%','u',0};
494 WCHAR buf[20];
495 sprintfW(buf, formatW, attr->wLibFlags);
496 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
497 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
498 res = E_FAIL;
500 RegCloseKey(subKey);
502 else
503 res = E_FAIL;
505 /* create the helpdir subkey */
506 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
507 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
509 BOOL freeHelpDir = FALSE;
510 OLECHAR* pIndexStr;
512 /* if we created a new key, and helpDir was null, set the helpdir
513 to the directory which contains the typelib. However,
514 if we just opened an existing key, we leave the helpdir alone */
515 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
516 szHelpDir = SysAllocString(szFullPath);
517 pIndexStr = strrchrW(szHelpDir, '\\');
518 if (pIndexStr) {
519 *pIndexStr = 0;
521 freeHelpDir = TRUE;
524 /* if we have an szHelpDir, set it! */
525 if (szHelpDir != NULL) {
526 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
527 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
528 res = E_FAIL;
532 /* tidy up */
533 if (freeHelpDir) SysFreeString(szHelpDir);
534 RegCloseKey(subKey);
536 } else {
537 res = E_FAIL;
540 RegCloseKey(key);
542 else
543 res = E_FAIL;
545 /* register OLE Automation-compatible interfaces for this typelib */
546 types = ITypeLib_GetTypeInfoCount(ptlib);
547 for (tidx=0; tidx<types; tidx++) {
548 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
549 LPOLESTR name = NULL;
550 ITypeInfo *tinfo = NULL;
552 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
554 switch (kind) {
555 case TKIND_INTERFACE:
556 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
557 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
558 break;
560 case TKIND_DISPATCH:
561 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
562 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
563 break;
565 default:
566 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
567 break;
570 if (tinfo) {
571 TYPEATTR *tattr = NULL;
572 ITypeInfo_GetTypeAttr(tinfo, &tattr);
574 if (tattr) {
575 TRACE_(typelib)("guid=%s, flags=%04x (",
576 debugstr_guid(&tattr->guid),
577 tattr->wTypeFlags);
579 if (TRACE_ON(typelib)) {
580 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
581 XX(FAPPOBJECT);
582 XX(FCANCREATE);
583 XX(FLICENSED);
584 XX(FPREDECLID);
585 XX(FHIDDEN);
586 XX(FCONTROL);
587 XX(FDUAL);
588 XX(FNONEXTENSIBLE);
589 XX(FOLEAUTOMATION);
590 XX(FRESTRICTED);
591 XX(FAGGREGATABLE);
592 XX(FREPLACEABLE);
593 XX(FDISPATCHABLE);
594 XX(FREVERSEBIND);
595 XX(FPROXY);
596 #undef XX
597 MESSAGE("\n");
600 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDISPATCHABLE))
602 /* register interface<->typelib coupling */
603 get_interface_key( &tattr->guid, keyName );
604 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
605 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
607 if (name)
608 RegSetValueExW(key, NULL, 0, REG_SZ,
609 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
611 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
612 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
613 RegSetValueExW(subKey, NULL, 0, REG_SZ,
614 (BYTE*)PSOA, sizeof PSOA);
615 RegCloseKey(subKey);
618 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
619 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
620 RegSetValueExW(subKey, NULL, 0, REG_SZ,
621 (BYTE*)PSOA, sizeof PSOA);
622 RegCloseKey(subKey);
625 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
626 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
628 WCHAR buffer[40];
629 static const WCHAR fmtver[] = {'%','u','.','%','u',0 };
630 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
632 StringFromGUID2(&attr->guid, buffer, 40);
633 RegSetValueExW(subKey, NULL, 0, REG_SZ,
634 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
635 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
636 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
637 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
638 RegCloseKey(subKey);
641 RegCloseKey(key);
645 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
648 ITypeInfo_Release(tinfo);
651 SysFreeString(name);
655 ITypeLib_ReleaseTLibAttr(ptlib, attr);
657 return res;
661 /******************************************************************************
662 * UnRegisterTypeLib [OLEAUT32.186]
663 * Removes information about a type library from the System Registry
664 * NOTES
666 * RETURNS
667 * Success: S_OK
668 * Failure: Status
670 HRESULT WINAPI UnRegisterTypeLib(
671 REFGUID libid, /* [in] Guid of the library */
672 WORD wVerMajor, /* [in] major version */
673 WORD wVerMinor, /* [in] minor version */
674 LCID lcid, /* [in] locale id */
675 SYSKIND syskind)
677 BSTR tlibPath = NULL;
678 DWORD tmpLength;
679 WCHAR keyName[60];
680 WCHAR subKeyName[50];
681 int result = S_OK;
682 DWORD i = 0;
683 BOOL deleteOtherStuff;
684 HKEY key = NULL;
685 HKEY subKey = NULL;
686 TYPEATTR* typeAttr = NULL;
687 TYPEKIND kind;
688 ITypeInfo* typeInfo = NULL;
689 ITypeLib* typeLib = NULL;
690 int numTypes;
692 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
694 /* Create the path to the key */
695 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
697 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
699 TRACE("Unsupported syskind %i\n", syskind);
700 result = E_INVALIDARG;
701 goto end;
704 /* get the path to the typelib on disk */
705 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
706 result = E_INVALIDARG;
707 goto end;
710 /* Try and open the key to the type library. */
711 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != S_OK) {
712 result = E_INVALIDARG;
713 goto end;
716 /* Try and load the type library */
717 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
718 result = TYPE_E_INVALIDSTATE;
719 goto end;
722 /* remove any types registered with this typelib */
723 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
724 for (i=0; i<numTypes; i++) {
725 /* get the kind of type */
726 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
727 goto enddeleteloop;
730 /* skip non-interfaces, and get type info for the type */
731 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
732 goto enddeleteloop;
734 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
735 goto enddeleteloop;
737 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
738 goto enddeleteloop;
741 /* the path to the type */
742 get_interface_key( &typeAttr->guid, subKeyName );
744 /* Delete its bits */
745 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != S_OK) {
746 goto enddeleteloop;
748 RegDeleteKeyW(subKey, ProxyStubClsidW);
749 RegDeleteKeyW(subKey, ProxyStubClsid32W);
750 RegDeleteKeyW(subKey, TypeLibW);
751 RegCloseKey(subKey);
752 subKey = NULL;
753 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
755 enddeleteloop:
756 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
757 typeAttr = NULL;
758 if (typeInfo) ITypeInfo_Release(typeInfo);
759 typeInfo = NULL;
762 /* Now, delete the type library path subkey */
763 get_lcid_subkey( lcid, syskind, subKeyName );
764 RegDeleteKeyW(key, subKeyName);
765 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
766 RegDeleteKeyW(key, subKeyName);
768 /* check if there is anything besides the FLAGS/HELPDIR keys.
769 If there is, we don't delete them */
770 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
771 deleteOtherStuff = TRUE;
772 i = 0;
773 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == S_OK) {
774 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
776 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
777 if (!strcmpW(subKeyName, FLAGSW)) continue;
778 if (!strcmpW(subKeyName, HELPDIRW)) continue;
779 deleteOtherStuff = FALSE;
780 break;
783 /* only delete the other parts of the key if we're absolutely sure */
784 if (deleteOtherStuff) {
785 RegDeleteKeyW(key, FLAGSW);
786 RegDeleteKeyW(key, HELPDIRW);
787 RegCloseKey(key);
788 key = NULL;
790 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
791 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
792 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
795 end:
796 if (tlibPath) SysFreeString(tlibPath);
797 if (typeLib) ITypeLib_Release(typeLib);
798 if (subKey) RegCloseKey(subKey);
799 if (key) RegCloseKey(key);
800 return result;
803 /*======================= ITypeLib implementation =======================*/
805 typedef struct tagTLBCustData
807 GUID guid;
808 VARIANT data;
809 struct tagTLBCustData* next;
810 } TLBCustData;
812 /* data structure for import typelibs */
813 typedef struct tagTLBImpLib
815 int offset; /* offset in the file (MSFT)
816 offset in nametable (SLTG)
817 just used to identify library while reading
818 data from file */
819 GUID guid; /* libid */
820 BSTR name; /* name */
822 LCID lcid; /* lcid of imported typelib */
824 WORD wVersionMajor; /* major version number */
825 WORD wVersionMinor; /* minor version number */
827 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
828 NULL if not yet loaded */
829 struct tagTLBImpLib * next;
830 } TLBImpLib;
832 /* internal ITypeLib data */
833 typedef struct tagITypeLibImpl
835 const ITypeLib2Vtbl *lpVtbl;
836 const ITypeCompVtbl *lpVtblTypeComp;
837 LONG ref;
838 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
840 /* strings can be stored in tlb as multibyte strings BUT they are *always*
841 * exported to the application as a UNICODE string.
843 BSTR Name;
844 BSTR DocString;
845 BSTR HelpFile;
846 BSTR HelpStringDll;
847 unsigned long dwHelpContext;
848 int TypeInfoCount; /* nr of typeinfo's in librarry */
849 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
850 int ctCustData; /* number of items in cust data list */
851 TLBCustData * pCustData; /* linked list to cust data */
852 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
853 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
854 libary. Only used while read MSFT
855 typelibs */
857 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
858 struct tagITypeLibImpl *next, *prev;
859 WCHAR *path;
860 INT index;
861 } ITypeLibImpl;
863 static const ITypeLib2Vtbl tlbvt;
864 static const ITypeCompVtbl tlbtcvt;
866 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
868 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
871 /* ITypeLib methods */
872 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
873 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
875 /*======================= ITypeInfo implementation =======================*/
877 /* data for referenced types */
878 typedef struct tagTLBRefType
880 INT index; /* Type index for internal ref or for external ref
881 it the format is SLTG. -2 indicates to
882 use guid */
884 GUID guid; /* guid of the referenced type */
885 /* if index == TLB_REF_USE_GUID */
887 HREFTYPE reference; /* The href of this ref */
888 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
889 TLB_REF_INTERNAL for internal refs
890 TLB_REF_NOT_FOUND for broken refs */
892 struct tagTLBRefType * next;
893 } TLBRefType;
895 #define TLB_REF_USE_GUID -2
897 #define TLB_REF_INTERNAL (void*)-2
898 #define TLB_REF_NOT_FOUND (void*)-1
900 /* internal Parameter data */
901 typedef struct tagTLBParDesc
903 BSTR Name;
904 int ctCustData;
905 TLBCustData * pCustData; /* linked list to cust data */
906 } TLBParDesc;
908 /* internal Function data */
909 typedef struct tagTLBFuncDesc
911 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
912 BSTR Name; /* the name of this function */
913 TLBParDesc *pParamDesc; /* array with param names and custom data */
914 int helpcontext;
915 int HelpStringContext;
916 BSTR HelpString;
917 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
918 int ctCustData;
919 TLBCustData * pCustData; /* linked list to cust data; */
920 struct tagTLBFuncDesc * next;
921 } TLBFuncDesc;
923 /* internal Variable data */
924 typedef struct tagTLBVarDesc
926 VARDESC vardesc; /* lots of info on the variable and its attributes. */
927 BSTR Name; /* the name of this variable */
928 int HelpContext;
929 int HelpStringContext; /* FIXME: where? */
930 BSTR HelpString;
931 int ctCustData;
932 TLBCustData * pCustData;/* linked list to cust data; */
933 struct tagTLBVarDesc * next;
934 } TLBVarDesc;
936 /* internal implemented interface data */
937 typedef struct tagTLBImplType
939 HREFTYPE hRef; /* hRef of interface */
940 int implflags; /* IMPLFLAG_*s */
941 int ctCustData;
942 TLBCustData * pCustData;/* linked list to custom data; */
943 struct tagTLBImplType *next;
944 } TLBImplType;
946 /* internal TypeInfo data */
947 typedef struct tagITypeInfoImpl
949 const ITypeInfo2Vtbl *lpVtbl;
950 const ITypeCompVtbl *lpVtblTypeComp;
951 LONG ref;
952 TYPEATTR TypeAttr ; /* _lots_ of type information. */
953 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
954 int index; /* index in this typelib; */
955 HREFTYPE hreftype; /* hreftype for app object binding */
956 /* type libs seem to store the doc strings in ascii
957 * so why should we do it in unicode?
959 BSTR Name;
960 BSTR DocString;
961 BSTR DllName;
962 unsigned long dwHelpContext;
963 unsigned long dwHelpStringContext;
965 /* functions */
966 TLBFuncDesc * funclist; /* linked list with function descriptions */
968 /* variables */
969 TLBVarDesc * varlist; /* linked list with variable descriptions */
971 /* Implemented Interfaces */
972 TLBImplType * impltypelist;
974 TLBRefType * reflist;
975 int ctCustData;
976 TLBCustData * pCustData; /* linked list to cust data; */
977 struct tagITypeInfoImpl * next;
978 } ITypeInfoImpl;
980 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
982 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
985 static const ITypeInfo2Vtbl tinfvt;
986 static const ITypeCompVtbl tcompvt;
988 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
990 typedef struct tagTLBContext
992 unsigned int oStart; /* start of TLB in file */
993 unsigned int pos; /* current pos */
994 unsigned int length; /* total length */
995 void *mapping; /* memory mapping */
996 MSFT_SegDir * pTblDir;
997 ITypeLibImpl* pLibInfo;
998 } TLBContext;
1001 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
1004 debug
1006 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1007 if (pTD->vt & VT_RESERVED)
1008 szVarType += strlen(strcpy(szVarType, "reserved | "));
1009 if (pTD->vt & VT_BYREF)
1010 szVarType += strlen(strcpy(szVarType, "ref to "));
1011 if (pTD->vt & VT_ARRAY)
1012 szVarType += strlen(strcpy(szVarType, "array of "));
1013 if (pTD->vt & VT_VECTOR)
1014 szVarType += strlen(strcpy(szVarType, "vector of "));
1015 switch(pTD->vt & VT_TYPEMASK) {
1016 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1017 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1018 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1019 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1020 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1021 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1022 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1023 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1024 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1025 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1026 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1027 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1028 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1029 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1030 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1031 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1032 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1033 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1034 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1035 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1036 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
1037 pTD->u.hreftype); break;
1038 case VT_PTR: sprintf(szVarType, "ptr to ");
1039 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1040 break;
1041 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1042 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1043 break;
1044 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1045 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1046 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1047 break;
1049 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1053 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1054 char buf[200];
1055 USHORT flags = edesc->u.paramdesc.wParamFlags;
1056 dump_TypeDesc(&edesc->tdesc,buf);
1057 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1058 MESSAGE("\t\tu.paramdesc.wParamFlags");
1059 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1060 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1061 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1062 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1063 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1064 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1065 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1066 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1067 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1069 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1070 int i;
1071 MESSAGE("memid is %08lx\n",funcdesc->memid);
1072 for (i=0;i<funcdesc->cParams;i++) {
1073 MESSAGE("Param %d:\n",i);
1074 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1076 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1077 switch (funcdesc->funckind) {
1078 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1079 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1080 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1081 case FUNC_STATIC: MESSAGE("static");break;
1082 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1083 default: MESSAGE("unknown");break;
1085 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1086 switch (funcdesc->invkind) {
1087 case INVOKE_FUNC: MESSAGE("func");break;
1088 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1089 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1090 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1092 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1093 switch (funcdesc->callconv) {
1094 case CC_CDECL: MESSAGE("cdecl");break;
1095 case CC_PASCAL: MESSAGE("pascal");break;
1096 case CC_STDCALL: MESSAGE("stdcall");break;
1097 case CC_SYSCALL: MESSAGE("syscall");break;
1098 default:break;
1100 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1101 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1102 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1104 MESSAGE("\telemdescFunc (return value type):\n");
1105 dump_ELEMDESC(&funcdesc->elemdescFunc);
1108 static const char * typekind_desc[] =
1110 "TKIND_ENUM",
1111 "TKIND_RECORD",
1112 "TKIND_MODULE",
1113 "TKIND_INTERFACE",
1114 "TKIND_DISPATCH",
1115 "TKIND_COCLASS",
1116 "TKIND_ALIAS",
1117 "TKIND_UNION",
1118 "TKIND_MAX"
1121 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1123 int i;
1124 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1125 for (i=0;i<pfd->funcdesc.cParams;i++)
1126 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1129 dump_FUNCDESC(&(pfd->funcdesc));
1131 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1132 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
1134 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1136 while (pfd)
1138 dump_TLBFuncDescOne(pfd);
1139 pfd = pfd->next;
1142 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1144 while (pvd)
1146 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1147 pvd = pvd->next;
1151 static void dump_TLBImpLib(const TLBImpLib *import)
1153 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1154 debugstr_w(import->name));
1155 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
1156 import->wVersionMinor, import->lcid, import->offset);
1159 static void dump_TLBRefType(const TLBRefType * prt)
1161 while (prt)
1163 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
1164 if(prt->index == -1)
1165 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1166 else
1167 TRACE_(typelib)("type no: %d\n", prt->index);
1169 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1170 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1171 TRACE_(typelib)("in lib\n");
1172 dump_TLBImpLib(prt->pImpTLInfo);
1174 prt = prt->next;
1178 static void dump_TLBImplType(const TLBImplType * impl)
1180 while (impl) {
1181 TRACE_(typelib)(
1182 "implementing/inheriting interface hRef = %lx implflags %x\n",
1183 impl->hRef, impl->implflags);
1184 impl = impl->next;
1188 void dump_Variant(const VARIANT * pvar)
1190 SYSTEMTIME st;
1192 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1194 if (pvar)
1196 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1197 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1199 TRACE(",%p", V_BYREF(pvar));
1201 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1203 TRACE(",%p", V_ARRAY(pvar));
1205 else switch (V_TYPE(pvar))
1207 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1208 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1209 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1210 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1211 case VT_INT:
1212 case VT_I4: TRACE(",%ld", V_I4(pvar)); break;
1213 case VT_UINT:
1214 case VT_UI4: TRACE(",%ld", V_UI4(pvar)); break;
1215 case VT_I8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_I8(pvar) >> 32),
1216 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1217 case VT_UI8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_UI8(pvar) >> 32),
1218 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1219 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1220 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1221 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1222 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1223 case VT_CY: TRACE(",0x%08lx,0x%08lx", V_CY(pvar).s.Hi,
1224 V_CY(pvar).s.Lo); break;
1225 case VT_DATE:
1226 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1227 TRACE(",<invalid>");
1228 else
1229 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1230 st.wHour, st.wMinute, st.wSecond);
1231 break;
1232 case VT_ERROR:
1233 case VT_VOID:
1234 case VT_USERDEFINED:
1235 case VT_EMPTY:
1236 case VT_NULL: break;
1237 default: TRACE(",?"); break;
1240 TRACE("}\n");
1243 static void dump_DispParms(const DISPPARAMS * pdp)
1245 int index = 0;
1247 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1249 while (index < pdp->cArgs)
1251 dump_Variant( &pdp->rgvarg[index] );
1252 ++index;
1256 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1258 TRACE("%p ref=%lu\n", pty, pty->ref);
1259 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1260 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1261 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1262 TRACE("fct:%u var:%u impl:%u\n",
1263 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1264 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1265 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1266 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1267 if (TRACE_ON(ole))
1268 dump_TLBFuncDesc(pty->funclist);
1269 dump_TLBVarDesc(pty->varlist);
1270 dump_TLBImplType(pty->impltypelist);
1273 static void dump_VARDESC(const VARDESC *v)
1275 MESSAGE("memid %ld\n",v->memid);
1276 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1277 MESSAGE("oInst %ld\n",v->u.oInst);
1278 dump_ELEMDESC(&(v->elemdescVar));
1279 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1280 MESSAGE("varkind %d\n",v->varkind);
1283 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1285 /* VT_LPWSTR is largest type that */
1286 /* may appear in type description*/
1287 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1288 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1289 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1290 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1291 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1292 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1293 {{0},30},{{0},31}
1296 static void TLB_abort(void)
1298 DebugBreak();
1300 static void * TLB_Alloc(unsigned size)
1302 void * ret;
1303 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1304 /* FIXME */
1305 ERR("cannot allocate memory\n");
1307 return ret;
1310 static void TLB_Free(void * ptr)
1312 HeapFree(GetProcessHeap(), 0, ptr);
1315 /* returns the size required for a deep copy of a typedesc into a
1316 * flat buffer */
1317 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1319 SIZE_T size = 0;
1321 if (alloc_initial_space)
1322 size += sizeof(TYPEDESC);
1324 switch (tdesc->vt)
1326 case VT_PTR:
1327 case VT_SAFEARRAY:
1328 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1329 break;
1330 case VT_CARRAY:
1331 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1332 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1333 break;
1335 return size;
1338 /* deep copy a typedesc into a flat buffer */
1339 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1341 if (!dest)
1343 dest = buffer;
1344 buffer = (char *)buffer + sizeof(TYPEDESC);
1347 *dest = *src;
1349 switch (src->vt)
1351 case VT_PTR:
1352 case VT_SAFEARRAY:
1353 dest->u.lptdesc = buffer;
1354 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1355 break;
1356 case VT_CARRAY:
1357 dest->u.lpadesc = buffer;
1358 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1359 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1360 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1361 break;
1363 return buffer;
1366 /**********************************************************************
1368 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1370 static inline unsigned int MSFT_Tell(TLBContext *pcx)
1372 return pcx->pos;
1375 static inline void MSFT_Seek(TLBContext *pcx, long where)
1377 if (where != DO_NOT_SEEK)
1379 where += pcx->oStart;
1380 if (where > pcx->length)
1382 /* FIXME */
1383 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1384 TLB_abort();
1386 pcx->pos = where;
1390 /* read function */
1391 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1393 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1394 pcx->pos, count, pcx->oStart, pcx->length, where);
1396 MSFT_Seek(pcx, where);
1397 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1398 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1399 pcx->pos += count;
1400 return count;
1403 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1404 long where )
1406 DWORD ret;
1408 ret = MSFT_Read(buffer, count, pcx, where);
1409 FromLEDWords(buffer, ret);
1411 return ret;
1414 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1415 long where )
1417 DWORD ret;
1419 ret = MSFT_Read(buffer, count, pcx, where);
1420 FromLEWords(buffer, ret);
1422 return ret;
1425 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1427 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1428 memset(pGuid,0, sizeof(GUID));
1429 return;
1431 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1432 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1433 pGuid->Data2 = FromLEWord(pGuid->Data2);
1434 pGuid->Data3 = FromLEWord(pGuid->Data3);
1435 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1438 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1440 MSFT_NameIntro niName;
1442 if (offset < 0)
1444 ERR_(typelib)("bad offset %d\n", offset);
1445 return -1;
1448 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1449 pcx->pTblDir->pNametab.offset+offset);
1451 return niName.hreftype;
1454 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1456 char * name;
1457 MSFT_NameIntro niName;
1458 int lengthInChars;
1459 WCHAR* pwstring = NULL;
1460 BSTR bstrName = NULL;
1462 if (offset < 0)
1464 ERR_(typelib)("bad offset %d\n", offset);
1465 return NULL;
1467 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1468 pcx->pTblDir->pNametab.offset+offset);
1469 niName.namelen &= 0xFF; /* FIXME: correct ? */
1470 name=TLB_Alloc((niName.namelen & 0xff) +1);
1471 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1472 name[niName.namelen & 0xff]='\0';
1474 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1475 name, -1, NULL, 0);
1477 /* no invalid characters in string */
1478 if (lengthInChars)
1480 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1482 /* don't check for invalid character since this has been done previously */
1483 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1485 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1486 lengthInChars = SysStringLen(bstrName);
1487 HeapFree(GetProcessHeap(), 0, pwstring);
1490 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1491 return bstrName;
1494 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1496 char * string;
1497 INT16 length;
1498 int lengthInChars;
1499 BSTR bstr = NULL;
1501 if(offset<0) return NULL;
1502 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1503 if(length <= 0) return 0;
1504 string=TLB_Alloc(length +1);
1505 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1506 string[length]='\0';
1508 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1509 string, -1, NULL, 0);
1511 /* no invalid characters in string */
1512 if (lengthInChars)
1514 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1516 /* don't check for invalid character since this has been done previously */
1517 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1519 bstr = SysAllocStringLen(pwstring, lengthInChars);
1520 lengthInChars = SysStringLen(bstr);
1521 HeapFree(GetProcessHeap(), 0, pwstring);
1524 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1525 return bstr;
1528 * read a value and fill a VARIANT structure
1530 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1532 int size;
1534 TRACE_(typelib)("\n");
1536 if(offset <0) { /* data are packed in here */
1537 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1538 V_I4(pVar) = offset & 0x3ffffff;
1539 return;
1541 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1542 pcx->pTblDir->pCustData.offset + offset );
1543 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1544 switch (V_VT(pVar)){
1545 case VT_EMPTY: /* FIXME: is this right? */
1546 case VT_NULL: /* FIXME: is this right? */
1547 case VT_I2 : /* this should not happen */
1548 case VT_I4 :
1549 case VT_R4 :
1550 case VT_ERROR :
1551 case VT_BOOL :
1552 case VT_I1 :
1553 case VT_UI1 :
1554 case VT_UI2 :
1555 case VT_UI4 :
1556 case VT_INT :
1557 case VT_UINT :
1558 case VT_VOID : /* FIXME: is this right? */
1559 case VT_HRESULT :
1560 size=4; break;
1561 case VT_R8 :
1562 case VT_CY :
1563 case VT_DATE :
1564 case VT_I8 :
1565 case VT_UI8 :
1566 case VT_DECIMAL : /* FIXME: is this right? */
1567 case VT_FILETIME :
1568 size=8;break;
1569 /* pointer types with known behaviour */
1570 case VT_BSTR :{
1571 char * ptr;
1572 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1573 if(size < 0) {
1574 char next;
1575 DWORD origPos = MSFT_Tell(pcx), nullPos;
1577 do {
1578 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1579 } while (next);
1580 nullPos = MSFT_Tell(pcx);
1581 size = nullPos - origPos;
1582 MSFT_Seek(pcx, origPos);
1584 ptr=TLB_Alloc(size);/* allocate temp buffer */
1585 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1586 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1587 /* FIXME: do we need a AtoW conversion here? */
1588 V_UNION(pVar, bstrVal[size])=L'\0';
1589 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1590 TLB_Free(ptr);
1592 size=-4; break;
1593 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1594 case VT_DISPATCH :
1595 case VT_VARIANT :
1596 case VT_UNKNOWN :
1597 case VT_PTR :
1598 case VT_SAFEARRAY :
1599 case VT_CARRAY :
1600 case VT_USERDEFINED :
1601 case VT_LPSTR :
1602 case VT_LPWSTR :
1603 case VT_BLOB :
1604 case VT_STREAM :
1605 case VT_STORAGE :
1606 case VT_STREAMED_OBJECT :
1607 case VT_STORED_OBJECT :
1608 case VT_BLOB_OBJECT :
1609 case VT_CF :
1610 case VT_CLSID :
1611 default:
1612 size=0;
1613 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1614 V_VT(pVar));
1617 if(size>0) /* (big|small) endian correct? */
1618 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1619 return;
1622 * create a linked list with custom data
1624 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1626 MSFT_CDGuid entry;
1627 TLBCustData* pNew;
1628 int count=0;
1630 TRACE_(typelib)("\n");
1632 while(offset >=0){
1633 count++;
1634 pNew=TLB_Alloc(sizeof(TLBCustData));
1635 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1636 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1637 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1638 /* add new custom data at head of the list */
1639 pNew->next=*ppCustData;
1640 *ppCustData=pNew;
1641 offset = entry.next;
1643 return count;
1646 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1647 ITypeInfoImpl *pTI)
1649 if(type <0)
1650 pTd->vt=type & VT_TYPEMASK;
1651 else
1652 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1654 if(pTd->vt == VT_USERDEFINED)
1655 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1657 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1660 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1662 /* resolve referenced type if any */
1663 while (lpTypeDesc)
1665 switch (lpTypeDesc->vt)
1667 case VT_PTR:
1668 lpTypeDesc = lpTypeDesc->u.lptdesc;
1669 break;
1671 case VT_CARRAY:
1672 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1673 break;
1675 case VT_USERDEFINED:
1676 MSFT_DoRefType(pcx, pTI,
1677 lpTypeDesc->u.hreftype);
1679 lpTypeDesc = NULL;
1680 break;
1682 default:
1683 lpTypeDesc = NULL;
1688 static void
1689 MSFT_DoFuncs(TLBContext* pcx,
1690 ITypeInfoImpl* pTI,
1691 int cFuncs,
1692 int cVars,
1693 int offset,
1694 TLBFuncDesc** pptfd)
1697 * member information is stored in a data structure at offset
1698 * indicated by the memoffset field of the typeinfo structure
1699 * There are several distinctive parts.
1700 * The first part starts with a field that holds the total length
1701 * of this (first) part excluding this field. Then follow the records,
1702 * for each member there is one record.
1704 * The first entry is always the length of the record (including this
1705 * length word).
1706 * The rest of the record depends on the type of the member. If there is
1707 * a field indicating the member type (function, variable, interface, etc)
1708 * I have not found it yet. At this time we depend on the information
1709 * in the type info and the usual order how things are stored.
1711 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1712 * for each member;
1714 * Third is an equal sized array with file offsets to the name entry
1715 * of each member.
1717 * The fourth and last (?) part is an array with offsets to the records
1718 * in the first part of this file segment.
1721 int infolen, nameoffset, reclength, nrattributes, i;
1722 int recoffset = offset + sizeof(INT);
1724 char recbuf[512];
1725 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1726 TLBFuncDesc *ptfd_prev = NULL;
1728 TRACE_(typelib)("\n");
1730 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1732 for ( i = 0; i < cFuncs ; i++ )
1734 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1736 /* name, eventually add to a hash table */
1737 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1738 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1740 /* nameoffset is sometimes -1 on the second half of a propget/propput
1741 * pair of functions */
1742 if ((nameoffset == -1) && (i > 0))
1743 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1744 else
1745 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1747 /* read the function information record */
1748 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1750 reclength &= 0x1ff;
1752 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1754 /* do the attributes */
1755 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1756 / sizeof(int);
1758 if ( nrattributes > 0 )
1760 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1762 if ( nrattributes > 1 )
1764 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1765 pFuncRec->OptAttr[1]) ;
1767 if ( nrattributes > 2 )
1769 if ( pFuncRec->FKCCIC & 0x2000 )
1771 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1773 else
1775 (*pptfd)->Entry = MSFT_ReadString(pcx,
1776 pFuncRec->OptAttr[2]);
1778 if( nrattributes > 5 )
1780 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1782 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1784 MSFT_CustData(pcx,
1785 pFuncRec->OptAttr[6],
1786 &(*pptfd)->pCustData);
1793 /* fill the FuncDesc Structure */
1794 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1795 offset + infolen + ( i + 1) * sizeof(INT));
1797 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1798 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1799 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1800 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1801 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1802 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1803 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1805 MSFT_GetTdesc(pcx,
1806 pFuncRec->DataType,
1807 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1808 pTI);
1809 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1811 /* do the parameters/arguments */
1812 if(pFuncRec->nrargs)
1814 int j = 0;
1815 MSFT_ParameterInfo paraminfo;
1817 (*pptfd)->funcdesc.lprgelemdescParam =
1818 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1820 (*pptfd)->pParamDesc =
1821 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1823 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1824 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1826 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1828 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1830 MSFT_GetTdesc(pcx,
1831 paraminfo.DataType,
1832 &elemdesc->tdesc,
1833 pTI);
1835 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1837 /* name */
1838 if (paraminfo.oName == -1)
1839 /* this occurs for [propput] or [propget] methods, so
1840 * we should just set the name of the parameter to the
1841 * name of the method. */
1842 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1843 else
1844 (*pptfd)->pParamDesc[j].Name =
1845 MSFT_ReadName( pcx, paraminfo.oName );
1846 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1848 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1850 /* default value */
1851 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1852 (pFuncRec->FKCCIC & 0x1000) )
1854 INT* pInt = (INT *)((char *)pFuncRec +
1855 reclength -
1856 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1858 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1860 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1861 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1863 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1864 pInt[j], pcx);
1866 else
1867 elemdesc->u.paramdesc.pparamdescex = NULL;
1868 /* custom info */
1869 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1871 MSFT_CustData(pcx,
1872 pFuncRec->OptAttr[7+j],
1873 &(*pptfd)->pParamDesc[j].pCustData);
1876 /* SEEK value = jump to offset,
1877 * from there jump to the end of record,
1878 * go back by (j-1) arguments
1880 MSFT_ReadLEDWords( &paraminfo ,
1881 sizeof(MSFT_ParameterInfo), pcx,
1882 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1883 * sizeof(MSFT_ParameterInfo)));
1887 /* scode is not used: archaic win16 stuff FIXME: right? */
1888 (*pptfd)->funcdesc.cScodes = 0 ;
1889 (*pptfd)->funcdesc.lprgscode = NULL ;
1891 ptfd_prev = *pptfd;
1892 pptfd = & ((*pptfd)->next);
1893 recoffset += reclength;
1897 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1898 int cVars, int offset, TLBVarDesc ** pptvd)
1900 int infolen, nameoffset, reclength;
1901 char recbuf[256];
1902 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1903 int i;
1904 int recoffset;
1906 TRACE_(typelib)("\n");
1908 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1909 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1910 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1911 recoffset += offset+sizeof(INT);
1912 for(i=0;i<cVars;i++){
1913 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1914 /* name, eventually add to a hash table */
1915 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1916 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
1917 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1918 /* read the variable information record */
1919 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1920 reclength &=0xff;
1921 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1922 /* Optional data */
1923 if(reclength >(6*sizeof(INT)) )
1924 (*pptvd)->HelpContext=pVarRec->HelpContext;
1925 if(reclength >(7*sizeof(INT)) )
1926 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1927 if(reclength >(8*sizeof(INT)) )
1928 if(reclength >(9*sizeof(INT)) )
1929 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1930 /* fill the VarDesc Structure */
1931 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1932 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
1933 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1934 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1935 MSFT_GetTdesc(pcx, pVarRec->DataType,
1936 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1937 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1938 if(pVarRec->VarKind == VAR_CONST ){
1939 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1940 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1941 pVarRec->OffsValue, pcx);
1942 } else
1943 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1944 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
1945 pptvd=&((*pptvd)->next);
1946 recoffset += reclength;
1949 /* fill in data for a hreftype (offset). When the referenced type is contained
1950 * in the typelib, it's just an (file) offset in the type info base dir.
1951 * If comes from import, it's an offset+1 in the ImpInfo table
1952 * */
1953 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1954 int offset)
1956 int j;
1957 TLBRefType **ppRefType = &pTI->reflist;
1959 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1961 while(*ppRefType) {
1962 if((*ppRefType)->reference == offset)
1963 return;
1964 ppRefType = &(*ppRefType)->next;
1967 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1968 sizeof(**ppRefType));
1970 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1971 /* external typelib */
1972 MSFT_ImpInfo impinfo;
1973 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1975 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1977 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1978 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1979 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1980 if(pImpLib->offset==impinfo.oImpFile) break;
1981 pImpLib=pImpLib->next;
1983 if(pImpLib){
1984 (*ppRefType)->reference=offset;
1985 (*ppRefType)->pImpTLInfo = pImpLib;
1986 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
1987 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1988 TRACE("importing by guid %s\n", debugstr_guid(&(*ppRefType)->guid));
1989 (*ppRefType)->index = TLB_REF_USE_GUID;
1990 } else
1991 (*ppRefType)->index = impinfo.oGuid;
1992 }else{
1993 ERR("Cannot find a reference\n");
1994 (*ppRefType)->reference=-1;
1995 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1997 }else{
1998 /* in this typelib */
1999 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
2000 (*ppRefType)->reference=offset;
2001 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
2005 /* process Implemented Interfaces of a com class */
2006 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2007 int offset)
2009 int i;
2010 MSFT_RefRecord refrec;
2011 TLBImplType **ppImpl = &pTI->impltypelist;
2013 TRACE_(typelib)("\n");
2015 for(i=0;i<count;i++){
2016 if(offset<0) break; /* paranoia */
2017 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2018 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2019 MSFT_DoRefType(pcx, pTI, refrec.reftype);
2020 (*ppImpl)->hRef = refrec.reftype;
2021 (*ppImpl)->implflags=refrec.flags;
2022 (*ppImpl)->ctCustData=
2023 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2024 offset=refrec.onext;
2025 ppImpl=&((*ppImpl)->next);
2029 * process a typeinfo record
2031 static ITypeInfoImpl * MSFT_DoTypeInfo(
2032 TLBContext *pcx,
2033 int count,
2034 INT dispatch_href,
2035 ITypeLibImpl * pLibInfo)
2037 MSFT_TypeInfoBase tiBase;
2038 ITypeInfoImpl *ptiRet;
2040 TRACE_(typelib)("count=%u\n", count);
2042 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2043 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2044 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2046 /* this is where we are coming from */
2047 ptiRet->pTypeLib = pLibInfo;
2048 ptiRet->index=count;
2049 /* fill in the typeattr fields */
2051 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2052 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2053 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2054 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2055 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2056 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2057 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2058 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2059 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2060 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2061 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2062 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2063 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2064 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2065 MSFT_GetTdesc(pcx, tiBase.datatype1,
2066 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2068 /* FIXME: */
2069 /* IDLDESC idldescType; *//* never saw this one != zero */
2071 /* name, eventually add to a hash table */
2072 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2073 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2074 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2075 /* help info */
2076 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2077 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2078 ptiRet->dwHelpContext=tiBase.helpcontext;
2080 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2081 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2083 /* note: InfoType's Help file and HelpStringDll come from the containing
2084 * library. Further HelpString and Docstring appear to be the same thing :(
2086 /* functions */
2087 if(ptiRet->TypeAttr.cFuncs >0 )
2088 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2089 ptiRet->TypeAttr.cVars,
2090 tiBase.memoffset, & ptiRet->funclist);
2091 /* variables */
2092 if(ptiRet->TypeAttr.cVars >0 )
2093 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2094 ptiRet->TypeAttr.cVars,
2095 tiBase.memoffset, & ptiRet->varlist);
2096 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2097 switch(ptiRet->TypeAttr.typekind)
2099 case TKIND_COCLASS:
2100 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2101 tiBase.datatype1);
2102 break;
2103 case TKIND_DISPATCH:
2104 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2106 if (tiBase.datatype1 != -1)
2108 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2109 ptiRet->impltypelist->hRef = tiBase.datatype1;
2111 else
2113 MSFT_DoRefType(pcx, ptiRet, dispatch_href);
2114 ptiRet->impltypelist->hRef = dispatch_href;
2116 break;
2117 default:
2118 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2119 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2120 ptiRet->impltypelist->hRef = tiBase.datatype1;
2121 break;
2124 ptiRet->ctCustData=
2125 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2127 TRACE_(typelib)("%s guid: %s kind:%s\n",
2128 debugstr_w(ptiRet->Name),
2129 debugstr_guid(&ptiRet->TypeAttr.guid),
2130 typekind_desc[ptiRet->TypeAttr.typekind]);
2132 return ptiRet;
2135 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2136 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2137 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2138 * tradeoff here.
2140 static ITypeLibImpl *tlb_cache_first;
2141 static CRITICAL_SECTION cache_section;
2142 static CRITICAL_SECTION_DEBUG cache_section_debug =
2144 0, 0, &cache_section,
2145 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2146 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2148 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2151 /****************************************************************************
2152 * TLB_ReadTypeLib
2154 * find the type of the typelib file and map the typelib resource into
2155 * the memory
2157 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2158 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2159 static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2161 ITypeLibImpl *entry;
2162 int ret = TYPE_E_CANTLOADLIBRARY;
2163 INT index = 1;
2164 HINSTANCE hinstDLL;
2166 *ppTypeLib = NULL;
2168 lstrcpynW(pszPath, pszFileName, cchPath);
2170 /* first try loading as a dll and access the typelib as a resource */
2171 hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES |
2172 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2173 if (!hinstDLL)
2175 /* it may have been specified with resource index appended to the
2176 * path, so remove it and try again */
2177 const WCHAR *pIndexStr = strrchrW(pszFileName, '\\');
2178 if(pIndexStr && pIndexStr != pszFileName && *++pIndexStr != '\0')
2180 index = atoiW(pIndexStr);
2181 pszPath[pIndexStr - pszFileName - 1] = '\0';
2183 hinstDLL = LoadLibraryExW(pszPath, 0, DONT_RESOLVE_DLL_REFERENCES |
2184 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2188 /* get the path to the specified typelib file */
2189 if (!hinstDLL)
2191 /* otherwise, try loading as a regular file */
2192 if (!SearchPathW(NULL, pszFileName, NULL, cchPath, pszPath, NULL))
2193 return TYPE_E_CANTLOADLIBRARY;
2196 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2198 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2199 EnterCriticalSection(&cache_section);
2200 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2202 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2204 TRACE("cache hit\n");
2205 *ppTypeLib = (ITypeLib2*)entry;
2206 ITypeLib_AddRef(*ppTypeLib);
2207 LeaveCriticalSection(&cache_section);
2208 return S_OK;
2211 LeaveCriticalSection(&cache_section);
2213 /* now actually load and parse the typelib */
2214 if (hinstDLL)
2216 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2217 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2218 if (hrsrc)
2220 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2221 if (hGlobal)
2223 LPVOID pBase = LockResource(hGlobal);
2224 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2226 if (pBase)
2228 /* try to load as incore resource */
2229 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2230 if (dwSignature == MSFT_SIGNATURE)
2231 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2232 else if (dwSignature == SLTG_SIGNATURE)
2233 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2234 else
2235 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2237 FreeResource( hGlobal );
2240 FreeLibrary(hinstDLL);
2242 else
2244 HANDLE hFile = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2245 if (INVALID_HANDLE_VALUE != hFile)
2247 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2248 if (hMapping)
2250 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2251 if(pBase)
2253 /* retrieve file size */
2254 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2255 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2257 if (dwSignature == MSFT_SIGNATURE)
2258 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2259 else if (dwSignature == SLTG_SIGNATURE)
2260 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2262 UnmapViewOfFile(pBase);
2264 CloseHandle(hMapping);
2266 CloseHandle(hFile);
2270 if(*ppTypeLib) {
2271 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2273 TRACE("adding to cache\n");
2274 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2275 lstrcpyW(impl->path, pszPath);
2276 /* We should really canonicalise the path here. */
2277 impl->index = index;
2279 /* FIXME: check if it has added already in the meantime */
2280 EnterCriticalSection(&cache_section);
2281 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2282 impl->prev = NULL;
2283 tlb_cache_first = impl;
2284 LeaveCriticalSection(&cache_section);
2285 ret = S_OK;
2286 } else
2287 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
2289 return ret;
2292 /*================== ITypeLib(2) Methods ===================================*/
2294 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2296 ITypeLibImpl* pTypeLibImpl;
2298 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2299 if (!pTypeLibImpl) return NULL;
2301 pTypeLibImpl->lpVtbl = &tlbvt;
2302 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2303 pTypeLibImpl->ref = 1;
2305 return pTypeLibImpl;
2308 /****************************************************************************
2309 * ITypeLib2_Constructor_MSFT
2311 * loading an MSFT typelib from an in-memory image
2313 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2315 TLBContext cx;
2316 long lPSegDir;
2317 MSFT_Header tlbHeader;
2318 MSFT_SegDir tlbSegDir;
2319 ITypeLibImpl * pTypeLibImpl;
2321 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2323 pTypeLibImpl = TypeLibImpl_Constructor();
2324 if (!pTypeLibImpl) return NULL;
2326 /* get pointer to beginning of typelib data */
2327 cx.pos = 0;
2328 cx.oStart=0;
2329 cx.mapping = pLib;
2330 cx.pLibInfo = pTypeLibImpl;
2331 cx.length = dwTLBLength;
2333 /* read header */
2334 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2335 TRACE_(typelib)("header:\n");
2336 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2337 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2338 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2339 return NULL;
2341 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2343 /* there is a small amount of information here until the next important
2344 * part:
2345 * the segment directory . Try to calculate the amount of data */
2346 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2348 /* now read the segment directory */
2349 TRACE("read segment directory (at %ld)\n",lPSegDir);
2350 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2351 cx.pTblDir = &tlbSegDir;
2353 /* just check two entries */
2354 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2356 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2357 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2358 return NULL;
2361 /* now fill our internal data */
2362 /* TLIBATTR fields */
2363 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2365 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2366 /* Windows seems to have zero here, is this correct? */
2367 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2368 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2369 else
2370 pTypeLibImpl->LibAttr.lcid = 0;
2372 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2373 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2374 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2375 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2377 /* name, eventually add to a hash table */
2378 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2380 /* help info */
2381 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2382 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2384 if( tlbHeader.varflags & HELPDLLFLAG)
2386 int offset;
2387 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2388 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2391 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2393 /* custom data */
2394 if(tlbHeader.CustomDataOffset >= 0)
2396 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2399 /* fill in typedescriptions */
2400 if(tlbSegDir.pTypdescTab.length > 0)
2402 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2403 INT16 td[4];
2404 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2405 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2406 for(i=0; i<cTD; )
2408 /* FIXME: add several sanity checks here */
2409 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2410 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2412 /* FIXME: check safearray */
2413 if(td[3] < 0)
2414 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2415 else
2416 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2418 else if(td[0] == VT_CARRAY)
2420 /* array descr table here */
2421 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2423 else if(td[0] == VT_USERDEFINED)
2425 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2427 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2430 /* second time around to fill the array subscript info */
2431 for(i=0;i<cTD;i++)
2433 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2434 if(tlbSegDir.pArrayDescriptions.offset>0)
2436 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2437 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2439 if(td[1]<0)
2440 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2441 else
2442 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2444 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2446 for(j = 0; j<td[2]; j++)
2448 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2449 sizeof(INT), &cx, DO_NOT_SEEK);
2450 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2451 sizeof(INT), &cx, DO_NOT_SEEK);
2454 else
2456 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2457 ERR("didn't find array description data\n");
2462 /* imported type libs */
2463 if(tlbSegDir.pImpFiles.offset>0)
2465 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2466 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2467 UINT16 size;
2469 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2471 char *name;
2472 DWORD len;
2474 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2475 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2476 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2478 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2479 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2480 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2481 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2483 size >>= 2;
2484 name = TLB_Alloc(size+1);
2485 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2486 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2487 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2488 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2489 TLB_Free(name);
2491 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2492 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2494 ppImpLib = &(*ppImpLib)->next;
2498 /* type info's */
2499 if(tlbHeader.nrtypeinfos >= 0 )
2501 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2502 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2503 int i;
2505 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2507 *ppTI = MSFT_DoTypeInfo(&cx, i, tlbHeader.dispatchpos, pTypeLibImpl);
2509 ppTI = &((*ppTI)->next);
2510 (pTypeLibImpl->TypeInfoCount)++;
2514 TRACE("(%p)\n", pTypeLibImpl);
2515 return (ITypeLib2*) pTypeLibImpl;
2519 static BSTR TLB_MultiByteToBSTR(char *ptr)
2521 DWORD len;
2522 WCHAR *nameW;
2523 BSTR ret;
2525 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2526 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2527 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2528 ret = SysAllocString(nameW);
2529 HeapFree(GetProcessHeap(), 0, nameW);
2530 return ret;
2533 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2535 char b[3];
2536 int i;
2537 short s;
2539 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2540 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2541 return FALSE;
2544 guid->Data4[0] = s >> 8;
2545 guid->Data4[1] = s & 0xff;
2547 b[2] = '\0';
2548 for(i = 0; i < 6; i++) {
2549 memcpy(b, str + 24 + 2 * i, 2);
2550 guid->Data4[i + 2] = strtol(b, NULL, 16);
2552 return TRUE;
2555 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2557 WORD bytelen;
2558 DWORD len;
2559 WCHAR *nameW;
2561 *pBstr = NULL;
2562 bytelen = *(WORD*)ptr;
2563 if(bytelen == 0xffff) return 2;
2564 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2565 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2566 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2567 *pBstr = SysAllocStringLen(nameW, len);
2568 HeapFree(GetProcessHeap(), 0, nameW);
2569 return bytelen + 2;
2572 static WORD SLTG_ReadStringA(char *ptr, char **str)
2574 WORD bytelen;
2576 *str = NULL;
2577 bytelen = *(WORD*)ptr;
2578 if(bytelen == 0xffff) return 2;
2579 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2580 memcpy(*str, ptr + 2, bytelen);
2581 (*str)[bytelen] = '\0';
2582 return bytelen + 2;
2585 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2587 char *ptr = pLibBlk;
2588 WORD w;
2590 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2591 FIXME("libblk magic = %04x\n", w);
2592 return 0;
2595 ptr += 6;
2596 if((w = *(WORD*)ptr) != 0xffff) {
2597 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2598 ptr += w;
2600 ptr += 2;
2602 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2604 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2606 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2607 ptr += 4;
2609 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2610 ptr += 2;
2612 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2613 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2614 else
2615 pTypeLibImpl->LibAttr.lcid = 0;
2616 ptr += 2;
2618 ptr += 4; /* skip res12 */
2620 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2621 ptr += 2;
2623 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2624 ptr += 2;
2626 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2627 ptr += 2;
2629 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2630 ptr += sizeof(GUID);
2632 return ptr - (char*)pLibBlk;
2635 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD)
2637 BOOL done = FALSE;
2639 while(!done) {
2640 if((*pType & 0xe00) == 0xe00) {
2641 pTD->vt = VT_PTR;
2642 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2643 sizeof(TYPEDESC));
2644 pTD = pTD->u.lptdesc;
2646 switch(*pType & 0x3f) {
2647 case VT_PTR:
2648 pTD->vt = VT_PTR;
2649 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2650 sizeof(TYPEDESC));
2651 pTD = pTD->u.lptdesc;
2652 break;
2654 case VT_USERDEFINED:
2655 pTD->vt = VT_USERDEFINED;
2656 pTD->u.hreftype = *(++pType) / 4;
2657 done = TRUE;
2658 break;
2660 case VT_CARRAY:
2662 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2663 array */
2665 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2667 pTD->vt = VT_CARRAY;
2668 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2669 sizeof(ARRAYDESC) +
2670 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2671 pTD->u.lpadesc->cDims = pSA->cDims;
2672 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2673 pSA->cDims * sizeof(SAFEARRAYBOUND));
2675 pTD = &pTD->u.lpadesc->tdescElem;
2676 break;
2679 case VT_SAFEARRAY:
2681 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2682 useful? */
2684 pType++;
2685 pTD->vt = VT_SAFEARRAY;
2686 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2687 sizeof(TYPEDESC));
2688 pTD = pTD->u.lptdesc;
2689 break;
2691 default:
2692 pTD->vt = *pType & 0x3f;
2693 done = TRUE;
2694 break;
2696 pType++;
2698 return pType;
2701 static WORD *SLTG_DoElem(WORD *pType, char *pBlk, ELEMDESC *pElem)
2703 /* Handle [in/out] first */
2704 if((*pType & 0xc000) == 0xc000)
2705 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2706 else if(*pType & 0x8000)
2707 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2708 else if(*pType & 0x4000)
2709 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2710 else
2711 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2713 if(*pType & 0x2000)
2714 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2716 if(*pType & 0x80)
2717 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2719 return SLTG_DoType(pType, pBlk, &pElem->tdesc);
2723 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2724 char *pNameTable)
2726 int ref;
2727 char *name;
2728 TLBRefType **ppRefType;
2730 if(pRef->magic != SLTG_REF_MAGIC) {
2731 FIXME("Ref magic = %x\n", pRef->magic);
2732 return;
2734 name = ( (char*)(&pRef->names) + pRef->number);
2736 ppRefType = &pTI->reflist;
2737 for(ref = 0; ref < pRef->number >> 3; ref++) {
2738 char *refname;
2739 unsigned int lib_offs, type_num;
2741 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2742 sizeof(**ppRefType));
2744 name += SLTG_ReadStringA(name, &refname);
2745 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2746 FIXME("Can't sscanf ref\n");
2747 if(lib_offs != 0xffff) {
2748 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2750 while(*import) {
2751 if((*import)->offset == lib_offs)
2752 break;
2753 import = &(*import)->next;
2755 if(!*import) {
2756 char fname[MAX_PATH+1];
2757 int len;
2759 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2760 sizeof(**import));
2761 (*import)->offset = lib_offs;
2762 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2763 &(*import)->guid);
2764 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2765 &(*import)->wVersionMajor,
2766 &(*import)->wVersionMinor,
2767 &(*import)->lcid, fname) != 4) {
2768 FIXME("can't sscanf ref %s\n",
2769 pNameTable + lib_offs + 40);
2771 len = strlen(fname);
2772 if(fname[len-1] != '#')
2773 FIXME("fname = %s\n", fname);
2774 fname[len-1] = '\0';
2775 (*import)->name = TLB_MultiByteToBSTR(fname);
2777 (*ppRefType)->pImpTLInfo = *import;
2778 } else { /* internal ref */
2779 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2781 (*ppRefType)->reference = ref;
2782 (*ppRefType)->index = type_num;
2784 HeapFree(GetProcessHeap(), 0, refname);
2785 ppRefType = &(*ppRefType)->next;
2787 if((BYTE)*name != SLTG_REF_MAGIC)
2788 FIXME("End of ref block magic = %x\n", *name);
2789 dump_TLBRefType(pTI->reflist);
2792 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2793 BOOL OneOnly)
2795 SLTG_ImplInfo *info;
2796 TLBImplType **ppImplType = &pTI->impltypelist;
2797 /* I don't really get this structure, usually it's 0x16 bytes
2798 long, but iuser.tlb contains some that are 0x18 bytes long.
2799 That's ok because we can use the next ptr to jump to the next
2800 one. But how do we know the length of the last one? The WORD
2801 at offs 0x8 might be the clue. For now I'm just assuming that
2802 the last one is the regular 0x16 bytes. */
2804 info = (SLTG_ImplInfo*)pBlk;
2805 while(1) {
2806 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2807 sizeof(**ppImplType));
2808 (*ppImplType)->hRef = info->ref;
2809 (*ppImplType)->implflags = info->impltypeflags;
2810 pTI->TypeAttr.cImplTypes++;
2811 ppImplType = &(*ppImplType)->next;
2813 if(info->next == 0xffff)
2814 break;
2815 if(OneOnly)
2816 FIXME("Interface inheriting more than one interface\n");
2817 info = (SLTG_ImplInfo*)(pBlk + info->next);
2819 info++; /* see comment at top of function */
2820 return (char*)info;
2823 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars, char *pNameTable)
2825 TLBVarDesc **ppVarDesc = &pTI->varlist;
2826 BSTR bstrPrevName = NULL;
2827 SLTG_Variable *pItem;
2828 unsigned short i;
2829 WORD *pType;
2830 char buf[300];
2832 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
2833 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
2835 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2836 sizeof(**ppVarDesc));
2837 (*ppVarDesc)->vardesc.memid = pItem->memid;
2839 if (pItem->magic != SLTG_VAR_MAGIC &&
2840 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
2841 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
2842 return;
2845 if (pItem->name == 0xfffe)
2846 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
2847 else
2848 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2850 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
2851 TRACE_(typelib)("memid = 0x%lx\n", pItem->memid);
2853 if (pItem->flags & 0x40) {
2854 TRACE_(typelib)("VAR_DISPATCH\n");
2855 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
2857 else if (pItem->flags & 0x10) {
2858 TRACE_(typelib)("VAR_CONST\n");
2859 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2860 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2861 sizeof(VARIANT));
2862 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2863 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2864 *(INT*)(pBlk + pItem->byte_offs);
2866 else {
2867 TRACE_(typelib)("VAR_PERINSTANCE\n");
2868 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2869 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2872 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
2873 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
2875 if (pItem->flags & 0x80)
2876 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
2878 if(pItem->flags & 0x02)
2879 pType = &pItem->type;
2880 else
2881 pType = (WORD*)(pBlk + pItem->type);
2883 if (pItem->flags & ~0xd2)
2884 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xd2);
2886 SLTG_DoElem(pType, pBlk,
2887 &(*ppVarDesc)->vardesc.elemdescVar);
2889 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2891 bstrPrevName = (*ppVarDesc)->Name;
2892 ppVarDesc = &((*ppVarDesc)->next);
2894 pTI->TypeAttr.cVars = cVars;
2897 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cFuncs, char *pNameTable)
2899 SLTG_Function *pFunc;
2900 unsigned short i;
2901 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2903 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
2904 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
2906 int param;
2907 WORD *pType, *pArg;
2909 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2910 sizeof(**ppFuncDesc));
2912 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
2913 case SLTG_FUNCTION_MAGIC:
2914 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
2915 break;
2916 case SLTG_DISPATCH_FUNCTION_MAGIC:
2917 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
2918 break;
2919 case SLTG_STATIC_FUNCTION_MAGIC:
2920 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
2921 break;
2922 default:
2923 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
2924 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
2925 *ppFuncDesc = NULL;
2926 return;
2928 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2930 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2931 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2932 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2933 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2934 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2935 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2937 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
2938 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2940 if(pFunc->retnextopt & 0x80)
2941 pType = &pFunc->rettype;
2942 else
2943 pType = (WORD*)(pBlk + pFunc->rettype);
2945 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2947 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2948 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2949 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2950 (*ppFuncDesc)->pParamDesc =
2951 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2952 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2954 pArg = (WORD*)(pBlk + pFunc->arg_off);
2956 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2957 char *paramName = pNameTable + *pArg;
2958 BOOL HaveOffs;
2959 /* If arg type follows then paramName points to the 2nd
2960 letter of the name, else the next WORD is an offset to
2961 the arg type and paramName points to the first letter.
2962 So let's take one char off paramName and see if we're
2963 pointing at an alpha-numeric char. However if *pArg is
2964 0xffff or 0xfffe then the param has no name, the former
2965 meaning that the next WORD is the type, the latter
2966 meaning the the next WORD is an offset to the type. */
2968 HaveOffs = FALSE;
2969 if(*pArg == 0xffff)
2970 paramName = NULL;
2971 else if(*pArg == 0xfffe) {
2972 paramName = NULL;
2973 HaveOffs = TRUE;
2975 else if(paramName[-1] && !isalnum(paramName[-1]))
2976 HaveOffs = TRUE;
2978 pArg++;
2980 if(HaveOffs) { /* the next word is an offset to type */
2981 pType = (WORD*)(pBlk + *pArg);
2982 SLTG_DoElem(pType, pBlk,
2983 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2984 pArg++;
2985 } else {
2986 if(paramName)
2987 paramName--;
2988 pArg = SLTG_DoElem(pArg, pBlk,
2989 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2992 /* Are we an optional param ? */
2993 if((*ppFuncDesc)->funcdesc.cParams - param <=
2994 (*ppFuncDesc)->funcdesc.cParamsOpt)
2995 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2997 if(paramName) {
2998 (*ppFuncDesc)->pParamDesc[param].Name =
2999 TLB_MultiByteToBSTR(paramName);
3003 ppFuncDesc = &((*ppFuncDesc)->next);
3004 if(pFunc->next == 0xffff) break;
3006 pTI->TypeAttr.cFuncs = cFuncs;
3009 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3010 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3011 SLTG_TypeInfoTail *pTITail)
3013 char *pFirstItem, *pNextItem;
3015 if(pTIHeader->href_table != 0xffffffff) {
3016 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3017 pNameTable);
3020 pFirstItem = pNextItem = pBlk;
3022 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3023 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
3028 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3029 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3030 SLTG_TypeInfoTail *pTITail)
3032 char *pFirstItem, *pNextItem;
3034 if(pTIHeader->href_table != 0xffffffff) {
3035 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3036 pNameTable);
3039 pFirstItem = pNextItem = pBlk;
3041 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3042 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
3045 if (pTITail->funcs_off != 0xffff)
3046 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3048 if (TRACE_ON(typelib))
3049 dump_TLBFuncDesc(pTI->funclist);
3052 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3053 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3054 SLTG_TypeInfoTail *pTITail)
3056 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3059 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3060 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3061 SLTG_TypeInfoTail *pTITail)
3063 WORD *pType;
3065 if (pTITail->simple_alias) {
3066 /* if simple alias, no more processing required */
3067 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3068 return;
3071 if(pTIHeader->href_table != 0xffffffff) {
3072 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3073 pNameTable);
3076 /* otherwise it is an offset to a type */
3077 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3079 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias);
3082 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3083 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3084 SLTG_TypeInfoTail *pTITail)
3086 if (pTIHeader->href_table != 0xffffffff)
3087 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3088 pNameTable);
3090 if (pTITail->vars_off != 0xffff)
3091 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3093 if (pTITail->funcs_off != 0xffff)
3094 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3096 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3097 * of dispinterface functons including the IDispatch ones, so
3098 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3099 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3101 if (TRACE_ON(typelib))
3102 dump_TLBFuncDesc(pTI->funclist);
3105 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3106 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3107 SLTG_TypeInfoTail *pTITail)
3109 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3112 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3113 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3114 SLTG_TypeInfoTail *pTITail)
3116 if (pTIHeader->href_table != 0xffffffff)
3117 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3118 pNameTable);
3120 if (pTITail->vars_off != 0xffff)
3121 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3123 if (pTITail->funcs_off != 0xffff)
3124 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3127 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3128 managable copy of it into this */
3129 typedef struct {
3130 WORD small_no;
3131 char *index_name;
3132 char *other_name;
3133 WORD res1a;
3134 WORD name_offs;
3135 WORD more_bytes;
3136 char *extra;
3137 WORD res20;
3138 DWORD helpcontext;
3139 WORD res26;
3140 GUID uuid;
3141 } SLTG_InternalOtherTypeInfo;
3143 /****************************************************************************
3144 * ITypeLib2_Constructor_SLTG
3146 * loading a SLTG typelib from an in-memory image
3148 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3150 ITypeLibImpl *pTypeLibImpl;
3151 SLTG_Header *pHeader;
3152 SLTG_BlkEntry *pBlkEntry;
3153 SLTG_Magic *pMagic;
3154 SLTG_Index *pIndex;
3155 SLTG_Pad9 *pPad9;
3156 LPVOID pBlk, pFirstBlk;
3157 SLTG_LibBlk *pLibBlk;
3158 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3159 char *pAfterOTIBlks = NULL;
3160 char *pNameTable, *ptr;
3161 int i;
3162 DWORD len, order;
3163 ITypeInfoImpl **ppTypeInfoImpl;
3165 TRACE_(typelib)("%p, TLB length = %ld\n", pLib, dwTLBLength);
3168 pTypeLibImpl = TypeLibImpl_Constructor();
3169 if (!pTypeLibImpl) return NULL;
3171 pHeader = pLib;
3173 TRACE_(typelib)("header:\n");
3174 TRACE_(typelib)("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
3175 pHeader->nrOfFileBlks );
3176 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3177 FIXME("Header type magic 0x%08lx not supported.\n",
3178 pHeader->SLTG_magic);
3179 return NULL;
3182 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3183 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3185 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3186 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3188 /* Next we have a magic block */
3189 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3191 /* Let's see if we're still in sync */
3192 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3193 sizeof(SLTG_COMPOBJ_MAGIC))) {
3194 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3195 return NULL;
3197 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3198 sizeof(SLTG_DIR_MAGIC))) {
3199 FIXME("dir magic = %s\n", pMagic->dir_magic);
3200 return NULL;
3203 pIndex = (SLTG_Index*)(pMagic+1);
3205 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3207 pFirstBlk = (LPVOID)(pPad9 + 1);
3209 /* We'll set up a ptr to the main library block, which is the last one. */
3211 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3212 pBlkEntry[order].next != 0;
3213 order = pBlkEntry[order].next - 1, i++) {
3214 pBlk = (char*)pBlk + pBlkEntry[order].len;
3216 pLibBlk = pBlk;
3218 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3220 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3221 interspersed */
3223 len += 0x40;
3225 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3227 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3228 sizeof(*pOtherTypeInfoBlks) *
3229 pTypeLibImpl->TypeInfoCount);
3232 ptr = (char*)pLibBlk + len;
3234 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3235 WORD w, extra;
3236 len = 0;
3238 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3240 w = *(WORD*)(ptr + 2);
3241 if(w != 0xffff) {
3242 len += w;
3243 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3244 w+1);
3245 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3246 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3248 w = *(WORD*)(ptr + 4 + len);
3249 if(w != 0xffff) {
3250 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3251 len += w;
3252 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3253 w+1);
3254 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3255 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3257 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3258 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3259 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3260 if(extra) {
3261 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3262 extra);
3263 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3264 len += extra;
3266 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3267 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3268 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3269 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3270 len += sizeof(SLTG_OtherTypeInfo);
3271 ptr += len;
3274 pAfterOTIBlks = ptr;
3276 /* Skip this WORD and get the next DWORD */
3277 len = *(DWORD*)(pAfterOTIBlks + 2);
3279 /* Now add this to pLibBLk look at what we're pointing at and
3280 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3281 dust and we should be pointing at the beginning of the name
3282 table */
3284 pNameTable = (char*)pLibBlk + len;
3286 switch(*(WORD*)pNameTable) {
3287 case 0xffff:
3288 break;
3289 case 0x0200:
3290 pNameTable += 0x20;
3291 break;
3292 default:
3293 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3294 break;
3297 pNameTable += 0x216;
3299 pNameTable += 2;
3301 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3303 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3306 /* Hopefully we now have enough ptrs set up to actually read in
3307 some TypeInfos. It's not clear which order to do them in, so
3308 I'll just follow the links along the BlkEntry chain and read
3309 them in in the order in which they're in the file */
3311 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3313 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3314 pBlkEntry[order].next != 0;
3315 order = pBlkEntry[order].next - 1, i++) {
3317 SLTG_TypeInfoHeader *pTIHeader;
3318 SLTG_TypeInfoTail *pTITail;
3319 SLTG_MemberHeader *pMemHeader;
3321 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3322 pOtherTypeInfoBlks[i].index_name)) {
3323 FIXME("Index strings don't match\n");
3324 return NULL;
3327 pTIHeader = pBlk;
3328 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3329 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3330 return NULL;
3332 TRACE("pTIHeader->res06 = %lx, pTIHeader->res0e = %lx, pTIHeader->res16 = %lx, pTIHeader->res1e = %lx\n",
3333 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3335 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3336 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3337 (*ppTypeInfoImpl)->index = i;
3338 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3339 pOtherTypeInfoBlks[i].name_offs +
3340 pNameTable);
3341 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3342 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3343 sizeof(GUID));
3344 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3345 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3346 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3347 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3348 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3350 if((pTIHeader->typeflags1 & 7) != 2)
3351 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3352 if(pTIHeader->typeflags3 != 2)
3353 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3355 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3356 debugstr_w((*ppTypeInfoImpl)->Name),
3357 typekind_desc[pTIHeader->typekind],
3358 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3359 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3361 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3363 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3365 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3366 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3367 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3369 switch(pTIHeader->typekind) {
3370 case TKIND_ENUM:
3371 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3372 pTIHeader, pTITail);
3373 break;
3375 case TKIND_RECORD:
3376 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3377 pTIHeader, pTITail);
3378 break;
3380 case TKIND_INTERFACE:
3381 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3382 pTIHeader, pTITail);
3383 break;
3385 case TKIND_COCLASS:
3386 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3387 pTIHeader, pTITail);
3388 break;
3390 case TKIND_ALIAS:
3391 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3392 pTIHeader, pTITail);
3393 break;
3395 case TKIND_DISPATCH:
3396 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3397 pTIHeader, pTITail);
3398 break;
3400 case TKIND_MODULE:
3401 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3402 pTIHeader, pTITail);
3403 break;
3405 default:
3406 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3407 break;
3411 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3412 but we've already set those */
3413 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3414 X(06);
3415 X(16);
3416 X(18);
3417 X(1a);
3418 X(1e);
3419 X(24);
3420 X(26);
3421 X(2a);
3422 X(2c);
3423 X(2e);
3424 X(30);
3425 X(32);
3426 X(34);
3428 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3429 pBlk = (char*)pBlk + pBlkEntry[order].len;
3432 if(i != pTypeLibImpl->TypeInfoCount) {
3433 FIXME("Somehow processed %d TypeInfos\n", i);
3434 return NULL;
3437 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3438 return (ITypeLib2*)pTypeLibImpl;
3441 /* ITypeLib::QueryInterface
3443 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3444 ITypeLib2 * iface,
3445 REFIID riid,
3446 VOID **ppvObject)
3448 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3450 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3452 *ppvObject=NULL;
3453 if(IsEqualIID(riid, &IID_IUnknown) ||
3454 IsEqualIID(riid,&IID_ITypeLib)||
3455 IsEqualIID(riid,&IID_ITypeLib2))
3457 *ppvObject = This;
3460 if(*ppvObject)
3462 ITypeLib2_AddRef(iface);
3463 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3464 return S_OK;
3466 TRACE("-- Interface: E_NOINTERFACE\n");
3467 return E_NOINTERFACE;
3470 /* ITypeLib::AddRef
3472 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3474 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3475 ULONG ref = InterlockedIncrement(&This->ref);
3477 TRACE("(%p)->ref was %lu\n",This, ref - 1);
3479 return ref;
3482 /* ITypeLib::Release
3484 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3486 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3487 ULONG ref = InterlockedDecrement(&This->ref);
3489 TRACE("(%p)->(%lu)\n",This, ref);
3491 if (!ref)
3493 /* remove cache entry */
3494 if(This->path)
3496 TRACE("removing from cache list\n");
3497 EnterCriticalSection(&cache_section);
3498 if (This->next) This->next->prev = This->prev;
3499 if (This->prev) This->prev->next = This->next;
3500 else tlb_cache_first = This->next;
3501 LeaveCriticalSection(&cache_section);
3502 HeapFree(GetProcessHeap(), 0, This->path);
3504 /* FIXME destroy child objects */
3505 TRACE(" destroying ITypeLib(%p)\n",This);
3507 if (This->Name)
3509 SysFreeString(This->Name);
3510 This->Name = NULL;
3513 if (This->DocString)
3515 SysFreeString(This->DocString);
3516 This->DocString = NULL;
3519 if (This->HelpFile)
3521 SysFreeString(This->HelpFile);
3522 This->HelpFile = NULL;
3525 if (This->HelpStringDll)
3527 SysFreeString(This->HelpStringDll);
3528 This->HelpStringDll = NULL;
3531 if (This->pTypeInfo) /* can be NULL */
3532 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3533 HeapFree(GetProcessHeap(),0,This);
3534 return 0;
3537 return ref;
3540 /* ITypeLib::GetTypeInfoCount
3542 * Returns the number of type descriptions in the type library
3544 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3546 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3547 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3548 return This->TypeInfoCount;
3551 /* ITypeLib::GetTypeInfo
3553 * retrieves the specified type description in the library.
3555 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3556 ITypeLib2 *iface,
3557 UINT index,
3558 ITypeInfo **ppTInfo)
3560 int i;
3562 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3563 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3565 TRACE("(%p)->(index=%d)\n", This, index);
3567 if (!ppTInfo) return E_INVALIDARG;
3569 /* search element n in list */
3570 for(i=0; i < index; i++)
3572 pTypeInfo = pTypeInfo->next;
3573 if (!pTypeInfo)
3575 TRACE("-- element not found\n");
3576 return TYPE_E_ELEMENTNOTFOUND;
3580 *ppTInfo = (ITypeInfo *) pTypeInfo;
3582 ITypeInfo_AddRef(*ppTInfo);
3583 TRACE("-- found (%p)\n",*ppTInfo);
3584 return S_OK;
3588 /* ITypeLibs::GetTypeInfoType
3590 * Retrieves the type of a type description.
3592 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3593 ITypeLib2 *iface,
3594 UINT index,
3595 TYPEKIND *pTKind)
3597 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3598 int i;
3599 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3601 TRACE("(%p) index %d\n", This, index);
3603 if(!pTKind) return E_INVALIDARG;
3605 /* search element n in list */
3606 for(i=0; i < index; i++)
3608 if(!pTInfo)
3610 TRACE("-- element not found\n");
3611 return TYPE_E_ELEMENTNOTFOUND;
3613 pTInfo = pTInfo->next;
3616 *pTKind = pTInfo->TypeAttr.typekind;
3617 TRACE("-- found Type (%d)\n", *pTKind);
3618 return S_OK;
3621 /* ITypeLib::GetTypeInfoOfGuid
3623 * Retrieves the type description that corresponds to the specified GUID.
3626 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3627 ITypeLib2 *iface,
3628 REFGUID guid,
3629 ITypeInfo **ppTInfo)
3631 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3632 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3634 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3636 if (!pTypeInfo)
3638 WARN("-- element not found\n");
3639 return TYPE_E_ELEMENTNOTFOUND;
3642 /* search linked list for guid */
3643 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3645 pTypeInfo = pTypeInfo->next;
3647 if (!pTypeInfo)
3649 /* end of list reached */
3650 WARN("-- element not found\n");
3651 return TYPE_E_ELEMENTNOTFOUND;
3655 TRACE("-- found (%p, %s)\n",
3656 pTypeInfo,
3657 debugstr_w(pTypeInfo->Name));
3659 *ppTInfo = (ITypeInfo*)pTypeInfo;
3660 ITypeInfo_AddRef(*ppTInfo);
3661 return S_OK;
3664 /* ITypeLib::GetLibAttr
3666 * Retrieves the structure that contains the library's attributes.
3669 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3670 ITypeLib2 *iface,
3671 LPTLIBATTR *ppTLibAttr)
3673 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3674 TRACE("(%p)\n",This);
3675 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3676 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3677 return S_OK;
3680 /* ITypeLib::GetTypeComp
3682 * Enables a client compiler to bind to a library's types, variables,
3683 * constants, and global functions.
3686 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3687 ITypeLib2 *iface,
3688 ITypeComp **ppTComp)
3690 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3692 TRACE("(%p)->(%p)\n",This,ppTComp);
3693 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3694 ITypeComp_AddRef(*ppTComp);
3696 return S_OK;
3699 /* ITypeLib::GetDocumentation
3701 * Retrieves the library's documentation string, the complete Help file name
3702 * and path, and the context identifier for the library Help topic in the Help
3703 * file.
3705 * On a successful return all non-null BSTR pointers will have been set,
3706 * possibly to NULL.
3708 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3709 ITypeLib2 *iface,
3710 INT index,
3711 BSTR *pBstrName,
3712 BSTR *pBstrDocString,
3713 DWORD *pdwHelpContext,
3714 BSTR *pBstrHelpFile)
3716 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3718 HRESULT result = E_INVALIDARG;
3720 ITypeInfo *pTInfo;
3723 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3724 This, index,
3725 pBstrName, pBstrDocString,
3726 pdwHelpContext, pBstrHelpFile);
3728 if(index<0)
3730 /* documentation for the typelib */
3731 if(pBstrName)
3733 if (This->Name)
3735 if(!(*pBstrName = SysAllocString(This->Name)))
3736 goto memerr1;
3738 else
3739 *pBstrName = NULL;
3741 if(pBstrDocString)
3743 if (This->DocString)
3745 if(!(*pBstrDocString = SysAllocString(This->DocString)))
3746 goto memerr2;
3748 else if (This->Name)
3750 if(!(*pBstrDocString = SysAllocString(This->Name)))
3751 goto memerr2;
3753 else
3754 *pBstrDocString = NULL;
3756 if(pdwHelpContext)
3758 *pdwHelpContext = This->dwHelpContext;
3760 if(pBstrHelpFile)
3762 if (This->HelpFile)
3764 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
3765 goto memerr3;
3767 else
3768 *pBstrHelpFile = NULL;
3771 result = S_OK;
3773 else
3775 /* for a typeinfo */
3776 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3778 if(SUCCEEDED(result))
3780 result = ITypeInfo_GetDocumentation(pTInfo,
3781 MEMBERID_NIL,
3782 pBstrName,
3783 pBstrDocString,
3784 pdwHelpContext, pBstrHelpFile);
3786 ITypeInfo_Release(pTInfo);
3789 return result;
3790 memerr3:
3791 if (pBstrDocString) SysFreeString (*pBstrDocString);
3792 memerr2:
3793 if (pBstrName) SysFreeString (*pBstrName);
3794 memerr1:
3795 return STG_E_INSUFFICIENTMEMORY;
3798 /* ITypeLib::IsName
3800 * Indicates whether a passed-in string contains the name of a type or member
3801 * described in the library.
3804 static HRESULT WINAPI ITypeLib2_fnIsName(
3805 ITypeLib2 *iface,
3806 LPOLESTR szNameBuf,
3807 ULONG lHashVal,
3808 BOOL *pfName)
3810 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3811 ITypeInfoImpl *pTInfo;
3812 TLBFuncDesc *pFInfo;
3813 TLBVarDesc *pVInfo;
3814 int i;
3815 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3817 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3818 pfName);
3820 *pfName=TRUE;
3821 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3822 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3823 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3824 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3825 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3826 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3827 goto ITypeLib2_fnIsName_exit;
3829 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3830 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3833 *pfName=FALSE;
3835 ITypeLib2_fnIsName_exit:
3836 TRACE("(%p)slow! search for %s: %s found!\n", This,
3837 debugstr_w(szNameBuf), *pfName?"NOT":"");
3839 return S_OK;
3842 /* ITypeLib::FindName
3844 * Finds occurrences of a type description in a type library. This may be used
3845 * to quickly verify that a name exists in a type library.
3848 static HRESULT WINAPI ITypeLib2_fnFindName(
3849 ITypeLib2 *iface,
3850 LPOLESTR szNameBuf,
3851 ULONG lHashVal,
3852 ITypeInfo **ppTInfo,
3853 MEMBERID *rgMemId,
3854 UINT16 *pcFound)
3856 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3857 ITypeInfoImpl *pTInfo;
3858 TLBFuncDesc *pFInfo;
3859 TLBVarDesc *pVInfo;
3860 int i,j = 0;
3861 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3863 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3864 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3865 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3866 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3867 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
3868 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3869 goto ITypeLib2_fnFindName_exit;
3872 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3873 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3874 continue;
3875 ITypeLib2_fnFindName_exit:
3876 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3877 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3878 j++;
3880 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3881 This, *pcFound, debugstr_w(szNameBuf), j);
3883 *pcFound=j;
3885 return S_OK;
3888 /* ITypeLib::ReleaseTLibAttr
3890 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3893 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3894 ITypeLib2 *iface,
3895 TLIBATTR *pTLibAttr)
3897 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3898 TRACE("freeing (%p)\n",This);
3899 HeapFree(GetProcessHeap(),0,pTLibAttr);
3903 /* ITypeLib2::GetCustData
3905 * gets the custom data
3907 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3908 ITypeLib2 * iface,
3909 REFGUID guid,
3910 VARIANT *pVarVal)
3912 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3913 TLBCustData *pCData;
3915 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3917 if( IsEqualIID(guid, &pCData->guid)) break;
3920 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3922 if(pCData)
3924 VariantInit( pVarVal);
3925 VariantCopy( pVarVal, &pCData->data);
3926 return S_OK;
3928 return E_INVALIDARG; /* FIXME: correct? */
3931 /* ITypeLib2::GetLibStatistics
3933 * Returns statistics about a type library that are required for efficient
3934 * sizing of hash tables.
3937 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3938 ITypeLib2 * iface,
3939 ULONG *pcUniqueNames,
3940 ULONG *pcchUniqueNames)
3942 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3944 FIXME("(%p): stub!\n", This);
3946 if(pcUniqueNames) *pcUniqueNames=1;
3947 if(pcchUniqueNames) *pcchUniqueNames=1;
3948 return S_OK;
3951 /* ITypeLib2::GetDocumentation2
3953 * Retrieves the library's documentation string, the complete Help file name
3954 * and path, the localization context to use, and the context ID for the
3955 * library Help topic in the Help file.
3958 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3959 ITypeLib2 * iface,
3960 INT index,
3961 LCID lcid,
3962 BSTR *pbstrHelpString,
3963 DWORD *pdwHelpStringContext,
3964 BSTR *pbstrHelpStringDll)
3966 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3967 HRESULT result;
3968 ITypeInfo *pTInfo;
3970 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3972 /* the help string should be obtained from the helpstringdll,
3973 * using the _DLLGetDocumentation function, based on the supplied
3974 * lcid. Nice to do sometime...
3976 if(index<0)
3978 /* documentation for the typelib */
3979 if(pbstrHelpString)
3980 *pbstrHelpString=SysAllocString(This->DocString);
3981 if(pdwHelpStringContext)
3982 *pdwHelpStringContext=This->dwHelpContext;
3983 if(pbstrHelpStringDll)
3984 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3986 result = S_OK;
3988 else
3990 /* for a typeinfo */
3991 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3993 if(SUCCEEDED(result))
3995 ITypeInfo2 * pTInfo2;
3996 result = ITypeInfo_QueryInterface(pTInfo,
3997 &IID_ITypeInfo2,
3998 (LPVOID*) &pTInfo2);
4000 if(SUCCEEDED(result))
4002 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4003 MEMBERID_NIL,
4004 lcid,
4005 pbstrHelpString,
4006 pdwHelpStringContext,
4007 pbstrHelpStringDll);
4009 ITypeInfo2_Release(pTInfo2);
4012 ITypeInfo_Release(pTInfo);
4015 return result;
4018 /* ITypeLib2::GetAllCustData
4020 * Gets all custom data items for the library.
4023 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4024 ITypeLib2 * iface,
4025 CUSTDATA *pCustData)
4027 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4028 TLBCustData *pCData;
4029 int i;
4030 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4031 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4032 if(pCustData->prgCustData ){
4033 pCustData->cCustData=This->ctCustData;
4034 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4035 pCustData->prgCustData[i].guid=pCData->guid;
4036 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4038 }else{
4039 ERR(" OUT OF MEMORY!\n");
4040 return E_OUTOFMEMORY;
4042 return S_OK;
4045 static const ITypeLib2Vtbl tlbvt = {
4046 ITypeLib2_fnQueryInterface,
4047 ITypeLib2_fnAddRef,
4048 ITypeLib2_fnRelease,
4049 ITypeLib2_fnGetTypeInfoCount,
4050 ITypeLib2_fnGetTypeInfo,
4051 ITypeLib2_fnGetTypeInfoType,
4052 ITypeLib2_fnGetTypeInfoOfGuid,
4053 ITypeLib2_fnGetLibAttr,
4054 ITypeLib2_fnGetTypeComp,
4055 ITypeLib2_fnGetDocumentation,
4056 ITypeLib2_fnIsName,
4057 ITypeLib2_fnFindName,
4058 ITypeLib2_fnReleaseTLibAttr,
4060 ITypeLib2_fnGetCustData,
4061 ITypeLib2_fnGetLibStatistics,
4062 ITypeLib2_fnGetDocumentation2,
4063 ITypeLib2_fnGetAllCustData
4067 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4069 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4071 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4074 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4076 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4078 return ITypeLib2_AddRef((ITypeLib2 *)This);
4081 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4083 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4085 return ITypeLib2_Release((ITypeLib2 *)This);
4088 static HRESULT WINAPI ITypeLibComp_fnBind(
4089 ITypeComp * iface,
4090 OLECHAR * szName,
4091 ULONG lHash,
4092 WORD wFlags,
4093 ITypeInfo ** ppTInfo,
4094 DESCKIND * pDescKind,
4095 BINDPTR * pBindPtr)
4097 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4098 ITypeInfoImpl *pTypeInfo;
4100 TRACE("(%s, 0x%lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4102 *pDescKind = DESCKIND_NONE;
4103 pBindPtr->lptcomp = NULL;
4104 *ppTInfo = NULL;
4106 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4108 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4110 /* FIXME: check wFlags here? */
4111 /* FIXME: we should use a hash table to look this info up using lHash
4112 * instead of an O(n) search */
4113 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4114 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4116 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4118 *pDescKind = DESCKIND_TYPECOMP;
4119 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4120 ITypeComp_AddRef(pBindPtr->lptcomp);
4121 TRACE("module or enum: %s\n", debugstr_w(szName));
4122 return S_OK;
4126 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4127 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4129 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4130 HRESULT hr;
4132 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4133 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4135 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4136 return S_OK;
4140 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4141 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4143 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4144 HRESULT hr;
4145 ITypeInfo *subtypeinfo;
4146 BINDPTR subbindptr;
4147 DESCKIND subdesckind;
4149 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4150 &subtypeinfo, &subdesckind, &subbindptr);
4151 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4153 TYPEDESC tdesc_appobject =
4156 (TYPEDESC *)pTypeInfo->hreftype
4158 VT_USERDEFINED
4160 const VARDESC vardesc_appobject =
4162 -2, /* memid */
4163 NULL, /* lpstrSchema */
4165 0 /* oInst */
4168 /* ELEMDESC */
4170 /* TYPEDESC */
4172 &tdesc_appobject
4174 VT_PTR
4177 0, /* wVarFlags */
4178 VAR_STATIC /* varkind */
4181 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4183 /* cleanup things filled in by Bind call so we can put our
4184 * application object data in there instead */
4185 switch (subdesckind)
4187 case DESCKIND_FUNCDESC:
4188 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4189 break;
4190 case DESCKIND_VARDESC:
4191 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4192 break;
4193 default:
4194 break;
4196 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4198 if (pTypeInfo->hreftype == -1)
4199 FIXME("no hreftype for interface %p\n", pTypeInfo);
4201 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4202 if (FAILED(hr))
4203 return hr;
4205 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4206 *ppTInfo = (ITypeInfo *)pTypeInfo;
4207 ITypeInfo_AddRef(*ppTInfo);
4208 return S_OK;
4213 TRACE("name not found %s\n", debugstr_w(szName));
4214 return S_OK;
4217 static HRESULT WINAPI ITypeLibComp_fnBindType(
4218 ITypeComp * iface,
4219 OLECHAR * szName,
4220 ULONG lHash,
4221 ITypeInfo ** ppTInfo,
4222 ITypeComp ** ppTComp)
4224 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4225 return E_NOTIMPL;
4228 static const ITypeCompVtbl tlbtcvt =
4231 ITypeLibComp_fnQueryInterface,
4232 ITypeLibComp_fnAddRef,
4233 ITypeLibComp_fnRelease,
4235 ITypeLibComp_fnBind,
4236 ITypeLibComp_fnBindType
4239 /*================== ITypeInfo(2) Methods ===================================*/
4240 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4242 ITypeInfoImpl * pTypeInfoImpl;
4244 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4245 if (pTypeInfoImpl)
4247 pTypeInfoImpl->lpVtbl = &tinfvt;
4248 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4249 pTypeInfoImpl->ref=1;
4250 pTypeInfoImpl->hreftype = -1;
4251 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4252 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4254 TRACE("(%p)\n", pTypeInfoImpl);
4255 return (ITypeInfo2*) pTypeInfoImpl;
4258 /* ITypeInfo::QueryInterface
4260 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4261 ITypeInfo2 *iface,
4262 REFIID riid,
4263 VOID **ppvObject)
4265 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4267 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4269 *ppvObject=NULL;
4270 if(IsEqualIID(riid, &IID_IUnknown) ||
4271 IsEqualIID(riid,&IID_ITypeInfo)||
4272 IsEqualIID(riid,&IID_ITypeInfo2))
4273 *ppvObject = This;
4275 if(*ppvObject){
4276 ITypeInfo_AddRef(iface);
4277 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4278 return S_OK;
4280 TRACE("-- Interface: E_NOINTERFACE\n");
4281 return E_NOINTERFACE;
4284 /* ITypeInfo::AddRef
4286 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4288 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4289 ULONG ref = InterlockedIncrement(&This->ref);
4291 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4293 TRACE("(%p)->ref is %lu\n",This, ref);
4294 return ref;
4297 /* ITypeInfo::Release
4299 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4301 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4302 ULONG ref = InterlockedDecrement(&This->ref);
4304 TRACE("(%p)->(%lu)\n",This, ref);
4306 if (ref) {
4307 /* We don't release ITypeLib when ref=0 because
4308 it means that function is called by ITypeLib2_Release */
4309 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4310 } else {
4311 static int once = 0;
4312 if (!once)
4314 once = 1;
4315 FIXME("destroy child objects\n");
4318 TRACE("destroying ITypeInfo(%p)\n",This);
4319 if (This->Name)
4321 SysFreeString(This->Name);
4322 This->Name = 0;
4325 if (This->DocString)
4327 SysFreeString(This->DocString);
4328 This->DocString = 0;
4331 if (This->DllName)
4333 SysFreeString(This->DllName);
4334 This->DllName = 0;
4337 if (This->next)
4339 ITypeInfo_Release((ITypeInfo*)This->next);
4342 HeapFree(GetProcessHeap(),0,This);
4343 return 0;
4345 return ref;
4348 /* ITypeInfo::GetTypeAttr
4350 * Retrieves a TYPEATTR structure that contains the attributes of the type
4351 * description.
4354 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4355 LPTYPEATTR *ppTypeAttr)
4357 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4358 SIZE_T size;
4360 TRACE("(%p)\n",This);
4362 size = sizeof(**ppTypeAttr);
4363 if (This->TypeAttr.typekind == TKIND_ALIAS)
4364 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4366 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4367 if (!*ppTypeAttr)
4368 return E_OUTOFMEMORY;
4370 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4372 if (This->TypeAttr.typekind == TKIND_ALIAS)
4373 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4374 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4376 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4377 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4378 funcs */
4379 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4380 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4382 return S_OK;
4385 /* ITypeInfo::GetTypeComp
4387 * Retrieves the ITypeComp interface for the type description, which enables a
4388 * client compiler to bind to the type description's members.
4391 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4392 ITypeComp * *ppTComp)
4394 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4396 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4398 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4399 ITypeComp_AddRef(*ppTComp);
4400 return S_OK;
4403 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4405 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4406 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4407 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4408 return size;
4411 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4413 memcpy(dest, src, sizeof(ELEMDESC));
4414 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4415 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4417 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4418 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4419 *buffer += sizeof(PARAMDESCEX);
4420 memcpy(pparamdescex_dest, pparamdescex_src, sizeof(PARAMDESCEX));
4421 VariantInit(&pparamdescex_dest->varDefaultValue);
4422 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4423 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4425 else
4426 dest->u.paramdesc.pparamdescex = NULL;
4427 return S_OK;
4430 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4432 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4433 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4436 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4438 FUNCDESC *dest;
4439 char *buffer;
4440 SIZE_T size = sizeof(*src);
4441 SHORT i;
4442 HRESULT hr;
4444 size += sizeof(*src->lprgscode) * src->cScodes;
4445 size += TLB_SizeElemDesc(&src->elemdescFunc);
4446 for (i = 0; i < src->cParams; i++)
4448 size += sizeof(ELEMDESC);
4449 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4452 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4453 if (!dest) return E_OUTOFMEMORY;
4455 memcpy(dest, src, sizeof(FUNCDESC));
4456 buffer = (char *)(dest + 1);
4458 dest->lprgscode = (SCODE *)buffer;
4459 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4460 buffer += sizeof(*src->lprgscode) * src->cScodes;
4462 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4463 if (FAILED(hr))
4465 SysFreeString((BSTR)dest);
4466 return hr;
4469 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4470 buffer += sizeof(ELEMDESC) * src->cParams;
4471 for (i = 0; i < src->cParams; i++)
4473 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4474 if (FAILED(hr))
4475 break;
4477 if (FAILED(hr))
4479 /* undo the above actions */
4480 for (i = i - 1; i >= 0; i--)
4481 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4482 TLB_FreeElemDesc(&dest->elemdescFunc);
4483 SysFreeString((BSTR)dest);
4484 return hr;
4487 /* special treatment for dispinterfaces: this makes functions appear
4488 * to return their [retval] value when it is really returning an
4489 * HRESULT */
4490 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4492 if (dest->cParams &&
4493 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4495 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4496 if (elemdesc->tdesc.vt != VT_PTR)
4498 ERR("elemdesc should have started with VT_PTR instead of:\n");
4499 if (ERR_ON(ole))
4500 dump_ELEMDESC(elemdesc);
4501 return E_UNEXPECTED;
4504 /* copy last parameter to the return value. we are using a flat
4505 * buffer so there is no danger of leaking memory in
4506 * elemdescFunc */
4507 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4509 /* remove the last parameter */
4510 dest->cParams--;
4512 else
4513 /* otherwise this function is made to appear to have no return
4514 * value */
4515 dest->elemdescFunc.tdesc.vt = VT_VOID;
4519 *dest_ptr = dest;
4520 return S_OK;
4523 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4525 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4526 const TLBFuncDesc *pFDesc;
4527 int i;
4529 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4532 if (pFDesc)
4534 *ppFuncDesc = &pFDesc->funcdesc;
4535 return S_OK;
4538 return E_INVALIDARG;
4541 /* ITypeInfo::GetFuncDesc
4543 * Retrieves the FUNCDESC structure that contains information about a
4544 * specified function.
4547 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4548 LPFUNCDESC *ppFuncDesc)
4550 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4551 const FUNCDESC *internal_funcdesc;
4552 HRESULT hr;
4554 TRACE("(%p) index %d\n", This, index);
4556 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index, &internal_funcdesc);
4557 if (FAILED(hr))
4558 return hr;
4560 return TLB_AllocAndInitFuncDesc(
4561 internal_funcdesc,
4562 ppFuncDesc,
4563 This->TypeAttr.typekind == TKIND_DISPATCH);
4566 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
4568 VARDESC *dest;
4569 char *buffer;
4570 SIZE_T size = sizeof(*src);
4571 HRESULT hr;
4573 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
4574 if (src->varkind == VAR_CONST)
4575 size += sizeof(VARIANT);
4576 size += TLB_SizeElemDesc(&src->elemdescVar);
4578 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
4579 if (!dest) return E_OUTOFMEMORY;
4581 *dest = *src;
4582 buffer = (char *)(dest + 1);
4583 if (src->lpstrSchema)
4585 int len;
4586 dest->lpstrSchema = (LPOLESTR)buffer;
4587 len = strlenW(src->lpstrSchema);
4588 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
4589 buffer += (len + 1) * sizeof(WCHAR);
4592 if (src->varkind == VAR_CONST)
4594 HRESULT hr;
4596 dest->u.lpvarValue = (VARIANT *)buffer;
4597 *dest->u.lpvarValue = *src->u.lpvarValue;
4598 buffer += sizeof(VARIANT);
4599 VariantInit(dest->u.lpvarValue);
4600 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
4601 if (FAILED(hr))
4603 SysFreeString((BSTR)dest_ptr);
4604 return hr;
4607 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
4608 if (FAILED(hr))
4610 if (src->varkind == VAR_CONST)
4611 VariantClear(dest->u.lpvarValue);
4612 SysFreeString((BSTR)dest);
4613 return hr;
4615 *dest_ptr = dest;
4616 return S_OK;
4619 /* ITypeInfo::GetVarDesc
4621 * Retrieves a VARDESC structure that describes the specified variable.
4624 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4625 LPVARDESC *ppVarDesc)
4627 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4628 int i;
4629 const TLBVarDesc *pVDesc;
4631 TRACE("(%p) index %d\n", This, index);
4633 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4636 if (pVDesc)
4637 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
4639 return E_INVALIDARG;
4642 /* ITypeInfo_GetNames
4644 * Retrieves the variable with the specified member ID (or the name of the
4645 * property or method and its parameters) that correspond to the specified
4646 * function ID.
4648 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4649 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4651 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4652 const TLBFuncDesc *pFDesc;
4653 const TLBVarDesc *pVDesc;
4654 int i;
4655 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4656 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4657 if(pFDesc)
4659 /* function found, now return function and parameter names */
4660 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4662 if(!i)
4663 *rgBstrNames=SysAllocString(pFDesc->Name);
4664 else
4665 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4667 *pcNames=i;
4669 else
4671 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4672 if(pVDesc)
4674 *rgBstrNames=SysAllocString(pVDesc->Name);
4675 *pcNames=1;
4677 else
4679 if(This->TypeAttr.cImplTypes &&
4680 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4681 /* recursive search */
4682 ITypeInfo *pTInfo;
4683 HRESULT result;
4684 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4685 &pTInfo);
4686 if(SUCCEEDED(result))
4688 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4689 ITypeInfo_Release(pTInfo);
4690 return result;
4692 WARN("Could not search inherited interface!\n");
4694 else
4696 WARN("no names found\n");
4698 *pcNames=0;
4699 return TYPE_E_ELEMENTNOTFOUND;
4702 return S_OK;
4706 /* ITypeInfo::GetRefTypeOfImplType
4708 * If a type description describes a COM class, it retrieves the type
4709 * description of the implemented interface types. For an interface,
4710 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4711 * if any exist.
4714 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4715 ITypeInfo2 *iface,
4716 UINT index,
4717 HREFTYPE *pRefType)
4719 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4720 int i;
4721 HRESULT hr = S_OK;
4722 const TLBImplType *pImpl = This->impltypelist;
4724 TRACE("(%p) index %d\n", This, index);
4725 if (TRACE_ON(ole)) dump_TypeInfo(This);
4727 if(index==(UINT)-1)
4729 /* only valid on dual interfaces;
4730 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4732 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4734 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4735 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4737 *pRefType = -1;
4739 else
4741 hr = TYPE_E_ELEMENTNOTFOUND;
4744 else
4746 /* get element n from linked list */
4747 for(i=0; pImpl && i<index; i++)
4749 pImpl = pImpl->next;
4752 if (pImpl)
4753 *pRefType = pImpl->hRef;
4754 else
4755 hr = TYPE_E_ELEMENTNOTFOUND;
4758 if(TRACE_ON(ole))
4760 if(SUCCEEDED(hr))
4761 TRACE("SUCCESS -- hRef = 0x%08lx\n", *pRefType );
4762 else
4763 TRACE("FAILURE -- hresult = 0x%08lx\n", hr);
4766 return hr;
4769 /* ITypeInfo::GetImplTypeFlags
4771 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4772 * or base interface in a type description.
4774 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4775 UINT index, INT *pImplTypeFlags)
4777 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4778 int i;
4779 TLBImplType *pImpl;
4781 TRACE("(%p) index %d\n", This, index);
4782 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4783 i++, pImpl=pImpl->next)
4785 if(i==index && pImpl){
4786 *pImplTypeFlags=pImpl->implflags;
4787 return S_OK;
4789 *pImplTypeFlags=0;
4790 return TYPE_E_ELEMENTNOTFOUND;
4793 /* GetIDsOfNames
4794 * Maps between member names and member IDs, and parameter names and
4795 * parameter IDs.
4797 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4798 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4800 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4801 const TLBFuncDesc *pFDesc;
4802 const TLBVarDesc *pVDesc;
4803 HRESULT ret=S_OK;
4804 int i;
4806 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4807 cNames);
4809 /* init out parameters in case of failure */
4810 for (i = 0; i < cNames; i++)
4811 pMemId[i] = MEMBERID_NIL;
4813 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4814 int j;
4815 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4816 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4817 for(i=1; i < cNames; i++){
4818 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4819 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4820 break;
4821 if( j<pFDesc->funcdesc.cParams)
4822 pMemId[i]=j;
4823 else
4824 ret=DISP_E_UNKNOWNNAME;
4826 TRACE("-- 0x%08lx\n", ret);
4827 return ret;
4830 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4831 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4832 if(cNames) *pMemId=pVDesc->vardesc.memid;
4833 return ret;
4836 /* not found, see if it can be found in an inherited interface */
4837 if(This->TypeAttr.cImplTypes) {
4838 /* recursive search */
4839 ITypeInfo *pTInfo;
4840 ret=ITypeInfo_GetRefTypeInfo(iface,
4841 This->impltypelist->hRef, &pTInfo);
4842 if(SUCCEEDED(ret)){
4843 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4844 ITypeInfo_Release(pTInfo);
4845 return ret;
4847 WARN("Could not search inherited interface!\n");
4848 } else
4849 WARN("no names found\n");
4850 return DISP_E_UNKNOWNNAME;
4853 /* ITypeInfo::Invoke
4855 * Invokes a method, or accesses a property of an object, that implements the
4856 * interface described by the type description.
4858 DWORD
4859 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4860 DWORD res;
4862 if (TRACE_ON(ole)) {
4863 int i;
4864 TRACE("Calling %p(",func);
4865 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4866 TRACE(")\n");
4869 switch (callconv) {
4870 case CC_STDCALL:
4872 switch (nrargs) {
4873 case 0:
4874 res = func();
4875 break;
4876 case 1:
4877 res = func(args[0]);
4878 break;
4879 case 2:
4880 res = func(args[0],args[1]);
4881 break;
4882 case 3:
4883 res = func(args[0],args[1],args[2]);
4884 break;
4885 case 4:
4886 res = func(args[0],args[1],args[2],args[3]);
4887 break;
4888 case 5:
4889 res = func(args[0],args[1],args[2],args[3],args[4]);
4890 break;
4891 case 6:
4892 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4893 break;
4894 case 7:
4895 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4896 break;
4897 case 8:
4898 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4899 break;
4900 case 9:
4901 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4902 break;
4903 case 10:
4904 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
4905 break;
4906 case 11:
4907 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
4908 break;
4909 case 12:
4910 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]);
4911 break;
4912 case 13:
4913 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]);
4914 break;
4915 case 14:
4916 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]);
4917 break;
4918 case 15:
4919 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]);
4920 break;
4921 case 16:
4922 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]);
4923 break;
4924 case 17:
4925 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]);
4926 break;
4927 case 18:
4928 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]);
4929 break;
4930 case 19:
4931 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]);
4932 break;
4933 case 20:
4934 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]);
4935 break;
4936 case 21:
4937 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]);
4938 break;
4939 case 22:
4940 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]);
4941 break;
4942 case 23:
4943 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]);
4944 break;
4945 default:
4946 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4947 res = -1;
4948 break;
4950 break;
4951 default:
4952 FIXME("unsupported calling convention %d\n",callconv);
4953 res = -1;
4954 break;
4956 TRACE("returns %08lx\n",res);
4957 return res;
4960 extern int _argsize(DWORD vt);
4962 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
4964 HRESULT hr = S_OK;
4965 ITypeInfo *tinfo2 = NULL;
4966 TYPEATTR *tattr = NULL;
4968 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
4969 if (hr)
4971 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4972 "hr = 0x%08lx\n",
4973 tdesc->u.hreftype, hr);
4974 return hr;
4976 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
4977 if (hr)
4979 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08lx\n", hr);
4980 ITypeInfo_Release(tinfo2);
4981 return hr;
4984 switch (tattr->typekind)
4986 case TKIND_ENUM:
4987 *vt |= VT_I4;
4988 break;
4990 case TKIND_ALIAS:
4991 tdesc = &tattr->tdescAlias;
4992 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
4993 break;
4995 case TKIND_INTERFACE:
4996 if (IsEqualIID(&IID_IDispatch, &tattr->guid))
4997 *vt |= VT_DISPATCH;
4998 else
4999 *vt |= VT_UNKNOWN;
5000 break;
5002 case TKIND_DISPATCH:
5003 *vt |= VT_DISPATCH;
5004 break;
5006 case TKIND_RECORD:
5007 FIXME("TKIND_RECORD unhandled.\n");
5008 hr = E_NOTIMPL;
5009 break;
5011 case TKIND_UNION:
5012 FIXME("TKIND_UNION unhandled.\n");
5013 hr = E_NOTIMPL;
5014 break;
5016 default:
5017 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5018 hr = E_NOTIMPL;
5019 break;
5021 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5022 ITypeInfo_Release(tinfo2);
5023 return hr;
5026 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5028 HRESULT hr = S_OK;
5030 /* enforce only one level of pointer indirection */
5031 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5033 tdesc = tdesc->u.lptdesc;
5035 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5036 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5037 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5038 if ((tdesc->vt == VT_USERDEFINED) ||
5039 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5041 VARTYPE vt_userdefined = 0;
5042 const TYPEDESC *tdesc_userdefined = tdesc;
5043 if (tdesc->vt == VT_PTR)
5045 vt_userdefined = VT_BYREF;
5046 tdesc_userdefined = tdesc->u.lptdesc;
5048 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5049 if ((hr == S_OK) &&
5050 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5051 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5053 *vt |= vt_userdefined;
5054 return S_OK;
5057 *vt = VT_BYREF;
5060 switch (tdesc->vt)
5062 case VT_HRESULT:
5063 *vt |= VT_ERROR;
5064 break;
5065 case VT_USERDEFINED:
5066 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5067 break;
5068 case VT_VOID:
5069 case VT_CARRAY:
5070 case VT_PTR:
5071 case VT_LPSTR:
5072 case VT_LPWSTR:
5073 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5074 hr = DISP_E_BADVARTYPE;
5075 break;
5076 case VT_SAFEARRAY:
5077 *vt |= VT_ARRAY;
5078 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5079 break;
5080 default:
5081 *vt |= tdesc->vt;
5082 break;
5084 return hr;
5087 /***********************************************************************
5088 * DispCallFunc (OLEAUT32.@)
5090 * Invokes a function of the specifed calling convention, passing the
5091 * specified arguments and returns the result.
5093 * PARAMS
5094 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5095 * oVft [I] The offset in the vtable. See notes.
5096 * cc [I] Calling convention of the function to call.
5097 * vtReturn [I] The return type of the function.
5098 * cActuals [I] Number of parameters.
5099 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5100 * prgpvarg [I] The arguments to pass.
5101 * pvargResult [O] The return value of the function. Can be NULL.
5103 * RETURNS
5104 * Success: S_OK.
5105 * Failure: HRESULT code.
5107 * NOTES
5108 * The HRESULT return value of this function is not affected by the return
5109 * value of the user supplied function, which is returned in pvargResult.
5111 * If pvInstance is NULL then a non-object function is to be called and oVft
5112 * is the address of the function to call.
5114 * The cc parameter can be one of the following values:
5115 *|CC_FASTCALL
5116 *|CC_CDECL
5117 *|CC_PASCAL
5118 *|CC_STDCALL
5119 *|CC_FPFASTCALL
5120 *|CC_SYSCALL
5121 *|CC_MPWCDECL
5122 *|CC_MPWPASCAL
5125 HRESULT WINAPI
5126 DispCallFunc(
5127 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5128 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5130 int i, argsize, argspos;
5131 DWORD *args;
5132 HRESULT hres;
5134 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5135 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5136 pvargResult, V_VT(pvargResult));
5138 argsize = 0;
5139 if (pvInstance)
5140 argsize++; /* for This pointer */
5142 for (i=0;i<cActuals;i++)
5144 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5145 dump_Variant(prgpvarg[i]);
5146 argsize += _argsize(prgvt[i]);
5148 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5150 argspos = 0;
5151 if (pvInstance)
5153 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5154 argspos++;
5157 for (i=0;i<cActuals;i++)
5159 VARIANT *arg = prgpvarg[i];
5160 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5161 if (prgvt[i] == VT_VARIANT)
5162 memcpy(&args[argspos], arg, _argsize(prgvt[i]) * sizeof(DWORD));
5163 else
5164 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5165 argspos += _argsize(prgvt[i]);
5168 if (pvInstance)
5170 FARPROC *vtable = *(FARPROC**)pvInstance;
5171 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5173 else
5174 /* if we aren't invoking an object then the function pointer is stored
5175 * in oVft */
5176 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5178 if (pvargResult && (vtReturn != VT_EMPTY))
5180 TRACE("Method returned 0x%08lx\n",hres);
5181 V_VT(pvargResult) = vtReturn;
5182 V_UI4(pvargResult) = hres;
5185 HeapFree(GetProcessHeap(),0,args);
5186 return S_OK;
5189 #define INVBUF_ELEMENT_SIZE \
5190 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5191 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5192 ((VARIANTARG *)(buffer))
5193 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5194 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5195 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5196 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5197 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5198 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5200 static HRESULT WINAPI ITypeInfo_fnInvoke(
5201 ITypeInfo2 *iface,
5202 VOID *pIUnk,
5203 MEMBERID memid,
5204 UINT16 wFlags,
5205 DISPPARAMS *pDispParams,
5206 VARIANT *pVarResult,
5207 EXCEPINFO *pExcepInfo,
5208 UINT *pArgErr)
5210 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5211 int i;
5212 unsigned int var_index;
5213 TYPEKIND type_kind;
5214 HRESULT hres;
5215 const TLBFuncDesc *pFuncInfo;
5217 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p)\n",
5218 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5220 dump_DispParms(pDispParams);
5222 /* we do this instead of using GetFuncDesc since it will return a fake
5223 * FUNCDESC for dispinterfaces and we want the real function description */
5224 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5225 if (memid == pFuncInfo->funcdesc.memid && (wFlags & pFuncInfo->funcdesc.invkind))
5226 break;
5228 if (pFuncInfo) {
5229 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5231 if (TRACE_ON(ole))
5233 TRACE("invoking:\n");
5234 dump_TLBFuncDescOne(pFuncInfo);
5237 switch (func_desc->funckind) {
5238 case FUNC_PUREVIRTUAL:
5239 case FUNC_VIRTUAL: {
5240 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
5241 VARIANT varresult;
5242 VARIANT retval; /* pointer for storing byref retvals in */
5243 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
5244 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
5245 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
5247 hres = S_OK;
5248 for (i = 0; i < func_desc->cParams; i++)
5250 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5251 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
5252 if (FAILED(hres))
5253 goto func_fail;
5256 TRACE("changing args\n");
5257 for (i = 0; i < func_desc->cParams; i++)
5259 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5261 if (wParamFlags & PARAMFLAG_FRETVAL)
5263 /* note: this check is placed so that if the caller passes
5264 * in a VARIANTARG for the retval we just ignore it, like
5265 * native does */
5266 if (i == func_desc->cParams - 1)
5268 VARIANTARG *arg;
5269 arg = prgpvarg[i] = &rgvarg[i];
5270 memset(arg, 0, sizeof(*arg));
5271 V_VT(arg) = rgvt[i];
5272 memset(&retval, 0, sizeof(retval));
5273 V_BYREF(arg) = &retval;
5275 else
5277 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
5278 hres = E_UNEXPECTED;
5279 break;
5282 else if (i < pDispParams->cArgs)
5284 VARIANTARG *src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5285 dump_Variant(src_arg);
5287 if (rgvt[i] == VT_VARIANT)
5288 hres = VariantCopy(&rgvarg[i], src_arg);
5289 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
5291 if (rgvt[i] == V_VT(src_arg))
5292 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
5293 else
5295 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5296 hres = VariantCopy(&missing_arg[i], src_arg);
5297 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
5299 V_VT(&rgvarg[i]) = rgvt[i];
5301 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
5303 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5304 V_VT(&missing_arg[i]) = V_VT(src_arg);
5305 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
5306 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
5307 V_VT(&rgvarg[i]) = rgvt[i];
5309 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
5311 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
5312 V_VT(&rgvarg[i]) = rgvt[i];
5314 else
5316 /* FIXME: this doesn't work for VT_BYREF arguments if
5317 * they are not the same type as in the paramdesc */
5318 V_VT(&rgvarg[i]) = V_VT(src_arg);
5319 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
5320 V_VT(&rgvarg[i]) = rgvt[i];
5323 if (FAILED(hres))
5325 ERR("failed to convert param %d to %s%s from %s%s\n", i,
5326 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
5327 debugstr_VT(src_arg), debugstr_VF(src_arg));
5328 break;
5330 prgpvarg[i] = &rgvarg[i];
5332 else if (wParamFlags & PARAMFLAG_FOPT)
5334 VARIANTARG *arg;
5335 arg = prgpvarg[i] = &rgvarg[i];
5336 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5338 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
5339 if (FAILED(hres))
5340 break;
5342 else
5344 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5345 V_VT(arg) = VT_VARIANT | VT_BYREF;
5346 V_VARIANTREF(arg) = &missing_arg[i];
5347 V_VT(V_VARIANTREF(arg)) = VT_ERROR;
5348 V_ERROR(V_VARIANTREF(arg)) = DISP_E_PARAMNOTFOUND;
5351 else
5353 hres = DISP_E_BADPARAMCOUNT;
5354 break;
5357 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5358 if (func_desc->cParamsOpt < 0)
5360 FIXME("Does not support safearray optional parameters\n");
5361 hres = DISP_E_BADPARAMCOUNT;
5362 goto func_fail; /* FIXME: we don't free changed types here */
5365 V_VT(&varresult) = 0;
5366 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
5367 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5369 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
5370 V_VT(&varresult), func_desc->cParams, rgvt,
5371 prgpvarg, &varresult);
5373 for (i = 0; i < func_desc->cParams; i++)
5375 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5376 if (wParamFlags & PARAMFLAG_FRETVAL)
5378 if (TRACE_ON(ole))
5380 TRACE("[retval] value: ");
5381 dump_Variant(prgpvarg[i]);
5384 if (pVarResult)
5385 /* deref return value */
5386 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
5388 /* free data stored in varresult. Note that
5389 * VariantClear doesn't do what we want because we are
5390 * working with byref types. */
5391 /* FIXME: clear safearrays, bstrs, records and
5392 * variants here too */
5393 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
5394 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
5396 if(*V_UNKNOWNREF(prgpvarg[i]))
5397 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
5399 break;
5401 else if (i < pDispParams->cArgs)
5403 if (wParamFlags & PARAMFLAG_FOUT)
5405 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5407 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
5408 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
5410 if (FAILED(hres))
5412 ERR("failed to convert param %d to vt %d\n", i,
5413 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
5414 break;
5417 VariantClear(&rgvarg[i]);
5419 else if (wParamFlags & PARAMFLAG_FOPT)
5421 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5422 VariantClear(&rgvarg[i]);
5426 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
5428 WARN("invoked function failed with error 0x%08lx\n", V_ERROR(&varresult));
5429 hres = DISP_E_EXCEPTION;
5430 if (pExcepInfo) pExcepInfo->scode = V_ERROR(&varresult);
5433 func_fail:
5434 HeapFree(GetProcessHeap(), 0, buffer);
5435 break;
5437 case FUNC_DISPATCH: {
5438 IDispatch *disp;
5440 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5441 if (SUCCEEDED(hres)) {
5442 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5443 hres = IDispatch_Invoke(
5444 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
5445 pVarResult,pExcepInfo,pArgErr
5447 if (FAILED(hres))
5448 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres);
5449 IDispatch_Release(disp);
5450 } else
5451 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5452 break;
5454 default:
5455 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5456 hres = E_FAIL;
5457 break;
5460 TRACE("-- 0x%08lx\n", hres);
5461 return hres;
5463 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5464 VARDESC *var_desc;
5466 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5467 if(FAILED(hres)) return hres;
5469 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5470 dump_VARDESC(var_desc);
5471 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
5472 return E_NOTIMPL;
5475 /* not found, look for it in inherited interfaces */
5476 ITypeInfo2_GetTypeKind(iface, &type_kind);
5477 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
5478 HREFTYPE ref_type;
5479 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
5480 /* recursive search */
5481 ITypeInfo *pTInfo;
5482 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
5483 if(SUCCEEDED(hres)){
5484 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
5485 ITypeInfo_Release(pTInfo);
5486 return hres;
5488 WARN("Could not search inherited interface!\n");
5491 ERR("did not find member id %ld, flags 0x%x!\n", memid, wFlags);
5492 return DISP_E_MEMBERNOTFOUND;
5495 /* ITypeInfo::GetDocumentation
5497 * Retrieves the documentation string, the complete Help file name and path,
5498 * and the context ID for the Help topic for a specified type description.
5500 * (Can be tested by the Visual Basic Editor in Word for instance.)
5502 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
5503 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
5504 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
5506 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5507 const TLBFuncDesc *pFDesc;
5508 const TLBVarDesc *pVDesc;
5509 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
5510 " HelpContext(%p) HelpFile(%p)\n",
5511 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5512 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5513 if(pBstrName)
5514 *pBstrName=SysAllocString(This->Name);
5515 if(pBstrDocString)
5516 *pBstrDocString=SysAllocString(This->DocString);
5517 if(pdwHelpContext)
5518 *pdwHelpContext=This->dwHelpContext;
5519 if(pBstrHelpFile)
5520 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5521 return S_OK;
5522 }else {/* for a member */
5523 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5524 if(pFDesc->funcdesc.memid==memid){
5525 if(pBstrName)
5526 *pBstrName = SysAllocString(pFDesc->Name);
5527 if(pBstrDocString)
5528 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5529 if(pdwHelpContext)
5530 *pdwHelpContext=pFDesc->helpcontext;
5531 return S_OK;
5533 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5534 if(pVDesc->vardesc.memid==memid){
5535 if(pBstrName)
5536 *pBstrName = SysAllocString(pVDesc->Name);
5537 if(pBstrDocString)
5538 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5539 if(pdwHelpContext)
5540 *pdwHelpContext=pVDesc->HelpContext;
5541 return S_OK;
5544 WARN("member %ld not found\n", memid);
5545 return TYPE_E_ELEMENTNOTFOUND;
5548 /* ITypeInfo::GetDllEntry
5550 * Retrieves a description or specification of an entry point for a function
5551 * in a DLL.
5553 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5554 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5555 WORD *pwOrdinal)
5557 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5558 const TLBFuncDesc *pFDesc;
5560 TRACE("(%p)->(memid %lx, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5562 if (pBstrDllName) *pBstrDllName = NULL;
5563 if (pBstrName) *pBstrName = NULL;
5564 if (pwOrdinal) *pwOrdinal = 0;
5566 if (This->TypeAttr.typekind != TKIND_MODULE)
5567 return TYPE_E_BADMODULEKIND;
5569 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5570 if(pFDesc->funcdesc.memid==memid){
5571 dump_TypeInfo(This);
5572 if (TRACE_ON(ole))
5573 dump_TLBFuncDescOne(pFDesc);
5575 if (pBstrDllName)
5576 *pBstrDllName = SysAllocString(This->DllName);
5578 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5579 if (pBstrName)
5580 *pBstrName = SysAllocString(pFDesc->Entry);
5581 if (pwOrdinal)
5582 *pwOrdinal = -1;
5583 return S_OK;
5585 if (pBstrName)
5586 *pBstrName = NULL;
5587 if (pwOrdinal)
5588 *pwOrdinal = (DWORD)pFDesc->Entry;
5589 return S_OK;
5591 return TYPE_E_ELEMENTNOTFOUND;
5594 /* ITypeInfo::GetRefTypeInfo
5596 * If a type description references other type descriptions, it retrieves
5597 * the referenced type descriptions.
5599 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5600 ITypeInfo2 *iface,
5601 HREFTYPE hRefType,
5602 ITypeInfo **ppTInfo)
5604 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5605 HRESULT result = E_FAIL;
5607 if ((This->hreftype != -1) && (This->hreftype == hRefType))
5609 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5610 ITypeInfo_AddRef(*ppTInfo);
5611 result = S_OK;
5613 else if (hRefType == -1 &&
5614 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5615 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5617 /* when we meet a DUAL dispinterface, we must create the interface
5618 * version of it.
5620 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5623 /* the interface version contains the same information as the dispinterface
5624 * copy the contents of the structs.
5626 *pTypeInfoImpl = *This;
5627 pTypeInfoImpl->ref = 1;
5629 /* change the type to interface */
5630 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5632 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5634 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
5636 result = S_OK;
5638 } else {
5639 TLBRefType *pRefType;
5640 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5641 if(pRefType->reference == hRefType)
5642 break;
5644 if(!pRefType)
5645 FIXME("Can't find pRefType for ref %lx\n", hRefType);
5646 if(pRefType && hRefType != -1) {
5647 ITypeLib *pTLib = NULL;
5649 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5650 UINT Index;
5651 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5652 } else {
5653 if(pRefType->pImpTLInfo->pImpTypeLib) {
5654 TRACE("typeinfo in imported typelib that is already loaded\n");
5655 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5656 ITypeLib2_AddRef((ITypeLib*) pTLib);
5657 result = S_OK;
5658 } else {
5659 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5660 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5661 pRefType->pImpTLInfo->wVersionMajor,
5662 pRefType->pImpTLInfo->wVersionMinor,
5663 pRefType->pImpTLInfo->lcid,
5664 &pTLib);
5666 if(!SUCCEEDED(result)) {
5667 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5668 result=LoadTypeLib(libnam, &pTLib);
5669 SysFreeString(libnam);
5671 if(SUCCEEDED(result)) {
5672 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5673 ITypeLib2_AddRef(pTLib);
5677 if(SUCCEEDED(result)) {
5678 if(pRefType->index == TLB_REF_USE_GUID)
5679 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5680 &pRefType->guid,
5681 ppTInfo);
5682 else
5683 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5684 ppTInfo);
5686 if (pTLib != NULL)
5687 ITypeLib2_Release(pTLib);
5691 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5692 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5693 return result;
5696 /* ITypeInfo::AddressOfMember
5698 * Retrieves the addresses of static functions or variables, such as those
5699 * defined in a DLL.
5701 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5702 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5704 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5705 HRESULT hr;
5706 BSTR dll, entry;
5707 WORD ordinal;
5708 HMODULE module;
5710 TRACE("(%p)->(0x%lx, 0x%x, %p)\n", This, memid, invKind, ppv);
5712 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
5713 if (FAILED(hr))
5714 return hr;
5716 module = LoadLibraryW(dll);
5717 if (!module)
5719 ERR("couldn't load %s\n", debugstr_w(dll));
5720 SysFreeString(dll);
5721 if (entry) SysFreeString(entry);
5722 return STG_E_FILENOTFOUND;
5724 /* FIXME: store library somewhere where we can free it */
5726 if (entry)
5728 LPSTR entryA;
5729 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
5730 entryA = HeapAlloc(GetProcessHeap(), 0, len);
5731 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
5733 *ppv = GetProcAddress(module, entryA);
5734 if (!*ppv)
5735 ERR("function not found %s\n", debugstr_a(entryA));
5737 HeapFree(GetProcessHeap(), 0, entryA);
5739 else
5741 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
5742 if (!*ppv)
5743 ERR("function not found %d\n", ordinal);
5746 SysFreeString(dll);
5747 if (entry) SysFreeString(entry);
5749 if (!*ppv)
5750 return TYPE_E_DLLFUNCTIONNOTFOUND;
5752 return S_OK;
5755 /* ITypeInfo::CreateInstance
5757 * Creates a new instance of a type that describes a component object class
5758 * (coclass).
5760 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5761 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
5763 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5764 FIXME("(%p) stub!\n", This);
5765 return S_OK;
5768 /* ITypeInfo::GetMops
5770 * Retrieves marshalling information.
5772 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5773 BSTR *pBstrMops)
5775 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5776 FIXME("(%p) stub!\n", This);
5777 return S_OK;
5780 /* ITypeInfo::GetContainingTypeLib
5782 * Retrieves the containing type library and the index of the type description
5783 * within that type library.
5785 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5786 ITypeLib * *ppTLib, UINT *pIndex)
5788 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5790 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5791 if (pIndex) {
5792 *pIndex=This->index;
5793 TRACE("returning pIndex=%d\n", *pIndex);
5796 if (ppTLib) {
5797 *ppTLib=(LPTYPELIB )(This->pTypeLib);
5798 ITypeLib2_AddRef(*ppTLib);
5799 TRACE("returning ppTLib=%p\n", *ppTLib);
5802 return S_OK;
5805 /* ITypeInfo::ReleaseTypeAttr
5807 * Releases a TYPEATTR previously returned by GetTypeAttr.
5810 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5811 TYPEATTR* pTypeAttr)
5813 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5814 TRACE("(%p)->(%p)\n", This, pTypeAttr);
5815 HeapFree(GetProcessHeap(), 0, pTypeAttr);
5818 /* ITypeInfo::ReleaseFuncDesc
5820 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5822 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5823 ITypeInfo2 *iface,
5824 FUNCDESC *pFuncDesc)
5826 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5827 SHORT i;
5829 TRACE("(%p)->(%p)\n", This, pFuncDesc);
5831 for (i = 0; i < pFuncDesc->cParams; i++)
5832 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
5833 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
5835 SysFreeString((BSTR)pFuncDesc);
5838 /* ITypeInfo::ReleaseVarDesc
5840 * Releases a VARDESC previously returned by GetVarDesc.
5842 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5843 VARDESC *pVarDesc)
5845 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5846 TRACE("(%p)->(%p)\n", This, pVarDesc);
5848 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
5849 if (pVarDesc->varkind == VAR_CONST)
5850 VariantClear(pVarDesc->u.lpvarValue);
5851 SysFreeString((BSTR)pVarDesc);
5854 /* ITypeInfo2::GetTypeKind
5856 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5859 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5860 TYPEKIND *pTypeKind)
5862 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5863 *pTypeKind=This->TypeAttr.typekind;
5864 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5865 return S_OK;
5868 /* ITypeInfo2::GetTypeFlags
5870 * Returns the type flags without any allocations. This returns a DWORD type
5871 * flag, which expands the type flags without growing the TYPEATTR (type
5872 * attribute).
5875 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5877 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5878 *pTypeFlags=This->TypeAttr.wTypeFlags;
5879 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5880 return S_OK;
5883 /* ITypeInfo2::GetFuncIndexOfMemId
5884 * Binds to a specific member based on a known DISPID, where the member name
5885 * is not known (for example, when binding to a default member).
5888 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5889 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5891 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5892 const TLBFuncDesc *pFuncInfo;
5893 int i;
5894 HRESULT result;
5896 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
5897 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
5898 break;
5899 if(pFuncInfo) {
5900 *pFuncIndex = i;
5901 result = S_OK;
5902 } else
5903 result = TYPE_E_ELEMENTNOTFOUND;
5905 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5906 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5907 return result;
5910 /* TypeInfo2::GetVarIndexOfMemId
5912 * Binds to a specific member based on a known DISPID, where the member name
5913 * is not known (for example, when binding to a default member).
5916 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5917 MEMBERID memid, UINT *pVarIndex)
5919 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5920 TLBVarDesc *pVarInfo;
5921 int i;
5922 HRESULT result;
5923 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5924 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5926 if(pVarInfo) {
5927 *pVarIndex = i;
5928 result = S_OK;
5929 } else
5930 result = TYPE_E_ELEMENTNOTFOUND;
5932 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5933 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5934 return result;
5937 /* ITypeInfo2::GetCustData
5939 * Gets the custom data
5941 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5942 ITypeInfo2 * iface,
5943 REFGUID guid,
5944 VARIANT *pVarVal)
5946 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5947 TLBCustData *pCData;
5949 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5950 if( IsEqualIID(guid, &pCData->guid)) break;
5952 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5954 if(pCData)
5956 VariantInit( pVarVal);
5957 VariantCopy( pVarVal, &pCData->data);
5958 return S_OK;
5960 return E_INVALIDARG; /* FIXME: correct? */
5963 /* ITypeInfo2::GetFuncCustData
5965 * Gets the custom data
5967 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5968 ITypeInfo2 * iface,
5969 UINT index,
5970 REFGUID guid,
5971 VARIANT *pVarVal)
5973 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5974 TLBCustData *pCData=NULL;
5975 TLBFuncDesc * pFDesc;
5976 int i;
5977 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5978 pFDesc=pFDesc->next);
5980 if(pFDesc)
5981 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
5982 if( IsEqualIID(guid, &pCData->guid)) break;
5984 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5986 if(pCData){
5987 VariantInit( pVarVal);
5988 VariantCopy( pVarVal, &pCData->data);
5989 return S_OK;
5991 return E_INVALIDARG; /* FIXME: correct? */
5994 /* ITypeInfo2::GetParamCustData
5996 * Gets the custom data
5998 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
5999 ITypeInfo2 * iface,
6000 UINT indexFunc,
6001 UINT indexParam,
6002 REFGUID guid,
6003 VARIANT *pVarVal)
6005 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6006 TLBCustData *pCData=NULL;
6007 TLBFuncDesc * pFDesc;
6008 int i;
6010 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
6012 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
6013 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
6014 pCData = pCData->next)
6015 if( IsEqualIID(guid, &pCData->guid)) break;
6017 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6019 if(pCData)
6021 VariantInit( pVarVal);
6022 VariantCopy( pVarVal, &pCData->data);
6023 return S_OK;
6025 return E_INVALIDARG; /* FIXME: correct? */
6028 /* ITypeInfo2::GetVarCustData
6030 * Gets the custom data
6032 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
6033 ITypeInfo2 * iface,
6034 UINT index,
6035 REFGUID guid,
6036 VARIANT *pVarVal)
6038 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6039 TLBCustData *pCData=NULL;
6040 TLBVarDesc * pVDesc;
6041 int i;
6043 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
6045 if(pVDesc)
6047 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
6049 if( IsEqualIID(guid, &pCData->guid)) break;
6053 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6055 if(pCData)
6057 VariantInit( pVarVal);
6058 VariantCopy( pVarVal, &pCData->data);
6059 return S_OK;
6061 return E_INVALIDARG; /* FIXME: correct? */
6064 /* ITypeInfo2::GetImplCustData
6066 * Gets the custom data
6068 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6069 ITypeInfo2 * iface,
6070 UINT index,
6071 REFGUID guid,
6072 VARIANT *pVarVal)
6074 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6075 TLBCustData *pCData=NULL;
6076 TLBImplType * pRDesc;
6077 int i;
6079 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6081 if(pRDesc)
6083 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6085 if( IsEqualIID(guid, &pCData->guid)) break;
6089 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6091 if(pCData)
6093 VariantInit( pVarVal);
6094 VariantCopy( pVarVal, &pCData->data);
6095 return S_OK;
6097 return E_INVALIDARG; /* FIXME: correct? */
6100 /* ITypeInfo2::GetDocumentation2
6102 * Retrieves the documentation string, the complete Help file name and path,
6103 * the localization context to use, and the context ID for the library Help
6104 * topic in the Help file.
6107 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6108 ITypeInfo2 * iface,
6109 MEMBERID memid,
6110 LCID lcid,
6111 BSTR *pbstrHelpString,
6112 DWORD *pdwHelpStringContext,
6113 BSTR *pbstrHelpStringDll)
6115 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6116 const TLBFuncDesc *pFDesc;
6117 const TLBVarDesc *pVDesc;
6118 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
6119 "HelpStringContext(%p) HelpStringDll(%p)\n",
6120 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6121 pbstrHelpStringDll );
6122 /* the help string should be obtained from the helpstringdll,
6123 * using the _DLLGetDocumentation function, based on the supplied
6124 * lcid. Nice to do sometime...
6126 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6127 if(pbstrHelpString)
6128 *pbstrHelpString=SysAllocString(This->Name);
6129 if(pdwHelpStringContext)
6130 *pdwHelpStringContext=This->dwHelpStringContext;
6131 if(pbstrHelpStringDll)
6132 *pbstrHelpStringDll=
6133 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6134 return S_OK;
6135 }else {/* for a member */
6136 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6137 if(pFDesc->funcdesc.memid==memid){
6138 if(pbstrHelpString)
6139 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6140 if(pdwHelpStringContext)
6141 *pdwHelpStringContext=pFDesc->HelpStringContext;
6142 if(pbstrHelpStringDll)
6143 *pbstrHelpStringDll=
6144 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6145 return S_OK;
6147 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6148 if(pVDesc->vardesc.memid==memid){
6149 if(pbstrHelpString)
6150 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6151 if(pdwHelpStringContext)
6152 *pdwHelpStringContext=pVDesc->HelpStringContext;
6153 if(pbstrHelpStringDll)
6154 *pbstrHelpStringDll=
6155 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6156 return S_OK;
6159 return TYPE_E_ELEMENTNOTFOUND;
6162 /* ITypeInfo2::GetAllCustData
6164 * Gets all custom data items for the Type info.
6167 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6168 ITypeInfo2 * iface,
6169 CUSTDATA *pCustData)
6171 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6172 TLBCustData *pCData;
6173 int i;
6175 TRACE("(%p) returning %d items\n", This, This->ctCustData);
6177 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6178 if(pCustData->prgCustData ){
6179 pCustData->cCustData=This->ctCustData;
6180 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
6181 pCustData->prgCustData[i].guid=pCData->guid;
6182 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
6184 }else{
6185 ERR(" OUT OF MEMORY!\n");
6186 return E_OUTOFMEMORY;
6188 return S_OK;
6191 /* ITypeInfo2::GetAllFuncCustData
6193 * Gets all custom data items for the specified Function
6196 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
6197 ITypeInfo2 * iface,
6198 UINT index,
6199 CUSTDATA *pCustData)
6201 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6202 TLBCustData *pCData;
6203 TLBFuncDesc * pFDesc;
6204 int i;
6205 TRACE("(%p) index %d\n", This, index);
6206 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6207 pFDesc=pFDesc->next)
6209 if(pFDesc){
6210 pCustData->prgCustData =
6211 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
6212 if(pCustData->prgCustData ){
6213 pCustData->cCustData=pFDesc->ctCustData;
6214 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
6215 pCData = pCData->next){
6216 pCustData->prgCustData[i].guid=pCData->guid;
6217 VariantCopy(& pCustData->prgCustData[i].varValue,
6218 & pCData->data);
6220 }else{
6221 ERR(" OUT OF MEMORY!\n");
6222 return E_OUTOFMEMORY;
6224 return S_OK;
6226 return TYPE_E_ELEMENTNOTFOUND;
6229 /* ITypeInfo2::GetAllParamCustData
6231 * Gets all custom data items for the Functions
6234 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
6235 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
6237 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6238 TLBCustData *pCData=NULL;
6239 TLBFuncDesc * pFDesc;
6240 int i;
6241 TRACE("(%p) index %d\n", This, indexFunc);
6242 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
6243 pFDesc=pFDesc->next)
6245 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
6246 pCustData->prgCustData =
6247 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
6248 sizeof(CUSTDATAITEM));
6249 if(pCustData->prgCustData ){
6250 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
6251 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
6252 pCData; i++, pCData = pCData->next){
6253 pCustData->prgCustData[i].guid=pCData->guid;
6254 VariantCopy(& pCustData->prgCustData[i].varValue,
6255 & pCData->data);
6257 }else{
6258 ERR(" OUT OF MEMORY!\n");
6259 return E_OUTOFMEMORY;
6261 return S_OK;
6263 return TYPE_E_ELEMENTNOTFOUND;
6266 /* ITypeInfo2::GetAllVarCustData
6268 * Gets all custom data items for the specified Variable
6271 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
6272 UINT index, CUSTDATA *pCustData)
6274 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6275 TLBCustData *pCData;
6276 TLBVarDesc * pVDesc;
6277 int i;
6278 TRACE("(%p) index %d\n", This, index);
6279 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
6280 pVDesc=pVDesc->next)
6282 if(pVDesc){
6283 pCustData->prgCustData =
6284 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
6285 if(pCustData->prgCustData ){
6286 pCustData->cCustData=pVDesc->ctCustData;
6287 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
6288 pCData = pCData->next){
6289 pCustData->prgCustData[i].guid=pCData->guid;
6290 VariantCopy(& pCustData->prgCustData[i].varValue,
6291 & pCData->data);
6293 }else{
6294 ERR(" OUT OF MEMORY!\n");
6295 return E_OUTOFMEMORY;
6297 return S_OK;
6299 return TYPE_E_ELEMENTNOTFOUND;
6302 /* ITypeInfo2::GetAllImplCustData
6304 * Gets all custom data items for the specified implementation type
6307 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
6308 ITypeInfo2 * iface,
6309 UINT index,
6310 CUSTDATA *pCustData)
6312 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6313 TLBCustData *pCData;
6314 TLBImplType * pRDesc;
6315 int i;
6316 TRACE("(%p) index %d\n", This, index);
6317 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
6318 pRDesc=pRDesc->next)
6320 if(pRDesc){
6321 pCustData->prgCustData =
6322 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
6323 if(pCustData->prgCustData ){
6324 pCustData->cCustData=pRDesc->ctCustData;
6325 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
6326 pCData = pCData->next){
6327 pCustData->prgCustData[i].guid=pCData->guid;
6328 VariantCopy(& pCustData->prgCustData[i].varValue,
6329 & pCData->data);
6331 }else{
6332 ERR(" OUT OF MEMORY!\n");
6333 return E_OUTOFMEMORY;
6335 return S_OK;
6337 return TYPE_E_ELEMENTNOTFOUND;
6340 static const ITypeInfo2Vtbl tinfvt =
6343 ITypeInfo_fnQueryInterface,
6344 ITypeInfo_fnAddRef,
6345 ITypeInfo_fnRelease,
6347 ITypeInfo_fnGetTypeAttr,
6348 ITypeInfo_fnGetTypeComp,
6349 ITypeInfo_fnGetFuncDesc,
6350 ITypeInfo_fnGetVarDesc,
6351 ITypeInfo_fnGetNames,
6352 ITypeInfo_fnGetRefTypeOfImplType,
6353 ITypeInfo_fnGetImplTypeFlags,
6354 ITypeInfo_fnGetIDsOfNames,
6355 ITypeInfo_fnInvoke,
6356 ITypeInfo_fnGetDocumentation,
6357 ITypeInfo_fnGetDllEntry,
6358 ITypeInfo_fnGetRefTypeInfo,
6359 ITypeInfo_fnAddressOfMember,
6360 ITypeInfo_fnCreateInstance,
6361 ITypeInfo_fnGetMops,
6362 ITypeInfo_fnGetContainingTypeLib,
6363 ITypeInfo_fnReleaseTypeAttr,
6364 ITypeInfo_fnReleaseFuncDesc,
6365 ITypeInfo_fnReleaseVarDesc,
6367 ITypeInfo2_fnGetTypeKind,
6368 ITypeInfo2_fnGetTypeFlags,
6369 ITypeInfo2_fnGetFuncIndexOfMemId,
6370 ITypeInfo2_fnGetVarIndexOfMemId,
6371 ITypeInfo2_fnGetCustData,
6372 ITypeInfo2_fnGetFuncCustData,
6373 ITypeInfo2_fnGetParamCustData,
6374 ITypeInfo2_fnGetVarCustData,
6375 ITypeInfo2_fnGetImplTypeCustData,
6376 ITypeInfo2_fnGetDocumentation2,
6377 ITypeInfo2_fnGetAllCustData,
6378 ITypeInfo2_fnGetAllFuncCustData,
6379 ITypeInfo2_fnGetAllParamCustData,
6380 ITypeInfo2_fnGetAllVarCustData,
6381 ITypeInfo2_fnGetAllImplTypeCustData,
6384 /******************************************************************************
6385 * CreateDispTypeInfo [OLEAUT32.31]
6387 * Build type information for an object so it can be called through an
6388 * IDispatch interface.
6390 * RETURNS
6391 * Success: S_OK. pptinfo contains the created ITypeInfo object.
6392 * Failure: E_INVALIDARG, if one or more arguments is invalid.
6394 * NOTES
6395 * This call allows an objects methods to be accessed through IDispatch, by
6396 * building an ITypeInfo object that IDispatch can use to call through.
6398 HRESULT WINAPI CreateDispTypeInfo(
6399 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
6400 LCID lcid, /* [I] Locale Id */
6401 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
6403 ITypeInfoImpl *pTIClass, *pTIIface;
6404 ITypeLibImpl *pTypeLibImpl;
6405 int param, func;
6406 TLBFuncDesc **ppFuncDesc;
6408 TRACE("\n");
6409 pTypeLibImpl = TypeLibImpl_Constructor();
6410 if (!pTypeLibImpl) return E_FAIL;
6412 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
6413 pTIIface->pTypeLib = pTypeLibImpl;
6414 pTIIface->index = 0;
6415 pTIIface->Name = NULL;
6416 pTIIface->dwHelpContext = -1;
6417 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
6418 pTIIface->TypeAttr.lcid = lcid;
6419 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
6420 pTIIface->TypeAttr.wMajorVerNum = 0;
6421 pTIIface->TypeAttr.wMinorVerNum = 0;
6422 pTIIface->TypeAttr.cbAlignment = 2;
6423 pTIIface->TypeAttr.cbSizeInstance = -1;
6424 pTIIface->TypeAttr.cbSizeVft = -1;
6425 pTIIface->TypeAttr.cFuncs = 0;
6426 pTIIface->TypeAttr.cImplTypes = 0;
6427 pTIIface->TypeAttr.cVars = 0;
6428 pTIIface->TypeAttr.wTypeFlags = 0;
6430 ppFuncDesc = &pTIIface->funclist;
6431 for(func = 0; func < pidata->cMembers; func++) {
6432 METHODDATA *md = pidata->pmethdata + func;
6433 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
6434 (*ppFuncDesc)->Name = SysAllocString(md->szName);
6435 (*ppFuncDesc)->funcdesc.memid = md->dispid;
6436 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
6437 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
6438 (*ppFuncDesc)->funcdesc.callconv = md->cc;
6439 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
6440 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
6441 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
6442 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
6443 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
6444 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
6445 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
6446 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6447 md->cArgs * sizeof(ELEMDESC));
6448 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6449 md->cArgs * sizeof(TLBParDesc));
6450 for(param = 0; param < md->cArgs; param++) {
6451 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
6452 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
6454 (*ppFuncDesc)->helpcontext = 0;
6455 (*ppFuncDesc)->HelpStringContext = 0;
6456 (*ppFuncDesc)->HelpString = NULL;
6457 (*ppFuncDesc)->Entry = NULL;
6458 (*ppFuncDesc)->ctCustData = 0;
6459 (*ppFuncDesc)->pCustData = NULL;
6460 (*ppFuncDesc)->next = NULL;
6461 ppFuncDesc = &(*ppFuncDesc)->next;
6464 dump_TypeInfo(pTIIface);
6466 pTypeLibImpl->pTypeInfo = pTIIface;
6467 pTypeLibImpl->TypeInfoCount++;
6469 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
6470 pTIClass->pTypeLib = pTypeLibImpl;
6471 pTIClass->index = 1;
6472 pTIClass->Name = NULL;
6473 pTIClass->dwHelpContext = -1;
6474 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
6475 pTIClass->TypeAttr.lcid = lcid;
6476 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
6477 pTIClass->TypeAttr.wMajorVerNum = 0;
6478 pTIClass->TypeAttr.wMinorVerNum = 0;
6479 pTIClass->TypeAttr.cbAlignment = 2;
6480 pTIClass->TypeAttr.cbSizeInstance = -1;
6481 pTIClass->TypeAttr.cbSizeVft = -1;
6482 pTIClass->TypeAttr.cFuncs = 0;
6483 pTIClass->TypeAttr.cImplTypes = 1;
6484 pTIClass->TypeAttr.cVars = 0;
6485 pTIClass->TypeAttr.wTypeFlags = 0;
6487 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
6488 pTIClass->impltypelist->hRef = 1;
6490 pTIClass->reflist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->reflist));
6491 pTIClass->reflist->index = 0;
6492 pTIClass->reflist->reference = 1;
6493 pTIClass->reflist->pImpTLInfo = TLB_REF_INTERNAL;
6495 dump_TypeInfo(pTIClass);
6497 pTIIface->next = pTIClass;
6498 pTypeLibImpl->TypeInfoCount++;
6500 *pptinfo = (ITypeInfo*)pTIClass;
6501 return S_OK;
6505 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
6507 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6509 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
6512 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
6514 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6516 return ITypeInfo_AddRef((ITypeInfo *)This);
6519 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
6521 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6523 return ITypeInfo_Release((ITypeInfo *)This);
6526 static HRESULT WINAPI ITypeComp_fnBind(
6527 ITypeComp * iface,
6528 OLECHAR * szName,
6529 ULONG lHash,
6530 WORD wFlags,
6531 ITypeInfo ** ppTInfo,
6532 DESCKIND * pDescKind,
6533 BINDPTR * pBindPtr)
6535 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6536 const TLBFuncDesc *pFDesc;
6537 const TLBVarDesc *pVDesc;
6539 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6541 *pDescKind = DESCKIND_NONE;
6542 pBindPtr->lpfuncdesc = NULL;
6543 *ppTInfo = NULL;
6545 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
6546 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
6547 if (!strcmpW(pFDesc->Name, szName)) {
6548 break;
6551 if (pFDesc)
6553 HRESULT hr = TLB_AllocAndInitFuncDesc(
6554 &pFDesc->funcdesc,
6555 &pBindPtr->lpfuncdesc,
6556 This->TypeAttr.typekind == TKIND_DISPATCH);
6557 if (FAILED(hr))
6558 return hr;
6559 *pDescKind = DESCKIND_FUNCDESC;
6560 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6561 ITypeInfo_AddRef(*ppTInfo);
6562 return S_OK;
6563 } else {
6564 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
6565 if (!strcmpW(pVDesc->Name, szName)) {
6566 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
6567 if (FAILED(hr))
6568 return hr;
6569 *pDescKind = DESCKIND_VARDESC;
6570 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6571 ITypeInfo_AddRef(*ppTInfo);
6572 return S_OK;
6576 /* FIXME: search each inherited interface, not just the first */
6577 if (This->TypeAttr.cImplTypes) {
6578 /* recursive search */
6579 ITypeInfo *pTInfo;
6580 ITypeComp *pTComp;
6581 HRESULT hr;
6582 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
6583 if (SUCCEEDED(hr))
6585 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
6586 ITypeInfo_Release(pTInfo);
6588 if (SUCCEEDED(hr))
6590 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6591 ITypeComp_Release(pTComp);
6592 return hr;
6594 WARN("Could not search inherited interface!\n");
6596 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
6597 return DISP_E_MEMBERNOTFOUND;
6600 static HRESULT WINAPI ITypeComp_fnBindType(
6601 ITypeComp * iface,
6602 OLECHAR * szName,
6603 ULONG lHash,
6604 ITypeInfo ** ppTInfo,
6605 ITypeComp ** ppTComp)
6607 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
6609 /* strange behaviour (does nothing) but like the
6610 * original */
6612 if (!ppTInfo || !ppTComp)
6613 return E_POINTER;
6615 *ppTInfo = NULL;
6616 *ppTComp = NULL;
6618 return S_OK;
6621 static const ITypeCompVtbl tcompvt =
6624 ITypeComp_fnQueryInterface,
6625 ITypeComp_fnAddRef,
6626 ITypeComp_fnRelease,
6628 ITypeComp_fnBind,
6629 ITypeComp_fnBindType