oleaut: Move the processing of functions in SLTG typelibs into a
[wine/wine64.git] / dlls / oleaut32 / typelib.c
blobc61bd369060756c8f52a21b21b75611069b63cb6
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, ITypeInfoImpl *pTI, unsigned short cVars, char *pNameTable)
2825 TLBVarDesc **ppVarDesc = &pTI->varlist;
2826 SLTG_Variable *pItem;
2827 unsigned short i;
2828 WORD *pType;
2829 char buf[300];
2831 for(pItem = (SLTG_Variable *)pBlk, i = 0; i < cVars;
2832 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
2834 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2835 sizeof(**ppVarDesc));
2836 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2837 (*ppVarDesc)->vardesc.memid = pItem->memid;
2839 if(pItem->magic != SLTG_VAR_MAGIC) {
2840 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
2841 return;
2844 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
2845 TRACE_(typelib)("memid = 0x%lx\n", pItem->memid);
2847 if (pItem->flags & 0x40) {
2848 TRACE_(typelib)("VAR_DISPATCH\n");
2849 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
2851 else if (pItem->flags & 0x10) {
2852 TRACE_(typelib)("VAR_CONST\n");
2853 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2854 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2855 sizeof(VARIANT));
2856 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2857 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2858 *(INT*)(pBlk + pItem->byte_offs);
2860 else {
2861 TRACE_(typelib)("VAR_PERINSTANCE\n");
2862 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2863 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2866 if (pItem->flags & 0x80)
2867 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
2869 if(pItem->flags & 0x02)
2870 pType = &pItem->type;
2871 else
2872 pType = (WORD*)(pBlk + pItem->type);
2874 if (pItem->flags & ~0xd2)
2875 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xd2);
2877 SLTG_DoElem(pType, pBlk,
2878 &(*ppVarDesc)->vardesc.elemdescVar);
2880 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2882 ppVarDesc = &((*ppVarDesc)->next);
2884 pTI->TypeAttr.cVars = cVars;
2887 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cFuncs, char *pNameTable)
2889 SLTG_Function *pFunc;
2890 unsigned short i;
2891 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2893 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
2894 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
2896 int param;
2897 WORD *pType, *pArg;
2899 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2900 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2901 FIXME("func magic = %02x\n", pFunc->magic);
2902 return;
2904 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2905 sizeof(**ppFuncDesc));
2906 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2908 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2909 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2910 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2911 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2912 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2913 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2915 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2916 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2918 if(pFunc->retnextopt & 0x80)
2919 pType = &pFunc->rettype;
2920 else
2921 pType = (WORD*)(pBlk + pFunc->rettype);
2923 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2925 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2926 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2927 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2928 (*ppFuncDesc)->pParamDesc =
2929 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2930 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2932 pArg = (WORD*)(pBlk + pFunc->arg_off);
2934 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2935 char *paramName = pNameTable + *pArg;
2936 BOOL HaveOffs;
2937 /* If arg type follows then paramName points to the 2nd
2938 letter of the name, else the next WORD is an offset to
2939 the arg type and paramName points to the first letter.
2940 So let's take one char off paramName and see if we're
2941 pointing at an alpha-numeric char. However if *pArg is
2942 0xffff or 0xfffe then the param has no name, the former
2943 meaning that the next WORD is the type, the latter
2944 meaning the the next WORD is an offset to the type. */
2946 HaveOffs = FALSE;
2947 if(*pArg == 0xffff)
2948 paramName = NULL;
2949 else if(*pArg == 0xfffe) {
2950 paramName = NULL;
2951 HaveOffs = TRUE;
2953 else if(paramName[-1] && !isalnum(paramName[-1]))
2954 HaveOffs = TRUE;
2956 pArg++;
2958 if(HaveOffs) { /* the next word is an offset to type */
2959 pType = (WORD*)(pBlk + *pArg);
2960 SLTG_DoElem(pType, pBlk,
2961 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2962 pArg++;
2963 } else {
2964 if(paramName)
2965 paramName--;
2966 pArg = SLTG_DoElem(pArg, pBlk,
2967 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2970 /* Are we an optional param ? */
2971 if((*ppFuncDesc)->funcdesc.cParams - param <=
2972 (*ppFuncDesc)->funcdesc.cParamsOpt)
2973 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2975 if(paramName) {
2976 (*ppFuncDesc)->pParamDesc[param].Name =
2977 TLB_MultiByteToBSTR(paramName);
2981 ppFuncDesc = &((*ppFuncDesc)->next);
2982 if(pFunc->next == 0xffff) break;
2984 pTI->TypeAttr.cFuncs = cFuncs;
2987 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2988 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
2989 SLTG_TypeInfoTail *pTITail)
2991 char *pFirstItem, *pNextItem;
2993 if(pTIHeader->href_table != 0xffffffff) {
2994 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
2995 pNameTable);
2998 pFirstItem = pNextItem = pBlk;
3000 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3001 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
3006 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3007 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3008 SLTG_TypeInfoTail *pTITail)
3010 char *pFirstItem, *pNextItem;
3012 if(pTIHeader->href_table != 0xffffffff) {
3013 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3014 pNameTable);
3017 pFirstItem = pNextItem = pBlk;
3019 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3020 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
3023 if (pTITail->funcs_off != 0xffff)
3024 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3026 if (TRACE_ON(typelib))
3027 dump_TLBFuncDesc(pTI->funclist);
3030 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3031 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3032 SLTG_TypeInfoTail *pTITail)
3034 SLTG_DoVars(pBlk, pTI, pTITail->cVars, pNameTable);
3037 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3038 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3039 SLTG_TypeInfoTail *pTITail)
3041 WORD *pType;
3043 if (pTITail->simple_alias) {
3044 /* if simple alias, no more processing required */
3045 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3046 return;
3049 if(pTIHeader->href_table != 0xffffffff) {
3050 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3051 pNameTable);
3054 /* otherwise it is an offset to a type */
3055 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3057 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias);
3060 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3061 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3062 SLTG_TypeInfoTail *pTITail)
3064 if (pTIHeader->href_table != 0xffffffff)
3065 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3066 pNameTable);
3068 if (pTITail->vars_off != 0xffff)
3069 SLTG_DoVars(pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3071 if (pTITail->funcs_off != 0xffff)
3072 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3075 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3076 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3077 SLTG_TypeInfoTail *pTITail)
3079 SLTG_DoVars(pBlk, pTI, pTITail->cVars, pNameTable);
3082 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3083 managable copy of it into this */
3084 typedef struct {
3085 WORD small_no;
3086 char *index_name;
3087 char *other_name;
3088 WORD res1a;
3089 WORD name_offs;
3090 WORD more_bytes;
3091 char *extra;
3092 WORD res20;
3093 DWORD helpcontext;
3094 WORD res26;
3095 GUID uuid;
3096 } SLTG_InternalOtherTypeInfo;
3098 /****************************************************************************
3099 * ITypeLib2_Constructor_SLTG
3101 * loading a SLTG typelib from an in-memory image
3103 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3105 ITypeLibImpl *pTypeLibImpl;
3106 SLTG_Header *pHeader;
3107 SLTG_BlkEntry *pBlkEntry;
3108 SLTG_Magic *pMagic;
3109 SLTG_Index *pIndex;
3110 SLTG_Pad9 *pPad9;
3111 LPVOID pBlk, pFirstBlk;
3112 SLTG_LibBlk *pLibBlk;
3113 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3114 char *pAfterOTIBlks = NULL;
3115 char *pNameTable, *ptr;
3116 int i;
3117 DWORD len, order;
3118 ITypeInfoImpl **ppTypeInfoImpl;
3120 TRACE_(typelib)("%p, TLB length = %ld\n", pLib, dwTLBLength);
3123 pTypeLibImpl = TypeLibImpl_Constructor();
3124 if (!pTypeLibImpl) return NULL;
3126 pHeader = pLib;
3128 TRACE_(typelib)("header:\n");
3129 TRACE_(typelib)("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
3130 pHeader->nrOfFileBlks );
3131 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3132 FIXME("Header type magic 0x%08lx not supported.\n",
3133 pHeader->SLTG_magic);
3134 return NULL;
3137 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3138 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3140 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3141 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3143 /* Next we have a magic block */
3144 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3146 /* Let's see if we're still in sync */
3147 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3148 sizeof(SLTG_COMPOBJ_MAGIC))) {
3149 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3150 return NULL;
3152 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3153 sizeof(SLTG_DIR_MAGIC))) {
3154 FIXME("dir magic = %s\n", pMagic->dir_magic);
3155 return NULL;
3158 pIndex = (SLTG_Index*)(pMagic+1);
3160 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3162 pFirstBlk = (LPVOID)(pPad9 + 1);
3164 /* We'll set up a ptr to the main library block, which is the last one. */
3166 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3167 pBlkEntry[order].next != 0;
3168 order = pBlkEntry[order].next - 1, i++) {
3169 pBlk = (char*)pBlk + pBlkEntry[order].len;
3171 pLibBlk = pBlk;
3173 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3175 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3176 interspersed */
3178 len += 0x40;
3180 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3182 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3183 sizeof(*pOtherTypeInfoBlks) *
3184 pTypeLibImpl->TypeInfoCount);
3187 ptr = (char*)pLibBlk + len;
3189 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3190 WORD w, extra;
3191 len = 0;
3193 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3195 w = *(WORD*)(ptr + 2);
3196 if(w != 0xffff) {
3197 len += w;
3198 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3199 w+1);
3200 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3201 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3203 w = *(WORD*)(ptr + 4 + len);
3204 if(w != 0xffff) {
3205 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3206 len += w;
3207 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3208 w+1);
3209 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3210 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3212 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3213 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3214 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3215 if(extra) {
3216 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3217 extra);
3218 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3219 len += extra;
3221 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3222 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3223 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3224 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3225 len += sizeof(SLTG_OtherTypeInfo);
3226 ptr += len;
3229 pAfterOTIBlks = ptr;
3231 /* Skip this WORD and get the next DWORD */
3232 len = *(DWORD*)(pAfterOTIBlks + 2);
3234 /* Now add this to pLibBLk look at what we're pointing at and
3235 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3236 dust and we should be pointing at the beginning of the name
3237 table */
3239 pNameTable = (char*)pLibBlk + len;
3241 switch(*(WORD*)pNameTable) {
3242 case 0xffff:
3243 break;
3244 case 0x0200:
3245 pNameTable += 0x20;
3246 break;
3247 default:
3248 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3249 break;
3252 pNameTable += 0x216;
3254 pNameTable += 2;
3256 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3258 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3261 /* Hopefully we now have enough ptrs set up to actually read in
3262 some TypeInfos. It's not clear which order to do them in, so
3263 I'll just follow the links along the BlkEntry chain and read
3264 them in in the order in which they're in the file */
3266 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3268 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3269 pBlkEntry[order].next != 0;
3270 order = pBlkEntry[order].next - 1, i++) {
3272 SLTG_TypeInfoHeader *pTIHeader;
3273 SLTG_TypeInfoTail *pTITail;
3274 SLTG_MemberHeader *pMemHeader;
3276 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3277 pOtherTypeInfoBlks[i].index_name)) {
3278 FIXME("Index strings don't match\n");
3279 return NULL;
3282 pTIHeader = pBlk;
3283 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3284 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3285 return NULL;
3287 TRACE("pTIHeader->res06 = %lx, pTIHeader->res0e = %lx, pTIHeader->res16 = %lx, pTIHeader->res1e = %lx\n",
3288 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3290 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3291 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3292 (*ppTypeInfoImpl)->index = i;
3293 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3294 pOtherTypeInfoBlks[i].name_offs +
3295 pNameTable);
3296 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3297 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3298 sizeof(GUID));
3299 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3300 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3301 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3302 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3303 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3305 if((pTIHeader->typeflags1 & 7) != 2)
3306 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3307 if(pTIHeader->typeflags3 != 2)
3308 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3310 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3311 debugstr_w((*ppTypeInfoImpl)->Name),
3312 typekind_desc[pTIHeader->typekind],
3313 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3314 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3316 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3318 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3320 switch(pTIHeader->typekind) {
3321 case TKIND_ENUM:
3322 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3323 pTIHeader, pTITail);
3324 break;
3326 case TKIND_RECORD:
3327 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3328 pTIHeader, pTITail);
3329 break;
3331 case TKIND_INTERFACE:
3332 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3333 pTIHeader, pTITail);
3334 break;
3336 case TKIND_COCLASS:
3337 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3338 pTIHeader, pTITail);
3339 break;
3341 case TKIND_ALIAS:
3342 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3343 pTIHeader, pTITail);
3344 break;
3346 case TKIND_DISPATCH:
3347 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3348 pTIHeader, pTITail);
3349 break;
3351 default:
3352 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3353 break;
3357 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3358 but we've already set those */
3359 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3360 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3361 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3363 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3364 X(06);
3365 X(16);
3366 X(18);
3367 X(1a);
3368 X(1e);
3369 X(24);
3370 X(26);
3371 X(2a);
3372 X(2c);
3373 X(2e);
3374 X(30);
3375 X(32);
3376 X(34);
3378 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3379 pBlk = (char*)pBlk + pBlkEntry[order].len;
3382 if(i != pTypeLibImpl->TypeInfoCount) {
3383 FIXME("Somehow processed %d TypeInfos\n", i);
3384 return NULL;
3387 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3388 return (ITypeLib2*)pTypeLibImpl;
3391 /* ITypeLib::QueryInterface
3393 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3394 ITypeLib2 * iface,
3395 REFIID riid,
3396 VOID **ppvObject)
3398 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3400 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3402 *ppvObject=NULL;
3403 if(IsEqualIID(riid, &IID_IUnknown) ||
3404 IsEqualIID(riid,&IID_ITypeLib)||
3405 IsEqualIID(riid,&IID_ITypeLib2))
3407 *ppvObject = This;
3410 if(*ppvObject)
3412 ITypeLib2_AddRef(iface);
3413 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3414 return S_OK;
3416 TRACE("-- Interface: E_NOINTERFACE\n");
3417 return E_NOINTERFACE;
3420 /* ITypeLib::AddRef
3422 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3424 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3425 ULONG ref = InterlockedIncrement(&This->ref);
3427 TRACE("(%p)->ref was %lu\n",This, ref - 1);
3429 return ref;
3432 /* ITypeLib::Release
3434 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3436 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3437 ULONG ref = InterlockedDecrement(&This->ref);
3439 TRACE("(%p)->(%lu)\n",This, ref);
3441 if (!ref)
3443 /* remove cache entry */
3444 if(This->path)
3446 TRACE("removing from cache list\n");
3447 EnterCriticalSection(&cache_section);
3448 if (This->next) This->next->prev = This->prev;
3449 if (This->prev) This->prev->next = This->next;
3450 else tlb_cache_first = This->next;
3451 LeaveCriticalSection(&cache_section);
3452 HeapFree(GetProcessHeap(), 0, This->path);
3454 /* FIXME destroy child objects */
3455 TRACE(" destroying ITypeLib(%p)\n",This);
3457 if (This->Name)
3459 SysFreeString(This->Name);
3460 This->Name = NULL;
3463 if (This->DocString)
3465 SysFreeString(This->DocString);
3466 This->DocString = NULL;
3469 if (This->HelpFile)
3471 SysFreeString(This->HelpFile);
3472 This->HelpFile = NULL;
3475 if (This->HelpStringDll)
3477 SysFreeString(This->HelpStringDll);
3478 This->HelpStringDll = NULL;
3481 if (This->pTypeInfo) /* can be NULL */
3482 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3483 HeapFree(GetProcessHeap(),0,This);
3484 return 0;
3487 return ref;
3490 /* ITypeLib::GetTypeInfoCount
3492 * Returns the number of type descriptions in the type library
3494 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3496 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3497 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3498 return This->TypeInfoCount;
3501 /* ITypeLib::GetTypeInfo
3503 * retrieves the specified type description in the library.
3505 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3506 ITypeLib2 *iface,
3507 UINT index,
3508 ITypeInfo **ppTInfo)
3510 int i;
3512 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3513 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3515 TRACE("(%p)->(index=%d)\n", This, index);
3517 if (!ppTInfo) return E_INVALIDARG;
3519 /* search element n in list */
3520 for(i=0; i < index; i++)
3522 pTypeInfo = pTypeInfo->next;
3523 if (!pTypeInfo)
3525 TRACE("-- element not found\n");
3526 return TYPE_E_ELEMENTNOTFOUND;
3530 *ppTInfo = (ITypeInfo *) pTypeInfo;
3532 ITypeInfo_AddRef(*ppTInfo);
3533 TRACE("-- found (%p)\n",*ppTInfo);
3534 return S_OK;
3538 /* ITypeLibs::GetTypeInfoType
3540 * Retrieves the type of a type description.
3542 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3543 ITypeLib2 *iface,
3544 UINT index,
3545 TYPEKIND *pTKind)
3547 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3548 int i;
3549 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3551 TRACE("(%p) index %d\n", This, index);
3553 if(!pTKind) return E_INVALIDARG;
3555 /* search element n in list */
3556 for(i=0; i < index; i++)
3558 if(!pTInfo)
3560 TRACE("-- element not found\n");
3561 return TYPE_E_ELEMENTNOTFOUND;
3563 pTInfo = pTInfo->next;
3566 *pTKind = pTInfo->TypeAttr.typekind;
3567 TRACE("-- found Type (%d)\n", *pTKind);
3568 return S_OK;
3571 /* ITypeLib::GetTypeInfoOfGuid
3573 * Retrieves the type description that corresponds to the specified GUID.
3576 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3577 ITypeLib2 *iface,
3578 REFGUID guid,
3579 ITypeInfo **ppTInfo)
3581 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3582 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3584 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3586 if (!pTypeInfo)
3588 WARN("-- element not found\n");
3589 return TYPE_E_ELEMENTNOTFOUND;
3592 /* search linked list for guid */
3593 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3595 pTypeInfo = pTypeInfo->next;
3597 if (!pTypeInfo)
3599 /* end of list reached */
3600 WARN("-- element not found\n");
3601 return TYPE_E_ELEMENTNOTFOUND;
3605 TRACE("-- found (%p, %s)\n",
3606 pTypeInfo,
3607 debugstr_w(pTypeInfo->Name));
3609 *ppTInfo = (ITypeInfo*)pTypeInfo;
3610 ITypeInfo_AddRef(*ppTInfo);
3611 return S_OK;
3614 /* ITypeLib::GetLibAttr
3616 * Retrieves the structure that contains the library's attributes.
3619 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3620 ITypeLib2 *iface,
3621 LPTLIBATTR *ppTLibAttr)
3623 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3624 TRACE("(%p)\n",This);
3625 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3626 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3627 return S_OK;
3630 /* ITypeLib::GetTypeComp
3632 * Enables a client compiler to bind to a library's types, variables,
3633 * constants, and global functions.
3636 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3637 ITypeLib2 *iface,
3638 ITypeComp **ppTComp)
3640 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3642 TRACE("(%p)->(%p)\n",This,ppTComp);
3643 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3644 ITypeComp_AddRef(*ppTComp);
3646 return S_OK;
3649 /* ITypeLib::GetDocumentation
3651 * Retrieves the library's documentation string, the complete Help file name
3652 * and path, and the context identifier for the library Help topic in the Help
3653 * file.
3655 * On a successful return all non-null BSTR pointers will have been set,
3656 * possibly to NULL.
3658 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3659 ITypeLib2 *iface,
3660 INT index,
3661 BSTR *pBstrName,
3662 BSTR *pBstrDocString,
3663 DWORD *pdwHelpContext,
3664 BSTR *pBstrHelpFile)
3666 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3668 HRESULT result = E_INVALIDARG;
3670 ITypeInfo *pTInfo;
3673 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3674 This, index,
3675 pBstrName, pBstrDocString,
3676 pdwHelpContext, pBstrHelpFile);
3678 if(index<0)
3680 /* documentation for the typelib */
3681 if(pBstrName)
3683 if (This->Name)
3685 if(!(*pBstrName = SysAllocString(This->Name)))
3686 goto memerr1;
3688 else
3689 *pBstrName = NULL;
3691 if(pBstrDocString)
3693 if (This->DocString)
3695 if(!(*pBstrDocString = SysAllocString(This->DocString)))
3696 goto memerr2;
3698 else if (This->Name)
3700 if(!(*pBstrDocString = SysAllocString(This->Name)))
3701 goto memerr2;
3703 else
3704 *pBstrDocString = NULL;
3706 if(pdwHelpContext)
3708 *pdwHelpContext = This->dwHelpContext;
3710 if(pBstrHelpFile)
3712 if (This->HelpFile)
3714 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
3715 goto memerr3;
3717 else
3718 *pBstrHelpFile = NULL;
3721 result = S_OK;
3723 else
3725 /* for a typeinfo */
3726 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3728 if(SUCCEEDED(result))
3730 result = ITypeInfo_GetDocumentation(pTInfo,
3731 MEMBERID_NIL,
3732 pBstrName,
3733 pBstrDocString,
3734 pdwHelpContext, pBstrHelpFile);
3736 ITypeInfo_Release(pTInfo);
3739 return result;
3740 memerr3:
3741 if (pBstrDocString) SysFreeString (*pBstrDocString);
3742 memerr2:
3743 if (pBstrName) SysFreeString (*pBstrName);
3744 memerr1:
3745 return STG_E_INSUFFICIENTMEMORY;
3748 /* ITypeLib::IsName
3750 * Indicates whether a passed-in string contains the name of a type or member
3751 * described in the library.
3754 static HRESULT WINAPI ITypeLib2_fnIsName(
3755 ITypeLib2 *iface,
3756 LPOLESTR szNameBuf,
3757 ULONG lHashVal,
3758 BOOL *pfName)
3760 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3761 ITypeInfoImpl *pTInfo;
3762 TLBFuncDesc *pFInfo;
3763 TLBVarDesc *pVInfo;
3764 int i;
3765 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3767 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3768 pfName);
3770 *pfName=TRUE;
3771 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3772 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3773 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3774 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3775 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3776 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3777 goto ITypeLib2_fnIsName_exit;
3779 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3780 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3783 *pfName=FALSE;
3785 ITypeLib2_fnIsName_exit:
3786 TRACE("(%p)slow! search for %s: %s found!\n", This,
3787 debugstr_w(szNameBuf), *pfName?"NOT":"");
3789 return S_OK;
3792 /* ITypeLib::FindName
3794 * Finds occurrences of a type description in a type library. This may be used
3795 * to quickly verify that a name exists in a type library.
3798 static HRESULT WINAPI ITypeLib2_fnFindName(
3799 ITypeLib2 *iface,
3800 LPOLESTR szNameBuf,
3801 ULONG lHashVal,
3802 ITypeInfo **ppTInfo,
3803 MEMBERID *rgMemId,
3804 UINT16 *pcFound)
3806 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3807 ITypeInfoImpl *pTInfo;
3808 TLBFuncDesc *pFInfo;
3809 TLBVarDesc *pVInfo;
3810 int i,j = 0;
3811 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3813 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3814 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3815 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3816 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3817 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
3818 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3819 goto ITypeLib2_fnFindName_exit;
3822 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3823 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3824 continue;
3825 ITypeLib2_fnFindName_exit:
3826 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3827 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3828 j++;
3830 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3831 This, *pcFound, debugstr_w(szNameBuf), j);
3833 *pcFound=j;
3835 return S_OK;
3838 /* ITypeLib::ReleaseTLibAttr
3840 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3843 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3844 ITypeLib2 *iface,
3845 TLIBATTR *pTLibAttr)
3847 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3848 TRACE("freeing (%p)\n",This);
3849 HeapFree(GetProcessHeap(),0,pTLibAttr);
3853 /* ITypeLib2::GetCustData
3855 * gets the custom data
3857 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3858 ITypeLib2 * iface,
3859 REFGUID guid,
3860 VARIANT *pVarVal)
3862 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3863 TLBCustData *pCData;
3865 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3867 if( IsEqualIID(guid, &pCData->guid)) break;
3870 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3872 if(pCData)
3874 VariantInit( pVarVal);
3875 VariantCopy( pVarVal, &pCData->data);
3876 return S_OK;
3878 return E_INVALIDARG; /* FIXME: correct? */
3881 /* ITypeLib2::GetLibStatistics
3883 * Returns statistics about a type library that are required for efficient
3884 * sizing of hash tables.
3887 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3888 ITypeLib2 * iface,
3889 ULONG *pcUniqueNames,
3890 ULONG *pcchUniqueNames)
3892 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3894 FIXME("(%p): stub!\n", This);
3896 if(pcUniqueNames) *pcUniqueNames=1;
3897 if(pcchUniqueNames) *pcchUniqueNames=1;
3898 return S_OK;
3901 /* ITypeLib2::GetDocumentation2
3903 * Retrieves the library's documentation string, the complete Help file name
3904 * and path, the localization context to use, and the context ID for the
3905 * library Help topic in the Help file.
3908 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3909 ITypeLib2 * iface,
3910 INT index,
3911 LCID lcid,
3912 BSTR *pbstrHelpString,
3913 DWORD *pdwHelpStringContext,
3914 BSTR *pbstrHelpStringDll)
3916 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3917 HRESULT result;
3918 ITypeInfo *pTInfo;
3920 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3922 /* the help string should be obtained from the helpstringdll,
3923 * using the _DLLGetDocumentation function, based on the supplied
3924 * lcid. Nice to do sometime...
3926 if(index<0)
3928 /* documentation for the typelib */
3929 if(pbstrHelpString)
3930 *pbstrHelpString=SysAllocString(This->DocString);
3931 if(pdwHelpStringContext)
3932 *pdwHelpStringContext=This->dwHelpContext;
3933 if(pbstrHelpStringDll)
3934 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3936 result = S_OK;
3938 else
3940 /* for a typeinfo */
3941 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3943 if(SUCCEEDED(result))
3945 ITypeInfo2 * pTInfo2;
3946 result = ITypeInfo_QueryInterface(pTInfo,
3947 &IID_ITypeInfo2,
3948 (LPVOID*) &pTInfo2);
3950 if(SUCCEEDED(result))
3952 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3953 MEMBERID_NIL,
3954 lcid,
3955 pbstrHelpString,
3956 pdwHelpStringContext,
3957 pbstrHelpStringDll);
3959 ITypeInfo2_Release(pTInfo2);
3962 ITypeInfo_Release(pTInfo);
3965 return result;
3968 /* ITypeLib2::GetAllCustData
3970 * Gets all custom data items for the library.
3973 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3974 ITypeLib2 * iface,
3975 CUSTDATA *pCustData)
3977 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3978 TLBCustData *pCData;
3979 int i;
3980 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3981 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3982 if(pCustData->prgCustData ){
3983 pCustData->cCustData=This->ctCustData;
3984 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3985 pCustData->prgCustData[i].guid=pCData->guid;
3986 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3988 }else{
3989 ERR(" OUT OF MEMORY!\n");
3990 return E_OUTOFMEMORY;
3992 return S_OK;
3995 static const ITypeLib2Vtbl tlbvt = {
3996 ITypeLib2_fnQueryInterface,
3997 ITypeLib2_fnAddRef,
3998 ITypeLib2_fnRelease,
3999 ITypeLib2_fnGetTypeInfoCount,
4000 ITypeLib2_fnGetTypeInfo,
4001 ITypeLib2_fnGetTypeInfoType,
4002 ITypeLib2_fnGetTypeInfoOfGuid,
4003 ITypeLib2_fnGetLibAttr,
4004 ITypeLib2_fnGetTypeComp,
4005 ITypeLib2_fnGetDocumentation,
4006 ITypeLib2_fnIsName,
4007 ITypeLib2_fnFindName,
4008 ITypeLib2_fnReleaseTLibAttr,
4010 ITypeLib2_fnGetCustData,
4011 ITypeLib2_fnGetLibStatistics,
4012 ITypeLib2_fnGetDocumentation2,
4013 ITypeLib2_fnGetAllCustData
4017 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4019 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4021 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4024 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4026 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4028 return ITypeLib2_AddRef((ITypeLib2 *)This);
4031 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4033 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4035 return ITypeLib2_Release((ITypeLib2 *)This);
4038 static HRESULT WINAPI ITypeLibComp_fnBind(
4039 ITypeComp * iface,
4040 OLECHAR * szName,
4041 ULONG lHash,
4042 WORD wFlags,
4043 ITypeInfo ** ppTInfo,
4044 DESCKIND * pDescKind,
4045 BINDPTR * pBindPtr)
4047 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4048 ITypeInfoImpl *pTypeInfo;
4050 TRACE("(%s, 0x%lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4052 *pDescKind = DESCKIND_NONE;
4053 pBindPtr->lptcomp = NULL;
4054 *ppTInfo = NULL;
4056 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4058 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4060 /* FIXME: check wFlags here? */
4061 /* FIXME: we should use a hash table to look this info up using lHash
4062 * instead of an O(n) search */
4063 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4064 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4066 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4068 *pDescKind = DESCKIND_TYPECOMP;
4069 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4070 ITypeComp_AddRef(pBindPtr->lptcomp);
4071 TRACE("module or enum: %s\n", debugstr_w(szName));
4072 return S_OK;
4076 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4077 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4079 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4080 HRESULT hr;
4082 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4083 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4085 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4086 return S_OK;
4090 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4091 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4093 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4094 HRESULT hr;
4095 ITypeInfo *subtypeinfo;
4096 BINDPTR subbindptr;
4097 DESCKIND subdesckind;
4099 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4100 &subtypeinfo, &subdesckind, &subbindptr);
4101 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4103 TYPEDESC tdesc_appobject =
4106 (TYPEDESC *)pTypeInfo->hreftype
4108 VT_USERDEFINED
4110 const VARDESC vardesc_appobject =
4112 -2, /* memid */
4113 NULL, /* lpstrSchema */
4115 0 /* oInst */
4118 /* ELEMDESC */
4120 /* TYPEDESC */
4122 &tdesc_appobject
4124 VT_PTR
4127 0, /* wVarFlags */
4128 VAR_STATIC /* varkind */
4131 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4133 /* cleanup things filled in by Bind call so we can put our
4134 * application object data in there instead */
4135 switch (subdesckind)
4137 case DESCKIND_FUNCDESC:
4138 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4139 break;
4140 case DESCKIND_VARDESC:
4141 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4142 break;
4143 default:
4144 break;
4146 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4148 if (pTypeInfo->hreftype == -1)
4149 FIXME("no hreftype for interface %p\n", pTypeInfo);
4151 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4152 if (FAILED(hr))
4153 return hr;
4155 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4156 *ppTInfo = (ITypeInfo *)pTypeInfo;
4157 ITypeInfo_AddRef(*ppTInfo);
4158 return S_OK;
4163 TRACE("name not found %s\n", debugstr_w(szName));
4164 return S_OK;
4167 static HRESULT WINAPI ITypeLibComp_fnBindType(
4168 ITypeComp * iface,
4169 OLECHAR * szName,
4170 ULONG lHash,
4171 ITypeInfo ** ppTInfo,
4172 ITypeComp ** ppTComp)
4174 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4175 return E_NOTIMPL;
4178 static const ITypeCompVtbl tlbtcvt =
4181 ITypeLibComp_fnQueryInterface,
4182 ITypeLibComp_fnAddRef,
4183 ITypeLibComp_fnRelease,
4185 ITypeLibComp_fnBind,
4186 ITypeLibComp_fnBindType
4189 /*================== ITypeInfo(2) Methods ===================================*/
4190 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4192 ITypeInfoImpl * pTypeInfoImpl;
4194 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4195 if (pTypeInfoImpl)
4197 pTypeInfoImpl->lpVtbl = &tinfvt;
4198 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4199 pTypeInfoImpl->ref=1;
4200 pTypeInfoImpl->hreftype = -1;
4201 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4202 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4204 TRACE("(%p)\n", pTypeInfoImpl);
4205 return (ITypeInfo2*) pTypeInfoImpl;
4208 /* ITypeInfo::QueryInterface
4210 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4211 ITypeInfo2 *iface,
4212 REFIID riid,
4213 VOID **ppvObject)
4215 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4217 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4219 *ppvObject=NULL;
4220 if(IsEqualIID(riid, &IID_IUnknown) ||
4221 IsEqualIID(riid,&IID_ITypeInfo)||
4222 IsEqualIID(riid,&IID_ITypeInfo2))
4223 *ppvObject = This;
4225 if(*ppvObject){
4226 ITypeInfo_AddRef(iface);
4227 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4228 return S_OK;
4230 TRACE("-- Interface: E_NOINTERFACE\n");
4231 return E_NOINTERFACE;
4234 /* ITypeInfo::AddRef
4236 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4238 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4239 ULONG ref = InterlockedIncrement(&This->ref);
4241 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4243 TRACE("(%p)->ref is %lu\n",This, ref);
4244 return ref;
4247 /* ITypeInfo::Release
4249 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4251 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4252 ULONG ref = InterlockedDecrement(&This->ref);
4254 TRACE("(%p)->(%lu)\n",This, ref);
4256 if (ref) {
4257 /* We don't release ITypeLib when ref=0 because
4258 it means that function is called by ITypeLib2_Release */
4259 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4260 } else {
4261 static int once = 0;
4262 if (!once)
4264 once = 1;
4265 FIXME("destroy child objects\n");
4268 TRACE("destroying ITypeInfo(%p)\n",This);
4269 if (This->Name)
4271 SysFreeString(This->Name);
4272 This->Name = 0;
4275 if (This->DocString)
4277 SysFreeString(This->DocString);
4278 This->DocString = 0;
4281 if (This->DllName)
4283 SysFreeString(This->DllName);
4284 This->DllName = 0;
4287 if (This->next)
4289 ITypeInfo_Release((ITypeInfo*)This->next);
4292 HeapFree(GetProcessHeap(),0,This);
4293 return 0;
4295 return ref;
4298 /* ITypeInfo::GetTypeAttr
4300 * Retrieves a TYPEATTR structure that contains the attributes of the type
4301 * description.
4304 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4305 LPTYPEATTR *ppTypeAttr)
4307 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4308 SIZE_T size;
4310 TRACE("(%p)\n",This);
4312 size = sizeof(**ppTypeAttr);
4313 if (This->TypeAttr.typekind == TKIND_ALIAS)
4314 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4316 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4317 if (!*ppTypeAttr)
4318 return E_OUTOFMEMORY;
4320 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4322 if (This->TypeAttr.typekind == TKIND_ALIAS)
4323 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4324 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4326 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4327 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4328 funcs */
4329 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4330 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4332 return S_OK;
4335 /* ITypeInfo::GetTypeComp
4337 * Retrieves the ITypeComp interface for the type description, which enables a
4338 * client compiler to bind to the type description's members.
4341 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4342 ITypeComp * *ppTComp)
4344 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4346 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4348 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4349 ITypeComp_AddRef(*ppTComp);
4350 return S_OK;
4353 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4355 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4356 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4357 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4358 return size;
4361 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4363 memcpy(dest, src, sizeof(ELEMDESC));
4364 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4365 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4367 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4368 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4369 *buffer += sizeof(PARAMDESCEX);
4370 memcpy(pparamdescex_dest, pparamdescex_src, sizeof(PARAMDESCEX));
4371 VariantInit(&pparamdescex_dest->varDefaultValue);
4372 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4373 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4375 else
4376 dest->u.paramdesc.pparamdescex = NULL;
4377 return S_OK;
4380 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4382 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4383 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4386 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4388 FUNCDESC *dest;
4389 char *buffer;
4390 SIZE_T size = sizeof(*src);
4391 SHORT i;
4392 HRESULT hr;
4394 size += sizeof(*src->lprgscode) * src->cScodes;
4395 size += TLB_SizeElemDesc(&src->elemdescFunc);
4396 for (i = 0; i < src->cParams; i++)
4398 size += sizeof(ELEMDESC);
4399 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4402 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4403 if (!dest) return E_OUTOFMEMORY;
4405 memcpy(dest, src, sizeof(FUNCDESC));
4406 buffer = (char *)(dest + 1);
4408 dest->lprgscode = (SCODE *)buffer;
4409 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4410 buffer += sizeof(*src->lprgscode) * src->cScodes;
4412 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4413 if (FAILED(hr))
4415 SysFreeString((BSTR)dest);
4416 return hr;
4419 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4420 buffer += sizeof(ELEMDESC) * src->cParams;
4421 for (i = 0; i < src->cParams; i++)
4423 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4424 if (FAILED(hr))
4425 break;
4427 if (FAILED(hr))
4429 /* undo the above actions */
4430 for (i = i - 1; i >= 0; i--)
4431 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4432 TLB_FreeElemDesc(&dest->elemdescFunc);
4433 SysFreeString((BSTR)dest);
4434 return hr;
4437 /* special treatment for dispinterfaces: this makes functions appear
4438 * to return their [retval] value when it is really returning an
4439 * HRESULT */
4440 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4442 if (dest->cParams &&
4443 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4445 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4446 if (elemdesc->tdesc.vt != VT_PTR)
4448 ERR("elemdesc should have started with VT_PTR instead of:\n");
4449 if (ERR_ON(ole))
4450 dump_ELEMDESC(elemdesc);
4451 return E_UNEXPECTED;
4454 /* copy last parameter to the return value. we are using a flat
4455 * buffer so there is no danger of leaking memory in
4456 * elemdescFunc */
4457 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4459 /* remove the last parameter */
4460 dest->cParams--;
4462 else
4463 /* otherwise this function is made to appear to have no return
4464 * value */
4465 dest->elemdescFunc.tdesc.vt = VT_VOID;
4469 *dest_ptr = dest;
4470 return S_OK;
4473 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4475 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4476 const TLBFuncDesc *pFDesc;
4477 int i;
4479 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4482 if (pFDesc)
4484 *ppFuncDesc = &pFDesc->funcdesc;
4485 return S_OK;
4488 return E_INVALIDARG;
4491 /* ITypeInfo::GetFuncDesc
4493 * Retrieves the FUNCDESC structure that contains information about a
4494 * specified function.
4497 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4498 LPFUNCDESC *ppFuncDesc)
4500 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4501 const FUNCDESC *internal_funcdesc;
4502 HRESULT hr;
4504 TRACE("(%p) index %d\n", This, index);
4506 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index, &internal_funcdesc);
4507 if (FAILED(hr))
4508 return hr;
4510 return TLB_AllocAndInitFuncDesc(
4511 internal_funcdesc,
4512 ppFuncDesc,
4513 This->TypeAttr.typekind == TKIND_DISPATCH);
4516 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
4518 VARDESC *dest;
4519 char *buffer;
4520 SIZE_T size = sizeof(*src);
4521 HRESULT hr;
4523 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
4524 if (src->varkind == VAR_CONST)
4525 size += sizeof(VARIANT);
4526 size += TLB_SizeElemDesc(&src->elemdescVar);
4528 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
4529 if (!dest) return E_OUTOFMEMORY;
4531 *dest = *src;
4532 buffer = (char *)(dest + 1);
4533 if (src->lpstrSchema)
4535 int len;
4536 dest->lpstrSchema = (LPOLESTR)buffer;
4537 len = strlenW(src->lpstrSchema);
4538 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
4539 buffer += (len + 1) * sizeof(WCHAR);
4542 if (src->varkind == VAR_CONST)
4544 HRESULT hr;
4546 dest->u.lpvarValue = (VARIANT *)buffer;
4547 *dest->u.lpvarValue = *src->u.lpvarValue;
4548 buffer += sizeof(VARIANT);
4549 VariantInit(dest->u.lpvarValue);
4550 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
4551 if (FAILED(hr))
4553 SysFreeString((BSTR)dest_ptr);
4554 return hr;
4557 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
4558 if (FAILED(hr))
4560 if (src->varkind == VAR_CONST)
4561 VariantClear(dest->u.lpvarValue);
4562 SysFreeString((BSTR)dest);
4563 return hr;
4565 *dest_ptr = dest;
4566 return S_OK;
4569 /* ITypeInfo::GetVarDesc
4571 * Retrieves a VARDESC structure that describes the specified variable.
4574 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4575 LPVARDESC *ppVarDesc)
4577 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4578 int i;
4579 const TLBVarDesc *pVDesc;
4581 TRACE("(%p) index %d\n", This, index);
4583 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4586 if (pVDesc)
4587 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
4589 return E_INVALIDARG;
4592 /* ITypeInfo_GetNames
4594 * Retrieves the variable with the specified member ID (or the name of the
4595 * property or method and its parameters) that correspond to the specified
4596 * function ID.
4598 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4599 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4601 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4602 const TLBFuncDesc *pFDesc;
4603 const TLBVarDesc *pVDesc;
4604 int i;
4605 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4606 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4607 if(pFDesc)
4609 /* function found, now return function and parameter names */
4610 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4612 if(!i)
4613 *rgBstrNames=SysAllocString(pFDesc->Name);
4614 else
4615 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4617 *pcNames=i;
4619 else
4621 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4622 if(pVDesc)
4624 *rgBstrNames=SysAllocString(pVDesc->Name);
4625 *pcNames=1;
4627 else
4629 if(This->TypeAttr.cImplTypes &&
4630 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4631 /* recursive search */
4632 ITypeInfo *pTInfo;
4633 HRESULT result;
4634 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4635 &pTInfo);
4636 if(SUCCEEDED(result))
4638 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4639 ITypeInfo_Release(pTInfo);
4640 return result;
4642 WARN("Could not search inherited interface!\n");
4644 else
4646 WARN("no names found\n");
4648 *pcNames=0;
4649 return TYPE_E_ELEMENTNOTFOUND;
4652 return S_OK;
4656 /* ITypeInfo::GetRefTypeOfImplType
4658 * If a type description describes a COM class, it retrieves the type
4659 * description of the implemented interface types. For an interface,
4660 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4661 * if any exist.
4664 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4665 ITypeInfo2 *iface,
4666 UINT index,
4667 HREFTYPE *pRefType)
4669 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4670 int i;
4671 HRESULT hr = S_OK;
4672 const TLBImplType *pImpl = This->impltypelist;
4674 TRACE("(%p) index %d\n", This, index);
4675 if (TRACE_ON(ole)) dump_TypeInfo(This);
4677 if(index==(UINT)-1)
4679 /* only valid on dual interfaces;
4680 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4682 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4684 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4685 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4687 *pRefType = -1;
4689 else
4691 hr = TYPE_E_ELEMENTNOTFOUND;
4694 else
4696 /* get element n from linked list */
4697 for(i=0; pImpl && i<index; i++)
4699 pImpl = pImpl->next;
4702 if (pImpl)
4703 *pRefType = pImpl->hRef;
4704 else
4705 hr = TYPE_E_ELEMENTNOTFOUND;
4708 if(TRACE_ON(ole))
4710 if(SUCCEEDED(hr))
4711 TRACE("SUCCESS -- hRef = 0x%08lx\n", *pRefType );
4712 else
4713 TRACE("FAILURE -- hresult = 0x%08lx\n", hr);
4716 return hr;
4719 /* ITypeInfo::GetImplTypeFlags
4721 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4722 * or base interface in a type description.
4724 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4725 UINT index, INT *pImplTypeFlags)
4727 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4728 int i;
4729 TLBImplType *pImpl;
4731 TRACE("(%p) index %d\n", This, index);
4732 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4733 i++, pImpl=pImpl->next)
4735 if(i==index && pImpl){
4736 *pImplTypeFlags=pImpl->implflags;
4737 return S_OK;
4739 *pImplTypeFlags=0;
4740 return TYPE_E_ELEMENTNOTFOUND;
4743 /* GetIDsOfNames
4744 * Maps between member names and member IDs, and parameter names and
4745 * parameter IDs.
4747 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4748 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4750 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4751 const TLBFuncDesc *pFDesc;
4752 const TLBVarDesc *pVDesc;
4753 HRESULT ret=S_OK;
4754 int i;
4756 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4757 cNames);
4759 /* init out parameters in case of failure */
4760 for (i = 0; i < cNames; i++)
4761 pMemId[i] = MEMBERID_NIL;
4763 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4764 int j;
4765 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4766 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4767 for(i=1; i < cNames; i++){
4768 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4769 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4770 break;
4771 if( j<pFDesc->funcdesc.cParams)
4772 pMemId[i]=j;
4773 else
4774 ret=DISP_E_UNKNOWNNAME;
4776 TRACE("-- 0x%08lx\n", ret);
4777 return ret;
4780 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4781 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4782 if(cNames) *pMemId=pVDesc->vardesc.memid;
4783 return ret;
4786 /* not found, see if it can be found in an inherited interface */
4787 if(This->TypeAttr.cImplTypes) {
4788 /* recursive search */
4789 ITypeInfo *pTInfo;
4790 ret=ITypeInfo_GetRefTypeInfo(iface,
4791 This->impltypelist->hRef, &pTInfo);
4792 if(SUCCEEDED(ret)){
4793 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4794 ITypeInfo_Release(pTInfo);
4795 return ret;
4797 WARN("Could not search inherited interface!\n");
4798 } else
4799 WARN("no names found\n");
4800 return DISP_E_UNKNOWNNAME;
4803 /* ITypeInfo::Invoke
4805 * Invokes a method, or accesses a property of an object, that implements the
4806 * interface described by the type description.
4808 DWORD
4809 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4810 DWORD res;
4812 if (TRACE_ON(ole)) {
4813 int i;
4814 TRACE("Calling %p(",func);
4815 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4816 TRACE(")\n");
4819 switch (callconv) {
4820 case CC_STDCALL:
4822 switch (nrargs) {
4823 case 0:
4824 res = func();
4825 break;
4826 case 1:
4827 res = func(args[0]);
4828 break;
4829 case 2:
4830 res = func(args[0],args[1]);
4831 break;
4832 case 3:
4833 res = func(args[0],args[1],args[2]);
4834 break;
4835 case 4:
4836 res = func(args[0],args[1],args[2],args[3]);
4837 break;
4838 case 5:
4839 res = func(args[0],args[1],args[2],args[3],args[4]);
4840 break;
4841 case 6:
4842 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4843 break;
4844 case 7:
4845 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4846 break;
4847 case 8:
4848 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4849 break;
4850 case 9:
4851 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4852 break;
4853 case 10:
4854 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
4855 break;
4856 case 11:
4857 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
4858 break;
4859 case 12:
4860 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]);
4861 break;
4862 case 13:
4863 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]);
4864 break;
4865 case 14:
4866 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]);
4867 break;
4868 case 15:
4869 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]);
4870 break;
4871 case 16:
4872 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]);
4873 break;
4874 case 17:
4875 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]);
4876 break;
4877 case 18:
4878 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]);
4879 break;
4880 case 19:
4881 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]);
4882 break;
4883 case 20:
4884 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]);
4885 break;
4886 case 21:
4887 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]);
4888 break;
4889 case 22:
4890 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]);
4891 break;
4892 case 23:
4893 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]);
4894 break;
4895 default:
4896 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4897 res = -1;
4898 break;
4900 break;
4901 default:
4902 FIXME("unsupported calling convention %d\n",callconv);
4903 res = -1;
4904 break;
4906 TRACE("returns %08lx\n",res);
4907 return res;
4910 extern int _argsize(DWORD vt);
4912 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
4914 HRESULT hr = S_OK;
4915 ITypeInfo *tinfo2 = NULL;
4916 TYPEATTR *tattr = NULL;
4918 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
4919 if (hr)
4921 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4922 "hr = 0x%08lx\n",
4923 tdesc->u.hreftype, hr);
4924 return hr;
4926 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
4927 if (hr)
4929 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08lx\n", hr);
4930 ITypeInfo_Release(tinfo2);
4931 return hr;
4934 switch (tattr->typekind)
4936 case TKIND_ENUM:
4937 *vt |= VT_I4;
4938 break;
4940 case TKIND_ALIAS:
4941 tdesc = &tattr->tdescAlias;
4942 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
4943 break;
4945 case TKIND_INTERFACE:
4946 if (IsEqualIID(&IID_IDispatch, &tattr->guid))
4947 *vt |= VT_DISPATCH;
4948 else
4949 *vt |= VT_UNKNOWN;
4950 break;
4952 case TKIND_DISPATCH:
4953 *vt |= VT_DISPATCH;
4954 break;
4956 case TKIND_RECORD:
4957 FIXME("TKIND_RECORD unhandled.\n");
4958 hr = E_NOTIMPL;
4959 break;
4961 case TKIND_UNION:
4962 FIXME("TKIND_UNION unhandled.\n");
4963 hr = E_NOTIMPL;
4964 break;
4966 default:
4967 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4968 hr = E_NOTIMPL;
4969 break;
4971 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
4972 ITypeInfo_Release(tinfo2);
4973 return hr;
4976 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
4978 HRESULT hr = S_OK;
4980 /* enforce only one level of pointer indirection */
4981 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
4983 tdesc = tdesc->u.lptdesc;
4985 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
4986 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
4987 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
4988 if ((tdesc->vt == VT_USERDEFINED) ||
4989 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
4991 VARTYPE vt_userdefined = 0;
4992 const TYPEDESC *tdesc_userdefined = tdesc;
4993 if (tdesc->vt == VT_PTR)
4995 vt_userdefined = VT_BYREF;
4996 tdesc_userdefined = tdesc->u.lptdesc;
4998 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
4999 if ((hr == S_OK) &&
5000 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5001 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5003 *vt |= vt_userdefined;
5004 return S_OK;
5007 *vt = VT_BYREF;
5010 switch (tdesc->vt)
5012 case VT_HRESULT:
5013 *vt |= VT_ERROR;
5014 break;
5015 case VT_USERDEFINED:
5016 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5017 break;
5018 case VT_VOID:
5019 case VT_CARRAY:
5020 case VT_PTR:
5021 case VT_LPSTR:
5022 case VT_LPWSTR:
5023 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5024 hr = DISP_E_BADVARTYPE;
5025 break;
5026 case VT_SAFEARRAY:
5027 *vt |= VT_ARRAY;
5028 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5029 break;
5030 default:
5031 *vt |= tdesc->vt;
5032 break;
5034 return hr;
5037 /***********************************************************************
5038 * DispCallFunc (OLEAUT32.@)
5040 * Invokes a function of the specifed calling convention, passing the
5041 * specified arguments and returns the result.
5043 * PARAMS
5044 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5045 * oVft [I] The offset in the vtable. See notes.
5046 * cc [I] Calling convention of the function to call.
5047 * vtReturn [I] The return type of the function.
5048 * cActuals [I] Number of parameters.
5049 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5050 * prgpvarg [I] The arguments to pass.
5051 * pvargResult [O] The return value of the function. Can be NULL.
5053 * RETURNS
5054 * Success: S_OK.
5055 * Failure: HRESULT code.
5057 * NOTES
5058 * The HRESULT return value of this function is not affected by the return
5059 * value of the user supplied function, which is returned in pvargResult.
5061 * If pvInstance is NULL then a non-object function is to be called and oVft
5062 * is the address of the function to call.
5064 * The cc parameter can be one of the following values:
5065 *|CC_FASTCALL
5066 *|CC_CDECL
5067 *|CC_PASCAL
5068 *|CC_STDCALL
5069 *|CC_FPFASTCALL
5070 *|CC_SYSCALL
5071 *|CC_MPWCDECL
5072 *|CC_MPWPASCAL
5075 HRESULT WINAPI
5076 DispCallFunc(
5077 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5078 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5080 int i, argsize, argspos;
5081 DWORD *args;
5082 HRESULT hres;
5084 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5085 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5086 pvargResult, V_VT(pvargResult));
5088 argsize = 0;
5089 if (pvInstance)
5090 argsize++; /* for This pointer */
5092 for (i=0;i<cActuals;i++)
5094 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5095 dump_Variant(prgpvarg[i]);
5096 argsize += _argsize(prgvt[i]);
5098 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5100 argspos = 0;
5101 if (pvInstance)
5103 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5104 argspos++;
5107 for (i=0;i<cActuals;i++)
5109 VARIANT *arg = prgpvarg[i];
5110 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5111 if (prgvt[i] == VT_VARIANT)
5112 memcpy(&args[argspos], arg, _argsize(prgvt[i]) * sizeof(DWORD));
5113 else
5114 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5115 argspos += _argsize(prgvt[i]);
5118 if (pvInstance)
5120 FARPROC *vtable = *(FARPROC**)pvInstance;
5121 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5123 else
5124 /* if we aren't invoking an object then the function pointer is stored
5125 * in oVft */
5126 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5128 if (pvargResult && (vtReturn != VT_EMPTY))
5130 TRACE("Method returned 0x%08lx\n",hres);
5131 V_VT(pvargResult) = vtReturn;
5132 V_UI4(pvargResult) = hres;
5135 HeapFree(GetProcessHeap(),0,args);
5136 return S_OK;
5139 #define INVBUF_ELEMENT_SIZE \
5140 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5141 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5142 ((VARIANTARG *)(buffer))
5143 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5144 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5145 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5146 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5147 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5148 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5150 static HRESULT WINAPI ITypeInfo_fnInvoke(
5151 ITypeInfo2 *iface,
5152 VOID *pIUnk,
5153 MEMBERID memid,
5154 UINT16 wFlags,
5155 DISPPARAMS *pDispParams,
5156 VARIANT *pVarResult,
5157 EXCEPINFO *pExcepInfo,
5158 UINT *pArgErr)
5160 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5161 int i;
5162 unsigned int var_index;
5163 TYPEKIND type_kind;
5164 HRESULT hres;
5165 const TLBFuncDesc *pFuncInfo;
5167 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p)\n",
5168 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5170 dump_DispParms(pDispParams);
5172 /* we do this instead of using GetFuncDesc since it will return a fake
5173 * FUNCDESC for dispinterfaces and we want the real function description */
5174 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5175 if (memid == pFuncInfo->funcdesc.memid && (wFlags & pFuncInfo->funcdesc.invkind))
5176 break;
5178 if (pFuncInfo) {
5179 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5181 if (TRACE_ON(ole))
5183 TRACE("invoking:\n");
5184 dump_TLBFuncDescOne(pFuncInfo);
5187 switch (func_desc->funckind) {
5188 case FUNC_PUREVIRTUAL:
5189 case FUNC_VIRTUAL: {
5190 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
5191 VARIANT varresult;
5192 VARIANT retval; /* pointer for storing byref retvals in */
5193 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
5194 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
5195 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
5197 hres = S_OK;
5198 for (i = 0; i < func_desc->cParams; i++)
5200 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5201 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
5202 if (FAILED(hres))
5203 goto func_fail;
5206 TRACE("changing args\n");
5207 for (i = 0; i < func_desc->cParams; i++)
5209 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5211 if (wParamFlags & PARAMFLAG_FRETVAL)
5213 /* note: this check is placed so that if the caller passes
5214 * in a VARIANTARG for the retval we just ignore it, like
5215 * native does */
5216 if (i == func_desc->cParams - 1)
5218 VARIANTARG *arg;
5219 arg = prgpvarg[i] = &rgvarg[i];
5220 memset(arg, 0, sizeof(*arg));
5221 V_VT(arg) = rgvt[i];
5222 memset(&retval, 0, sizeof(retval));
5223 V_BYREF(arg) = &retval;
5225 else
5227 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
5228 hres = E_UNEXPECTED;
5229 break;
5232 else if (i < pDispParams->cArgs)
5234 VARIANTARG *src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5235 dump_Variant(src_arg);
5237 if (rgvt[i] == VT_VARIANT)
5238 hres = VariantCopy(&rgvarg[i], src_arg);
5239 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
5241 if (rgvt[i] == V_VT(src_arg))
5242 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
5243 else
5245 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5246 hres = VariantCopy(&missing_arg[i], src_arg);
5247 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
5249 V_VT(&rgvarg[i]) = rgvt[i];
5251 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
5253 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5254 V_VT(&missing_arg[i]) = V_VT(src_arg);
5255 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
5256 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
5257 V_VT(&rgvarg[i]) = rgvt[i];
5259 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
5261 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
5262 V_VT(&rgvarg[i]) = rgvt[i];
5264 else
5266 /* FIXME: this doesn't work for VT_BYREF arguments if
5267 * they are not the same type as in the paramdesc */
5268 V_VT(&rgvarg[i]) = V_VT(src_arg);
5269 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
5270 V_VT(&rgvarg[i]) = rgvt[i];
5273 if (FAILED(hres))
5275 ERR("failed to convert param %d to %s%s from %s%s\n", i,
5276 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
5277 debugstr_VT(src_arg), debugstr_VF(src_arg));
5278 break;
5280 prgpvarg[i] = &rgvarg[i];
5282 else if (wParamFlags & PARAMFLAG_FOPT)
5284 VARIANTARG *arg;
5285 arg = prgpvarg[i] = &rgvarg[i];
5286 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5288 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
5289 if (FAILED(hres))
5290 break;
5292 else
5294 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5295 V_VT(arg) = VT_VARIANT | VT_BYREF;
5296 V_VARIANTREF(arg) = &missing_arg[i];
5297 V_VT(V_VARIANTREF(arg)) = VT_ERROR;
5298 V_ERROR(V_VARIANTREF(arg)) = DISP_E_PARAMNOTFOUND;
5301 else
5303 hres = DISP_E_BADPARAMCOUNT;
5304 break;
5307 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5308 if (func_desc->cParamsOpt < 0)
5310 FIXME("Does not support safearray optional parameters\n");
5311 hres = DISP_E_BADPARAMCOUNT;
5312 goto func_fail; /* FIXME: we don't free changed types here */
5315 V_VT(&varresult) = 0;
5316 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
5317 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5319 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
5320 V_VT(&varresult), func_desc->cParams, rgvt,
5321 prgpvarg, &varresult);
5323 for (i = 0; i < func_desc->cParams; i++)
5325 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5326 if (wParamFlags & PARAMFLAG_FRETVAL)
5328 if (TRACE_ON(ole))
5330 TRACE("[retval] value: ");
5331 dump_Variant(prgpvarg[i]);
5334 if (pVarResult)
5335 /* deref return value */
5336 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
5338 /* free data stored in varresult. Note that
5339 * VariantClear doesn't do what we want because we are
5340 * working with byref types. */
5341 /* FIXME: clear safearrays, bstrs, records and
5342 * variants here too */
5343 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
5344 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
5346 if(*V_UNKNOWNREF(prgpvarg[i]))
5347 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
5349 break;
5351 else if (i < pDispParams->cArgs)
5353 if (wParamFlags & PARAMFLAG_FOUT)
5355 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5357 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
5358 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
5360 if (FAILED(hres))
5362 ERR("failed to convert param %d to vt %d\n", i,
5363 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
5364 break;
5367 VariantClear(&rgvarg[i]);
5369 else if (wParamFlags & PARAMFLAG_FOPT)
5371 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5372 VariantClear(&rgvarg[i]);
5376 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
5378 WARN("invoked function failed with error 0x%08lx\n", V_ERROR(&varresult));
5379 hres = DISP_E_EXCEPTION;
5380 if (pExcepInfo) pExcepInfo->scode = V_ERROR(&varresult);
5383 func_fail:
5384 HeapFree(GetProcessHeap(), 0, buffer);
5385 break;
5387 case FUNC_DISPATCH: {
5388 IDispatch *disp;
5390 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5391 if (SUCCEEDED(hres)) {
5392 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5393 hres = IDispatch_Invoke(
5394 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
5395 pVarResult,pExcepInfo,pArgErr
5397 if (FAILED(hres))
5398 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres);
5399 IDispatch_Release(disp);
5400 } else
5401 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5402 break;
5404 default:
5405 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5406 hres = E_FAIL;
5407 break;
5410 TRACE("-- 0x%08lx\n", hres);
5411 return hres;
5413 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5414 VARDESC *var_desc;
5416 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5417 if(FAILED(hres)) return hres;
5419 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5420 dump_VARDESC(var_desc);
5421 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
5422 return E_NOTIMPL;
5425 /* not found, look for it in inherited interfaces */
5426 ITypeInfo2_GetTypeKind(iface, &type_kind);
5427 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
5428 HREFTYPE ref_type;
5429 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
5430 /* recursive search */
5431 ITypeInfo *pTInfo;
5432 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
5433 if(SUCCEEDED(hres)){
5434 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
5435 ITypeInfo_Release(pTInfo);
5436 return hres;
5438 WARN("Could not search inherited interface!\n");
5441 ERR("did not find member id %ld, flags 0x%x!\n", memid, wFlags);
5442 return DISP_E_MEMBERNOTFOUND;
5445 /* ITypeInfo::GetDocumentation
5447 * Retrieves the documentation string, the complete Help file name and path,
5448 * and the context ID for the Help topic for a specified type description.
5450 * (Can be tested by the Visual Basic Editor in Word for instance.)
5452 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
5453 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
5454 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
5456 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5457 const TLBFuncDesc *pFDesc;
5458 const TLBVarDesc *pVDesc;
5459 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
5460 " HelpContext(%p) HelpFile(%p)\n",
5461 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5462 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5463 if(pBstrName)
5464 *pBstrName=SysAllocString(This->Name);
5465 if(pBstrDocString)
5466 *pBstrDocString=SysAllocString(This->DocString);
5467 if(pdwHelpContext)
5468 *pdwHelpContext=This->dwHelpContext;
5469 if(pBstrHelpFile)
5470 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5471 return S_OK;
5472 }else {/* for a member */
5473 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5474 if(pFDesc->funcdesc.memid==memid){
5475 if(pBstrName)
5476 *pBstrName = SysAllocString(pFDesc->Name);
5477 if(pBstrDocString)
5478 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5479 if(pdwHelpContext)
5480 *pdwHelpContext=pFDesc->helpcontext;
5481 return S_OK;
5483 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5484 if(pVDesc->vardesc.memid==memid){
5485 if(pBstrName)
5486 *pBstrName = SysAllocString(pVDesc->Name);
5487 if(pBstrDocString)
5488 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5489 if(pdwHelpContext)
5490 *pdwHelpContext=pVDesc->HelpContext;
5491 return S_OK;
5494 WARN("member %ld not found\n", memid);
5495 return TYPE_E_ELEMENTNOTFOUND;
5498 /* ITypeInfo::GetDllEntry
5500 * Retrieves a description or specification of an entry point for a function
5501 * in a DLL.
5503 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5504 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5505 WORD *pwOrdinal)
5507 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5508 const TLBFuncDesc *pFDesc;
5510 TRACE("(%p)->(memid %lx, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5512 if (pBstrDllName) *pBstrDllName = NULL;
5513 if (pBstrName) *pBstrName = NULL;
5514 if (pwOrdinal) *pwOrdinal = 0;
5516 if (This->TypeAttr.typekind != TKIND_MODULE)
5517 return TYPE_E_BADMODULEKIND;
5519 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5520 if(pFDesc->funcdesc.memid==memid){
5521 dump_TypeInfo(This);
5522 if (TRACE_ON(ole))
5523 dump_TLBFuncDescOne(pFDesc);
5525 if (pBstrDllName)
5526 *pBstrDllName = SysAllocString(This->DllName);
5528 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5529 if (pBstrName)
5530 *pBstrName = SysAllocString(pFDesc->Entry);
5531 if (pwOrdinal)
5532 *pwOrdinal = -1;
5533 return S_OK;
5535 if (pBstrName)
5536 *pBstrName = NULL;
5537 if (pwOrdinal)
5538 *pwOrdinal = (DWORD)pFDesc->Entry;
5539 return S_OK;
5541 return TYPE_E_ELEMENTNOTFOUND;
5544 /* ITypeInfo::GetRefTypeInfo
5546 * If a type description references other type descriptions, it retrieves
5547 * the referenced type descriptions.
5549 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5550 ITypeInfo2 *iface,
5551 HREFTYPE hRefType,
5552 ITypeInfo **ppTInfo)
5554 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5555 HRESULT result = E_FAIL;
5557 if ((This->hreftype != -1) && (This->hreftype == hRefType))
5559 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5560 ITypeInfo_AddRef(*ppTInfo);
5561 result = S_OK;
5563 else if (hRefType == -1 &&
5564 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5565 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5567 /* when we meet a DUAL dispinterface, we must create the interface
5568 * version of it.
5570 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5573 /* the interface version contains the same information as the dispinterface
5574 * copy the contents of the structs.
5576 *pTypeInfoImpl = *This;
5577 pTypeInfoImpl->ref = 1;
5579 /* change the type to interface */
5580 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5582 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5584 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
5586 result = S_OK;
5588 } else {
5589 TLBRefType *pRefType;
5590 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5591 if(pRefType->reference == hRefType)
5592 break;
5594 if(!pRefType)
5595 FIXME("Can't find pRefType for ref %lx\n", hRefType);
5596 if(pRefType && hRefType != -1) {
5597 ITypeLib *pTLib = NULL;
5599 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5600 UINT Index;
5601 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5602 } else {
5603 if(pRefType->pImpTLInfo->pImpTypeLib) {
5604 TRACE("typeinfo in imported typelib that is already loaded\n");
5605 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5606 ITypeLib2_AddRef((ITypeLib*) pTLib);
5607 result = S_OK;
5608 } else {
5609 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5610 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5611 pRefType->pImpTLInfo->wVersionMajor,
5612 pRefType->pImpTLInfo->wVersionMinor,
5613 pRefType->pImpTLInfo->lcid,
5614 &pTLib);
5616 if(!SUCCEEDED(result)) {
5617 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5618 result=LoadTypeLib(libnam, &pTLib);
5619 SysFreeString(libnam);
5621 if(SUCCEEDED(result)) {
5622 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5623 ITypeLib2_AddRef(pTLib);
5627 if(SUCCEEDED(result)) {
5628 if(pRefType->index == TLB_REF_USE_GUID)
5629 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5630 &pRefType->guid,
5631 ppTInfo);
5632 else
5633 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5634 ppTInfo);
5636 if (pTLib != NULL)
5637 ITypeLib2_Release(pTLib);
5641 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5642 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5643 return result;
5646 /* ITypeInfo::AddressOfMember
5648 * Retrieves the addresses of static functions or variables, such as those
5649 * defined in a DLL.
5651 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5652 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5654 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5655 HRESULT hr;
5656 BSTR dll, entry;
5657 WORD ordinal;
5658 HMODULE module;
5660 TRACE("(%p)->(0x%lx, 0x%x, %p)\n", This, memid, invKind, ppv);
5662 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
5663 if (FAILED(hr))
5664 return hr;
5666 module = LoadLibraryW(dll);
5667 if (!module)
5669 ERR("couldn't load %s\n", debugstr_w(dll));
5670 SysFreeString(dll);
5671 if (entry) SysFreeString(entry);
5672 return STG_E_FILENOTFOUND;
5674 /* FIXME: store library somewhere where we can free it */
5676 if (entry)
5678 LPSTR entryA;
5679 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
5680 entryA = HeapAlloc(GetProcessHeap(), 0, len);
5681 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
5683 *ppv = GetProcAddress(module, entryA);
5684 if (!*ppv)
5685 ERR("function not found %s\n", debugstr_a(entryA));
5687 HeapFree(GetProcessHeap(), 0, entryA);
5689 else
5691 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
5692 if (!*ppv)
5693 ERR("function not found %d\n", ordinal);
5696 SysFreeString(dll);
5697 if (entry) SysFreeString(entry);
5699 if (!*ppv)
5700 return TYPE_E_DLLFUNCTIONNOTFOUND;
5702 return S_OK;
5705 /* ITypeInfo::CreateInstance
5707 * Creates a new instance of a type that describes a component object class
5708 * (coclass).
5710 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5711 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
5713 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5714 FIXME("(%p) stub!\n", This);
5715 return S_OK;
5718 /* ITypeInfo::GetMops
5720 * Retrieves marshalling information.
5722 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5723 BSTR *pBstrMops)
5725 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5726 FIXME("(%p) stub!\n", This);
5727 return S_OK;
5730 /* ITypeInfo::GetContainingTypeLib
5732 * Retrieves the containing type library and the index of the type description
5733 * within that type library.
5735 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5736 ITypeLib * *ppTLib, UINT *pIndex)
5738 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5740 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5741 if (pIndex) {
5742 *pIndex=This->index;
5743 TRACE("returning pIndex=%d\n", *pIndex);
5746 if (ppTLib) {
5747 *ppTLib=(LPTYPELIB )(This->pTypeLib);
5748 ITypeLib2_AddRef(*ppTLib);
5749 TRACE("returning ppTLib=%p\n", *ppTLib);
5752 return S_OK;
5755 /* ITypeInfo::ReleaseTypeAttr
5757 * Releases a TYPEATTR previously returned by GetTypeAttr.
5760 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5761 TYPEATTR* pTypeAttr)
5763 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5764 TRACE("(%p)->(%p)\n", This, pTypeAttr);
5765 HeapFree(GetProcessHeap(), 0, pTypeAttr);
5768 /* ITypeInfo::ReleaseFuncDesc
5770 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5772 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5773 ITypeInfo2 *iface,
5774 FUNCDESC *pFuncDesc)
5776 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5777 SHORT i;
5779 TRACE("(%p)->(%p)\n", This, pFuncDesc);
5781 for (i = 0; i < pFuncDesc->cParams; i++)
5782 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
5783 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
5785 SysFreeString((BSTR)pFuncDesc);
5788 /* ITypeInfo::ReleaseVarDesc
5790 * Releases a VARDESC previously returned by GetVarDesc.
5792 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5793 VARDESC *pVarDesc)
5795 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5796 TRACE("(%p)->(%p)\n", This, pVarDesc);
5798 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
5799 if (pVarDesc->varkind == VAR_CONST)
5800 VariantClear(pVarDesc->u.lpvarValue);
5801 SysFreeString((BSTR)pVarDesc);
5804 /* ITypeInfo2::GetTypeKind
5806 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5809 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5810 TYPEKIND *pTypeKind)
5812 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5813 *pTypeKind=This->TypeAttr.typekind;
5814 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5815 return S_OK;
5818 /* ITypeInfo2::GetTypeFlags
5820 * Returns the type flags without any allocations. This returns a DWORD type
5821 * flag, which expands the type flags without growing the TYPEATTR (type
5822 * attribute).
5825 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5827 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5828 *pTypeFlags=This->TypeAttr.wTypeFlags;
5829 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5830 return S_OK;
5833 /* ITypeInfo2::GetFuncIndexOfMemId
5834 * Binds to a specific member based on a known DISPID, where the member name
5835 * is not known (for example, when binding to a default member).
5838 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5839 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5841 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5842 const TLBFuncDesc *pFuncInfo;
5843 int i;
5844 HRESULT result;
5846 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
5847 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
5848 break;
5849 if(pFuncInfo) {
5850 *pFuncIndex = i;
5851 result = S_OK;
5852 } else
5853 result = TYPE_E_ELEMENTNOTFOUND;
5855 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5856 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5857 return result;
5860 /* TypeInfo2::GetVarIndexOfMemId
5862 * Binds to a specific member based on a known DISPID, where the member name
5863 * is not known (for example, when binding to a default member).
5866 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5867 MEMBERID memid, UINT *pVarIndex)
5869 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5870 TLBVarDesc *pVarInfo;
5871 int i;
5872 HRESULT result;
5873 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5874 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5876 if(pVarInfo) {
5877 *pVarIndex = i;
5878 result = S_OK;
5879 } else
5880 result = TYPE_E_ELEMENTNOTFOUND;
5882 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5883 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5884 return result;
5887 /* ITypeInfo2::GetCustData
5889 * Gets the custom data
5891 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5892 ITypeInfo2 * iface,
5893 REFGUID guid,
5894 VARIANT *pVarVal)
5896 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5897 TLBCustData *pCData;
5899 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5900 if( IsEqualIID(guid, &pCData->guid)) break;
5902 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5904 if(pCData)
5906 VariantInit( pVarVal);
5907 VariantCopy( pVarVal, &pCData->data);
5908 return S_OK;
5910 return E_INVALIDARG; /* FIXME: correct? */
5913 /* ITypeInfo2::GetFuncCustData
5915 * Gets the custom data
5917 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5918 ITypeInfo2 * iface,
5919 UINT index,
5920 REFGUID guid,
5921 VARIANT *pVarVal)
5923 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5924 TLBCustData *pCData=NULL;
5925 TLBFuncDesc * pFDesc;
5926 int i;
5927 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5928 pFDesc=pFDesc->next);
5930 if(pFDesc)
5931 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
5932 if( IsEqualIID(guid, &pCData->guid)) break;
5934 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5936 if(pCData){
5937 VariantInit( pVarVal);
5938 VariantCopy( pVarVal, &pCData->data);
5939 return S_OK;
5941 return E_INVALIDARG; /* FIXME: correct? */
5944 /* ITypeInfo2::GetParamCustData
5946 * Gets the custom data
5948 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
5949 ITypeInfo2 * iface,
5950 UINT indexFunc,
5951 UINT indexParam,
5952 REFGUID guid,
5953 VARIANT *pVarVal)
5955 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5956 TLBCustData *pCData=NULL;
5957 TLBFuncDesc * pFDesc;
5958 int i;
5960 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
5962 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
5963 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
5964 pCData = pCData->next)
5965 if( IsEqualIID(guid, &pCData->guid)) break;
5967 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5969 if(pCData)
5971 VariantInit( pVarVal);
5972 VariantCopy( pVarVal, &pCData->data);
5973 return S_OK;
5975 return E_INVALIDARG; /* FIXME: correct? */
5978 /* ITypeInfo2::GetVarCustData
5980 * Gets the custom data
5982 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
5983 ITypeInfo2 * iface,
5984 UINT index,
5985 REFGUID guid,
5986 VARIANT *pVarVal)
5988 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5989 TLBCustData *pCData=NULL;
5990 TLBVarDesc * pVDesc;
5991 int i;
5993 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
5995 if(pVDesc)
5997 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
5999 if( IsEqualIID(guid, &pCData->guid)) break;
6003 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6005 if(pCData)
6007 VariantInit( pVarVal);
6008 VariantCopy( pVarVal, &pCData->data);
6009 return S_OK;
6011 return E_INVALIDARG; /* FIXME: correct? */
6014 /* ITypeInfo2::GetImplCustData
6016 * Gets the custom data
6018 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6019 ITypeInfo2 * iface,
6020 UINT index,
6021 REFGUID guid,
6022 VARIANT *pVarVal)
6024 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6025 TLBCustData *pCData=NULL;
6026 TLBImplType * pRDesc;
6027 int i;
6029 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6031 if(pRDesc)
6033 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6035 if( IsEqualIID(guid, &pCData->guid)) break;
6039 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6041 if(pCData)
6043 VariantInit( pVarVal);
6044 VariantCopy( pVarVal, &pCData->data);
6045 return S_OK;
6047 return E_INVALIDARG; /* FIXME: correct? */
6050 /* ITypeInfo2::GetDocumentation2
6052 * Retrieves the documentation string, the complete Help file name and path,
6053 * the localization context to use, and the context ID for the library Help
6054 * topic in the Help file.
6057 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6058 ITypeInfo2 * iface,
6059 MEMBERID memid,
6060 LCID lcid,
6061 BSTR *pbstrHelpString,
6062 DWORD *pdwHelpStringContext,
6063 BSTR *pbstrHelpStringDll)
6065 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6066 const TLBFuncDesc *pFDesc;
6067 const TLBVarDesc *pVDesc;
6068 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
6069 "HelpStringContext(%p) HelpStringDll(%p)\n",
6070 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6071 pbstrHelpStringDll );
6072 /* the help string should be obtained from the helpstringdll,
6073 * using the _DLLGetDocumentation function, based on the supplied
6074 * lcid. Nice to do sometime...
6076 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6077 if(pbstrHelpString)
6078 *pbstrHelpString=SysAllocString(This->Name);
6079 if(pdwHelpStringContext)
6080 *pdwHelpStringContext=This->dwHelpStringContext;
6081 if(pbstrHelpStringDll)
6082 *pbstrHelpStringDll=
6083 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6084 return S_OK;
6085 }else {/* for a member */
6086 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6087 if(pFDesc->funcdesc.memid==memid){
6088 if(pbstrHelpString)
6089 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6090 if(pdwHelpStringContext)
6091 *pdwHelpStringContext=pFDesc->HelpStringContext;
6092 if(pbstrHelpStringDll)
6093 *pbstrHelpStringDll=
6094 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6095 return S_OK;
6097 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6098 if(pVDesc->vardesc.memid==memid){
6099 if(pbstrHelpString)
6100 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6101 if(pdwHelpStringContext)
6102 *pdwHelpStringContext=pVDesc->HelpStringContext;
6103 if(pbstrHelpStringDll)
6104 *pbstrHelpStringDll=
6105 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6106 return S_OK;
6109 return TYPE_E_ELEMENTNOTFOUND;
6112 /* ITypeInfo2::GetAllCustData
6114 * Gets all custom data items for the Type info.
6117 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6118 ITypeInfo2 * iface,
6119 CUSTDATA *pCustData)
6121 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6122 TLBCustData *pCData;
6123 int i;
6125 TRACE("(%p) returning %d items\n", This, This->ctCustData);
6127 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6128 if(pCustData->prgCustData ){
6129 pCustData->cCustData=This->ctCustData;
6130 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
6131 pCustData->prgCustData[i].guid=pCData->guid;
6132 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
6134 }else{
6135 ERR(" OUT OF MEMORY!\n");
6136 return E_OUTOFMEMORY;
6138 return S_OK;
6141 /* ITypeInfo2::GetAllFuncCustData
6143 * Gets all custom data items for the specified Function
6146 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
6147 ITypeInfo2 * iface,
6148 UINT index,
6149 CUSTDATA *pCustData)
6151 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6152 TLBCustData *pCData;
6153 TLBFuncDesc * pFDesc;
6154 int i;
6155 TRACE("(%p) index %d\n", This, index);
6156 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6157 pFDesc=pFDesc->next)
6159 if(pFDesc){
6160 pCustData->prgCustData =
6161 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
6162 if(pCustData->prgCustData ){
6163 pCustData->cCustData=pFDesc->ctCustData;
6164 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
6165 pCData = pCData->next){
6166 pCustData->prgCustData[i].guid=pCData->guid;
6167 VariantCopy(& pCustData->prgCustData[i].varValue,
6168 & pCData->data);
6170 }else{
6171 ERR(" OUT OF MEMORY!\n");
6172 return E_OUTOFMEMORY;
6174 return S_OK;
6176 return TYPE_E_ELEMENTNOTFOUND;
6179 /* ITypeInfo2::GetAllParamCustData
6181 * Gets all custom data items for the Functions
6184 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
6185 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
6187 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6188 TLBCustData *pCData=NULL;
6189 TLBFuncDesc * pFDesc;
6190 int i;
6191 TRACE("(%p) index %d\n", This, indexFunc);
6192 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
6193 pFDesc=pFDesc->next)
6195 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
6196 pCustData->prgCustData =
6197 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
6198 sizeof(CUSTDATAITEM));
6199 if(pCustData->prgCustData ){
6200 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
6201 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
6202 pCData; i++, pCData = pCData->next){
6203 pCustData->prgCustData[i].guid=pCData->guid;
6204 VariantCopy(& pCustData->prgCustData[i].varValue,
6205 & pCData->data);
6207 }else{
6208 ERR(" OUT OF MEMORY!\n");
6209 return E_OUTOFMEMORY;
6211 return S_OK;
6213 return TYPE_E_ELEMENTNOTFOUND;
6216 /* ITypeInfo2::GetAllVarCustData
6218 * Gets all custom data items for the specified Variable
6221 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
6222 UINT index, CUSTDATA *pCustData)
6224 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6225 TLBCustData *pCData;
6226 TLBVarDesc * pVDesc;
6227 int i;
6228 TRACE("(%p) index %d\n", This, index);
6229 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
6230 pVDesc=pVDesc->next)
6232 if(pVDesc){
6233 pCustData->prgCustData =
6234 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
6235 if(pCustData->prgCustData ){
6236 pCustData->cCustData=pVDesc->ctCustData;
6237 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
6238 pCData = pCData->next){
6239 pCustData->prgCustData[i].guid=pCData->guid;
6240 VariantCopy(& pCustData->prgCustData[i].varValue,
6241 & pCData->data);
6243 }else{
6244 ERR(" OUT OF MEMORY!\n");
6245 return E_OUTOFMEMORY;
6247 return S_OK;
6249 return TYPE_E_ELEMENTNOTFOUND;
6252 /* ITypeInfo2::GetAllImplCustData
6254 * Gets all custom data items for the specified implementation type
6257 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
6258 ITypeInfo2 * iface,
6259 UINT index,
6260 CUSTDATA *pCustData)
6262 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6263 TLBCustData *pCData;
6264 TLBImplType * pRDesc;
6265 int i;
6266 TRACE("(%p) index %d\n", This, index);
6267 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
6268 pRDesc=pRDesc->next)
6270 if(pRDesc){
6271 pCustData->prgCustData =
6272 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
6273 if(pCustData->prgCustData ){
6274 pCustData->cCustData=pRDesc->ctCustData;
6275 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
6276 pCData = pCData->next){
6277 pCustData->prgCustData[i].guid=pCData->guid;
6278 VariantCopy(& pCustData->prgCustData[i].varValue,
6279 & pCData->data);
6281 }else{
6282 ERR(" OUT OF MEMORY!\n");
6283 return E_OUTOFMEMORY;
6285 return S_OK;
6287 return TYPE_E_ELEMENTNOTFOUND;
6290 static const ITypeInfo2Vtbl tinfvt =
6293 ITypeInfo_fnQueryInterface,
6294 ITypeInfo_fnAddRef,
6295 ITypeInfo_fnRelease,
6297 ITypeInfo_fnGetTypeAttr,
6298 ITypeInfo_fnGetTypeComp,
6299 ITypeInfo_fnGetFuncDesc,
6300 ITypeInfo_fnGetVarDesc,
6301 ITypeInfo_fnGetNames,
6302 ITypeInfo_fnGetRefTypeOfImplType,
6303 ITypeInfo_fnGetImplTypeFlags,
6304 ITypeInfo_fnGetIDsOfNames,
6305 ITypeInfo_fnInvoke,
6306 ITypeInfo_fnGetDocumentation,
6307 ITypeInfo_fnGetDllEntry,
6308 ITypeInfo_fnGetRefTypeInfo,
6309 ITypeInfo_fnAddressOfMember,
6310 ITypeInfo_fnCreateInstance,
6311 ITypeInfo_fnGetMops,
6312 ITypeInfo_fnGetContainingTypeLib,
6313 ITypeInfo_fnReleaseTypeAttr,
6314 ITypeInfo_fnReleaseFuncDesc,
6315 ITypeInfo_fnReleaseVarDesc,
6317 ITypeInfo2_fnGetTypeKind,
6318 ITypeInfo2_fnGetTypeFlags,
6319 ITypeInfo2_fnGetFuncIndexOfMemId,
6320 ITypeInfo2_fnGetVarIndexOfMemId,
6321 ITypeInfo2_fnGetCustData,
6322 ITypeInfo2_fnGetFuncCustData,
6323 ITypeInfo2_fnGetParamCustData,
6324 ITypeInfo2_fnGetVarCustData,
6325 ITypeInfo2_fnGetImplTypeCustData,
6326 ITypeInfo2_fnGetDocumentation2,
6327 ITypeInfo2_fnGetAllCustData,
6328 ITypeInfo2_fnGetAllFuncCustData,
6329 ITypeInfo2_fnGetAllParamCustData,
6330 ITypeInfo2_fnGetAllVarCustData,
6331 ITypeInfo2_fnGetAllImplTypeCustData,
6334 /******************************************************************************
6335 * CreateDispTypeInfo [OLEAUT32.31]
6337 * Build type information for an object so it can be called through an
6338 * IDispatch interface.
6340 * RETURNS
6341 * Success: S_OK. pptinfo contains the created ITypeInfo object.
6342 * Failure: E_INVALIDARG, if one or more arguments is invalid.
6344 * NOTES
6345 * This call allows an objects methods to be accessed through IDispatch, by
6346 * building an ITypeInfo object that IDispatch can use to call through.
6348 HRESULT WINAPI CreateDispTypeInfo(
6349 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
6350 LCID lcid, /* [I] Locale Id */
6351 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
6353 ITypeInfoImpl *pTIClass, *pTIIface;
6354 ITypeLibImpl *pTypeLibImpl;
6355 int param, func;
6356 TLBFuncDesc **ppFuncDesc;
6358 TRACE("\n");
6359 pTypeLibImpl = TypeLibImpl_Constructor();
6360 if (!pTypeLibImpl) return E_FAIL;
6362 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
6363 pTIIface->pTypeLib = pTypeLibImpl;
6364 pTIIface->index = 0;
6365 pTIIface->Name = NULL;
6366 pTIIface->dwHelpContext = -1;
6367 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
6368 pTIIface->TypeAttr.lcid = lcid;
6369 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
6370 pTIIface->TypeAttr.wMajorVerNum = 0;
6371 pTIIface->TypeAttr.wMinorVerNum = 0;
6372 pTIIface->TypeAttr.cbAlignment = 2;
6373 pTIIface->TypeAttr.cbSizeInstance = -1;
6374 pTIIface->TypeAttr.cbSizeVft = -1;
6375 pTIIface->TypeAttr.cFuncs = 0;
6376 pTIIface->TypeAttr.cImplTypes = 0;
6377 pTIIface->TypeAttr.cVars = 0;
6378 pTIIface->TypeAttr.wTypeFlags = 0;
6380 ppFuncDesc = &pTIIface->funclist;
6381 for(func = 0; func < pidata->cMembers; func++) {
6382 METHODDATA *md = pidata->pmethdata + func;
6383 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
6384 (*ppFuncDesc)->Name = SysAllocString(md->szName);
6385 (*ppFuncDesc)->funcdesc.memid = md->dispid;
6386 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
6387 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
6388 (*ppFuncDesc)->funcdesc.callconv = md->cc;
6389 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
6390 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
6391 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
6392 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
6393 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
6394 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
6395 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
6396 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6397 md->cArgs * sizeof(ELEMDESC));
6398 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6399 md->cArgs * sizeof(TLBParDesc));
6400 for(param = 0; param < md->cArgs; param++) {
6401 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
6402 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
6404 (*ppFuncDesc)->helpcontext = 0;
6405 (*ppFuncDesc)->HelpStringContext = 0;
6406 (*ppFuncDesc)->HelpString = NULL;
6407 (*ppFuncDesc)->Entry = NULL;
6408 (*ppFuncDesc)->ctCustData = 0;
6409 (*ppFuncDesc)->pCustData = NULL;
6410 (*ppFuncDesc)->next = NULL;
6411 ppFuncDesc = &(*ppFuncDesc)->next;
6414 dump_TypeInfo(pTIIface);
6416 pTypeLibImpl->pTypeInfo = pTIIface;
6417 pTypeLibImpl->TypeInfoCount++;
6419 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
6420 pTIClass->pTypeLib = pTypeLibImpl;
6421 pTIClass->index = 1;
6422 pTIClass->Name = NULL;
6423 pTIClass->dwHelpContext = -1;
6424 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
6425 pTIClass->TypeAttr.lcid = lcid;
6426 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
6427 pTIClass->TypeAttr.wMajorVerNum = 0;
6428 pTIClass->TypeAttr.wMinorVerNum = 0;
6429 pTIClass->TypeAttr.cbAlignment = 2;
6430 pTIClass->TypeAttr.cbSizeInstance = -1;
6431 pTIClass->TypeAttr.cbSizeVft = -1;
6432 pTIClass->TypeAttr.cFuncs = 0;
6433 pTIClass->TypeAttr.cImplTypes = 1;
6434 pTIClass->TypeAttr.cVars = 0;
6435 pTIClass->TypeAttr.wTypeFlags = 0;
6437 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
6438 pTIClass->impltypelist->hRef = 1;
6440 pTIClass->reflist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->reflist));
6441 pTIClass->reflist->index = 0;
6442 pTIClass->reflist->reference = 1;
6443 pTIClass->reflist->pImpTLInfo = TLB_REF_INTERNAL;
6445 dump_TypeInfo(pTIClass);
6447 pTIIface->next = pTIClass;
6448 pTypeLibImpl->TypeInfoCount++;
6450 *pptinfo = (ITypeInfo*)pTIClass;
6451 return S_OK;
6455 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
6457 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6459 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
6462 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
6464 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6466 return ITypeInfo_AddRef((ITypeInfo *)This);
6469 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
6471 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6473 return ITypeInfo_Release((ITypeInfo *)This);
6476 static HRESULT WINAPI ITypeComp_fnBind(
6477 ITypeComp * iface,
6478 OLECHAR * szName,
6479 ULONG lHash,
6480 WORD wFlags,
6481 ITypeInfo ** ppTInfo,
6482 DESCKIND * pDescKind,
6483 BINDPTR * pBindPtr)
6485 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6486 const TLBFuncDesc *pFDesc;
6487 const TLBVarDesc *pVDesc;
6489 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6491 *pDescKind = DESCKIND_NONE;
6492 pBindPtr->lpfuncdesc = NULL;
6493 *ppTInfo = NULL;
6495 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
6496 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
6497 if (!strcmpW(pFDesc->Name, szName)) {
6498 break;
6501 if (pFDesc)
6503 HRESULT hr = TLB_AllocAndInitFuncDesc(
6504 &pFDesc->funcdesc,
6505 &pBindPtr->lpfuncdesc,
6506 This->TypeAttr.typekind == TKIND_DISPATCH);
6507 if (FAILED(hr))
6508 return hr;
6509 *pDescKind = DESCKIND_FUNCDESC;
6510 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6511 ITypeInfo_AddRef(*ppTInfo);
6512 return S_OK;
6513 } else {
6514 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
6515 if (!strcmpW(pVDesc->Name, szName)) {
6516 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
6517 if (FAILED(hr))
6518 return hr;
6519 *pDescKind = DESCKIND_VARDESC;
6520 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6521 ITypeInfo_AddRef(*ppTInfo);
6522 return S_OK;
6526 /* FIXME: search each inherited interface, not just the first */
6527 if (This->TypeAttr.cImplTypes) {
6528 /* recursive search */
6529 ITypeInfo *pTInfo;
6530 ITypeComp *pTComp;
6531 HRESULT hr;
6532 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
6533 if (SUCCEEDED(hr))
6535 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
6536 ITypeInfo_Release(pTInfo);
6538 if (SUCCEEDED(hr))
6540 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6541 ITypeComp_Release(pTComp);
6542 return hr;
6544 WARN("Could not search inherited interface!\n");
6546 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
6547 return DISP_E_MEMBERNOTFOUND;
6550 static HRESULT WINAPI ITypeComp_fnBindType(
6551 ITypeComp * iface,
6552 OLECHAR * szName,
6553 ULONG lHash,
6554 ITypeInfo ** ppTInfo,
6555 ITypeComp ** ppTComp)
6557 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
6559 /* strange behaviour (does nothing) but like the
6560 * original */
6562 if (!ppTInfo || !ppTComp)
6563 return E_POINTER;
6565 *ppTInfo = NULL;
6566 *ppTComp = NULL;
6568 return S_OK;
6571 static const ITypeCompVtbl tcompvt =
6574 ITypeComp_fnQueryInterface,
6575 ITypeComp_fnAddRef,
6576 ITypeComp_fnRelease,
6578 ITypeComp_fnBind,
6579 ITypeComp_fnBindType